ubuntu 22.04에 k8s 구성해보기

astroid·2024년 9월 27일

k8s를 홈서버에 아래와 같이 직접 구성해보았다.

이런저런 삽질의 과정이 있었는데 다음 번에 또 구성할 일이 생겼을 때 동일한 삽질 과정을 반복하지 않고자 기록으로 남겨보려 한다.

k8s 자동 설치 스크립트

k8s를 여러번 설치해보면서 여러 명령어를 다수의 노드에 반복적으로 치는 게 매우 귀찮았다. 그래서 k8s 설치 스크립트 작성하여 명령어 한줄로 처리할수 있도록 자동 설치 스크립트를 작성해보았다.
https://github.com/rosenari/k8s_install/tree/main

세부과정이 궁금하신 분을 이어서 아래 내용을 읽어주세요. (՞ ܸ.‪ˬ.ܸ՞)”

k8s 설치

control-plane, worker node 모두 설치해야한다.

사전 설치

docker

docker 설치는 공식문서를 참고하는게 가장 좋더라. 도구의 업데이트나 변경사항이 있을때 공식문서에 바로 게시되기 때문에 블로그나 GPT는 참고 정도만 하는 것이 좋다고 생각한다.

우선 k8s가 구동되기 위해 docker가 사전 설치되어야 한다.
k8s는 containerd 런타임 위에서 동작하며 containerd는 docker 설치시 포함되는 구성 요소 중 하나이다.

sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

sudo usermod -aG docker $USER
sudo chmod 666 /var/run/docker.sock

시스템 설정 변경

CRI, SystemdCgroup

CRI와 SystemdCgroup 기능을 활성화한다.

CRI: containerd 위에서 k8s를 동작시키기 위해 활성화 하여야 한다.
SystemdCgroup: 활성화시 k8s에서 해당 기능을 사용해 컨테이너의 자원을 최적화 한다.

sudo containerd config default | tee /etc/containerd/config.toml
sudo sed -i '/^\s*disabled_plugins/ s/^/#/' /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
sudo systemctl restart containerd

위 과정 없이 설치한 적이 있었는데 SystemdCgroup을 설정하지 않고 k8s를 초기화할 경우 api 서버와 특정 파드들이 꺼졌다 켜졌다하는 증상이 반복되었다..

찾아보니 SystemdCgroup가 설정되어있지 않을 경우 k8s는 리소스 사용을 정확히 추적하지 못하게 되며 그로 인해 파드가 불안정하게 동작하게 된다라더라.

자세히 말하면 기존에는 kubelet과 docker가 독자적으로 관리하던 cgroup(리소스 관리 커널 기능) 기능(docker는 default가 cgroupfs이고, k8s는 default가 systemd이다.)을 systemd가 통합적으로 관리하도록 위임하여, 관리자를 1인 체제로 만들어 안정성을 유지한다. (사공이 많으면 배가 산으로 간다는 말처럼 리소스 관리 주체가 2명이라면 충돌이 날수 밖에 없다.)

스왑공간 비활성화 및 socat 설치

k8s는 pod 생성시 swap을 고려하지 않도록 설계되었다.
어떤 컨테이너는 swap 메모리를 쓰고 어떤 컨테이너는 안쓰고하는 프로세스는 k8s에서 자원 최적화에 대한 예측을 어렵게 만든다.

sudo swapoff -a
sudo sed -i '/swap/s/^/#/' /etc/fstab
sudo apt-get install socat

vm이 껐다 켜질 경우 swap 기능이 on 될수도 있기때문에 영구적으로 설정되도록 /etc/fatab 파일에서 /swap/s 부분을 주석처리해주자 !

ip forward 활성화

패킷이 호스트에 도착했을때 내부 컨테이너 IP로 패킷을 적절하게 전달하기 위해서는 ip forward가 활성화 되어야 한다.

sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf

커널 기능 중 ip forward가 설정되어 있어야 vm내 구성된 네트워크 인터페이스간 패킷을 전달할 수 있을 것이다.

방화벽 해제

멀티 호스트에서 노드간 통신이 원활하기 위해 방화벽을 해제한다.

sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo ufw disable

방화벽 때문에 노드간 통신이 안돼서 몇시간을 헤맸는지 모른다.
통신이 안된다면 반드시 방화벽을 확인하자 !

그리고 중간에 NetworkManager를 disable 시켜버렸는데, dhcp로 아이피를 할당받는 환경에서는 NetworkManager를 비활성화하면 안된다.
아이피가 계속 빠져서 노드가 죽더라..

kubelet, kubeadm, kubectl 설치

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/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.31/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
sudo systemctl enable --now kubelet

cluster 초기화

초기화

sudo kubeadm init --pod-network-cidr=172.16.0.0/16

파드 네트워크 cidr을 192.168.0.xxx 대역으로 설정 해보진 않았지만 파드 아이피와 vm 아이피가 동일한 아이피로 설정되는 게 뭔가 꺼림칙해서 파드 네트워크 cidr을 vm 아이피 대역과 다른 아이피 대역으로 초기화하였다.

초기화 후 아래 예시와 같은 출력이 나오는 데 복사하여 워커 노드에서 실행한다.

sudo kubeadm join 192.168.0.28:6443 --token v68fmb.9gwc28ccvchzzhyg \
	--discovery-token-ca-cert-hash sha256:800db7ed17c0944c73fee748d84bf92d836dcf5431ac00f97dc2b4f78a207dce

CNI 설치 (calico)

설치

마스터 노드에서 cni를 설치한다.

kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

CNI는 멀티호스트 환경에서 각 노드의 파드에 고유한 IP 주소를 할당하고, IP 주소 충돌을 방지하기 위해 각 노드에 서로 다른 CIDR 블록을 사용하도록 합니다.
calico는 cni 플러그인 중 하나입니다.

내가 구성한 환경은 멀티 호스트 환경이라서 CNI를 설치하지 않으면 다른 노드에 있는 파드간 서로 통신이 안되더라..
이것도 구성을 딜레이 시킨 문제 중 하나였는데 멀티호스트라는 키워드로 검색하다보니 CNI라는 존재와 각 노드 내의 파드 아이피가 동일하게 설정될 수 있다는 것을 알게되었다.

모니터링

마스터 노드에서 노드와 파드가 정상 실행되는지 모니터링 한다.
STATUS를 체크한다. (Ready 및 Running 상태인지)

kubectl get nodes -o wide
kubectl get pods --all-namespaces

노드의 상태와 파드의 상태가 정상화 되는 것을 보면서 k8s 구성 완료 여부를 확인하면 마무리 된다 !

profile
소프트웨어 엔지니어

0개의 댓글