Haru Utils

POD RESTART LOOP

Kubernetes CrashLoopBackOff·OOMKilled·Probe 장애

반복 재시작을 이전 컨테이너 로그, 종료 이유, 리소스 제한, startup·liveness·readiness probe 순서로 분리해 원인에 맞는 최소 변경만 적용합니다.
CrashLoopBackOffOOMKilled exit 137liveness probe failedreadiness probe failedstartup probe failedkubectl logs previous
환경Kubernetes v1.35·v1.36·v1.37 · kubectl · Deployment/StatefulSet 관리 Pod
분류컨테이너
검토일2026-09-02
진행5단계 · 조회 우선

SAFE OPERATING BOUNDARY

중단·복구 기준부터 확인하세요

STOP CONDITIONS

여기서는 멈추세요

  • 현재 kube-context·namespace·워크로드 소유자를 확정하지 못했거나 백업 manifest와 정상 revision을 확보하지 못했다면 변경 단계로 이동하지 않습니다.
  • Secret 원문, 고객 데이터, 인증 토큰이 로그·yaml·공유 자료에 나타나면 수집을 중단하고 마스킹·접근 통제를 먼저 적용합니다.
  • DB migration·상태 저장 워크로드가 포함돼 rollback 호환성이 불명확하면 애플리케이션·데이터베이스 담당자 승인 없이 rollout을 되돌리지 않습니다.
ROLLBACK

복구 기준

적용 전 기록한 정상 revision과 백업 manifest를 기준으로 되돌립니다. Deployment rollback은 컨테이너 이미지·Pod template만 되돌릴 뿐 외부 DB migration과 영구 볼륨 데이터는 복구하지 않으므로, 데이터 호환성을 확인하고 승인된 revision 또는 GitOps 변경으로 복원한 뒤 rollout·Ready·오류율을 재검증합니다.

ESCALATION PACK

담당자에게 전달할 자료

  • Pod containerStatuses의 current·lastState·restartCount와 Warning 이벤트 시각
  • 민감정보를 제거한 current·previous 로그, 리소스 request·limit·사용량과 Node condition
  • 상위 workload revision, 적용 전후 diff, rollout 결과와 서비스 오류율·지연 변화
2026년 9월 2일 기준 upstream 공식 문서와 현재 지원 버전을 대조했습니다. 먼저 읽기 전용 명령으로 사실을 확인하고, 변경 명령은 영향·백업·복구 경로를 확인한 뒤 승인된 대상에만 적용하세요. <...> 자리표시자는 승인된 리터럴 값으로 직접 치환하고 외부 입력으로 shell 명령을 조립하거나 eval하지 마세요.

BEFORE YOU START

이런 증상에서 시작합니다

  • Pod STATUS가 CrashLoopBackOff이며 RESTARTS가 계속 증가함
  • lastState.reason이 OOMKilled이고 exitCode가 137임
  • 이벤트에 Liveness probe failed 또는 Startup probe failed가 반복됨
  • 컨테이너는 실행 중이지만 Ready가 0/1이고 서비스 트래픽을 받지 못함

CHECK THE BRANCH

놓치기 쉬운 원인 분기

01

종료 코드와 이전 로그에 애플리케이션 오류가 있는 경우

exitCode, reason, finishedAt과 --previous 로그를 같은 재시작 회차로 묶어 봅니다. 설정 누락·마이그레이션 실패·의존 서비스 오류라면 probe 지연부터 늘려 원인을 숨기지 않습니다.

02

OOMKilled 또는 노드 메모리 압박인 경우

컨테이너 limit 초과와 노드 전체 MemoryPressure를 구분합니다. limit만 즉시 높이기 전에 실제 working set, 누수 여부, request와 노드 allocatable을 함께 확인합니다.

03

Probe 실패만 반복되는 경우

startup probe가 없거나 검사 경로·포트·timeout이 실제 애플리케이션 기동 특성과 맞지 않을 수 있습니다. readiness 실패는 트래픽 제외, liveness·startup 실패는 재시작으로 이어진다는 차이를 반영합니다.

04

배포 직후 여러 Pod에서 동시에 시작된 경우

개별 Pod 수정보다 Deployment·StatefulSet의 최근 revision과 ConfigMap·Secret 참조 변경을 먼저 확인합니다. 생성된 Pod를 직접 편집하면 다음 재생성 때 사라집니다.

