배포된 워크로드 문제 해결


이 페이지에서는 Google Kubernetes Engine(GKE)에서 배포된 워크로드의 오류를 해결하는 방법을 보여줍니다.

애플리케이션 문제 해결에 관한 일반적인 도움말은 Kubernetes 문서의 애플리케이션 문제 해결을 참조하세요.

모든 오류: 포드 상태 확인

워크로드의 포드에 문제가 있으면 Kubernetes는 오류 메시지와 함께 포드 상태를 업데이트합니다. Google Cloud 콘솔이나 kubectl 명령줄 도구를 사용하여 포드 상태를 확인해 이러한 오류를 볼 수 있습니다.

콘솔

다음 단계를 수행합니다.

  1. Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.

    워크로드로 이동

  2. 조사할 워크로드를 선택합니다. 개요 탭에 워크로드 상태가 표시됩니다.

  3. 관리형 포드 섹션에서 오류 상태 메시지를 클릭합니다.

kubectl

클러스터에서 실행 중인 모든 Pod를 확인하려면 다음 명령어를 실행합니다.

kubectl get pods

출력은 다음과 비슷합니다.

NAME       READY  STATUS             RESTARTS  AGE
POD_NAME   0/1    CrashLoopBackOff   23        8d

잠재적 오류는 Status 열에 나열됩니다.

특정 포드에 대한 자세한 내용을 보려면 다음 명령어를 실행합니다.

kubectl describe pod POD_NAME

POD_NAME을 조사하려는 포드의 이름으로 바꿉니다.

출력에서 Events 필드에는 오류에 관한 추가 정보가 표시됩니다.

자세한 내용은 컨테이너 로그를 확인하세요.

kubectl logs POD_NAME

이러한 로그를 통해 컨테이너의 명령어 또는 코드로 인해 포드가 비정상 종료되었는지 확인할 수 있습니다.

오류를 식별한 후 다음 섹션을 사용하여 문제를 해결해 보세요.

오류: CrashLoopBackOff

CrashLoopBackOff 상태는 특정 오류가 있음을 의미하지 않으며 대신 컨테이너가 다시 시작 후 반복적으로 비정상 종료됨을 나타냅니다. 컨테이너가 시작 직후 비정상 종료되거나 종료되면(CrashLoop) Kubernetes는 컨테이너를 다시 시작하려고 시도합니다. 다시 시작할 때마다 다음 시도 전 지연 시간(BackOff)이 기하급수적으로 증가(10초, 20초, 40초 등)하여 최대 5분까지 늘어납니다.

다음 섹션에서는 컨테이너가 비정상 종료되는 이유를 파악하는 데 도움이 됩니다.

비정상 종료 루프 포드 대화형 플레이북 사용

Google Cloud 콘솔의 대화형 플레이북을 사용하여 CrashLoopBackOff 상태의 원인을 해결합니다.

  1. 비정상 종료 루프 포드 대화형 플레이북으로 이동합니다.

    플레이북으로 이동

  2. 클러스터 드롭다운 목록에서 문제를 해결할 클러스터를 선택합니다. 클러스터를 찾을 수 없는 경우 필터 필드에 클러스터 이름을 입력합니다.

  3. 네임스페이스 드롭다운 목록에서 문제 해결을 원하는 네임스페이스를 선택합니다. 네임스페이스를 찾을 수 없는 경우 필터 필드에 네임스페이스를 입력합니다.

  4. 원인을 파악하는 데 도움이 되도록 각 섹션을 살펴보세요.

    1. 애플리케이션 오류 확인
    2. 메모리 부족 문제 조사
    3. 노드 중단 조사
    4. 활성 프로브 실패 조사
    5. 변경 이벤트 상관관계 파악
  5. 선택사항: 향후 CrashLoopBackOff 오류에 관한 알림을 받으려면 향후 문제 완화 팁 섹션에서 알림 만들기를 선택합니다.

로그 검사

컨테이너는 다양한 원인으로 인해 비정상 종료될 수 있습니다. 포드의 로그를 확인하면 근본 원인을 해결할 수 있습니다.

Google Cloud 콘솔이나 kubectl 명령줄 도구를 사용하여 로그를 확인할 수 있습니다.

콘솔

다음 단계를 수행합니다.

  1. Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.

    워크로드로 이동

  2. 조사할 워크로드를 선택합니다. 개요 탭에 워크로드 상태가 표시됩니다.

  3. 관리형 포드 섹션에서 문제가 있는 포드를 클릭합니다.

  4. 포드의 메뉴에서 로그 탭을 클릭합니다.

