Kubernetes를 이제 막 배우기 시작한 동료 개발자들에게 Kubernetes 클러스터의 기본 구성에 대해 설명하다보면 많이들 헷갈려하는 것이 있다. 바로, kubelet과 kube-proxy이다.
두 컴포넌트는 모두 Kubernetes 클러스터를 구성하는 각 노드에 설치되어 동작하지만, 실제로 클러스터를 운영할 때 우리가 이들을 다룰 일이 많지 않아서 그렇다. (둘 다 kube로 시작해서 헷갈려하는 경우도 있을 것이다.)
하지만 kubelet와 kube-proxy가 어떤 일을 하는지 이해하고 있다면 Kubernetes 클러스터를 운영할 때의 트러블슈팅에도 큰 도움이 된다. 문제의 원인 의심 지점을 더 제대로 파악할 수 있기 때문이다.
그래서 이번 아티클에서는 클러스터의 각 노드에서 리소스 상태 관리를 담당하는 kubelet과 트래픽 전달을 담당하는 kube-proxy에 대해 컴팩트하게 알아보려 한다.
1. 리소스 상태 관리를 담당하는 kubelet
Kubernetes의 Pod가 한 개 이상의 컨테이너로 구성된다는 것은 익히 알려진 사실이다. 즉, Kubernetes에 배포되는 애플리케이션은 기본적으로 컨테이너 내에서 동작한다.
각 노드에서 동작하는 kubelet은 이 컨테이너가 매니페스트에 정의된 Pod의 사양(spec)대로 노드에 잘 배포되도록 관리하는 역할을 수행한다.
kubelet은 각 노드에 설치된 컨테이너 런타임(예: Docker, containerd)과 연동되어 있다. 그래서 전달받은 매니페스트 파일의 spec 내용에 맞춰 필요한 컨테이너 이미지와 각종 설정을 컨테이너 런타임에게 알려줘 올바른 컨테이너를 실행하도록 관리할 수 있다.

Pod에 Liveness Probe가 설정되어 있다면 kubelet이 해당 설정을 통해 컨테이너가 정상 동작 중인지 체크할 수 있다. 만약 컨테이너 동작에 이상이 있다고 판단되면 Restart Policy에 정의된 대로 컨테이너 재시작을 수행할 수도 있다.
이런 kubelet에 문제가 생길 경우 발생할 수 있는 이슈는 아래와 같다.
- 해당 노드에 새로운 컨테이너 배포 불가
- 해당 노드에 배포된 기존 컨테이너의 상태 관리 불가
즉, kubelet의 작동이 멈춘 노드는 Kubernetes 클러스터 관점에서 사용할 수 없는 것이다.
만약 위와 같이 클러스터 노드를 사용할 수 없다면 해당 노드에 설치된 kubelet의 상태와 로그를 확인해봐야 한다.
해당 노드에 SSH 접속 후 systemctl status kubelet 명령어로 kubelet의 상태를 먼저 체크하고, 만약 정상 동작 중이 아니라면 아래 방법 중 하나로 kubelet의 로그를 확인하여 문제 원인을 찾아보자.
journalctl -u kubelet/var/log/kubelet.log또는/var/log/syslog로그 파일의 내용 확인
2. 트래픽 전달을 담당하는 kube-proxy
클러스터에 배포한 애플리케이션의 컨테이너를 kubelet이 아무리 잘 관리한다고 해도 외부에서 해당 애플리케이션으로 접속할 수 없다면 무용지물이다.
외부에서 Kubernetes 클러스터 안으로 들어온 사용자의 트래픽을 올바른 컨테이너로 잘 인도해야 하는 것이다.
각 노드에서 동작하는 kube-proxy가 바로 이런 길잡이 역할을 수행한다.
특히 Kubernetes의 Service 리소스가 제 역할을 해낼 수 있도록 도와주는데, Service의 IP와 포트번호로 접근한 외부 트래픽을 Service와 연동된 실제 컨테이너의 IP로 전달해주기 때문이다.

모든 노드에서 동작하는 kube-proxy는 클러스터에 배포된 Service나 Pod의 IP 주소 등을 주기적으로 확인하고 업데이트한다. 그래서 어떤 노드에 배포되었든 상관없이 외부 트래픽이 사전에 정의된 대로 Service를 거쳐 올바른 컨테이너로 전해질 수 있는 것이다.
이런 kube-proxy에 문제가 생긴다면 어떻게 될까?
- 외부 트래픽이 Service로 전달되지 못해 Timeout 발생
- 특히 일부 노드에 배포된 kube-proxy에 문제가 생겼다면, 일부 사용자만 접속 오류를 경험하게 될 위험이 있다. (간헐적 장애)
kube-proxy는 각 노드에 Daemonset 리소스로 배포된다. 만약 위와 같은 간헐적 장애가 발생한다면 kube-proxy Daemonset의 로그와 이벤트를 확인해보자.
Kubernetes 클러스터의 기본 구성에 포함되어있는 kube-proxy이지만, 최근에는 kube-proxy를 쓰지 않고 다른 대체재를 사용하는 경우도 있다.
특히 수많은 리소스가 배포되고 사라지는 대규모 클러스터에서 그렇다. 무수히 많은 컨테이너의 IP 주소가 매번 변경되기 때문에 kube-proxy가 이를 기록하고 업데이트하는 데에 시간이 오래 걸리고 리소스도 많이 소모될 수 있기 때문이다.
kube-proxy의 대체재로 주목받는 Cilium은 eBPF 기술(리눅스 커널 내부에서 작업을 더욱 빠르게 처리하는 기술)을 활용한다. 그 덕분에 복잡한 단계를 거치지 않고 기존 kube-proxy의 역할을 더 빠르게 수행할 수 있다.
마무리
지금까지 kubelet과 kube-proxy가 정확히 어떤 역할을 수행하는지 알아봤다. 이제 여러분은 클러스터 운영 시 이 두 컴포넌트도 염두에 두고 트러블슈팅을 할 수 있을 것이다.
이번에 kube-proxy를 살펴봤기 때문에 Kubernetes 클러스터 내부에서의 트래픽 흐름을 OSI 계층과 연관지어 함께 알아보는 심화 주제도 추후 아티클로 다뤄볼 수 있을 것이다. 이와 관련하여 아이디어를 주신 구독자분께 감사 인사를 드린다.
또한 kubelet의 역할에 대해서 이해했으니, 터미널에서 kubectl apply 명령어를 실행한 시점에서부터 실제 Pod가 배포되기까지의 흐름도 다른 아티클에서 정리해보겠다.