쿠버네티스(Kubernetes)를 공부하다 보면 "도대체 kubectl create deployment 명령어를 쳤을 뿐인데, 어떻게 내 컨테이너가 특정 노드에 딱 뜨는 거지?"라는 궁금증이 생기기 마련입니다.
오늘은 쿠버네티스 아키텍처 다이어그램을 통해, 사용자의 요청이 Master(Control Plane)를 거쳐 Node(Worker Node)에 실제 컨테이너로 생성되기까지의 전체 여정을 아주 상세하게 파헤쳐 보겠습니다. 🕵️♂️✨

1. Master 영역: 명령을 받고 설계도를 그리다 🧠
모든 여정은 사용자의 키보드에서 시작되어 Master 노드의 API Server로 향합니다.
1️⃣ 사용자 요청 (User → API Server)
- Action: 사용자가 kubectl 명령이나 UI를 통해 디플로이먼트(Deployment) 생성을 요청합니다.
- Protocol: 이때 요청은 JSON 형식의 HTTP 통신으로 API Server에 전달됩니다. (그림의 파란색 화살표 🟦)
- Role: API Server는 쿠버네티스 클러스터의 '대문'이자 모든 컴포넌트의 중심입니다.
2️⃣ 정보 저장 (API Server ↔ etcd)
- Action: API Server는 요청이 유효한지 검사한 후, 이 정보를 etcd에 저장합니다.
- Role: etcd는 클러스터의 모든 데이터를 저장하는 Key-Value 저장소이자 SSOT(Single Source of Truth)입니다. 이제 클러스터의 '바라는 상태(Desired State)'에 Deployment가 기록되었습니다.
3️⃣ 컨트롤러의 설계 (Controller Manager)
이제 Controller Manager가 바쁘게 움직일 차례입니다. (그림의 분홍색 화살표 🟪)
- Deployment Controller: 새로운 Deployment 정보를 감지하고, 이에 맞는 ReplicaSet(RS) 생성을 API Server에 요청합니다.
- ReplicaSet Controller: 생성된 RS를 감지하고, 설정된 복제 개수(Replicas)만큼 Pod 객체를 생성해달라고 요청합니다.
- Point: ⚠️ 중요! 이때 생성된 Pod 정보는 "어떤 노드에 갈지(nodeName)"가 아직 비어있는 Pending 상태의 데이터 덩어리일 뿐입니다.
4️⃣ 스케줄링 (Scheduler)
- Action: Scheduler는 nodeName이 없는 외로운 Pod를 발견합니다. (그림의 분홍색 화살표 🟪)
- Logic: 노드들의 자원 상태를 확인(Filtering)하고 가장 적합한 노드(Scoring)를 선발합니다. 예를 들어 'Node 2'가 당첨되었다고 합시다.
- Binding: 스케줄러는 "이 Pod는 Node 2로 가라!"는 바인딩 정보를 API Server에 업데이트합니다.
2. Node 영역: 설계도를 현실로 구현하다 🏗️
이제 무대는 실제 워크로드가 실행될 Node(Worker Node)로 넘어갑니다.
5️⃣ Kubelet의 임무 수령 (API Server → Kubelet)
- Action: 각 노드의 선장 격인 Kubelet은 주기적으로 API Server와 통신하며 "내 담당(Node 2)으로 배정된 Pod가 있는지" 확인(Watch)합니다.
- Protocol: 이 통신은 효율성을 위해 Protobuf (gRPC)를 주로 사용합니다. (그림의 자주색 화살표 🟪)
- 새로운 Pod 할당 정보를 확인한 Kubelet은 본격적인 생성 작업에 착수합니다.
6️⃣ 네트워크 도로 깔기 (Kubelet ↔ CNI)
컨테이너가 생겨도 통신이 안 되면 무용지물이죠? 먼저 네트워크부터 뚫습니다.
- Interface: Kubelet은 CNI(Container Network Interface)를 통해 네트워크 플러그인을 호출합니다. (그림의 하늘색 화살표 🟦)
- Result: Pod가 사용할 IP를 할당받고, 통신 가능한 네트워크 환경을 구성합니다.
7️⃣ 컨테이너 실행 요청 (Kubelet ↔ CRI)
네트워크 준비가 끝났으니 실제 컨테이너를 만들 차례입니다.
- Interface: Kubelet은 CRI(Container Runtime Interface)를 통해 컨테이너 런타임(Containerd, CRI-O 등)에게 명령을 내립니다.
- Protocol: 이 과정은 gRPC 통신으로 이루어집니다. (그림의 초록색 화살표 🟩)
8️⃣ OS 위에서 프로세스 실행 (Runtime ↔ OCI ↔ OS)
- Action: 요청을 받은 Container Runtime은 이미지를 가져오고(Pull), OCI(Open Container Initiative) 표준에 따라 리눅스 커널(OS)과 소통합니다. (그림의 노란색 화살표 🟨)
- Final: 드디어 격리된 환경에서 우리가 요청한 애플리케이션(Container)이 실행됩니다! 🎉
📝 요약: 흐름을 한 눈에!
이 복잡해 보이는 과정은 사실 4단계의 티키타카입니다.
- User & API Server: "Deployment 만들어줘!" → 기록 💾
- Controller: "그럼 RS 만들고, Pod 데이터 생성해야지." ⚙️
- Scheduler: "이 Pod는 Node 2가 딱이네. 배정!" ⚖️
- Kubelet (Node): "어? 내 거네? CNI로 길 뚫고, CRI로 컨테이너 띄워!" 🚀
이 그림 한 장에는 JSON, gRPC, Protobuf와 같은 통신 방식부터 CNI, CRI, OCI와 같은 표준 인터페이스가 모두 담겨 있습니다. 쿠버네티스가 얼마나 체계적이고 모듈화된 시스템인지 알 수 있는 대목이죠.
이제 kubectl create를 입력할 때, 이 수많은 컴포넌트들의 노고를 한번쯤 떠올려주세요! 😉