Docker
쿠버네티스(k8s) 클러스터 만들기
기억보다는 기록을...
2025. 2. 26. 13:58
쿠버네티스 클러스터 만들기
- 최소 구성은 마스터 1노드, 워커 2노드로 가능하나, 마스터 1노드, 워커 3노드로 구성 진행
- 최소 사양
- Minimum 2GB RAM or more.
- Minimum 2 CPU cores (or 2 vCPUs).
- 20 GB of free disk space on /var (or more).
서버 구성
Master Node | Worker Node | Worker Node | Worker Node |
- k8smaster1 - 10.0.0.230 - 4Core, 4GB 메모리 - Ubuntu 24.04.2 LTS |
- k8sworker1 - 10.0.0.231 - 4Core, 4GB 메모리 - Ubuntu 24.04.2 LTS |
- k8sworker2 - 10.0.0.232 - 4Core, 4GB 메모리 - Ubuntu 24.04.2 LTS |
- k8sworker3 - 10.0.0.233 - 4Core, 4GB 메모리 - Ubuntu 24.04.2 LTS |
공통 설정
1. Swap Memory 비활성화
- Pod가 SWAP 영역으로 빠지게 되면 성능저하가 발생하기 때문에 쿠버네티스에서는 SWAP을 사용하지 않음.
- 재부팅 후에도 적용 되도록 /etc/fstab 에서 swap 영역 주석 처리
# free -g
total used free shared buff/cache available
Mem: 0 0 0 0 0 0
Swap: 15 0 15
# swapoff -a
# free -g
total used free shared buff/cache available
Mem: 0 0 0 0 0 0
Swap: 0 0 0
2. IPv4 Forwarding 기능 활성화
- 리눅스는 기본적으로 보안상 이슈로 다른 인터페이스로 패킷을 forward 하지 않음
- 네트워크간 패킷 통신이 가능하도록 forward 설정
# cat /proc/sys/net/ipv4/ip_forward
0
# sed -i 's/^#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
# sysctl --quiet --system
# cat /proc/sys/net/ipv4/ip_forward
1
3. 커널 파라미터 설정
- 쿠버네티스 네트워크와 컨테이너 네트워크 간 통신을 위해 설정
# tee /etc/modules-load.d/containerd.conf <<EOF
> overlay
> br_netfilter
> EOF
# modprobe overlay
# modprobe br_netfilter
# tee /etc/sysctl.d/kubernetes.conf <<EOF
> net.bridge.bridge-nf-call-ip6tables = 1
> net.bridge.bridge-nf-call-iptables = 1
> EOF
더보기
커널 모듈 로드
- overlay
- 오버레이 파일시스템을 지원하는 모듈
- 컨테이너 런타임(예: Docker, containerd)에서 사용하는 스토리지 드라이버로, 컨테이너의 계층화된 파일시스템을 생성하는 데 필요
- br_netfilter
- 리눅스 브리지 네트워크 스택에서 iptables를 사용한 네트워크 필터링을 지원
- Kubernetes의 네트워킹 플러그인(예: Calico, Flannel)이 정상적으로 작동하기 위해 필요
시스템 설정 (sysctl)
- net.bridge.bridge-nf-call-ip6tables = 1 / net.bridge.bridge-nf-call-iptables = 1
- 이 두 설정은 브리지를 통과하는 패킷이 iptables 규칙을 통과하도록 함.
- Kubernetes의 서비스 네트워크와 파드 간 통신을 위해 필요.
- 대부분의 Kubernetes CNI(Container Network Interface) 플러그인이 iptables를 사용하므로 이 설정이 필요.
4. Containerd 런타임 설치
- 의존성 패키지 설치
# apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
- 도커 GPG 키 추가 및 레포지토리 설정
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- Containerd 설치
# apt update
# apt install -y containerd.io
- Containerd 설정 추가
# containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
# sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
더보기
기본 설정 파일 생성
- containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
- containerd config default 명령어로 기본 설정값을 출력하여 /etc/containerd/config.toml 파일에 저장
- /dev/null 2>&1는 표준 출력과 오류 출력을 버려서 터미널 화면을 깔끔하게 유지
cgroup 드라이버를 systemd로 변경하는 과정
- sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
- 기본적으로 containerd는 SystemdCgroup = false 상태로 설정
- Kubernetes는 systemd를 기본적으로 사용하여 컨테이너 리소스 관리
- SystemdCgroup = false 상태에서는 cgroupfs가 사용되며, Kubernetes와 충돌이 발생할 수 있음.
- 서비스 시작 및 활성화
# systemctl restart containerd
# systemctl enable containerd
# systemctl status containerd
5. 쿠버네티스(k8s) apt 레포지토리 추가
- Ubuntu 기본 레포지토리에서는 쿠버네티스 패키지를 사용할 수 없음.
# echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
# curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
6. Kubectl, Kubeadm, Kubelet 설치
- kubectl - Kubernetes 클러스터를 관리하는 CLI
- kubeadm - 클러스터를 설치 및 초기화하는 도구
- kubelet - 각 노드에서 컨테이너(Pod)를 실행 및 모니터링하는 에이전트
# apt update
# apt install -y kubelet kubeadm kubectl
# apt-mark hold kubelet kubeadm kubectl
더보기
apt-mark hold
- apt upgrade나 apt dist-upgrade 실행 시 패키지가 최신 버전으로 업데이트 되는것을 방지.
- 쿠버네티스의 kubelet, kubeadm, kubectl 패키지는 클러스터의 안정성을 위해 특정 버전을 유지해야 하는 경우 많음
잠금 해제 방법
- apt-mark unhold kubelet kubeadm kubectl
이 후 설정은 쿠버네티스를 운영할 일반 사용자 계정(dockeruser)으로 설치를 진행하였음.
초기 설치 시 사용자 변경을 깜빡하고 진행.;;;
마스터 노드
1. k8s 초기화 (kubeadm 사용)
- VM의 메모리 설정을 동적으로 해 놨더니 전체 메모리가 1GB로 잡혀 오류 발생
$ sudo kubeadm init --pod-network-cidr=192.168.0.0/16
I0226 16:20:57.459189 4472 version.go:256] remote version is much newer: v1.32.2; falling back to: stable-1.30
[init] Using Kubernetes version: v1.30.10
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR Mem]: the system RAM (970 MB) is less than the minimum 1700 MB
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher
$ free -gh
total used free shared buff/cache available
Mem: 966Mi 453Mi 120Mi 3.3Mi 611Mi 513Mi
Swap: 0B 0B 0B
- 동적 메모리 설정 해제 후 초기화 진행
- CNI 플러그인을 Calico 사용 예정이라 IP 대역을 198.168.0.0/16으로 설정
- 플러그인별 기본 CIDR - Flannel(10.244.0.0/16), Calico(192.168.0.0/16)
- 네트워크 플러그인에 맞는 CIDR을 설정하지 않으면 클러스터 내 Pod 간 통신이 되지 않을 수 있음
- 마지막 kubeadm join 부분은 워커 노드 추가를 위해 복사
$ sudo kubeadm init --pod-network-cidr=192.168.0.0/16
I0226 16:27:38.259697 1179 version.go:256] remote version is much newer: v1.32.2; falling back to: stable-1.30
[init] Using Kubernetes version: v1.30.10
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
생략...
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.0.0.230:6443 --token llxpmg.wao1c2cj5dwn2l3s \
--discovery-token-ca-cert-hash sha256:b192d79f1eff212762c8e6a99c7d782c28373641a33c8b12eacb57e74a62663e
2. 클러스터 운영 계정 설정
- 일반 사용자 계정(dockeruser)에서 kubectl 명령어를 사용하여 쿠버네티스 클러스터를 관리 할 수 있도록 설정
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
3. Calico 플러그인 설치
- 쿠버네티스 사용자 계정(dockeruser)에서 실행
$ kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
- kubelet(모니터링 에이전트) 재시작
$ sudo systemctl restart kubelet
4. 상태 확인
- NotReady -> Ready 로 변경까지 시간이 걸림.
dockeruser@k8smaster1:~$ kubectl get no
NAME STATUS ROLES AGE VERSION
k8smaster1 NotReady control-plane 11m v1.30.10
dockeruser@k8smaster1:~$ kubectl get no
NAME STATUS ROLES AGE VERSION
k8smaster1 Ready control-plane 12m v1.30.10
워커 노드
1. 워커 노드 추가
- 각 노드(k8sworker1~3)에서 실행
$ sudo kubeadm join 10.0.0.230:6443 --token llxpmg.wao1c2cj5dwn2l3s \
--discovery-token-ca-cert-hash sha256:b192d79f1eff212762c8e6a99c7d782c28373641a33c8b12eacb57e74a62663e
마스터 노드
1. 클러스터 구성 확인
$ kubectl get no
NAME STATUS ROLES AGE VERSION
k8smaster1 Ready control-plane 4m36s v1.30.10
k8sworker1 Ready <none> 2m41s v1.30.10
k8sworker2 Ready <none> 2m v1.30.10
k8sworker3 Ready <none> 110s v1.30.10
2. 서비스 IP 범위와 클러스터 Pod IP 범위 확인
- --service-cluster-ip-range - 클러스터 내에서 서비스에 할당될 IP 주소 범위
- --cluster-cidr - Pod들에게 할당되는 IP 주소 범위
$ kubectl cluster-info dump | grep -m 2 -E "cluster-cidr|service-cluster-ip-range"
"--service-cluster-ip-range=10.96.0.0/12",
"--cluster-cidr=192.168.0.0/16",