/엔지니어/트러블슈팅/Kubernetes Pod CrashLoopBack
트러블슈팅중급linuxkubernetescrashloopbackoffdebugging

Kubernetes Pod CrashLoopBackOff 진단 — 원인별 완전 해결

CrashLoopBackOff의 정확한 의미와 백오프 동작을 이해하고, 종료 코드·로그·프로브·OOMKilled·설정 누락 등 원인별 진단 절차와 해결법을 체계적으로 정리합니다.

CrashLoopBackOff 란?

CrashLoopBackOff는 그 자체가 오류가 아니라 상태입니다. 컨테이너가 시작 → 종료(크래시) → 재시작을 반복하자, kubelet이 재시작 간격을 점점 늘려(back-off) 폭주를 막고 있다는 뜻입니다. 즉 "컨테이너가 자꾸 죽어서 잠시 쉬었다가 다시 시도 중"인 상태입니다.

  • 재시작 간격은 10s → 20s → 40s … 로 두 배씩 증가, 최대 5분
  • 원인은 컨테이너 안에 있으므로, 핵심은 왜 죽었는지를 찾는 것
  • restartPolicyAlways(기본)/OnFailure일 때 발생

CrashLoopBackOff는 원인 그 자체가 아니라 "증상의 묶음"입니다. 종료 코드와 로그를 보지 않고 매니페스트만 수정하면 헛수고하기 쉽습니다. 항상 종료 코드 → 로그 → 이벤트 순으로 좁혀가세요.


1단계: 전체 상태 파악

Bash
kubectl get pods
# NAME        READY   STATUS             RESTARTS   AGE
# myapp-xxx   0/1     CrashLoopBackOff   5          3m

kubectl describe pod myapp-xxx

describe 출력에서 다음 두 곳을 먼저 봅니다.

CODE
Last State:     Terminated
  Reason:       Error
  Exit Code:    1            ← 핵심 단서
Events:
  Warning  BackOff  ...  Back-off restarting failed container

2단계: 종료 코드(Exit Code) 해석

종료 코드는 원인을 빠르게 좁혀줍니다.

Exit Code의미흔한 원인
0정상 종료메인 프로세스가 할 일 끝내고 종료(데몬이 아님)
1일반 애플리케이션 오류코드 예외, 설정 누락, 의존 서비스 미연결
2셸 사용법/명령 오류command/args 오타
126실행 불가권한 없음, 바이너리 아님
127명령 없음command 경로 오타, 패키지 미설치
137SIGKILL(128+9)OOMKilled 또는 강제 종료
139SIGSEGV(128+11)세그폴트(네이티브 크래시)
143SIGTERM(128+15)종료 신호 정상 수신

3단계: 로그 확인 — 가장 중요한 단서

현재 컨테이너가 아니라 직전에 죽은 컨테이너의 로그를 봐야 합니다.

Bash
kubectl logs myapp-xxx                 # 현재(또는 마지막) 인스턴스
kubectl logs myapp-xxx --previous      # 이전에 크래시한 인스턴스 ← 핵심
kubectl logs myapp-xxx -c sidecar      # 멀티 컨테이너 시 특정 컨테이너

재시작이 빠르면 로그를 잡기 전에 컨테이너가 사라집니다. --previous로 직전 인스턴스 로그를 봐야 진짜 원인이 보입니다.


원인별 해결

A. 애플리케이션 시작 실패 (Exit 1)

설정/환경변수 누락, DB 연결 실패가 대부분입니다.

Bash
kubectl logs myapp-xxx --previous
# 예: "ECONNREFUSED postgres:5432" → DB가 아직 안 떴거나 Service명 오타
  • 환경변수/ConfigMap/Secret이 제대로 주입됐는지 확인
  • 의존 서비스 기동 순서 문제라면 initContainers로 대기
YAML
initContainers:
- name: wait-db
  image: busybox:1.36
  command: ['sh','-c','until nc -z postgres 5432; do echo waiting; sleep 2; done']

B. OOMKilled (Exit 137)

메모리 limit 초과로 커널이 컨테이너를 죽인 경우입니다.

Bash
kubectl describe pod myapp-xxx | grep -A3 'Last State'
#   Reason: OOMKilled

해결: limit 상향 또는 앱 메모리 사용 점검.

