도입부: 운영 중 “Pod 재시작”이라는 한 마디가 컨테이너 재시작과 Pod 재생성까지 한데 섞여 장애 판단을 흐리는 경우를 자주 봤습니다. 이 글에서는 무엇이 실제로 재시작됐는지(컨테이너 vs Pod) 를 신호(UID/IP/RestartCount/이벤트)로 표준화해, 런북 오판을 줄이는 방법을 정리합니다.
왜 “재시작”을 구분해야 하나요?
실무에서 “재시작”은 보통 좋은 의미로도, 나쁜 의미로도 쓰입니다. 예를 들어 “업데이트했으니 재시작해서 설정이 잘 먹었는지 보자”처럼요. 문제는 쿠버네티스에서 재시작은 하나의 사건이 아니라는 점입니다.
- 컨테이너만 재시작: Pod는 그대로인데, 프로세스만 죽었다가 다시 뜹니다.
- Pod가 재생성(recreate): ReplicaSet/Deployment 등 컨트롤러가 기존 Pod를 버리고 새 Pod를 만듭니다. 이때는 사실상 “새로운 인스턴스”입니다.
- 재시작처럼 보이지만 다른 변화: 예를 들면 리소스 변경(인플레이스 리사이즈), 노드 드레인/축출(Evicted)처럼 원인이 컨테이너 내부가 아닐 수 있습니다.
이걸 구분하지 않으면 이런 사고가 나기 쉽습니다.
RestartCount만 보고 “앱이 죽었네”라고 단정했는데, 사실은 Pod가 갈아끼워져서(recreate) RestartCount가 0으로 초기화된 케이스- 반대로 “그냥 재시작이네” 하고 넘겼는데, 실제로는 UID/IP가 바뀐 Pod 재생성이라 세션/캐시/커넥션/PVC 재부착 이슈가 연쇄로 터지는 케이스
쿠버네티스 “재시작”의 3가지 대표 시나리오
아래는 운영 관점에서 최소한으로 구분해야 하는 분류입니다.
1) 컨테이너 재시작(동일 Pod 유지)
Pod는 그대로(UID 동일) 인데 컨테이너만 재시작합니다. 보통 다음 신호가 함께 보입니다.
kubectl get pod에서 Pod AGE가 계속 증가(Pod 자체는 살아있음)kubectl describe pod에서 컨테이너의 Restart Count 증가Last State에OOMKilled,Error등이 남음- 이벤트에
BackOff,Killing등이 찍힘
주요 원인 예:
- 프로세스 크래시, exit code
livenessProbe가 컨테이너를 죽임- OOMKilled
2) Pod 재생성(새 Pod 생성: UID/IP 변경)
이건 “재시작”이 아니라 새로 배포된 것에 가깝습니다.
- Pod UID가 바뀝니다.
- Pod IP가 바뀌는 경우가 흔합니다.
- 기존 Pod의
RestartCount기록은 새 Pod로 이어지지 않습니다(초기화).
대표 트리거:
- Deployment 롤링 업데이트/리비전 교체
- 노드 장애로 Pod가 다른 노드에 재스케줄
- 스케줄링 정책/노드 드레인으로 인한 축출(Eviction)
- Pod 템플릿 변경(라벨/어노테이션/컨테이너 spec 변경 등)으로 컨트롤러가 새 Pod 생성
운영적으로는 여기서 네트워크/스토리지/상태 문제가 자주 튀어나옵니다.
- 커넥션 리셋, 캐시 미스, 세션 소실
- PVC 재부착 지연(특히 stateful workload)
- 기존 Pod에 붙어 있던 디버깅 컨텍스트(로그/메트릭 연속성) 단절
3) 재시작처럼 보이는 “비슷한 사건”(운영이 특히 헷갈리는 구간)
여기서 실무 엔지니어가 가장 조심해야 합니다. “재시작”이 아니라 환경 변화/리소스 변화/운영 조치일 수 있기 때문입니다.
예:
- Evicted: 컨테이너가 죽어서가 아니라 노드 자원 압박/정책으로 쫓겨남
- 인플레이스 리사이즈(in-place resize): 리소스가 바뀌었는데 꼭 재생성/재시작처럼 보일 수 있음
- 노드/컨트롤플레인 컴포넌트 업데이트 후의 파급: 워치 재연결, 컨트롤러 리컨실 폭주 등 “앱 문제처럼 보이는” 증상
이 구간은 “컨테이너 로그만 보면 답이 없다”는 특징이 있어, 이벤트/노드 상태/클러스터 레벨 신호까지 같이 봐야 합니다.
런북 오판을 줄이는 “표준 판별 신호” 제안
열린 질문의 답을 제 방식대로 정리하면, 런북에서 “재시작”을 다음처럼 2단계로 표준화하는 것이 오판을 가장 줄였습니다.
1단계: “Pod가 바뀌었나?”를 UID로 먼저 판정합니다 (가장 중요)
- Pod UID가 바뀌면 = Pod 재생성
- UID가 같으면 = “동일 Pod 내 사건”(컨테이너 재시작/프로브/리소스 등)을 의심
IP는 환경에 따라 바뀌지 않을 수도 있고(또는 우연히 같을 수도 있고), Service 뒤에 있으면 체감이 어렵습니다. 그래서 저는 UID를 1순위로 둡니다.
UID 확인 예시:
kubectl get pod <pod-name> -o jsonpath='{.metadata.uid}{"\n"}'
kubectl get pod <pod-name> -o jsonpath='{.status.podIP}{"\n"}'
2단계: “컨테이너가 죽었나?”는 RestartCount + Last State + 이벤트로 판정합니다
kubectl describe pod <pod-name>
kubectl get pod <pod-name> -o jsonpath='{range .status.containerStatuses[*]}{.name}{" restart="}{.restartCount}{" lastReason="}{.lastState.terminated.reason}{"\n"}{end}'
kubectl get events --field-selector involvedObject.name=<pod-name> --sort-by=.lastTimestamp
restartCount가 증가했고lastState.terminated.reason=OOMKilled→ 컨테이너 OOM- 이벤트에
BackOff가 반복 → 크래시 루프/프로브 오탐 가능성 - 이벤트에
Evicted→ 컨테이너 이슈가 아니라 노드/정책/리소스 압박 가능성
“업데이트 후 재시작” 습관에 대한 제 인사이트(특히 컨트롤플레인/운영자 관점)
대화에서 나왔던 포인트처럼, 업데이트 후 “설정이 제대로 작동하는지 불안해서 재시작한다”는 마음은 정말 공감합니다. 다만 컨트롤플레인/클러스터 핵심 컴포넌트일수록 “재시작”은 검증이 아니라 변수 추가가 되기 쉽습니다.
제가 권하는 방향은 이겁니다.
- “항상 재시작”이 아니라 재시작이 ‘필수인 변경’과 ‘선택인 변경’을 분리합니다.
- “설정이 잘 먹었는지”는 재시작 대신 명시적 검증 체크로 확인합니다.
예: readiness/health endpoint, 핵심 API 리소스 create/list/watch, 이벤트 폭주 여부, 리더 선출 상태 등 - 재시작이 필요하다면 전체 동시 재시작이 아니라 순차 롤링으로 가드레일(쿼럼/가용성)을 지킵니다.
결국 런북의 목표는 “재시작을 잘한다”가 아니라, 재시작 신호를 정확히 해석해서 원인과 조치를 엇갈리지 않게 하는 것이라고 생각합니다.
마무리
“Pod가 재시작됐다”는 말을 그대로 받아들이기 전에, 최소한 UID로 Pod 재생성 여부를 먼저 가르고, 그 다음에 RestartCount/LastState/이벤트로 컨테이너 재시작 원인을 좁히는 흐름을 런북 표준으로 두면 오판이 확 줄어듭니다. 운영에서 제일 위험한 건 장애 자체보다, 서로 다른 사건을 같은 이름(재시작)으로 처리해 잘못된 조치를 반복하는 습관입니다.
