devops2023-10-22·9 min·338/348

Kubernetes Pod CrashLoopBackOff 해결 가이드

Kubernetes Pod이 CrashLoopBackOff 상태가 되는 원인을 분석하고 해결하는 방법을 알아봅니다.

Kubernetes Pod CrashLoopBackOff 해결 가이드

CrashLoopBackOff는 Pod이 반복적으로 시작 실패 후 종료되는 상태입니다. 이 상태가 되면 Pod이 정상적으로 동작하지 않으며, 서비스에 영향을 줍니다.

Environment

$ kubectl version --client
Client Version: v1.28.4
Kustomize Version: v5.3.0

$ kubectl get nodes
NAME           STATUS   ROLES           AGE   VERSION
k8s-master     Ready    control-plane   30d   v1.28.4
k8s-worker-1   Ready              30d   v1.28.4

Problem: Pod이 계속 재시작됨

$ kubectl get pods
NAME                    READY   STATUS             RESTARTS      AGE
myapp-7d4b8c9f5-abc12   0/1     CrashLoopBackOff   5 (30s ago)   2m

$ kubectl describe pod myapp-7d4b8c9f5-abc12

출력:

Events:
  Type     Reason     Age                From               Message
  ----     ----      ----               ----               -------
  Normal   Pulled     2m                 kubelet            Container image "myapp:latest" already present on machine
  Normal   Created    2m                 kubelet            Created container myapp
  Normal   Started    2m                 kubelet            Started container myapp
  Warning  BackOff    30s (x5 over 2m)   kubelet            Back-off restarting failed container

Analysis: Pod 로그 분석

# Pod 로그 확인
$ kubectl logs myapp-7d4b8c9f5-abc12
2024-01-15 10:30:00 ERROR: Database connection refused
Traceback (most recent call last):
  File "/app/main.py", line 10, in 
    connect_to_database()
ConnectionRefusedError: [Errno 111] Connection refused

# 이전 컨테이너 로그 확인
$ kubectl logs myapp-7d4b8c9f5-abc12 --previous

# Pod 상태 상세 확인
$ kubectl get pod myapp-7d4b8c9f5-abc12 -o yaml

Solution: CrashLoopBackOff 해결 방법

방법 1: 로그 분석 후 설정 수정

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: url
        ports:
        - containerPort: 8000

방법 2: Health Checks 설정

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        ports:
        - containerPort: 8000
        
        # Liveness Probe - Is the container alive?
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 30
          periodSeconds: 10
          failureThreshold: 3
        
        # Readiness Probe - Is the container ready?
        readinessProbe:
          httpGet:
            path: /ready
            port: 8000
          initialDelaySeconds: 5
          periodSeconds: 5

방법 3: 리소스 제한 설정

containers:
- name: myapp
  image: myapp:latest
  resources:
    requests:
      memory: "256Mi"
      cpu: "250m"
    limits:
      memory: "512Mi"
      cpu: "500m"

방법 4: 커맨드 오버라이드

# 디버깅을 위해 커맨드 오버라이드
containers:
- name: myapp
  image: myapp:latest
  command: ["sleep"]
  args: ["infinity"]
# Pod exec로 디버깅
$ kubectl exec -it myapp-7d4b8c9f5-abc12 -- /bin/bash

# 수동으로 앱 실행
$ kubectl exec -it myapp-7d4b8c9f5-abc12 -- python app.py

방법 5: Init Container 사용

spec:
  initContainers:
  - name: wait-for-db
    image: busybox
    command: ['sh', '-c', 'until nc -z db-service 5432; do sleep 2; done']
  
  containers:
  - name: myapp
    image: myapp:latest
    dependsOn:
      - wait-for-db

Advanced: 디버깅 명령어 모음

# Pod 상태 확인
$ kubectl get pods -o wide

# 상세 이벤트 확인
$ kubectl describe pod 

# 로그 확인
$ kubectl logs 
$ kubectl logs  --previous
$ kubectl logs  -f  # Follow logs

# Pod exec
$ kubectl exec -it  -- /bin/bash

# 디버그 컨테이너로 Pod 진입
$ kubectl debug -it  --image=busybox

# Pod 리소스 사용량 확인
$ kubectl top pod 

# Pod YAML 확인
$ kubectl get pod  -o yaml

Lessons Learned

  1. 로그가 첫 번째 단계: CrashLoopBackOff 발생 시 먼저 kubectl logs로 에러 메시지를 확인하세요.

  2. Health Check 필수: Liveness/Readiness Probe를 설정하여 Pod 상태를 모니터링하세요.

  3. Init Container 활용: 의존성이 있는 서비스가 준비될 때까지 기다리는 init container를 사용하세요.

  4. 리소스 제한: 메모리/CPU 제한을 설정하여 OOM Killed를 방지하세요.

  5. 디버깅 전략: 문제가 지속되면 커맨드 오버라이드로 Pod을 유지하고 수동 디버깅을 수행하세요.


This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.