LabHub
开始
学习 学习路径 课程

CKA — Kubernetes 管理员

三个节点 — join、drain 与 kubelet 恢复

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

노드 세 대에 ssh 로 들어가 kubeadm 클러스터를 조립하고, 워커 하나를 비워 정비한 뒤, 재부팅하고 돌아오지 않는 다른 워커를 되살립니다. CKA 실기가 요구하는 "여러 노드를 오가며 일하는 손" 을 진짜 VM 세 대에서 익힙니다.

왜 중요한가

한 대짜리 클러스터에서는 노드가 무엇인지 보이지 않습니다. 노드가 여럿이 되는 순간 세 가지가 달라집니다. 첫째, 노드의 주소가 문제가 됩니다. 이 실습의 세 VM 은 첫 NIC 의 주소가 모두 10.0.2.2 이고, 실제 클러스터 망은 두 번째 NIC(eth1)입니다. kubelet 의 --node-ip, API 서버의 advertise 주소, CNI 의 터널 NIC 가 모두 eth1 을 가리켜야 합니다 — 다중 NIC 서버에서 쿠버네티스를 세울 때 실제로 가장 많이 틀리는 곳입니다. 둘째, 정비가 생깁니다. 노드를 끄기 전에 파드를 비우는 drain 과, 되돌리는 uncordon 은 운영의 일상입니다. 셋째, kubelet 은 파드가 아니라 systemd 서비스입니다. 노드가 NotReady 일 때 kubectl 로는 원인에 닿지 않고, 그 노드에 들어가 서비스를 봐야 합니다.

단계

  1. controlplane 에서 ssh node01·ssh node02 로 각 노드에 들어가 hostnameeth1 의 IPv4 주소를 확인하세요. 세 노드를 /root/cluster/nodes.txt이름 주소 한 줄씩(controlplane·node01·node02) 적습니다.
  2. controlplane 에서 kubeadm init--kubernetes-version v1.36.4 --apiserver-advertise-address <controlplane 의 eth1 주소> --pod-network-cidr 172.20.0.0/16 --service-cidr 172.21.0.0/16 로 실행하고, /etc/kubernetes/admin.conf/root/.kube/config 로 복사하세요. controlplane 노드의 InternalIP 가 eth1 주소여야 합니다.
  3. 미리 받아 둔 /root/cluster/kube-flannel.yml(Flannel v0.28.9)에서 net-conf.jsonNetwork172.20.0.0/16 로 바꾸고, kube-flannel 컨테이너 args 에 --iface=eth1 을 더해 적용하세요. controlplane 이 Ready 가 되고 CoreDNS 가 Available 이어야 합니다.
  4. controlplane 에서 조인 명령을 만들어(kubeadm token create --print-join-command) node01 과 node02 에서 실행하세요. 세 노드가 모두 Ready 이고, node01·node02 의 InternalIP 가 각자의 eth1 주소여야 합니다.
  5. default 네임스페이스에 Deployment web 을 이미지 registry.k8s.io/e2e-test-images/agnhost:2.53, 명령 /agnhost netexec --http-port=8080, 레플리카 2 로 만드세요. 두 파드가 워커에서 Ready 이고, controlplane 에서 각 파드 IP 의 :8080/hostname 이 그 파드 이름을 돌려줘야 합니다.
  6. node01 을 kubectl drain 으로 비우고(DaemonSet 파드는 남겨 둡니다) 그 출력 전체를 /root/cluster/drain.log 에 저장하세요. node01 에 DaemonSet 이 아닌 파드가 하나도 없어야 하고, web 은 두 파드가 모두 Ready 여야 합니다.
  7. node02 를 재부팅하세요(ssh node02 reboot). 돌아온 뒤 node02 가 NotReady 로 남는 원인을 node02 에서 찾아 고치고, 다음 재부팅에도 스스로 돌아오게 하세요.
  8. node01 을 다시 스케줄 가능하게 하세요. 세 노드가 모두 Ready·스케줄 가능이고, Flannel DaemonSet 이 세 노드에서 준비되어 있으며, web 의 두 파드가 Ready 여야 합니다.

참고

세 노드에 들어가 두 번째 NIC 를 확인한다

controlplane 에서 ssh node01·ssh node02 로 각 노드에 들어가 hostnameeth1 의 IPv4 주소를 확인하세요. 세 노드를 /root/cluster/nodes.txt이름 주소 한 줄씩(controlplane·node01·node02) 적습니다.

ip -4 addr 를 보면 NIC 가 둘입니다. 첫 NIC(enp1s0)의 주소가 세 노드 모두 같다는 것을 확인해 보세요 — 그 주소로는 노드를 구별할 수 없습니다. ssh node01 'ip -4 -o addr show eth1' 처럼 명령만 보내도 됩니다.

eth1 주소로 컨트롤 플레인을 세운다

