Tokomon - Digimon
티쿠스 IT 블로그

Kubernetes

[Kubernetes] K8s 설치 (RHEL 8 기반)

티쿠스 2023. 2. 13. 09:22

<Table of Contents>


Ⅰ. OVERVIEW

Ⅱ. 기본환경 구성 

1. 컨테이너 배포 시대의 도래
2. 기본 환경 구성

. Docker 설치

1. Docker의 배경 기술
2. Docker 설치
3. Docker 버전 확인

. Kubernetes 설치 (마스터 노드)

1. 오케스트레이션의 필요성
2. Kubernetes 설치
3. Kubernetes 클러스터 구성
4. kubectl 사전작업
5. Kubernetes 네트워크 구성
6. Kubernetes 버전 확인

Ⅴ. Kubernetes 설치 (워커 노드)

1. Kubernetes 설치
2. Kubernetes 클러스터 가입
3. kubectl 사전작업
4. Kubernetes 네트워크 구성 확인
5. Kubernetes 버전 확인
6. 노드 레이블 변경

 

Ⅰ. Overview

이 문서는 RHEL8 환경에서의 Docker 및 Kubernetes 설치에 관한 간략한 연동 가이드를 제공합니다.

 

Product Version IP
OS Red Hat Enterprise Linux 8 192.168.56.1xx (모든 노드)
Kubernetes kubeadm 1.26.1 192.168.56.1xx (모든 노드)
kubectl 1.26.1
kubelet 1.26.1
Docker docker 23.0.1 192.168.56.1xx (모든 노드)
containerd 1.6.16

 

간략하게 K8s 클러스터 구성 정보를 설명하자면 총 4 대의 장비로 구성됩니다.

 

 

192.168.56.120 - 마스터노드 (master)

192.168.56.101 - 워커노드 (worker1)

192.168.56.102 - 워커노드 (worker2)

192.168.56.103 - 워커노드 (worker3)

 

 

Ⅱ. 기본환경 구성 (모든 노드 - 192.168.56.1xx)

1. 컨테이너 환경

시대의 흐름에 따른 배포 방식의 변화

완전 물리 서버에서 어플리케이션을 실행할 수 밖에 없었던 전통적인 배포 방식에서

리소스를 효율적으로 배분할 수 있게 해준 가상화 배포시대를 거쳐

컨테이너 배포 환경을 통해 기존 인프라와의 종속성을 끊어버릴 수 있게 되었습니다.

따라서 클라우드 혹은 온프레미스 환경 모두에 이식이 가능합니다.

 

2. 기본환경 구성

# swap 비활성화
cmd>
 swapoff -a && sed -i '/swap/s/^/#/' /etc/fstab

# 방화벽 비활성화
cmd> systemctl stop firewalld 
cmd> systemctl disable firewalld

# SELINUX 정책 수정
cmd> setenforce 0
cmd>
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

cmd> cat <<EOF > /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cmd> cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

cmd> sysctl --system

cmd> vi /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.56.120  master master.test.org
192.168.56.101  node1 node1.test.org
192.168.56.102  node2 node2.test.org
192.168.56.103  node3 node3.test.org
192.168.56.104  node4 node4.test.org
192.168.56.105  node5 node5.test.org

 

 

Ⅲ. Docker 설치 (모든 노드 - 192.168.56.1xx)

1. Docker의 배경기술

컨테이너의 배경기술

 

컨테이너는 리눅스의 몇몇 기술로부터 시작이 되었습니다.

 

프로세스마다 컴퓨팅 자원을 제어 가능하게 해주는 cgroups

프로세스에 대한 파일시스템 격리를 도와주는 chroot

프로세스에 대한 환경 자체를 격리시키는 namespace

 

이후 cgroups와 namespace를 결합한 LXC(Linux Container)라는 지금의 컨테이너의 시초라고 볼 수 있는 기술이 등장합니다.

이후 이는 runc로 대체가 되었고, 아래와 같은 구조를 갖게 되었습니다.

 

Docker의 구조

 

2. Docker 설치

cmd> yum install -y yum-utils device-mapper-persistent-data lvm2
cmd> yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
cmd> yum install -y docker-ce docker-ce-cli containerd.io
패키지 충돌이 난다면, '--allowerasing' 옵션 추가

cmd> mkdir /etc/docker
cmd> cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native-cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
EOF


cmd> mkdir -p /etc/systemd/system/docker.service.d

cmd> systemctl enable --now docker
cmd> systemctl status docker

 

3. Docker 버전 확인

cmd> docker -v
Docker version 23.0.1, build a5ee5b1

cmd> containerd -v
containerd containerd.io 1.6.16 31aa4358a36870b21a992d3ad2bef29e1d693bec

 

 

Ⅳ. Kubernetes 설치 (192.168.56.120 - 마스터 노드)

1. 컨테이너 오케스트레이션의 필요성

K8s 클러스터 아키텍쳐

어플리케이션의 아키텍쳐가 Monolithic 보다는 MSA의 흐름으로 가면서
각각의 컨테이너에 대한 세밀한 관리도 중요하지만, 
시스템이 커지면 커질수록 통합 관리(Container Orchestration)가 더욱 필요해졌습니다.

 

