2. 쿠버네티스의 기본 구성 요소: Container, Pod, Node
1편에서 쿠버네티스의 철학을 배웠습니다. 이제 본격적으로 쿠버네티스 안으로 들어가기 전에, 가장 기본이 되는 구성 요소들을 이해해야 합니다. 마치 건축을 배우기 전에 ‘벽돌’, ‘기둥’, ‘지붕’이 무엇인지 알아야 하는 것처럼요.
이번 아티클에서는 쿠버네티스를 이루는 가장 기본적인 세 가지 요소인 Container, Pod, Node를 차근차근 알아보겠습니다.
Container: 애플리케이션을 담는 가장 작은 상자
Container가 뭔가요?
컨테이너는 애플리케이션과 그 애플리케이션이 실행되는 데 필요한 모든 것(라이브러리, 설정 파일, 환경 변수 등)을 하나로 묶은 실행 단위입니다.
전통적인 방식에서는 서버에 직접 애플리케이션을 설치했습니다:
서버 A: Python 3.8 설치 → Flask 앱 설치 → 환경 설정
서버 B: Python 3.8 설치 → Flask 앱 설치 → 환경 설정
...반복...
컨테이너 방식은 다릅니다:
컨테이너 이미지 한 번 만들기: Python 3.8 + Flask 앱 + 설정
→ 이 이미지를 어디서든 실행하면 똑같이 동작!
왜 Container가 필요한가요?
1. 일관성: “내 컴퓨터에서는 됐는데요?”를 해결
개발자의 로컬 환경, 테스트 서버, 운영 서버가 모두 다른 환경이면 버그가 발생하기 쉽습니다. 컨테이너는 어디서 실행하든 똑같은 환경을 보장합니다.
2. 격리: 서로 방해하지 않기
같은 서버에서 여러 애플리케이션을 실행할 때, 컨테이너는 각 애플리케이션을 독립된 공간에서 실행시킵니다:
- A 앱은 Python 3.8 사용
- B 앱은 Python 3.10 사용
- 서로 충돌 없이 같은 서버에서 동작!
3. 가벼움: 빠른 시작과 종료
가상 머신(VM)과 달리 컨테이너는 운영체제 커널을 공유하므로 매우 가볍고 빠릅니다:
- VM: 시작에 수 분 소요
- Container: 시작에 수 초 소요
비유로 이해하기
컨테이너는 **“이사할 때 쓰는 표준 박스”**와 같습니다:
- 물건(애플리케이션)과 필요한 모든 것을 박스에 담으면
- 트럭(서버)에 실어도, 배(클라우드)에 실어도
- 항상 같은 상태로 이동하고 개봉할 수 있습니다
Pod: 쿠버네티스의 가장 작은 배포 단위
Pod가 뭔가요?
쿠버네티스는 컨테이너를 직접 관리하지 않습니다. 대신 Pod라는 단위로 관리합니다. Pod는 하나 이상의 컨테이너를 묶은 그룹입니다.
Pod = Container 1개 이상을 담은 "꾸러미"
가장 일반적인 경우는 Pod 1개 = Container 1개입니다. 하지만 때로는 여러 컨테이너를 하나의 Pod에 넣기도 합니다.
왜 Container가 아니라 Pod인가요?
이유 1: 밀접하게 연관된 컨테이너들을 함께 관리
어떤 애플리케이션은 여러 개의 컨테이너가 매우 밀접하게 협력해야 할 때가 있습니다:
[웹 서버 Pod]
├── nginx 컨테이너 (웹 서버)
└── log-collector 컨테이너 (로그 수집기)
이 두 컨테이너는:
- 같은 로그 파일을 공유해야 하고
- 항상 같은 서버에 배치되어야 하고
- 함께 시작되고 함께 종료되어야 합니다
Pod는 이런 컨테이너들을 “한 몸”처럼 다룹니다.
이유 2: 네트워크와 스토리지 공유
같은 Pod 안의 컨테이너들은:
- 같은 IP 주소를 공유합니다 (localhost로 통신 가능)
- **같은 볼륨(저장소)**을 공유할 수 있습니다
- 같은 네트워크 네임스페이스를 사용합니다
이유 3: 쿠버네티스의 설계 철학
쿠버네티스는 컨테이너 런타임(Docker, containerd 등)에 의존하지 않는 추상화 계층을 원했습니다. Pod는 이런 추상화의 결과입니다.
Pod의 생명주기
Pod는 태어나고(생성), 살아가고(실행), 죽습니다(종료). 한 번 죽은 Pod는 부활하지 않습니다:
Pod 생성 → 실행 중 → 종료
↓ (장애 발생)
새 Pod 생성 (이전 Pod와는 다른 존재)
이것이 중요한 이유는, Pod가 죽으면:
- 새로운 IP 주소를 받고
- 저장된 데이터는 사라지고 (별도 볼륨이 없으면)
- 완전히 새로운 Pod가 됩니다
핵심: Pod는 **일회용(Ephemeral)**입니다. 죽으면 새 Pod를 만들지, 같은 Pod를 되살리지 않습니다.
실제 사용 패턴
패턴 1: 1 Pod = 1 Container (가장 흔함)
[Nginx Pod]
└── nginx 컨테이너
패턴 2: Sidecar 패턴
[애플리케이션 Pod]
├── 메인 앱 컨테이너
└── 사이드카 컨테이너 (로깅, 모니터링, 프록시 등)
패턴 3: Init Container 패턴
[애플리케이션 Pod]
├── init 컨테이너 (초기 설정, 준비 작업)
└── 메인 앱 컨테이너 (init이 끝난 후 시작)
Node: Pod를 실행하는 물리적/가상 서버
Node가 뭔가요?
Node는 실제로 Pod(컨테이너)를 실행하는 서버입니다. 쿠버네티스 클러스터는 여러 개의 Node로 구성됩니다.
쿠버네티스 클러스터
├── Node 1 (서버)
│ ├── Pod A
│ └── Pod B
├── Node 2 (서버)
│ ├── Pod C
│ └── Pod D
└── Node 3 (서버)
└── Pod E
Node는 물리 서버일 수도 있고, 가상 머신(VM)일 수도 있고, 클라우드 인스턴스(EC2, GCE 등)일 수도 있습니다.
Node의 두 가지 종류
1. Control Plane Node (마스터 노드)
- 클러스터를 관리하는 “뇌” 역할
- API Server, Scheduler, Controller Manager 등이 실행됨
- 보통 사용자의 애플리케이션 Pod는 실행하지 않음
- 고가용성을 위해 보통 3개 이상으로 구성
2. Worker Node (작업 노드)
- 실제 사용자의 애플리케이션 Pod를 실행하는 “근육” 역할
- 개수는 필요에 따라 자유롭게 추가/제거 가능
- 대부분의 Pod가 여기서 실행됨
왜 여러 개의 Node가 필요한가요?
1. 고가용성 (High Availability)
한 Node가 죽어도 다른 Node가 있으면 서비스는 계속됩니다:
Node 1 장애 발생!
└── Node 1의 Pod들이 자동으로 Node 2, 3으로 재배치
2. 부하 분산 (Load Balancing)
트래픽이 많은 서비스는 여러 Node에 Pod를 분산시켜 부하를 나눕니다:
100개의 요청
├── Node 1: 33개 처리
├── Node 2: 33개 처리
└── Node 3: 34개 처리
3. 확장성 (Scalability)
서비스가 성장하면 Node를 추가하기만 하면 됩니다:
트래픽 증가!
└── Node 4, 5 추가 → Pod 자동 분산 배치
4. 리소스 격리
특정 워크로드를 특정 Node에 배치할 수 있습니다:
- GPU 작업 → GPU 장착된 Node
- 메모리 집약적 작업 → 고메모리 Node
- 일반 웹 서비스 → 표준 Node
Node의 구성 요소 (간단히)
각 Worker Node에는 다음과 같은 컴포넌트가 실행됩니다:
- kubelet: Node의 “현장 관리자”. Control Plane의 명령을 받아 Pod를 실행하고 관리
- Container Runtime: 실제로 컨테이너를 실행하는 엔진 (containerd, CRI-O 등)
- kube-proxy: 네트워크 트래픽을 Pod로 전달하는 역할
(자세한 내용은 4편 “워커 노드 분석”에서 다룹니다)
전체 그림 보기: Container → Pod → Node → Cluster
지금까지 배운 개념을 조합하면 다음과 같은 계층 구조가 됩니다:
[쿠버네티스 클러스터]
│
├── [Control Plane Nodes] ─── 클러스터를 관리하는 뇌
│ ├── API Server
│ ├── Scheduler
│ ├── Controller Manager
│ └── etcd
│
└── [Worker Nodes] ─────────── 실제 워크로드를 실행하는 근육
│
├── [Node 1]
│ ├── [Pod A]
│ │ └── Container 1
│ └── [Pod B]
│ ├── Container 1
│ └── Container 2 (sidecar)
│
├── [Node 2]
│ ├── [Pod C]
│ │ └── Container 1
│ └── [Pod D]
│ └── Container 1
│
└── [Node 3]
└── [Pod E]
└── Container 1
실전 시나리오로 이해하기
당신이 Nginx 웹 서버를 3개 복제본으로 실행하고 싶다면:
- Container 이미지 준비:
nginx:1.21이미지 사용 - Pod 정의: 각 Pod는 nginx 컨테이너 1개를 포함
- Node 배치: 쿠버네티스가 자동으로 3개의 Pod를 여러 Node에 분산 배치
- 결과:
Node 1: [Nginx Pod 1] Node 2: [Nginx Pod 2] Node 3: [Nginx Pod 3]
만약 Node 2가 장애로 죽는다면:
Node 1: [Nginx Pod 1]
Node 2: (죽음)
Node 3: [Nginx Pod 3]
[Nginx Pod 2'] ← 새로 생성됨!
쿠버네티스가 자동으로 “원하는 상태(Pod 3개)“를 유지하기 위해 새 Pod를 생성합니다.
아직 다루지 않은 개념들 (예고편)
여기까지는 가장 기본적인 “실행 단위”에 대해 배웠습니다. 하지만 실전에서는 다음과 같은 질문들이 생깁니다:
- “Pod가 죽으면 새로 만든다는데, 누가 만들어주나요?” → Deployment, ReplicaSet (나중에 배움)
- “Pod의 IP가 계속 바뀌는데, 어떻게 접속하나요?” → Service (나중에 배움)
- “외부에서 클러스터 안의 Pod에 어떻게 접근하나요?” → Ingress (나중에 배움)
- “설정 정보나 비밀번호는 어떻게 관리하나요?” → ConfigMap, Secret (나중에 배움)
- “데이터를 영구적으로 저장하려면?” → Volume, PersistentVolume (나중에 배움)
이런 개념들은 Container, Pod, Node라는 기초 위에 세워진 “더 높은 수준의 추상화”입니다. 하지만 걱정하지 마세요. 지금 배운 기초가 탄탄하면 이런 개념들도 쉽게 이해할 수 있습니다.
정리
오늘 배운 세 가지 핵심 개념:
-
Container: 애플리케이션과 환경을 담은 표준화된 실행 단위
- 일관성, 격리, 가벼움이 장점
-
Pod: 쿠버네티스의 최소 배포 단위
- 하나 이상의 컨테이너를 묶은 그룹
- 일회용(Ephemeral) 특성을 가짐
- 밀접한 컨테이너들을 함께 관리
-
Node: Pod를 실행하는 물리적/가상 서버
- Control Plane Node: 관리 역할
- Worker Node: 실행 역할
- 여러 Node로 고가용성과 확장성 확보
이 세 가지는 쿠버네티스를 이해하는 가장 기본적인 빌딩 블록입니다. 이제 다음 아티클에서 이 Pod들을 누가, 어떻게 관리하는지 알아보겠습니다.
다음 아티클
다음 아티클
작성일: 2025-10-30