쿠버네티스 마스터 — Pod·생명주기·멀티 컨테이너

2026-05-03확률과 통계 마스터 노트

쿠버네티스 마스터 노트 시리즈 2편. Pod이 K8s의 최소 배포 단위인 이유, Pod = 1+ 컨테이너 + 공유 네트워크/볼륨의 의미, Pause Container의 숨은 역할, Pod 생명주기 5단계(Pending/Running/Succeeded/Failed/Unknown), Init Container와 Sidecar 패턴, Pod이 일회용(Ephemeral)인 이유와 그것이 K8s 설계 철학에 미치는 영향까지.

이 글은 쿠버네티스 마스터 노트 시리즈의 두 번째 편입니다. 1편(아키텍처)에서 클러스터 구조를 다졌다면, 이번엔 K8s의 가장 작은 단위 — Pod.

Pod을 이해 못 하면 K8s 전체가 막연합니다. 컨테이너와 다른 점, 왜 1+ 컨테이너 묶음인지, 왜 일회용인지가 핵심.

처음 Pod이 어렵게 느껴지는 이유

처음 이 단원이 어렵게 느껴지는 이유는 두 가지예요. 첫째, "Pod = 컨테이너 아닌가" 헷갈립니다. 둘째, "왜 K8s는 컨테이너를 직접 안 다루나" 막연합니다.

해결법은 한 가지예요. "Pod = 컨테이너의 봉투" 비유. 같은 봉투에 들어간 컨테이너끼리는 같은 사무실(네트워크·볼륨) 공유. 다른 봉투끼리는 별도 사무실. 이 그림이 잡히면 모든 동작이 따라옵니다.

Pod — K8s 최소 배포 단위

Pod = 1개 이상 컨테이너 + 공유 자원
                                  ├── 공유 네트워크 (같은 IP)
                                  ├── 공유 볼륨
                                  └── 공유 IPC·UTS namespace

같은 Pod 안 컨테이너끼리:

  • localhost로 통신 가능 (같은 IP)
  • 볼륨 공유

다른 Pod끼리:

  • 별도 IP, 클러스터 내부 네트워크로 통신

여기서 정말 중요한 시험 함정 — K8s는 컨테이너 직접 X, Pod 단위로 다룸. 모든 자원·스케줄링·생명주기가 Pod 단위. 컨테이너 1개 = Pod 1개라도 OK.

가장 단순한 Pod

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.25
      ports:
        - containerPort: 80
kubectl apply -f pod.yaml
kubectl get pods
kubectl describe pod nginx-pod
kubectl logs nginx-pod
kubectl delete pod nginx-pod

Pause Container — 숨은 영웅

각 Pod엔 사용자가 안 보지만 Pause 컨테이너가 자동:

Pod
  ├── pause container (숨겨진)
  ├── nginx
  └── (다른 컨테이너)

역할:

  • Pod의 네트워크·IPC namespace 소유
  • 다른 컨테이너들이 join
  • 컨테이너 다운돼도 Pod 자체 살아 있음
docker ps  # 노드에서 실행
# pause 컨테이너가 모든 Pod마다 보임

여기서 시험 함정이 하나 있어요. Pause는 K8s 내부 메커니즘. 사용자가 직접 다룰 일 X. 다만 알아두면 디버깅 시 도움.

Pod 생명주기 — 5 Phase

Pending → Running → Succeeded
                  → Failed
                  → Unknown
Phase 의미
Pending API Server에 등록, 노드 배정 또는 이미지 pull 중
Running 노드에 배정 + 모든 컨테이너 시작됨
Succeeded 모든 컨테이너 정상 종료 (exit 0)
Failed 1개 이상 컨테이너 실패 (exit ≠ 0)
Unknown API Server가 노드 상태 못 받음

컨테이너 상태

각 컨테이너 상태 별도:

status:
  containerStatuses:
    - name: nginx
      state:
        running:        # waiting / running / terminated
          startedAt: ...
      ready: true
      restartCount: 0

여기서 정말 중요한 시험 함정 — Pod Phase ≠ 컨테이너 Ready. Pod Running이라도 컨테이너 readiness probe 실패 시 not ready. Service에서 트래픽 안 받음. 7편에서 자세히.

멀티 컨테이너 Pod — 두 패턴

1. Sidecar 패턴

주 컨테이너 + 보조 컨테이너 함께.

spec:
  containers:
    - name: app
      image: my-app
      volumeMounts:
        - name: logs
          mountPath: /var/log
    - name: log-shipper        # Sidecar
      image: fluentd
      volumeMounts:
        - name: logs
          mountPath: /var/log
  volumes:
    - name: logs
      emptyDir: {}

용도:

  • 로그 수집 (Fluentd·Filebeat)
  • 프록시 (Envoy·Istio sidecar)
  • 모니터링 (Prometheus exporter)
  • TLS terminator

2. Adapter / Ambassador 패턴

특수 변환 또는 외부 서비스 추상화.

여기서 시험 함정이 하나 있어요. 하나의 Pod에 너무 많은 컨테이너 X. 권장 = 1~3개. 강하게 결합된 것만 같은 Pod (라이프사이클 함께).

Init Container — 시작 전 준비

