테크믈리에의 리뷰 공간

[K8S / Rancher 강좌] 3. Kubeadm을 통한 K8S 환경 구축 방법 본문

프로그래밍|소프트웨어/Rancher

[K8S / Rancher 강좌] 3. Kubeadm을 통한 K8S 환경 구축 방법

테크믈리에 2023. 8. 19. 18:08

 

서론

  이번 시간에는 본격적으로 K8S 환경 구축을 위해 Kubeadm을 설치하고 다루는 방법에 관하여 다뤄보도록 하겠다. 로컬에 K8S를 구축하는 방법은 대표적으로 Kubeadm, MiniKube, Rancher 등을 통한 방법이 있는데, 이 중 MiniKube는 보통 간이 실험을 위하여 단일 노드에서 다수의 가상 노드를 쉽게 띄우기 위하여 사용된다. Rancher의 경우, 컨테이너 런타임으로 Docker를 쓰는 RKE1 및 Containerd나 K3S 기반으로 동작하는 RKE2를 자동으로 설치하고 관리할 수 있는 웹 기반 GUI 툴을 제공하는 배포판이다. Kubeadm은 K8S에서 공식으로 제공하는 K8S 클러스터 구축 툴로, 가장 기본적인 클러스터 구축방법이라고 볼 수 있다.

 

  Kubeadm으로 클러스터를 구축하는 방법에 관심이 있다면, 이 글을 읽고 4번을 건너뛰면 되고 만약 Rancher를 기반으로 한 클러스터 구축에 있다면 바로 4번 글로 넘어가는 것을 추천한다. 만약에, Rancher에 관심이 없어도 Kubeadm으로 Nvidia GPU를 사용하는 것에 관심이 있다면 4-1을 참고하면 도움이 될 것이다.

 

사전 준비

  우선은 Kubeadm을 설치하기에 앞서 필수 프로그램 및 네트워크 설정을 해야한다.

sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common gnupg2
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

sudo sysctl --system

  첫 명령어 블록은 Kubeadm 설치 과정 등에서 필요한 프로그램을 설치하는 명령어이고 그 아래 명령어는 K8S 클러스터 내 노드 간 통신을 위해 브릿지를 설정해주는 명령어이다.

 

 

Kubectl, Kubeadm, Kubelet 설치

  Kubectl이란 K8S 환경을 다루기 위한 CLI 도구를 뜻하는데, 이 도구를 통하여 K8S 클러스터 외부에서 K8S 클러스터에 명령을 내려 클러스터를 관리할 수 있게 된다. Kubeadm 환경이 굳이 아니더라도 Rancher 등 다른 방식으로 구성된 K8S 클러스터 역시 이 툴을 이용하여 관리할 수 있다.

  Kubelet이란 각 노드에서 동작하는 Node Agent로 각 노드를 API 서버를 통하여 K8S 클러스터에 등록하게끔 도와준다. Kubectl, Kubeadm, Kubelet은 모두 K8S의 APT 저장소를 통하여 설치할 수 있는 만큼 해당 저장소 정보를 추가하는 과정부터 진행해야한다.

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update

  저장소 등록 후에는 아래 명령어를 통하여 각 프로그램을 설치할 수 있다.

# 최신 버전 설치
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

#특정 버전 지정 설치 (ex. 1.20버전)
sudo apt-get install -y kubelet=1.20* kubeadm=1.20* kubectl=1.20*
sudo apt-mark hold kubelet kubeadm kubectl

  프로그램 설치 후에는 기본적으로 Docker를 사용하는 만큼 Docker에서 systemd 및 cgroup 관련 설정을 추가해야 한다.

sudo mkdir /etc/docker
cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "insecure-registries": ["143.248.152.38:9304"] // Harbor 및 Private Repo HTTP 통신용 추가
}
EOF

sudo systemctl enable docker 
sudo systemctl daemon-reload 
sudo systemctl restart docker

  설치 후 / 혹은 K8S 클러스터를 초기화하고 싶을 때는 아래 명령어를 이용한다.

sudo kubeadm reset

 

  해당 과정은 Control Plane 역할을 맡을 Master 노드 외에도 각 Worker Node에서 전부 진행해줘야 한다.

 

