콘텐츠로 건너뛰기

Kubernetes Pod가 CrashLoopBackOff에 빠지는 7가지 원인과 해결 순서

핵심 요약

  • CrashLoopBackOff는 Pod 안의 컨테이너가 시작하자마자 죽고, Kubernetes가 다시 띄우고, 또 죽는 과정을 반복하는 상태입니다. 그 자체는 “오류 이름”이 아니라 “재시작을 반복 중”이라는 신호입니다.
  • Kubernetes는 계속 죽는 컨테이너를 무한정 빠르게 재시작하지 않고, 재시작 간격을 점점 늘립니다(back-off). 그래서 이름에 BackOff가 붙습니다.
  • 원인은 대부분 7가지로 좁혀집니다: 앱 자체 오류, 잘못된 실행 명령, 설정·환경변수 누락, 의존 서비스 연결 실패, 헬스체크(probe) 오설정, 리소스 부족(OOM), 볼륨·권한 문제.
  • 해결은 순서가 핵심입니다: kubectl describe → kubectl logs(특히 --previous) → 이벤트·종료 코드 확인 → 원인별 조치. 감이 아니라 로그와 종료 코드를 보고 좁혀 갑니다.

kubectl get pods를 쳤는데 STATUS 칸에 CrashLoopBackOff가 떠 있으면, Kubernetes를 처음 다루는 사람은 당황하기 쉽습니다. 에러 메시지도 아니고, 무엇이 잘못됐는지 바로 알려주지도 않기 때문입니다. 하지만 이 상태는 사실 “컨테이너가 자꾸 죽어서 재시작을 반복하고 있다”는 뜻일 뿐이고, 원인은 몇 가지로 정해져 있습니다. 이 글에서는 CrashLoopBackOff가 정확히 무엇인지, 자주 나오는 7가지 원인, 그리고 어떤 순서로 진단하면 빠르게 해결되는지를 신입 엔지니어 눈높이에서 정리합니다.

CrashLoopBackOff란 무엇인가?

Kubernetes는 “컨테이너는 항상 살아 있어야 한다”는 원칙으로 움직입니다. 그래서 컨테이너가 죽으면(종료되면) 기본 정책상 자동으로 다시 띄웁니다. 그런데 다시 띄운 컨테이너도 또 죽으면? Kubernetes는 다시 띄웁니다. 이 “죽고 → 재시작 → 또 죽고”가 반복되는 상황이 바로 CrashLoopBackOff입니다.

여기서 BackOff가 중요합니다. 계속 죽는 컨테이너를 1초마다 무한히 재시작하면 서버 자원만 낭비되겠죠. 그래서 Kubernetes는 재시작 간격을 점점 늘립니다. 10초 → 20초 → 40초 … 이렇게 최대 5분까지 간격을 벌리며 재시도합니다. 즉 CrashLoopBackOff는 “재시작을 시도하되, 지쳐서 간격을 늘려 가며 기다리는 중“인 상태입니다.

CrashLoopBackOff 순환 ① 컨테이너 시작 ② 실행 (잠깐) ③ 비정상 종료(exit≠0) ④ 대기(back-off) 10s→20s→40s… 다시 시작 → 또 죽으면 간격을 늘려 반복 (최대 5분)

그림처럼 CrashLoopBackOff는 하나의 순환입니다. 이 순환을 끊으려면 “왜 ③에서 죽는가”를 찾아야 합니다. 그리고 그 원인은 대개 아래 7가지 안에 있습니다.

자주 나오는 7가지 원인

1. 애플리케이션 자체의 오류. 코드에서 예외가 나거나 시작 직후 비정상 종료(exit code가 0이 아님)하는 경우입니다. 가장 흔하며, 로그에 스택 트레이스가 남습니다.

2. 잘못된 실행 명령(command/args). 컨테이너의 command나 엔트리포인트가 잘못됐거나, 존재하지 않는 실행 파일을 가리키면 컨테이너가 곧바로 종료됩니다. “executable file not found” 류 메시지가 단서입니다.

3. 설정·환경변수 누락. 앱이 꼭 필요로 하는 환경변수나 설정 파일이 없어서 시작 단계에서 죽는 경우입니다. 참조하는 ConfigMap/Secret이 없거나 키 이름이 틀렸을 때 자주 발생합니다.

4. 의존 서비스 연결 실패. 앱이 시작하자마자 데이터베이스·캐시·외부 API에 접속을 시도하는데 그 대상이 아직 안 떠 있거나 주소가 틀리면, 연결 실패로 종료됩니다. 여러 Pod가 동시에 뜰 때 순서 문제로 흔히 나타납니다.

5. 헬스체크(probe) 오설정. liveness probe가 너무 빡빡하게 설정되면(예: 앱이 뜨는 데 30초 걸리는데 5초 만에 검사), Kubernetes는 “죽었다”고 판단해 컨테이너를 죽이고 재시작합니다. 앱은 멀쩡한데 probe 설정 때문에 루프에 빠지는 경우입니다.

6. 리소스 부족(OOMKilled). 메모리 limit보다 많이 쓰면 컨테이너가 강제 종료됩니다. 이때 kubectl describe의 종료 사유에 OOMKilled가 찍히고, 종료 코드는 보통 137입니다.