FOLLOW THE FLOW

순서대로 확인하기

1
조회시스템을 변경하지 않는 확인 단계

1분 점검: 상태·종료 이유·이벤트 확인

NAMESPACE와 POD를 실제 값으로 바꾸고 재시작 횟수, 현재·직전 종료 상태, 최근 이벤트를 한 번에 확인합니다.

Pod 상태와 노드
kubectl get pod -n <NAMESPACE> <POD> -o wide
컨테이너별 현재·직전 상태
kubectl get pod -n <NAMESPACE> <POD> -o jsonpath='{range .status.containerStatuses[*]}{.name}{" current="}{.state}{" last="}{.lastState}{" restarts="}{.restartCount}{"\n"}{end}'
Pod 이벤트
kubectl events -n <NAMESPACE> --for pod/<POD> --types=Warning,Normal
결과 읽기

Waiting.reason, terminated.reason·exitCode와 이벤트 시각이 같은 원인을 가리키는지 봅니다. OOMKilled, probe 실패, 애플리케이션 종료를 먼저 분류합니다.

다음 판단

이미지 가져오기 오류라면 ImagePullBackOff 가이드로, Pending이면 스케줄링·PVC·Node 가이드로 이동합니다.

2
조회시스템을 변경하지 않는 확인 단계

현재 로그와 직전 컨테이너 로그 비교

재시작 뒤 현재 로그만 보면 최초 오류가 사라질 수 있으므로 --previous 결과를 반드시 함께 봅니다. 민감정보가 포함될 수 있어 공유 전 마스킹합니다.

컨테이너 이름 확인
kubectl get pod -n <NAMESPACE> <POD> -o jsonpath='{.spec.containers[*].name}{"\n"}'
현재 로그 마지막 200줄
kubectl logs -n <NAMESPACE> <POD> -c <CONTAINER> --tail=200 --timestamps
직전 종료 로그 마지막 200줄
kubectl logs -n <NAMESPACE> <POD> -c <CONTAINER> --previous --tail=200 --timestamps
재시작 이력이 없으면 previous 로그가 없다는 오류가 정상입니다. 로그의 토큰·개인정보는 외부 공유 전에 제거합니다.
결과 읽기

현재 로그는 새 실행 회차, --previous는 직전 종료 회차입니다. 직전 로그 마지막 오류가 종료 reason·exitCode와 일치하는지 확인합니다.

다음 판단

애플리케이션 자체 종료면 설정과 의존성을, OOMKilled면 리소스를, probe 실패면 검사 정의를 각각 확인합니다.

3
조회시스템을 변경하지 않는 확인 단계

리소스 제한과 실제 사용량 확인

Pod 원본 리소스 요청·제한과 가능한 경우 Metrics API 사용량을 비교하고 노드 압박도 함께 확인합니다.

요청·제한과 종료 상태
kubectl get pod -n <NAMESPACE> <POD> -o jsonpath='{range .spec.containers[*]}{.name}{" requests="}{.resources.requests}{" limits="}{.resources.limits}{"\n"}{end}{range .status.containerStatuses[*]}{.name}{" reason="}{.lastState.terminated.reason}{" exit="}{.lastState.terminated.exitCode}{"\n"}{end}'
필요한 리소스와 종료 필드만 조회합니다. 출력의 container 이름도 외부 공유 전 업무 식별정보인지 확인합니다.
Pod 사용량
kubectl top pod -n <NAMESPACE> <POD> --containers
metrics.k8s.io가 설치되지 않은 클러스터에서는 오류가 날 수 있으며, 그 자체가 Pod 장애 원인은 아닙니다.
노드 조건과 할당량
kubectl describe node <NODE>
describe 출력에는 내부 주소·label·annotation·workload 이름이 포함될 수 있습니다. 제한된 터미널에서 확인하고 외부 공유 전 마스킹합니다.
결과 읽기

limit 근처에서 OOMKilled면 누수·정상 최대 사용량과 limit을 재산정합니다. Node MemoryPressure가 True면 개별 Pod 외에 노드 수용량 문제도 해결해야 합니다.

다음 판단

기존 관측 구간이 부족하면 limit을 추측으로 변경하지 말고 지표와 힙·프로세스 진단을 먼저 확보합니다.

4
조회시스템을 변경하지 않는 확인 단계

Probe와 상위 워크로드 원본 확인