Control Plane 구축

  Control Plane을 구축하기에 앞서 Worker Node에서 Control Plane에 접속하기 위한 주소를 알아야하고 CIDR 중 어떠한 것을 쓸지 정해야한다. 앞서 주소는 만약 같은 네트워크 망 내부에서만 클러스터를 구축할 예정이라 하면 ifconfig 에서 조회되는 IP를 그대로 사용해도 되고 외부에 공개될 예정이라면 공인 IP값을 알아놔야할 것이다.

  CIDR의 경우 K8S에서 주로 사용되는 것은 Calico, Flannel, Canal, Weave 등이 있다. K8S 클러스터 구축 이전에 정해놔야하는 이유 중 하나는 Kubeadm 명령어를 사용하여 K8S를 구축할 때 pod-network-cidr이라는 IP 주소 범위를 설정해야하는데 이 Default 값이 각 CIDR에 따라 다르기 때문이다. 가령 예를 들어 Calico의 경우 192.168.0.0/16 이고 Flannel의 경우 10.244.0.0/16이다. 이 값은 사실 CIDR의 설정 파일에서 바꿔줄 수 있지만, 해당 내용까지 설명하기엔 이 시리즈는 간단하게 시스템 구축 방법만 설명하는 것이 목적이니 Calico를 기본 설정대로 사용하는 경우를 가정하여 설명하도록 하겠다.

 

sudo kubeadm init --apiserver-advertise-address <master IP> --pod-network-cidr=<포드 네트워크 IP 주소 범위>

#예시 (Calico 사용의 경우 / Master Node가 111.222.333.444인 경우)
sudo kubeadm init --apiserver-advertise-address 111.222.333.444 --pod-network-cidr=192.168.0.0/16

  위 명령어를 입력하면 자동적으로 K8S 클러스터 구축이 진행된다.

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

  성공적으로 클러스터 구축이 완료되었다면 위와 같은 출력이 나온다. 우선, 위 코드 블록의 경우 Kubectl이 새로 생성된 Kubeadm 클러스터에 접속할 수 있게끔 해주는 작업이기에 반드시 진행해주도록 하자. 그리고 제일 마지막을 보면 kubeadm join 명령어가 보이는데, 이는 Worker Node에서 클러스터에 접속할 수 있게끔 해주는 명령어로 까먹으면 다시 토큰을 추출하는 과정이 매우 귀찮기 때문에 되도록 기억해두도록 하자.

   성공적으로 여태까지의 모든 과정을 진행하였다면 kubectl version --short의 결과가 위와 비슷하게 나올 것이다. 여기서 Client Version은 kubectl의 버전을 의미하고 Server Version은 구축된 K8S 클러스터의 K8S 버전을 의미한다.

  이제 추가로 진행해야하는 것은 CIDR을 클러스터에 설치하는 과정이다. 여기서는 대표적으로 사용되는 Calico를 예시로 들도록 하겠다.

 

System requirements | Calico Documentation

Review requirements before installing Calico to ensure success.

docs.tigera.io

  우선 필요한 것은 현재 설치된 K8S 클러스터와 호환되는 Calico 버전을 확인하는 것이다. 위 링크에 들어가보면 상단에 Calico 버전을 선택할 수 있고 requirements 항목에서 호환되는 K8S 버전을 확인할 수 있다. 예를 들어 Calico v3.26은 K8S 버전 v1.24~v.1.27까지 호환되는 것을 알 수 있다.

# v3.25 버전까지의 경우 (<버전> = v3.17, v3.23, 등등)
curl https://docs.projectcalico.org/archive/<버전>/manifests/calico.yaml -O
kubectl apply -f calico.yaml

# v3.26 버전의 경우
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml

  여기까지 했으면 기본적으로 K8S Control Plane 노드의 준비는 됐다고 볼 수 있다. 하지만, 기본적으로 Control Plane의 경우 Taint가 주어져 있어서 Pod를 올릴 수 없기 때문에 Worker 노드 추가 없이는 작업을 진행할 수 없으며, Worker 노드를 추가하더라도 Control Plane은 Worker 노드로 사용할 수 없을 것이다. 만약 단일 노드에서 테스트를 진행해보고 싶거나 Control Plane도 활용해야하는 경우라면 아래 명령어를 참고해보자.

# Node 이름 확인
kubectl get nodes