controlplane 에서 kubeadm init--kubernetes-version v1.36.4 --apiserver-advertise-address <controlplane 의 eth1 주소> --pod-network-cidr 172.20.0.0/16 --service-cidr 172.21.0.0/16 로 실행하고, /etc/kubernetes/admin.conf/root/.kube/config 로 복사하세요. controlplane 노드의 InternalIP 가 eth1 주소여야 합니다.

advertise 주소를 주지 않으면 kubeadm 은 기본 경로의 NIC(10.0.2.2)를 고릅니다. 그러면 워커가 그 주소로 API 서버를 찾아가 자기 자신에게 붙습니다. kubelet 쪽 주소는 /etc/default/kubelet--node-ip 가 정합니다 — 이미 적혀 있으니 읽어 보세요.

Flannel 에게 어느 NIC 로 터널을 만들지 알려 준다

미리 받아 둔 /root/cluster/kube-flannel.yml(Flannel v0.28.9)에서 net-conf.jsonNetwork172.20.0.0/16 로 바꾸고, kube-flannel 컨테이너 args 에 --iface=eth1 을 더해 적용하세요. controlplane 이 Ready 가 되고 CoreDNS 가 Available 이어야 합니다.

Flannel 은 기본 경로의 NIC 로 VXLAN 을 만듭니다. 그 NIC 의 주소가 세 노드 모두 같으면 터널의 목적지가 전부 자기 자신이 됩니다 — 노드는 Ready 인데 다른 노드의 파드에 닿지 않는 증상입니다. args 는 --kube-subnet-mgr 줄 아래에 같은 들여쓰기로 한 줄 더합니다.

워커 둘을 조인한다

controlplane 에서 조인 명령을 만들어(kubeadm token create --print-join-command) node01 과 node02 에서 실행하세요. 세 노드가 모두 Ready 이고, node01·node02 의 InternalIP 가 각자의 eth1 주소여야 합니다.

조인 명령은 워커에서 root 로 실행합니다 — ssh node01 '<조인 명령>'. 조인이 끝나도 Flannel 파드가 그 노드에 뜨기까지 Ready 는 잠시 늦습니다. 조인 출력의 WARNING 줄도 읽어 두세요. 나중에 쓸모가 있습니다.

다른 노드의 파드에 실제로 닿는지 본다

default 네임스페이스에 Deployment web 을 이미지 registry.k8s.io/e2e-test-images/agnhost:2.53, 명령 /agnhost netexec --http-port=8080, 레플리카 2 로 만드세요. 두 파드가 워커에서 Ready 이고, controlplane 에서 각 파드 IP 의 :8080/hostname 이 그 파드 이름을 돌려줘야 합니다.

kubectl create deployment web --image=… --replicas=2 -- /agnhost netexec --http-port=8080 한 줄이면 됩니다. controlplane 에는 control-plane 테인트가 있어 파드가 워커로만 갑니다. curl 이 멈춘다면 Flannel 의 NIC 부터 의심하세요.

node01 을 정비하려고 비운다

node01 을 kubectl drain 으로 비우고(DaemonSet 파드는 남겨 둡니다) 그 출력 전체를 /root/cluster/drain.log 에 저장하세요. node01 에 DaemonSet 이 아닌 파드가 하나도 없어야 하고, web 은 두 파드가 모두 Ready 여야 합니다.

드레인은 cordon(스케줄 금지) + 축출입니다. Flannel·kube-proxy 같은 DaemonSet 파드는 축출해도 곧바로 같은 노드에 다시 생기므로 --ignore-daemonsets 로 건너뜁니다. 축출된 web 파드는 node02 로 옮겨 갑니다. 출력은 2>&1 | tee 로 화면과 파일에 함께 남기면 됩니다.

재부팅한 node02 가 돌아오지 않는다

node02 를 재부팅하세요(ssh node02 reboot). 돌아온 뒤 node02 가 NotReady 로 남는 원인을 node02 에서 찾아 고치고, 다음 재부팅에도 스스로 돌아오게 하세요.

노드가 NotReady 면 그 노드의 kubelet 부터 봅니다 — systemctl status kubelet. 지금 떠 있는지(active)와 부팅 때 켜지는지(enabled)는 다른 질문입니다. 조인할 때 나온 WARNING 을 기억하나요?

정비를 끝내고 되돌린다

node01 을 다시 스케줄 가능하게 하세요. 세 노드가 모두 Ready·스케줄 가능이고, Flannel DaemonSet 이 세 노드에서 준비되어 있으며, web 의 두 파드가 Ready 여야 합니다.

drain 을 되돌리는 것은 uncordon 입니다. 되돌려도 이미 node02 로 옮겨 간 파드가 저절로 돌아오지는 않습니다 — 스케줄러는 새 파드를 놓을 때만 판단합니다.