kubectl

  1. 클러스터에서 실행 중인 모든 포드를 확인합니다.

    kubectl get pods
    
  2. 위 명령어의 출력에서 Status 열에 CrashLoopBackOff 오류가 있는 포드를 찾습니다.

  3. 포드 로그를 가져옵니다.

    kubectl logs POD_NAME
    

    POD_NAME을 문제가 있는 pod의 이름으로 바꿉니다.

    -p 플래그를 전달하여 포드 컨테이너의 이전 인스턴스 로그(있는 경우)를 가져올 수도 있습니다.

비정상 종료된 컨테이너의 종료 코드 확인

컨테이너가 비정상 종료된 이유를 더 잘 이해하려면 종료 코드를 찾으세요.

  1. 포드를 설명합니다.

    kubectl describe pod POD_NAME
    

    POD_NAME을 문제가 있는 pod의 이름으로 바꿉니다.

  2. containers: CONTAINER_NAME: last state: exit code 필드 값을 검토합니다.

    • 종료 코드가 1이면 애플리케이션 비정상 종료로 인해 컨테이너가 비정상 종료된 것입니다.
    • 종료 코드가 0이면 앱이 실행된 시간을 확인합니다. 애플리케이션의 기본 프로세스가 종료되면 컨테이너가 종료됩니다. 앱의 실행이 아주 빨리 끝나면 컨테이너가 계속 다시 시작될 수 있습니다. 이 오류가 발생하면 restartPolicy 필드를 OnFailure로 설정하는 것이 하나의 해결 방법입니다. 이렇게 변경하면 종료 코드가 0이 아닌 경우에만 앱이 다시 시작됩니다.

실행 중인 컨테이너에 연결

네트워크를 테스트하거나 애플리케이션에서 사용하는 파일 또는 데이터베이스에 액세스할 수 있는지 확인할 수 있도록 컨테이너에서 bash 명령어를 실행하려면 포드에 대한 셸을 엽니다.

kubectl exec -it POD_NAME -- /bin/bash

포드에 컨테이너가 두 개 이상 있으면 -c CONTAINER_NAME을 추가합니다.

오류: ImagePullBackOff 및 ErrImagePull

상태가 ImagePullBackOff 또는 ErrImagePull이면 컨테이너가 사용하는 이미지를 이미지 레지스트리에서 로드할 수 없음을 나타냅니다.

이러한 상태를 해결하는 방법에 대한 안내는 이미지 가져오기 문제 해결을 참조하세요.

오류: 예약할 수 없는 포드

PodUnschedulable 상태는 리소스 부족 또는 일부 구성 오류로 인해 포드를 예약할 수 없음을 나타냅니다.

컨트롤 플레인 측정항목을 구성한 경우 스케줄러 측정항목API 서버 측정항목에서 이러한 오류에 대한 자세한 정보를 찾을 수 있습니다.

예약할 수 없는 포드 대화형 플레이북 사용

Google Cloud 콘솔의 대화형 플레이북을 사용하여 PodUnschedulable 오류를 해결할 수 있습니다.

  1. 예약할 수 없는 포드 대화형 플레이북으로 이동합니다.

    플레이북으로 이동

  2. 클러스터 드롭다운 목록에서 문제를 해결할 클러스터를 선택합니다. 클러스터를 찾을 수 없는 경우 필터 필드에 클러스터 이름을 입력합니다.

  3. 네임스페이스 드롭다운 목록에서 문제 해결을 원하는 네임스페이스를 선택합니다. 네임스페이스를 찾을 수 없는 경우 필터 필드에 네임스페이스를 입력합니다.

  4. 원인을 파악하는 데 도움이 되도록 플레이북의 각 섹션을 살펴보세요.

    1. CPU 및 메모리 조사
    2. 노드당 최대 포드 수 조사
    3. 자동 확장 처리 동작 조사
    4. 기타 실패 모드 조사
    5. 변경 이벤트 상관관계 파악
  5. 선택사항: 향후 PodUnschedulable 오류에 관한 알림을 받으려면 향후 문제 완화 팁 섹션에서 알림 만들기를 선택합니다.

오류: 리소스 부족

CPU, 메모리 또는 다른 리소스 부족을 나타내는 오류가 발생할 수 있습니다. 예를 들면 No nodes are available that match all of the predicates: Insufficient cpu (2)는 2개의 노드에 포드의 요청을 충족하는 데 사용할 수 있는 CPU가 충분하지 않음을 나타냅니다.

