실패한 배포 디버깅: 일반적인 YAML 및 구성 오류 식별

이벤트, YAML 구조, 이미지 풀, 프로브, 리소스 및 스케줄링 규칙을 확인하여 실패한 Kubernetes 배포를 디버깅합니다.

실패한 배포 디버깅: 일반적인 YAML 및 구성 오류 식별

Kubernetes 배포 실패는 일반적으로 Pending, ImagePullBackOff, CrashLoopBackOff 상태의 파드 또는 사용 가능한 복제본이 0개인 형태로 나타납니다. 원인은 종종 이벤트에서 확인할 수 있지만, 올바른 순서로 Deployment, ReplicaSet 및 Pod를 검사해야 합니다.

이 가이드는 일반적으로 YAML 오류, 이미지 풀 문제, 잘못된 프로브, 리소스 제약 조건 및 배포가 정상 상태가 되는 것을 방해하는 스케줄링 규칙을 찾는 검사 과정을 안내합니다.

첫 번째 단계: 배포 상태 및 이벤트 확인

배포가 실패하면 첫 번째 진단 단계는 항상 기본 리소스 자체와 관리되는 ReplicaSet 및 Pod와 관련된 이벤트를 확인하는 것입니다. 이를 통해 Kubernetes가 무엇을 시도하고 있는지, 왜 실패하는지에 대한 최상위 수준의 개요를 얻을 수 있습니다.

1. 배포 상태 확인

kubectl get deployments를 사용하여 전체 상태를 확인합니다. 특히 READY, UP-TO-DATEAVAILABLE 열을 살펴보세요. 여기서 불일치가 발견되면 기본 Pod에 문제가 있음을 나타냅니다.

kubectl get deployments <deployment-name>

배포 상태에 준비된 복제본이 거의 없거나 전혀 없으면 ReplicaSet을 확인하세요.

2. ReplicaSet 및 Pod 이벤트 검토

ReplicaSet은 원하는 수의 Pod를 관리합니다. 배포가 실패하면 일반적으로 ReplicaSet이 오류 연쇄의 원인입니다. 일반적으로 <deployment-name>-<hash> 형식으로 이름이 지정된 ReplicaSet에 describe 명령을 사용합니다:

kubectl describe rs <replicaset-name>

중요한 것은 출력 하단의 Events 섹션을 검토하는 것입니다. 이 섹션은 스케줄링 시도, 이미지 풀 실패, 볼륨 마운트 문제 등 최근 작업을 자세히 설명합니다. 이러한 이벤트는 종종 결정적인 증거입니다.

마지막으로 Pod 자체를 확인하여 즉각적인 실패를 보고합니다:

kubectl get pods -l app=<your-app-label>
kubectl describe pod <pod-name>

Pod 설명에서 StateReason 필드를 찾으세요. 일반적인 이유로는 ImagePullBackOff, ErrImagePull, CrashLoopBackOffPending이 있습니다.

YAML 매니페스트의 일반적인 구성 오류

YAML 파일의 잘못된 구성은 배포 실패의 가장 빈번한 원인입니다. 이러한 오류는 단순한 들여쓰기 실수부터 복잡한 구조적 문제까지 다양할 수 있습니다.

1. YAML 구문 및 구조 오류

Kubernetes API는 올바른 YAML 구문(들여쓰기, 공백 및 데이터 유형)에 매우 민감합니다. YAML이 유효하지 않으면 kubectl apply는 종종 즉시 실패하며 파일을 구문 분석할 수 없다고 표시합니다.

모범 사례: 린터 사용 적용하기 전에 항상 YAML 구문의 유효성을 검사하세요. yamllint와 같은 도구나 통합 IDE 지원을 사용하면 기본 구문 오류를 즉시 잡을 수 있습니다.

일반적인 구조 오류의 예: 잘못된 매핑 또는 들여쓰기.

# 잘못됨: containers는 spec.template.spec 아래에 속하며, spec.template 바로 아래에 있지 않습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    metadata:
      labels:
        app: my-app
    containers:
      - name: my-app
        image: myregistry/myapp:v1

올바른 배치:

spec:
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: myregistry/myapp:v1
          ports:
            - containerPort: 8080

2. 이미지 참조 및 풀 오류

Pod가 ImagePullBackOff 또는 ErrImagePull 상태가 되면 컨테이너 이미지에 액세스하는 데 문제가 있는 것입니다.

  • 이미지 이름/태그 오타: 이미지 저장소, 이름 및 태그의 철자를 다시 확인하세요.
  • 프라이빗 레지스트리 인증: 프라이빗 레지스트리에서 가져오는 경우 이미지 풀 시크릿을 생성하고 Pod 사양에서 imagePullSecrets로 참조했는지 확인하세요.