# Node에 주어진 Taint 확인
kubectl describe node <노드명> | grep Taints

# 주어진 Taint를 제거하는 방법 (taint 뒤에 -를 붙이면 해당 taint를 제거한다는 의미이다)
kubectl taint nodes <노드명> <taint>-

# 예시
kubectl taint nodes master node-role.kubernetes.io/master:NoSchedule-

 

Worker Node 구축

  이제는 Worker Node를 구축하여 K8S 클러스터에 추가하는 방법을 보도록 하자. 사실 방법은 간단해서 위의 방법대로 Control Plane을 구축하는 과정에서 출력된 kubeadm join 명령어를 Worker Node에서 실행하기만 하면 된다. 다만, 경험해본 바로는 바로 kubeadm join만 하는 경우에는 Failed create pod sandbox: open /run/systemd/resolve/resolv.conf: no such file or directory 오류가 발생하는 경우가 많았다. 해당 오류가 나는 경우에는 아래 명령어를 해당 Worker Node에서 실행하면 문제가 해결될 것이다.

sudo mkdir -p /run/systemd/resolve
sudo ln -s /etc/resolv.conf /run/systemd/resolve/resolv.conf

 

노드 초기화 방법

  모든 환경이 그렇듯이, K8S 역시 작업하다보면 뭔가가 꼬여서 각 노드를 초기화해줘야하는 경우가 있을 것이다. 특히, Docker를 기반으로 RKE1 구축이든 Kubeadm 구축이든 하고난 다음에는 CIDR 관련 정보가 남아서 여간 사람을 괴롭게 하는 것이 아니다. 그러한 경우에는 아래 방법을 통하여 초기화해보도록 하자.

 

 ** 단 중요한 점은 아래 명령어 중 Docker 전체 초기화 명령어셋의 경우, docker에 떠있는 모든 컨테이너를 삭제하고 볼륨 역시 삭제하며 모든 이미지를 제거하기 때문에 Docker에 날라가선 안 되는 정보가 있는 경우에는 아래 명령어를 쓰지 않고 자신이 직접 K8S관련된 컨테이너, 이미지 등만 골라서 지우도록 하자. 아래 명령어를 따라하여 생기는 문제는 자신의 책임이다. **

# Docker 전체 초기화
docker stop $(docker ps -aq)
docker system prune -f
docker volume rm $(docker volume ls -q)
docker image rm $(docker image ls -q)

# 리부팅
sudo reboot

# 관련 폴더 삭제
sudo rm -rf /etc/ceph \
       /etc/cni \
       /etc/kubernetes \
       /opt/cni \
       /opt/rke \
       /run/secrets/kubernetes.io \
       /run/calico \
       /run/flannel \
       /var/lib/calico \
       /var/lib/etcd \
       /var/lib/cni \
       /var/lib/kubelet \
       /var/lib/rancher/rke/log \
       /var/log/containers \
       /var/log/pods \
       /var/run/calico

  만약 마지막 관련 폴더 삭제 단계에서 몇몇 폴더가 말썽을 부린다면 docker 등의 서비스를 중단하고 다시 리부팅을 한 다음 지우도록 해보자. 대부분의 경우에는 지워질 것이지만, Longhorn 등을 이용하여 생성한 저장소의 경우에는 지워지지 않을 수도 있다.

 

마침글

  이번 시간에는 kubeadm을 사용하여 K8S 클러스터를 구축하는 방법에 관하여 알아보았다. 이 시리즈의 경우 K8S에 하나하나 자세하게 설명하기보단 환경 구축에 초점을 두었기 때문에 클러스터 구축 이후 Pod, Deployment 등을 올리는 방법은 설명하지 않을 예정이다. 때문에, 이후의 자세한 K8S 클러스터 내 서비스 구축 방법에 관하여서는 다른 블로그 혹은 아래 공식 문서를 참고해보도록 하고 겸사겸사 Helm, Kustomize에 관하여 공부한다면 다양한 서비스를 올리는데 도움이 많이 될 것이다. 만약 나중에 기회(라고 쓰고 체력이라 읽는다)가 된다면 서비스 구축에 관하여서도 글을 올려보도록 하겠다.

 

 

파드

운영 수준의 컨테이너 오케스트레이션

kubernetes.io

 

 

Comments