■ 별개의 컨테이너들을 통합 관리
■ 네트워크/스토리지/컴퓨트 자원 관리
■ 빠르고 유연한 컨테이너 증감
■ 동적 컨테이너 연결 및 부하분산

 

이외에도 위와 같은 장점으로 인해 Kubernetes가 더욱 각광을 받게 되었습니다.

 

2. Kubernetes 설치

cmd> cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF


cmd> yum install -y --disableexcludes=kubernetes kubeadm kubelet kubectl

# kubelet 은 마스터 노드의 api 서버와 worker 노드 간의 통신을 위한 서비스
cmd> systemctl status kubelet
...
Active: inactive (dead) 
...

cmd> systemctl start kubelet

# 아직 정상적으로 k8s 클러스터가 구성되지 않았기 때문에, 기동이 안되는게 정상입니다.
cmd>
 systemctl status kubelet
...
Active: failed 
...

 

3. Kubernetes 클러스터 구성

# 기존에 구성된 containerd 설정파일의 존재 때문에 런타임 에러가 발생할 수 있기 때문에 아래와 같이 지워주고, 데몬 재실행
cmd> rm -rf /etc/containerd/config.toml
cmd> systemctl restart containerd


# kubeadm라는 api로 클러스터를 구성해주기 위한 커맨드
cmd> kubeadm init --pod-network-cidr=192.168.56.0/24 --apiserver-advertise-address=192.168.56.120
...
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.56.120:6443 --token xxxxxx.xxxxxxxxxxxxxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# k8s 클러스터에 worker 노드를 추가하기 위한 커맨드를 파일 형태로 미리 저장해두기
cmd> cat << EOF > auth_token.txt
kubeadm join 192.168.56.120:6443 --token xxxxxx.xxxxxxxxxxxxxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
EOF

# kubeadm init 과정에서 kubelet 이 자동적으로 실행이 되기 때문에, 따로 데몬을 start 시켜줄 필요 없음.
cmd> systemctl status kubelet
...
Active: active (running)
...

 

※ 참고할 만한 에러 케이스

- 마스터노드 VM의 CPU 코어가 1개라면 아래와 같은 에러 발생 (ERROR NumCPU)

 

- kubeadm init 하고 다시 해야할 필요가 있는 경우,

  kubeadm reset으로 설정 깔끔하게 비워주고 다시 kubeadm init 해주기

 

- containerd 설정파일의 존재 때문에 런타임 에러가 발생할 수 있음 (이는 v1.26.1 기준이나, k8s 버전마다 다를 수 있음.)

 

4. kubectl 사전작업

cmd> mkdir $HOME/.kube
cmd> 
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

kubeadm init 을 통해 생성된 admin.conf 파일을 위 경로($HOME/.kube)로 복사합니다.

admin.conf 파일은 이 클러스터를 kubectl 커맨드로 제어할 수 있게 만들어주며,
기본 환경변수로 Shell에서 kubectl을 기본 환경변수로 선언하기 위한 작업입니다.

또는 이 작업 대신에  'export KUBECONFIG=/etc/kubernetes/admin.conf'라고 선언해줘도 되지만,
export의 특성으로 인해 이 세션 연결이 끊어지면 기억을 못하기 때문에, 매번 선언해줘야해서 번거로워집니다.

 

5. Kubernetes 네트워크 구성

# coredns 파드는 CNI 플러그인이 마저 구성이 되어야 Running으로 변함.
cmd>
 watch kubectl get po -A

NAMESPACE    NAME                                                           READY   STATUS
----------------------------------------------------------------------------------------------------

kube-system    coredns-787d4945fb-272w7                        0/1         ContainerCreating
kube-system    coredns-787d4945fb-gxtf8                          0/1         ContainerCreating
kube-system      etcd-master.test.org                                      1/1          Running
kube-system      kube-apiserver-master.test.org                     1/1          Running
kube-system      kube-controller-manager-master.test.org      1/1         Running
kube-system      kube-proxy-28xk6                                         1/1          Running
kube-system      kube-scheduler-master.test.org                    1/1          Running


# CNI 플러그인으로 Calico 를 배포
cmd>
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml

# watch로 변화상황을 모니터링해보면, Pod들이 Init을 거쳐 Running으로 변하는 모습을 볼 수 있음.

cmd>
 watch kubectl get po -A

NAMESPACE    NAME                                                           READY   STATUS
----------------------------------------------------------------------------------------------------

kube-system    calico-kube-controllers-57b57c56f-jxzvd  1/1         Running
kube-system    calico-node-h2ztl                                         1/1         Running
kube-system    coredns-787d4945fb-272w7                        1/1         Running
kube-system    coredns-787d4945fb-gxtf8                          1/1         Running

kube-system      etcd-master.test.org                                      1/1          Running
kube-system      kube-apiserver-master.test.org                     1/1          Running
kube-system      kube-controller-manager-master.test.org      1/1         Running
kube-system      kube-proxy-28xk6                                         1/1          Running
kube-system      kube-scheduler-master.test.org                    1/1          Running

 