spec:
  initContainers:
    - name: wait-for-db
      image: busybox
      command: ['sh', '-c', 'until nc -z db 5432; do sleep 1; done']
  containers:
    - name: app
      image: my-app

흐름:

  1. Init 컨테이너 순차 실행 (모두 성공해야)
  2. 메인 컨테이너 시작

용도:

  • DB 준비 대기
  • 설정 파일 다운로드
  • 마이그레이션 실행
  • 권한 설정

여기서 정말 중요한 시험 함정 — Init 컨테이너는 순차 실행. 모두 성공해야 메인 시작. 하나라도 실패 시 무한 재시도 (또는 backoff). 디버깅 = kubectl logs <pod> -c <init-container>.

restartPolicy — 종료 시 정책

spec:
  restartPolicy: Always   # Always (기본) / OnFailure / Never
정책 의미
Always 항상 재시작 (기본, Deployment에 자동)
OnFailure 실패(exit ≠ 0) 시만
Never 재시작 X (Job에 흔히)

여기서 시험 함정이 하나 있어요. Pod 직접 만들면 restartPolicy 적용. Deployment·StatefulSet은 Always 강제.

Pod이 일회용인 이유

K8s 철학 — Pod = Ephemeral (휘발).

Pod 다운 → K8s가 자동으로 새 Pod 생성
새 Pod = 새 IP, 새 식별자
이전 Pod의 상태·로컬 데이터는 사라짐

이래서 K8s 설계:

  • Stateless 우선 — 영속 상태는 외부 (DB·Volume)
  • Service로 IP 변경 추상화
  • Deployment로 Pod 수 유지
  • PV/PVC로 데이터 영속화

여기서 정말 중요한 시험 함정 — Pod 이름·IP 고정 의존 X. 항상 추상화 (Service·DNS) 사용. Pod 다운 가정 설계.

자원 요청·제한

spec:
  containers:
    - name: app
      image: my-app
      resources:
        requests:        # 보장 자원 (스케줄링)
          cpu: 100m
          memory: 128Mi
        limits:          # 최대 자원 (강제)
          cpu: 500m
          memory: 512Mi
  • requests — 노드 자원에 따라 스케줄링 결정
  • limits — 초과 시 throttle(CPU) 또는 OOMKill(Memory)

여기서 정말 중요한 시험 함정 — Memory limit 초과 = OOMKilled. CPU는 throttle만, Memory는 강제 종료. limits 너무 낮으면 자주 죽음.

m = millicore (1000m = 1 CPU core). Mi = Mebibyte.

Pod 라벨·셀렉터

metadata:
  labels:
    app: nginx
    tier: frontend
    version: v1

라벨로 그룹화 → Service·Deployment·NetworkPolicy가 셀렉터로 매칭.

kubectl get pods -l app=nginx
kubectl get pods -l tier=frontend,version=v1

Annotations — 메타 정보

metadata:
  annotations:
    description: "Frontend nginx server"
    deployedBy: "team-a"
    git-sha: "abc123"

라벨과 다름:

  • 라벨 = 셀렉터 매칭용 (필수 정보)
  • Annotation = 메타 정보 (도구·운영용)

Pod 디버깅

# 상세 정보
kubectl describe pod <name>

# 로그
kubectl logs <name>
kubectl logs <name> -c <container>     # 멀티 컨테이너
kubectl logs <name> -f                 # follow
kubectl logs <name> --previous         # 이전 인스턴스

# 컨테이너 진입
kubectl exec -it <name> -- bash
kubectl exec -it <name> -c <container> -- bash

# 임시 디버깅 컨테이너 (1.25+)
kubectl debug <name> -it --image=busybox

# 포트 포워딩
kubectl port-forward <name> 8080:80

시험 직전 한 번 더 — 자주 헷갈리는 함정 모음

여기까지가 2편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.

  • Pod = K8s 최소 배포 단위
  • 1+ 컨테이너 + 공유 네트워크/볼륨/IPC
  • 같은 Pod 안 = localhost 통신
  • K8s는 컨테이너 X, Pod 단위로 다룸
  • Pause Container = 숨겨진 namespace 소유자
  • 생명주기 5 — Pending / Running / Succeeded / Failed / Unknown
  • Pod Phase ≠ 컨테이너 Ready
  • 멀티 컨테이너 — Sidecar (로그·프록시·모니터링) / Adapter / Ambassador
  • 하나의 Pod에 1~3개 권장
  • Init Container — 메인 전 순차 실행
  • 모두 성공해야 메인 시작
  • restartPolicy — Always (기본) / OnFailure / Never
  • Deployment는 Always 강제
  • Pod = Ephemeral (휘발)
  • IP·이름 고정 의존 X
  • Service·Deployment·PV로 추상화
  • resources — requests (보장·스케줄링) / limits (강제)
  • Memory limit 초과 = OOMKilled
  • CPU throttle / Memory 강제 종료
  • m = millicore (1000m=1core), Mi = Mebibyte
  • 라벨 = 셀렉터용 / Annotation = 메타 정보
  • 디버깅 — describe·logs (-c, --previous)·exec·debug·port-forward

시리즈 다른 편

공식 문서: Kubernetes Pods 에서 더 깊이.

다음 글(3편)에서는 Workloads — ReplicaSet·Deployment·StatefulSet·DaemonSet·Job 5종 추상화까지 풀어 갑니다.

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!