LabHub
Get started
배우기 러닝패스 코스

CKA — Kubernetes Administrator

What changes when there is more than one node

LabHub 에서 이어서 보기

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

한 줄 요약

노드가 여럿이 되면 쿠버네티스의 문제는 "파드가 안 뜬다" 에서 "어느 노드의 무엇이 틀렸나" 로 바뀝니다. 그 답은 대개 kubectl 이 아니라 그 노드 안에 있습니다.

왜 이게 필요했나

한 대짜리 클러스터에서 연습하면 노드는 배경처럼 보입니다. 노드 이름이 하나뿐이니 스케줄링도, 네트워크도, 정비도 고민할 거리가 없습니다. 그런데 실제 클러스터는 노드 여러 대이고, CKA 실기도 노드 여러 대에 ssh 로 들어가 일하게 합니다. 워커를 조인하고, 한 노드를 비우고, NotReady 인 노드를 살리는 것이 전부 노드 안에서 일어나는 일입니다.

어떻게 동작하나

노드의 주소. kubelet 은 자기 주소를 노드 객체의 InternalIP 로 등록하고, API 서버·다른 노드·CNI 가 그 주소로 이 노드를 찾아옵니다. 주소를 따로 주지 않으면 kubelet 은 기본 경로가 나가는 NIC 의 주소를 고릅니다. NIC 가 하나인 서버에서는 그것이 맞지만, 관리망과 클러스터망이 갈라진 서버에서는 틀린 주소가 등록됩니다. 그래서 --node-ip(kubelet), --apiserver-advertise-address(kubeadm), --iface(Flannel)처럼 같은 질문을 구성요소마다 따로 답해야 합니다. 이 실습의 VM 들은 첫 NIC 가 모두 10.0.2.2 라서, 한 곳이라도 빠뜨리면 증상이 바로 드러납니다.

조인. kubeadm join 은 부트스트랩 토큰으로 API 서버에 자기를 소개하고, --discovery-token-ca-cert-hash 로 그 API 서버가 진짜인지 확인한 뒤, kubelet 이 쓸 인증서를 받아 /etc/kubernetes/kubelet.conf 를 씁니다. 조인이 끝나면 kubelet 이 노드 객체를 만들고, CNI DaemonSet 이 그 노드에 파드를 띄워야 Ready 가 됩니다.

정비. kubectl cordon 은 노드에 스케줄 금지 표시만 합니다. kubectl drain 은 거기에 더해 파드를 축출합니다 — 축출은 삭제와 달리 PodDisruptionBudget 을 지킵니다. DaemonSet 파드는 축출해도 같은 노드에 다시 생기므로 --ignore-daemonsets 로 건너뜁니다. 정비가 끝나면 uncordon 으로 되돌리는데, 이미 옮겨 간 파드는 돌아오지 않습니다. 스케줄러는 새 파드를 놓을 때만 판단하기 때문입니다.

kubelet 은 서비스입니다. 컨트롤 플레인 구성요소는 정적 파드로 돌지만, 그 정적 파드를 띄우는 kubelet 자신은 systemd 가 관리합니다. 그래서 kubelet 이 죽으면 그 노드의 상태를 보고할 주체가 없어 노드가 NotReady 가 되고, 원인은 systemctl status kubeletjournalctl -u kubelet 에만 남습니다. 여기서 active(지금 떠 있다)와 enabled(부팅 때 켜진다)는 다른 질문입니다. kubeadm 은 조인할 때 kubelet 을 직접 띄우지만 enable 해 주지는 않고 경고만 남깁니다.

이 실습의 환경이 실제와 같은 점과 다른 점

같은 점부터 봅니다. 세 VM 은 각자 커널·systemd·containerd 를 가진 진짜 서버이고, 노드 사이 트래픽은 진짜 네트워크를 탑니다. Flannel 의 VXLAN 이 UDP 8472 로 나가고, API 서버는 6443 으로, kubelet 은 10250 으로 서로를 부릅니다. 그래서 설정 한 곳이 틀리면 증상이 실제 클러스터와 똑같이 나타납니다.

다른 점은 두 가지입니다. 첫째, eth1 은 실제 NIC 가 아니라 이 세션의 VM 끼리만 연결된 가상 L2 망입니다. 바깥에서 보면 VM 사이에 UDP 4789 하나만 오가고, 다른 수강생의 VM 에는 닿지 않습니다. 둘째, 세 VM 의 첫 NIC 는 모두 10.0.2.2 라는 같은 주소를 받습니다. 실제 서버에서는 드문 일이지만, 덕분에 "주소를 명시하지 않으면 무엇이 선택되는가" 가 흐릿하지 않고 분명하게 드러납니다. 기본값에 기대는 설정은 이 환경에서 반드시 실패합니다.

현장에서 만나는 모습

온프렘 서버는 관리망·스토리지망·서비스망 NIC 를 따로 두는 경우가 흔합니다. 여기에 kubeadm 을 기본값으로 올리면 노드들이 관리망 주소로 등록되고, 파드 사이 통신이 스토리지망 스위치를 타거나 아예 닿지 않습니다. 노드는 전부 Ready 로 보여서 한참 뒤에야 알게 됩니다. 커널 패치 뒤 재부팅한 노드가 돌아오지 않는 것도 흔합니다. 누군가 손으로 서비스를 띄웠을 뿐 enable 하지 않았고, 그 사실은 재부팅 전까지 아무 증상도 없습니다. 그래서 정비 절차서에는 "재부팅 뒤 Ready 로 돌아오는지 확인" 이 늘 마지막 줄에 들어갑니다. 정비는 노드를 끄는 순간이 아니라 돌아온 것을 확인하는 순간에 끝나고, 확인하지 않은 재부팅은 다음 장애를 예약해 두는 것과 같습니다.

다음 실습에서 할 것

세 노드에 ssh 로 들어가 NIC 를 확인하고, eth1 주소로 컨트롤 플레인을 세운 뒤 Flannel 에게 터널 NIC 를 알려 줍니다. 워커 둘을 조인하고 다른 노드의 파드에 실제로 닿는지 확인한 다음, node01 을 비워 정비하고, 재부팅 뒤 돌아오지 않는 node02 를 그 노드 안에서 되살립니다.