Kubernetes cluster는 크게 컨트롤 플레인과 워커 노드로 나눠 이해할 수 있다. 컨트롤 플레인은 원하는 상태를 API object로 저장하고 조정한다. 워커 노드의 kubelet과 container runtime은 배정된 Pod를 실제로 실행한다.
현장에서 워커 노드 쪽을 data plane이라고 부르기도 하지만 Kubernetes 공식 component 분류의 이름은 control plane components와 node components다. 이 글에서는 용어보다 kubectl apply 뒤에 어떤 component가 어떤 API를 거치는지에 초점을 맞춘다.
컨트롤 플레인의 구성 요소
| 구성 요소 | 맡는 일 | 직접 하지 않는 일 |
|---|---|---|
kube-apiserver |
Kubernetes API 제공, 인증·인가·admission 처리 | Pod container 직접 실행 |
etcd |
cluster API data를 보관하는 일관된 key-value store | scheduler·controller 역할 |
kube-scheduler |
아직 node가 정해지지 않은 Pod에 적합한 node 선택 | container 생성 |
kube-controller-manager |
여러 controller의 reconciliation loop 실행 | worker node 명령을 직접 수행 |
cloud-controller-manager |
cloud provider API와 연동하는 controller 실행 | 모든 cluster에 반드시 존재 |
핵심 허브는 kube-apiserver다. scheduler와 controller는 etcd를 제각각 직접 수정하지 않고 API server를 통해 object를 읽고 쓴다. API server가 storage layer를 통해 etcd에 cluster state를 영속화한다.
컨트롤러는 “한 번 명령하고 끝내는 프로세스”가 아니다. 현재 상태를 관찰하고 원하는 상태와의 차이를 줄이는 reconciliation loop를 반복한다. 이 관점은 Kubernetes GitOps와 reconciliation에서도 그대로 이어진다.
워커 노드의 구성 요소
워커 노드는 workload를 실행하는 machine이다. virtual machine일 수도 있고 physical machine일 수도 있다.
kubelet: 자기 node에 배정된 PodSpec을 확인하고 container가 그 상태에 맞게 실행되도록 조정한다.- container runtime: image를 가져오고 container lifecycle을 관리한다. kubelet은 CRI(Container Runtime Interface)를 통해 runtime과 연동한다.
- network plugin: Pod network interface와 route 등 CNI 규격에 따른 network 설정을 맡는다.
kube-proxy: Service network rule을 구현하는 대표적인 node component다. 다른 dataplane 구현으로 대체될 수 있다.
kubelet이 컨트롤 플레인의 명령을 받는다라고만 외우면 실제 동작이 흐려진다. kubelet은 보통 API server를 계속 관찰하며 자기 node에 배정된 원하는 상태를 알아내고, local runtime의 현재 상태를 그에 맞춘다.
Deployment가 Pod로 실행되는 순서
다음 흐름을 기준으로 component 관계를 잡으면 된다.
- 사용자가
kubectl apply로 Deployment manifest를 API server에 보낸다. - API server가 요청을 인증·인가하고 admission 단계를 거쳐 object를 저장한다.
- Deployment controller가 object를 관찰하고 필요한 ReplicaSet을 만든다.
- ReplicaSet controller가 필요한 수만큼 Pod object를 만든다.
- scheduler가 node가 없는 Pod를 발견하고 조건과 자원을 비교해 node binding을 기록한다.
- 해당 node의 kubelet이 배정된 PodSpec을 확인한다.
- kubelet이 CRI를 통해 container runtime에 sandbox와 container 생성을 요청하고, network plugin이 Pod network를 준비한다.
- kubelet이 Pod 상태와 node 상태를 API server에 보고한다.
여기서 scheduler는 Pod를 직접 실행하지 않는다. controller도 kubelet에 임의의 RPC 명령을 보내 container를 만들지 않는다. 각 component가 API object를 관찰하고 자기 책임 범위의 상태를 갱신하면서 전체 흐름이 이어진다.
실제 통신 경로
Kubernetes의 node-to-control-plane 통신은 hub-and-spoke API pattern을 따른다. node와 그 위의 Pod가 사용하는 Kubernetes API 요청은 API server의 secure HTTPS endpoint로 모인다. control plane component 역시 API server를 통해 통신한다.
반대 방향의 통신도 있다. API server는 다음 기능을 위해 kubelet의 HTTPS endpoint에 연결할 수 있다.
- Pod log 조회
- 실행 중인 container에 attach
kubectl port-forward
그래서 control plane → node 통신은 전혀 없다도 정확하지 않다. 다만 일반적인 desired-state 전달은 API server가 kubelet에 imperative command를 밀어 넣는 방식보다 kubelet이 API state를 관찰하는 구조로 이해해야 한다.
JSON, Protobuf, gRPC를 한 문장으로 섞지 않기
Kubernetes 내부 통신을 모두 gRPC라고 설명하면 지나치게 단순하다.
- Kubernetes API client와 API server 사이에는 HTTP 기반 RESTful resource API가 있다.
- API object는 요청 조건에 따라 JSON 또는 Kubernetes Protobuf 등으로 표현될 수 있다.
- kubelet과 container runtime 사이의 CRI는 일반적으로 local Unix socket 위의 gRPC API를 사용한다.
- CNI는 kubelet이 직접 호출하는 하나의 network RPC server라는 뜻이 아니라 runtime과 plugin이 규격에 따라 Pod network를 구성하는 경계다.
같은 cluster 안에서도 통신 목적과 component 경계에 따라 protocol이 다르다.
장애를 볼 때 따라갈 순서
Pod가 Pending 또는 ContainerCreating에 머문다면 component 이름을 무작정 외우기보다 object event를 따라간다.
kubectl get deployment,replicaset,pod -n <namespace>
kubectl describe pod <pod-name> -n <namespace>
kubectl get events -n <namespace> --sort-by=.lastTimestamp
kubectl get node
- Pod에 node가 배정되지 않았다면 scheduler 조건, taint·toleration, request와 가용 자원을 본다.
- node는 정해졌지만 container가 만들어지지 않으면 kubelet, image pull, CRI와 CNI event를 본다.
- container가 실행됐지만 통신이 안 되면 Service, endpoint, network policy와 network dataplane을 본다.
resource request와 QoS 판단은 Kubernetes resource와 QoS에서 이어서 확인할 수 있다.
자주 묻는 질문
etcd는 워커 노드에도 있어야 하나?
일반적인 cluster에서 etcd는 control plane storage다. worker node가 API object를 얻기 위해 etcd에 직접 접속하지 않는다. kubelet은 API server와 통신한다.
scheduler가 가장 여유 있는 node에 바로 container를 띄우나?
scheduler는 filtering과 scoring 등을 거쳐 Pod가 사용할 node를 결정하고 API에 binding을 기록한다. 실제 container 생성은 그 node의 kubelet과 container runtime이 맡는다.
control plane node에서도 Pod를 실행할 수 있나?
기술적으로 가능하다. 많은 배포판은 control plane node에 taint를 두어 일반 workload scheduling을 막지만, 학습용 단일 node cluster처럼 control plane과 workload 역할을 한 machine에 둘 수도 있다.
참고 자료
'배움과 성장 > DevOps·클라우드' 카테고리의 다른 글
| AWS IMDSv2 보안: SSRF와 인스턴스 자격 증명 노출 줄이기 (0) | 2024.08.28 |
|---|---|
| Apache·IIS·NGINX 비교: 웹 서버를 고르는 실무 기준 (2) | 2024.08.15 |
| GitHub 인증 오류 해결: 비밀번호 대신 CLI·Credential Manager·SSH 사용하기 (4) | 2023.04.09 |
| Terraform 표현식 이해하기: 값·참조·조건식·for 식을 구분하는 기준 (0) | 2023.03.30 |
| Docker란 무엇인가: 이미지·컨테이너·VM 차이와 격리 구조 (0) | 2023.03.25 |
댓글