1. 개요
쿠버네티스가 다루는 가장 작은 배포 단위는 컨테이너가 아니라 Pod 다. 처음에는 “컨테이너에 이름표 하나 더 붙은 것” 정도로 생각했는데, 이 오해가 나중에 프로브 설정에서 사고를 낸다. 이 글에서는 Pod 가 무엇인지, 왜 직접 만들지 않는지, 그리고 살아 있는지와 받을 준비가 됐는지를 따로 묻는 프로브 셋을 본다.
2. 핵심 내용
2-1. Pod 는 컨테이너 묶음이다
Pod 안의 컨테이너들은 네트워크 네임스페이스를 공유한다. IP 가 하나고, 서로 localhost 로 통신한다. 그래서 같이 배치돼야 하는 것(앱과 로그 수집 사이드카 등)만 한 Pod 에 넣는다. 대부분은 컨테이너 하나짜리 Pod 다.
apiVersion: v1
kind: Pod
metadata:
name: web
labels: { app: web }
spec:
containers:
- name: web
image: ghcr.io/example/web:1.4.0
ports:
- containerPort: 80802-2. 일회용이라서 직접 만들지 않는다
Pod 는 죽으면 그 Pod 그대로는 돌아오지 않는다. 노드가 사라지면 그 위의 Pod 도 같이 사라진다. 새로 뜨는 Pod 는 이름도 IP 도 다르다. 위 YAML 을 그대로 apply 하면 되긴 하지만, 지켜봐 주는 컨트롤러가 없으니 1편의 조정 루프가 돌 대상이 없다. 그래서 보통 Deployment 같은 컨트롤러가 Pod 를 만들게 한다(3편).
2-3. 생명주기
Pod 의 상태(phase)는 Pending, Running, Succeeded, Failed, Unknown 이다. Pending 은 아직 노드에 배정되지 않았거나 이미지를 받는 중이라는 뜻이다. Running 이라고 해서 요청을 받을 수 있다는 뜻은 아니다. 프로세스가 떴을 뿐이다.
종료할 때는 SIGTERM 을 보내고, terminationGracePeriodSeconds(기본 30초) 안에 안 끝나면 SIGKILL 을 보낸다. 앱이 SIGTERM 을 받고 진행 중인 요청을 마무리하게 만들어야 롤링 업데이트 때 요청이 끊기지 않는다.
2-4. 프로브 셋
kubelet 이 컨테이너에 주기적으로 물어보는 세 가지 질문이다.
| 프로브 | 질문 | 실패하면 |
|---|---|---|
| startup | 기동이 끝났나 | 컨테이너를 재시작. 성공 전에는 나머지 둘을 실행하지 않는다 |
| liveness | 살아 있나 | 컨테이너를 재시작 |
| readiness | 요청 받을 준비가 됐나 | 재시작 없이 Service 대상에서 빠진다 |
startupProbe:
httpGet: { path: /healthz, port: 8080 }
failureThreshold: 30
periodSeconds: 5 # 최대 150초까지 기동을 기다린다
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
periodSeconds: 10
readinessProbe:
httpGet: { path: /ready, port: 8080 }
periodSeconds: 5startup 프로브는 느리게 뜨는 앱(JVM 이 대표적이다)이 기동 도중에 liveness 에 걸려 재시작 루프를 도는 걸 막는다. 이 개념은 인프라 기초 6 - 로드밸런싱과 헬스체크에서 다룬 로드밸런서의 헬스체크와 같은 뿌리다. 다만 쿠버네티스는 “트래픽에서 뺀다” 와 “죽이고 다시 띄운다” 를 프로브별로 나눠 놨다.
2-5. 어디서 실수하나
가장 흔한 사고는 liveness 와 readiness 를 같은 경로에 걸고, 그 경로가 DB 까지 확인하는 것이다. DB 가 잠깐 느려지면 모든 Pod 의 liveness 가 동시에 실패하고, kubelet 은 앱을 통째로 재시작한다. 앱은 문제가 없는데 재시작 때문에 DB 에 연결 폭주가 몰려 상황이 더 나빠진다.
기준은 이렇다.
- liveness 는 “이 프로세스가 스스로 복구 불가능하게 망가졌나” 만 본다. 외부 의존성은 보지 않는다.
- readiness 는 “지금 요청을 처리할 수 있나” 를 본다. 의존성이 죽었다면 여기서 빠지는 게 맞다. 재시작은 하지 않는다.
- liveness 의 timeout·threshold 를 너무 빡빡하게 잡지 않는다. 부하가 높을 때 응답이 늦어진 걸 죽은 걸로 오판한다.
3. 마무리
요약
- Pod 는 IP 를 공유하는 컨테이너 묶음이고, 일회용이라 컨트롤러를 통해 만든다.
- Running 은 프로세스가 떴다는 뜻일 뿐, 요청을 받을 준비가 됐다는 뜻이 아니다.
- liveness 실패는 재시작, readiness 실패는 트래픽 제외, startup 은 느린 기동을 보호한다.
- 외부 의존성 확인을 liveness 에 넣으면 의존성 지연이 앱 전체 재시작으로 번진다.
다음은 Kubernetes 기초 3 - Deployment 와 롤링 업데이트이다.