6. Kubernetes 버전 확인

cmd> kubeadm version -o short
v1.26.1

cmd> kubectl version --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.26.1
Kustomize Version: v4.5.7
Server Version: v1.26.1

cmd> kubelet --version
Kubernetes v1.26.1

 

 

Ⅴ. Kubernetes 설치 (192.168.56.10x - 워커 노드)

1. Kubernetes 설치

cmd> cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF


cmd> yum install -y --disableexcludes=kubernetes kubeadm kubelet kubectl

# kubelet 은 마스터 노드의 api 서버와 worker 노드 간의 통신을 위한 서비스
cmd> systemctl status kubelet
...
Active: inactive (dead) 
...

cmd> systemctl start kubelet

# 아직 정상적으로 k8s 클러스터가 구성되지 않았기 때문에, 기동이 안되는게 정상입니다.
cmd>
 systemctl status kubelet
...
Active: failed 
...

 

2. Kubernetes 클러스터 가입

# 기존에 구성된 containerd 설정파일의 존재 때문에 런타임 에러가 발생할 수 있기 때문에 아래와 같이 지워주고, 데몬 재실행
cmd>
rm -rf /etc/containerd/config.toml
cmd>
 systemctl restart containerd

# 아까 저장해둔 토큰 커맨드로 클러스터에 worker 노드 join

cmd> kubeadm join 192.168.56.120:6443 --token xxxxxx.xxxxxxxxxxxxxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
...
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

# kubeadm join 과정에서 kubelet 이 자동적으로 실행이 되기 때문에, 따로 데몬을 start 시켜줄 필요 없음.
cmd> systemctl status kubelet
...
Active: active (running)
...

 

3. kubectl 사전작업

cmd> mkdir $HOME/.kube/
cmd>
s
cp master:/etc/kubernetes/admin.conf  $HOME/.kube/config

워커 노드에서 kubectl 커맨드를 쓸 일은 굳이 잘 없지만,

마스터 노드의 admin.conf 파일을 워커 노드의 경로($HOME/.kube)로 옮겨오는 방법도 있습니다.

 

4. Kubernetes 네트워크 구성확인

# watch로 변화상황을 모니터링해보면, 총 노드의 개수만큼(마스터 포함) calico-node라는 이름의 pod 생성 확인됨.
cmd>
 watch kubectl get po -A

NAMESPACE    NAME                                                           READY   STATUS
----------------------------------------------------------------------------------------------------

kube-system      calico-kube-controllers-57b57c56f-jxzvd       1/1         Running
kube-system    calico-node-h2ztl                                         1/1          Running
kube-system    calico-node-drfkc                                         1/1         Running

kube-system    calico-node-dtpz5                                        1/1         Running
kube-system    calico-node-ace2c                                        1/1         Running

kube-system      coredns-787d4945fb-272w7                         1/1          Running
kube-system      coredns-787d4945fb-gxtf8                            1/1          Running

kube-system      etcd-master.test.org                                      1/1          Running
kube-system      kube-apiserver-master.test.org                     1/1          Running
kube-system      kube-controller-manager-master.test.org      1/1         Running
kube-system      kube-proxy-28xk6                                         1/1          Running
kube-system      kube-scheduler-master.test.org                    1/1          Running

 

5. Kubernetes 버전 확인

cmd> kubeadm version -o short
v1.26.1

cmd> kubectl version --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.26.1
Kustomize Version: v4.5.7
Server Version: v1.26.1

cmd> kubelet --version
Kubernetes v1.26.1

 

6. 노드 레이블 변경

# watch로 변화상황을 모니터링해보면, 총 노드의 개수만큼 calico-node라는 이름의 pod가 생성된 것을 확인 가능
cmd>
 watch kubectl get nodes

NAME              STATUS     ROLES           AGE     VERSION
-------------------------------------------------------------------------------
master.test.org   Ready      control-plane   19m     v1.26.1
node1.test.org    Ready      <none>          8m43s   v1.26.1
node2.test.org    Ready      <none>          8m47s   v1.26.1
node3.test.org    Ready      <none>          8m57s   v1.26.1

cmd> kubectl label node master.test.org node-role.kubernetes.io/master=""
node/master.test.org labeled

cmd>
kubectl label node node1.test.org node-role.kubernetes.io/worker=""
node/node1.test.org labeled

cmd>
 kubectl label node node2.test.org node-role.kubernetes.io/worker=""
node/node2.test.org labeled
cmd> kubectl label node node3.test.org node-role.kubernetes.io/worker=""
node/node3.test.org labeled

cmd> watch kubectl get nodes

NAME              STATUS     ROLES           AGE     VERSION
-------------------------------------------------------------------------------
master.test.org   Ready      control-plane,master   19m     v1.26.1
node1.test.org    Ready      worker          8m43s   v1.26.1
node2.test.org    Ready      worker          8m47s   v1.26.1
node2.test.org    Ready      worker          8m57s   v1.26.1