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

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

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

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

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

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

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

1. 배포 상태 확인

kubectl get deployments를 사용하여 전체 상태를 확인합니다. 특히 READY, UP-TO-DATE 및 AVAILABLE 열을 살펴보세요. 여기서 불일치가 발견되면 기본 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 설명에서 State 및 Reason 필드를 찾으세요. 일반적인 이유로는 ImagePullBackOff, ErrImagePull, CrashLoopBackOff 및 Pending이 있습니다.

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 변경을 수행하세요.