YAML
resources:
  requests: { memory: 256Mi }
  limits:   { memory: 512Mi }   # 실제 사용량 + 여유

JVM·Node 등은 limit과 무관하게 호스트 메모리를 보고 힙을 잡으려다 OOM이 납니다. -XX:MaxRAMPercentage 또는 --max-old-space-size로 컨테이너 limit에 맞춰 제한하세요.

C. 잘못된 command/args (Exit 127/126)

Bash
kubectl logs myapp-xxx --previous
# "exec: \"node\": executable file not found" → 이미지에 없는 명령

이미지의 ENTRYPOINT를 덮어쓸 때 경로/철자를 확인하고, 디버깅용으로 직접 셸을 띄워봅니다.

Bash
kubectl run debug --rm -it --image=myapp:1.0 --command -- /bin/sh

D. 라이브니스 프로브 실패

앱은 멀쩡한데 livenessProbe가 너무 빡빡해 kubelet이 계속 죽이는 경우입니다. 이때는 종료 코드가 137/143이고 로그에는 에러가 없습니다.

YAML
livenessProbe:
  httpGet: { path: /healthz, port: 8080 }
  initialDelaySeconds: 30      # 부팅 느린 앱은 충분히
  periodSeconds: 10
  failureThreshold: 3
# 부팅이 매우 느리면 startupProbe로 분리
startupProbe:
  httpGet: { path: /healthz, port: 8080 }
  failureThreshold: 30
  periodSeconds: 5
단서가능성 높은 원인
로그에 앱 에러 + Exit 1설정/의존성 문제 (A)
Reason: OOMKilled, Exit 137메모리 부족 (B)
"not found" + Exit 127command/이미지 문제 (C)
로그 깨끗 + 주기적 137/143프로브 오설정 (D)

E. 설정 리소스 누락 (CreateContainerConfigError)

엄밀히는 CrashLoop 직전 단계지만 함께 자주 만납니다.

Bash
kubectl describe pod myapp-xxx
# Warning  Failed  ... configmap "app-config" not found

참조하는 ConfigMap/Secret/key가 같은 네임스페이스에 있는지 확인합니다.


실시간 디버깅 기법

Bash
# 이벤트를 시간순으로 — 클러스터 차원 원인(스케줄링/이미지풀) 파악
kubectl get events --sort-by=.lastTimestamp

# 임시로 죽지 않게 만들어 안에서 진단 (command를 sleep로 덮어쓰기)
kubectl run probe --rm -it --image=myapp:1.0 \
  --command -- sleep 3600
kubectl exec -it probe -- sh

# 기존 Pod에 디버그 컨테이너 주입(이미지 변경 없이)
kubectl debug -it myapp-xxx --image=busybox:1.36 --target=myapp

운영 중인 Deployment를 임시 검사할 때 kubectl edit로 command를 sleep로 바꾸면 크래시 루프가 멈춰 안에서 천천히 조사할 수 있습니다. 조사 후 원복을 잊지 마세요.


정리

단계명령얻는 것
상태kubectl get/describe podSTATUS, Exit Code, 이벤트
종료 코드describe의 Last State원인 카테고리 추정
로그kubectl logs --previous진짜 크래시 원인
이벤트kubectl get events스케줄링/이미지/설정 문제
진단kubectl run/exec/debug컨테이너 내부 직접 확인
종료 코드1순위 해결
1로그 확인 → 설정/의존성
137메모리 limit 상향 (OOMKilled)
127/126command/이미지 점검
137/143 + 로그 정상프로브 완화/ startupProbe

CrashLoopBackOff는 "다시 시도 중"이라는 상태일 뿐, 원인은 항상 컨테이너 안에 있습니다. 종료 코드 → --previous 로그 → 이벤트 순서로 좁히면 거의 모든 케이스를 체계적으로 해결할 수 있습니다.

#kubernetes#crashloopbackoff#debugging#troubleshooting
편집 안내 · Editorial Note

이 가이드는 AI 도구를 활용해 초안을 구성하고 사람이 명령어·문맥을 검토해 발행했습니다. 운영체제와 도구 버전에 따라 결과가 달라질 수 있으므로 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요.

관련 공식 문서Kubernetes 공식 문서

질문 & 답변 (Q&A)

이 가이드에 대해 궁금한 점을 질문해보세요. 확인 후 답변드립니다.