실패 Pod가 아니라 이를 관리하는 Deployment·StatefulSet의 probe, 포트, 리소스와 최근 rollout 이력을 확인합니다.

Pod 소유자 확인
kubectl get pod -n <NAMESPACE> <POD> -o jsonpath='{range .metadata.ownerReferences[*]}{.kind}{"/"}{.name}{"\n"}{end}'
Deployment 정의 조회 예시
kubectl get deployment -n <NAMESPACE> <DEPLOYMENT> -o jsonpath='{range .spec.template.spec.containers[*]}{.name}{" image="}{.image}{" command="}{.command}{" args="}{.args}{" resources="}{.resources}{" startupProbe="}{.startupProbe}{" livenessProbe="}{.livenessProbe}{" readinessProbe="}{.readinessProbe}{"\n"}{end}'
전체 YAML 대신 진단 필드만 조회합니다. command·args·probe header에 literal 민감값이 없는지 확인하고 원문을 외부에 붙여넣지 않습니다.
배포 revision 이력
kubectl rollout history deployment/<DEPLOYMENT> -n <NAMESPACE>
결과 읽기

startupProbe 부재, 잘못된 path·port, 너무 짧은 timeout·failureThreshold, 변경된 command·args·resource limit을 이전 정상 revision과 비교합니다.

다음 판단

수정안은 소스 관리 manifest에서 만들고 diff, 백업, 승인, 검증, 되돌리기 순서를 정합니다.

5
변경데이터·서비스 상태가 달라질 수 있는 단계

승인된 최소 변경 후 rollout 검증

이 단계부터 클러스터 상태가 바뀝니다. 정상 revision과 현재 manifest를 보관하고, 애플리케이션 원인에 맞는 한 가지 수정만 검토된 파일로 적용합니다.

변경 단계입니다. 실행 전 대상 이름과 경로, 서비스 중단 영향, 복구 방법을 다시 확인하세요.
현재 워크로드 백업
install -d -m 0700 "<APPROVED_BACKUP_PATH>"
umask 077
kubectl get deployment -n <NAMESPACE> <DEPLOYMENT> -o yaml > "<APPROVED_BACKUP_PATH>/deployment.before.yaml"
chmod 0600 "<APPROVED_BACKUP_PATH>/deployment.before.yaml"
stat -Lc '%a %U:%G %n' "<APPROVED_BACKUP_PATH>/deployment.before.yaml"
전체 YAML에는 literal env.value·annotation·내부 URL·식별자가 포함될 수 있습니다. 전용 0700 디렉터리와 0600 파일에서만 보관하고 원문을 외부 티켓·채팅에 붙여넣지 않습니다.
서버측 변경 미리보기
kubectl diff --server-side -f <REVIEWED_MANIFEST.yaml>
승인된 manifest 적용
kubectl apply --server-side -f <REVIEWED_MANIFEST.yaml>
probe 완화, 리소스 변경, 이미지·설정 변경을 한꺼번에 섞지 않습니다. diff와 복구 revision을 승인받은 뒤 실행합니다.
rollout과 새 Pod 상태
kubectl rollout status deployment/<DEPLOYMENT> -n <NAMESPACE> --timeout=5m
kubectl get pods -n <NAMESPACE> -l <LABEL_SELECTOR> -o wide
결과 읽기

새 Pod가 Ready이고 restartCount가 더 늘지 않으며 서비스 지표가 정상이어야 합니다. rollout timeout은 성공이 아니므로 이벤트와 새 Pod 로그를 다시 확인합니다.

다음 판단

실패하면 kubectl rollout undo를 즉시 실행하기보다 보존한 revision·manifest와 데이터 마이그레이션 호환성을 확인한 뒤 승인된 revision으로 되돌리고, 재발 방지를 위해 메모리·재시작·probe 실패 알림과 부하 기반 값을 운영 기준에 반영합니다.

PRIMARY REFERENCES

공식 문서

배포판과 버전에 따라 옵션·로그 위치가 다를 수 있습니다. 실행 전 서버의 --help와 로컬 매뉴얼을 함께 확인하세요.

도구 빠른 검색

최근 사용한 도구를 다시 열거나, 이름과 기능으로 검색하세요.

검색어와 도구의 입력·결과는 저장하지 않습니다.

↑↓ 이동 · Enter 열기 · Esc 닫기