# ImagePullSecret 사용을 보여주는 스니펫
spec:
  imagePullSecrets:
    - name: my-registry-secret
  containers:
    - name: my-app
      image: private.example.com/my-app:v1

3. 리소스 요청 및 제한 위반

Pod가 Pending 상태로 유지되고 이벤트에 리소스 부족이 언급되면 클러스터 노드가 YAML에 정의된 CPU 또는 메모리 요구 사항을 충족할 수 없는 것입니다.

배포 매니페스트에 지정된 제한을 확인하세요:

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1Gi"
    cpu: "1"

문제 해결 단계:

  1. kubectl describe nodes를 사용하여 사용 가능한 용량을 확인합니다.
  2. 0/3 nodes are available: 3 Insufficient cpu와 같은 이벤트가 표시되면 YAML에서 requests를 낮추거나 클러스터에 노드를 더 추가해야 합니다.

고급 구성 문제

기본 구문 및 이미지 풀 외에도 네트워킹, 스토리지 및 스케줄링과 관련된 복잡한 구성은 진단하기 어려운 실패로 이어질 수 있습니다.

1. 잘못 구성된 프로브(Liveness 및 Readiness)

Pod가 CrashLoopBackOff 상태로 전환되면 컨테이너가 시작되지만 즉시 검사에 실패하거나 시작되었지만 준비 상태 프로브(readiness probe)가 계속 실패하는 경우가 많습니다.

  • Liveness 프로브: 이것이 반복적으로 실패하면 Kubernetes가 컨테이너를 다시 시작합니다. kubectl describe pod <pod-name>에서 프로브 실패 이벤트를 확인하고 재시작 후 kubectl logs <pod-name> --previous를 확인하세요.
  • Readiness 프로브: 이것이 실패하면 Pod는 계속 실행되지만 Service 엔드포인트에서 제외됩니다. 경로, 포트 및 예상 응답 코드가 애플리케이션이 실제로 제공하는 것과 일치하는지 확인하세요.

일반적인 Readiness 프로브 오류의 예: 잘못된 포트를 대상으로 하거나 앱이 TCP만 노출할 때 HTTP를 예상하는 경우.

2. 볼륨 및 PersistentVolumeClaim(PVC) 실패

볼륨 문제로 인해 Pod가 보류 중인 경우 PVC 상태를 확인하세요:

kubectl get pvc <pvc-name>

PVC 상태가 Pending이면 클러스터가 일치하는 StorageClass 또는 바인딩할 적절한 PersistentVolume을 찾을 수 없음을 의미합니다. 특정 바인딩 오류에 대한 PVC 이벤트를 확인하세요.

3. 어피니티 및 안티-어피니티 규칙

nodeAffinity 또는 podAntiAffinity와 같은 복잡한 스케줄링 규칙은 모든 기준을 충족하는 노드가 없으면 의도치 않게 Pod 스케줄링을 방해할 수 있습니다. Pod가 Pending 상태로 유지되고 이벤트에 스케줄링 제한이 언급되면 이러한 규칙을 검토하세요.

예를 들어, 특정 레이블(disktype: ssd)이 있는 노드에서 Pod를 실행해야 하는데 해당 레이블을 가진 노드가 없으면 Pod는 절대 스케줄링되지 않습니다.

# 예: 'disktype: ssd' 레이블이 있는 노드로 배포 제한
spec:
  nodeSelector:
    disktype: ssd
  containers:
  # ...

문제 해결 팁: 제한적인 nodeSelector 또는 affinity 규칙을 일시적으로 주석 처리하세요. Pod가 성공적으로 스케줄링되면 선택 기준에 문제가 있는 것입니다.

디버깅 워크플로우

실패한 배포에 직면했을 때 이 구조화된 경로를 따르세요:

  1. 배포 상태: kubectl get deployments -> 복제본이 준비 상태를 보고합니까?
  2. Pod 이벤트: kubectl describe pod <failing-pod> -> Events 섹션에서 즉각적인 오류(ImagePull, OOMKilled, 볼륨 문제)를 확인합니다.
  3. 컨테이너 로그: kubectl logs <failing-pod> -> 컨테이너가 시작되지만 충돌하는 경우(CrashLoopBackOff), 애플리케이션 로직 또는 liveness 프로브가 의심됩니다.
  4. 리소스 확인: Pod가 Pending 상태이면 리소스 제약(Insufficient cpu/memory) 또는 실패한 볼륨 바인딩(PVC 상태)을 확인합니다.
  5. 구성 검증: 들여쓰기, 올바른 필드 이름 및 유효한 리소스 값(requests/limits)에 대해 YAML을 검토합니다.

추측하는 대신 클러스터의 증거를 기반으로 작업하세요. 상태, 이벤트, 로그, 리소스 및 매니페스트 구조를 해당 순서로 확인한 다음, 발견한 오류와 일치하는 가장 작은 YAML 변경을 수행하세요.