포드 리소스 요청이 적격한 노드 풀에서 단일 노드의 요청을 초과할 경우 GKE가 포드를 예약하지 않고 새 노드를 추가하기 위한 수직 확장을 트리거하지 않습니다. GKE가 포드를 예약할 수 있도록 하려면 포드에 대해 더 적은 수의 리소스를 요청하거나 리소스가 충분한 새 노드 풀을 만들어야 합니다.

또한 예약되지 않은 포드가 실행될 수 있는 노드를 사용해서 GKE가 노드 풀을 자동으로 만들 수 있도록 노드 자동 프로비저닝을 사용 설정할 수 있습니다.

기본 CPU 요청은 100m 또는 CPU의 10%(또는 코어 한 개)입니다. 더 많은 리소스 또는 더 적은 리소스를 요청하려면 spec: containers: resources: requests의 포드 사양에 값을 지정합니다.

오류: MatchNodeSelector

MatchNodeSelector는 Pod의 라벨 선택기와 일치하는 노드가 없음을 나타냅니다.

spec: nodeSelector에서 Pod 사양의 nodeSelector 필드에 지정된 라벨을 통해 이를 확인할 수 있습니다.

클러스터의 노드에 라벨이 어떻게 지정되어 있는지 확인하려면 다음 명령어를 실행합니다.

kubectl get nodes --show-labels

노드에 라벨을 연결하려면 다음 명령어를 실행합니다.

kubectl label nodes NODE_NAME LABEL_KEY=LABEL_VALUE

다음을 바꿉니다.

  • NODE_NAME: 라벨을 추가하려는 노드입니다.
  • LABEL_KEY: 라벨의 키
  • LABEL_VALUE: 라벨의 값

자세한 내용은 Kubernetes 문서의 포드를 노드에 할당을 참조하세요.

오류: PodToleratesNodeTaints

PodToleratesNodeTaints는 포드에 기존 노드 taint에 해당하는 톨러레이션(toleration)이 없으므로 포드를 어떠한 노드에도 예약할 수 없음을 나타냅니다.

이 경우인지 확인하려면 다음 명령어를 실행합니다.

kubectl describe nodes NODE_NAME

출력에서 키-값 쌍과 예약 효과가 나열되는 Taints 필드를 확인합니다.

나열된 효과가 NoSchedule이면 일치하는 톨러레이션이 없는 한 노드에서 pod를 예약할 수 없습니다.

이 문제를 해결하는 한 가지 방법은 taint를 제거하는 것입니다. 예를 들어 NoSchedule taint를 삭제하려면 다음 명령어를 실행합니다.

kubectl taint nodes NODE_NAME key:NoSchedule-

오류: PodFitsHostPorts

PodFitsHostPorts 오류는 노드가 이미 사용 중인 포트를 사용하려 한다는 의미입니다.

이 문제를 해결하려면 Kubernetes 권장사항을 따르고 hostPort 대신 NodePort를 사용하는 것이 좋습니다.

hostPort를 사용해야 하는 경우 포드의 매니페스트를 확인하고 hostPort에 정의한 고유한 값이 같은 노드의 모든 포드에 있는지 확인합니다.

오류: 최소 가용성 없음

노드에 적절한 리소스가 있지만 여전히 Does not have minimum availability 메시지가 표시되면 Pod 상태를 확인합니다. 상태가 SchedulingDisabled 또는 Cordoned이면 노드가 새 포드를 예약할 수 없습니다. Google Cloud 콘솔이나 kubectl 명령줄 도구를 사용하여 노드 상태를 확인할 수 있습니다.

콘솔

다음 단계를 수행합니다.

  1. Google Cloud 콘솔에서 Google Kubernetes Engine 페이지로 이동합니다.

    Google Kubernetes Engine으로 이동

  2. 조사하려는 클러스터를 선택합니다. 노드 탭에 노드와 노드 상태가 표시됩니다.

노드에서 예약을 사용 설정하려면 다음 단계를 수행합니다.

  1. 목록에서 조사하려는 노드를 클릭합니다.

  2. 노드 세부정보 섹션에서 차단 해제를 클릭합니다.

kubectl

노드 상태를 가져오려면 다음 명령어를 실행합니다.

kubectl get nodes

노드에서 예약을 사용 설정하려면 다음을 실행합니다.

kubectl uncordon NODE_NAME

오류: 노드당 최대 노드 수 한도 도달

