kubectl get pods를 치면 Running, Pending, CrashLoopBackOff 같은 상태가 보입니다. 이 단어들은 그냥 라벨이 아니라 Pod이 태어나서 사라지기까지 거치는 단계를 나타냅니다. 생명주기를 알면 "왜 안 뜨지", "왜 자꾸 재시작하지" 같은 질문에 추측이 아니라 근거로 답할 수 있습니다.
Pod의 다섯 가지 페이즈
Pod에는 status.phase라는 큰 단계가 있습니다. 이건 컨테이너 단위가 아니라 Pod 전체를 요약한 값입니다.
| Phase | 의미 |
|---|---|
| Pending | API에 등록됐지만 아직 컨테이너 실행 전(스케줄·이미지 풀 대기) |
| Running | 노드에 배정됐고 컨테이너가 최소 하나 실행 중 |
| Succeeded | 모든 컨테이너가 정상 종료(exit 0), 재시작 안 함 |
| Failed | 컨테이너가 비정상 종료 |
| Unknown | 노드와 통신이 끊겨 상태를 알 수 없음 |
여기서 CrashLoopBackOff는 phase가 아니라 **컨테이너 상태(state)**입니다. phase는 Running인데 그 안의 컨테이너가 떴다 죽기를 반복하는 상황이죠.
단계가 흐르는 과정
Pod을 만들면 먼저 Pending에서 시작합니다. 스케줄러가 노드를 고르고, 그 노드의 kubelet이 이미지를 받아 컨테이너를 띄우는 동안 계속 Pending입니다.
kubectl get pod my-app -o wide
kubectl describe pod my-app | grep -A10 Events
Events를 보면 Scheduled → Pulling → Pulled → Created → Started 순서로 찍힙니다. 어디서 멈췄는지가 곧 원인입니다. Pulling에서 오래 멈추면 이미지 문제, Scheduled가 안 보이면 배치할 노드가 없는 문제입니다.
프로브가 상태를 좌우한다
Running이라고 해서 트래픽을 받을 준비가 된 건 아닙니다. 여기서 프로브가 개입합니다.
readinessProbe: # 통과해야 Service가 트래픽을 보냄
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
livenessProbe: # 실패하면 컨테이너를 재시작
httpGet:
path: /healthz
port: 8080
readinessProbe가 실패하면 Pod은 Running이어도 Service의 엔드포인트에서 빠져 트래픽을 안 받습니다. livenessProbe가 실패하면 kubelet이 컨테이너를 죽이고 재시작합니다 — 이 재시작이 반복되면 CrashLoopBackOff로 나타납니다.
종료 단계
Pod을 지우면 kubelet이 컨테이너에 SIGTERM을 보내고, terminationGracePeriodSeconds(기본 30초) 동안 정상 종료를 기다린 뒤 안 끝나면 SIGKILL로 강제 종료합니다. 이 유예 시간 덕에 진행 중인 요청을 마무리할 수 있습니다.
요점 정리
- Pod의 phase는 Pending, Running, Succeeded, Failed, Unknown 다섯이다.
CrashLoopBackOff는 phase가 아니라 반복 재시작하는 컨테이너 상태다.kubectl describe의 Events 순서로 어느 단계에서 막혔는지 짚는다.- readinessProbe는 트래픽 수신을, livenessProbe는 재시작을 결정한다.
각 단계를 직접 멈춰 세우고 Events로 추적하는 실습은 쿠버네티스 트랙에서 할 수 있습니다 — 회원가입 없이 무료로.