본문 바로가기
클라우드/쿠버네티스

[쿠버네티스 구조] 사용자가 Deployment를 생성하면 내부에서는 무슨 일이 일어날까?

by gasbugs 2025. 11. 26.

쿠버네티스(Kubernetes)를 공부하다 보면 "도대체 kubectl create deployment 명령어를 쳤을 뿐인데, 어떻게 내 컨테이너가 특정 노드에 딱 뜨는 거지?"라는 궁금증이 생기기 마련입니다.

 

오늘은 쿠버네티스 아키텍처 다이어그램을 통해, 사용자의 요청이 Master(Control Plane)를 거쳐 Node(Worker Node)에 실제 컨테이너로 생성되기까지의 전체 여정을 아주 상세하게 파헤쳐 보겠습니다. 🕵️‍♂️✨

 

https://kubernetes.io/blog/2018/07/18/11-ways-not-to-get-hacked/


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단계의 티키타카입니다.

  1. User & API Server: "Deployment 만들어줘!" → 기록 💾
  2. Controller: "그럼 RS 만들고, Pod 데이터 생성해야지." ⚙️
  3. Scheduler: "이 Pod는 Node 2가 딱이네. 배정!" ⚖️
  4. Kubelet (Node): "어? 내 거네? CNI로 길 뚫고, CRI로 컨테이너 띄워!" 🚀

이 그림 한 장에는 JSON, gRPC, Protobuf와 같은 통신 방식부터 CNI, CRI, OCI와 같은 표준 인터페이스가 모두 담겨 있습니다. 쿠버네티스가 얼마나 체계적이고 모듈화된 시스템인지 알 수 있는 대목이죠.

 

이제 kubectl create를 입력할 때, 이 수많은 컴포넌트들의 노고를 한번쯤 떠올려주세요! 😉