7. 볼륨·권한·파일 문제. 마운트하려는 볼륨이 없거나, 파일 권한이 맞지 않거나, 앱이 쓰려는 경로에 쓰기 권한이 없을 때도 시작에 실패합니다. 권한 관련 메시지(“permission denied”)가 로그에 보입니다.

해결 순서: 감이 아니라 로그로

CrashLoopBackOff를 만났을 때 초보가 가장 많이 하는 실수는 “일단 재배포부터” 하는 것입니다. 원인을 모른 채 다시 띄우면 똑같이 죽습니다. 아래 순서대로 정보를 모으면 원인이 거의 드러납니다.

  1. kubectl get pods — 상태와 RESTARTS 횟수를 확인합니다. 재시작 횟수가 계속 늘고 있는지 봅니다.
  2. kubectl describe pod <이름> — 가장 중요한 단계입니다. 맨 아래 Events와 컨테이너의 Last State(종료 사유·Exit Code)를 봅니다. 여기서 OOMKilled, 마운트 실패, probe 실패가 바로 드러나는 경우가 많습니다.
  3. kubectl logs <이름> — 앱이 남긴 로그를 봅니다. 예외·스택 트레이스가 있으면 1번 원인입니다.
  4. kubectl logs <이름> --previous — 컨테이너가 이미 죽어 재시작된 경우, 직전에 죽은 컨테이너의 로그를 봐야 진짜 원인이 보입니다. 이 --previous를 모르면 한참 헤맵니다.
  5. 종료 코드로 좁히기 — Exit Code가 단서입니다. 137(OOM/강제 종료), 1(앱 일반 오류), 127(명령어 없음) 등으로 방향을 잡습니다.
  6. 원인별 조치 — 위에서 좁힌 원인에 맞춰 설정·리소스·probe·의존성을 고치고 다시 배포합니다.

원인 → 확인 포인트 요약표

원인어디서 드러나나대표 단서
앱 자체 오류logs예외·스택 트레이스, Exit 1
잘못된 실행 명령describe / logsexecutable not found, Exit 127
설정·환경변수 누락logs / describe설정 못 찾음, ConfigMap/Secret 오류
의존 서비스 연결 실패logsconnection refused, timeout
probe 오설정describe(Events)Liveness probe failed
리소스 부족describe(Last State)OOMKilled, Exit 137
볼륨·권한 문제describe(Events)mount 실패, permission denied

이 표 한 장만 옆에 두면, CrashLoopBackOff를 만나도 “어디를 먼저 볼지”가 분명해집니다. 거의 모든 경우가 describe와 logs 두 명령 안에서 답이 나옵니다.

저도 처음 Kubernetes 실습을 할 때 CrashLoopBackOff를 만나고 한참을 헤맸습니다. 계속 kubectl logs만 쳤는데 아무것도 안 나와서 당황했었죠. 알고 보니 컨테이너가 이미 죽고 재시작된 상태라 현재 로그는 비어 있었고, --previous를 붙이자 그제서야 “환경변수 하나가 없다”는 메시지가 떡 하니 찍혀 있었습니다. 원인은 ConfigMap 키 이름 오타였습니다. 그때 “CrashLoopBackOff는 describe와 –previous 로그부터”라는 습관이 생겼고, 이후로는 같은 상황에서 몇 분 만에 원인을 찾게 됐습니다.

자주 묻는 질문 (FAQ)

Q. CrashLoopBackOff와 Error 상태는 다른가요?
네. Error는 컨테이너가 한 번 비정상 종료한 상태이고, CrashLoopBackOff는 그 종료가 반복되어 재시작 간격이 늘어난 상태입니다. 원인을 찾는 방법은 같습니다.

Q. 재시작 간격(back-off)은 조절할 수 있나요?
back-off 자체는 Kubernetes가 자동으로 관리하며 사용자가 세밀하게 바꾸긴 어렵습니다. 중요한 건 간격 조절이 아니라 죽는 원인을 없애는 것입니다.

Q. 앱은 멀쩡한데 CrashLoopBackOff가 떠요.
liveness probe 오설정(원인 5)일 가능성이 큽니다. 앱이 완전히 뜨기 전에 probe가 검사하지 않도록 initialDelaySeconds를 늘리거나 probe 조건을 완화해 보세요.

마무리

CrashLoopBackOff는 무서운 에러가 아니라, “컨테이너가 자꾸 죽고 있으니 원인을 찾아 달라”는 Kubernetes의 신호입니다. 당황하지 말고 describe로 종료 사유·이벤트를 보고, logs(특히 --previous)로 앱이 남긴 말을 읽는 순서만 지키면, 원인은 위 7가지 안에서 대부분 드러납니다. 쿠버네티스 트러블슈팅의 첫 관문인 만큼, 이 순서를 몸에 익혀 두면 실무에서도 큰 무기가 됩니다.

더 읽어보기

이 글은 학습·정보 제공을 목적으로 작성되었습니다. Kubernetes 버전과 배포 환경에 따라 명령어 옵션과 동작은 달라질 수 있으니, 실제 운영 시에는 공식 문서를 함께 확인하시기 바랍니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다