클러스터의 모든 노드에서 노드당 최대 노드 수 한도에 도달하면 포드가 예약 불가능한 상태로 멈춥니다. 포드 이벤트 탭에서 Too many pods 문구가 포함된 메시지가 표시됩니다.

이 오류를 해결하려면 다음 단계를 수행합니다.

  1. Google Cloud 콘솔의 GKE 클러스터 세부정보에 있는 노드 탭에서 Maximum pods per node 구성을 확인합니다.

  2. 노드 목록을 가져옵니다.

    kubectl get nodes
    
  3. 각 노드에 대해 노드에서 실행 중인 포드 수를 확인합니다.

    kubectl get pods -o wide | grep NODE_NAME | wc -l
    
  4. 한도에 도달하면 새 노드 풀을 추가하거나 기존 노드 풀에 노드를 더 추가합니다.

문제: 클러스터 자동 확장 처리가 사용 설정된 상태로 최대 노드 풀 크기에 도달

클러스터 자동 확장 처리 구성에 따라 노드 풀이 최대 크기에 도달했으면 GKE에서 이 노드 풀로 예약되었을 포드에 대해 수직 확장이 트리거되지 않습니다. 이 노드 풀로 포드를 예약하려면 클러스터 자동 확장 처리 구성을 변경합니다.

문제: 클러스터 자동 확장 처리가 사용 중지된 상태로 최대 노드 풀 크기에 도달

노드 풀이 최대 노드 수에 도달했고 클러스터 자동 확장 처리가 사용 중지되어 있으면 GKE가 노드 풀로 포드를 예약할 수 없습니다. GKE가 클러스터 크기를 자동으로 조정할 수 있도록 노드 풀의 크기를 늘리거나 또는 클러스터 자동 확장 처리를 사용 설정합니다.

오류: 결합 해제된 PersistentVolumeClaims

Unbound PersistentVolumeClaims는 Pod가 결합되지 않은 PersistentVolumeClaim을 참조함을 나타냅니다. 이 오류는 PersistentVolume이 프로비저닝을 실패한 경우에 발생할 수 있습니다. PersistentVolumeClaim의 이벤트를 가져오고 실패를 검사하여 프로비저닝 실패를 확인할 수 있습니다.

이벤트를 가져오려면 다음 명령어를 실행합니다.

kubectl describe pvc STATEFULSET_NAME-PVC_NAME-0

다음을 바꿉니다.

  • STATEFULSET_NAME: StatefulSet 객체의 이름입니다.
  • PVC_NAME: PersistentVolumeClaim 객체의 이름입니다.

이는 PersistentVolume을 수동으로 사전 프로비저닝하고 PersistentVolumeClaim에 결합하는 중에 구성 오류가 있어도 발생할 수 있습니다.

이 오류를 해결하려면 볼륨을 다시 사전 프로비저닝해 보세요.

오류: 할당량 부족

GKE가 클러스터를 수직 확장할 수 있도록 프로젝트에 Compute Engine 할당량이 충분한지 확인합니다. GKE가 포드를 예약할 수 있도록 클러스터에 노드를 추가하려고 시도할 때 수직 확장으로 인해 프로젝트의 가용 할당량이 초과될 경우 scale.up.error.quota.exceeded 오류 메시지가 표시됩니다.

자세한 내용은 ScaleUp 오류를 참조하세요.

문제: 지원 중단된 API

클러스터의 부 버전에서 삭제된 지원 중단된 API를 사용 중이 아닌지 확인합니다. 자세한 내용은 기능 및 API 지원 중단을 참조하세요.

오류: 요청된 포드 포트에 사용 가능한 포트 없음

다음과 유사한 오류가 표시되면 같은 노드의 포드 여러 개에 hostPort 필드에 정의된 값과 동일한 값이 있을 가능성이 높습니다.

0/1 nodes are available: 1 node(s) didn't have free ports for the requested pod ports. preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.

포드를 hostPort에 바인딩하면 GKE에서 포드를 예약할 수 있는 위치가 제한됩니다. 각 hostIP, hostPort, protocol 조합이 고유해야 하기 때문입니다.

이 문제를 해결하려면 Kubernetes 권장사항을 따르고 hostPort 대신 NodePort를 사용하는 것이 좋습니다.

hostPort를 사용해야 하는 경우 포드의 매니페스트를 확인하고 hostPort에 정의한 고유한 값이 같은 노드의 모든 포드에 있는지 확인합니다.

다음 단계

  • 문서에서 문제의 해결 방법을 찾을 수 없는 경우 지원 받기에서 다음 주제에 관한 조언을 포함한 추가 도움을 받으세요.