배포된 워크로드 문제 해결


이 페이지에서는 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이면 컨테이너가 사용하는 이미지를 이미지 레지스트리에서 로드할 수 없음을 나타냅니다.

Google Cloud 콘솔 또는 kubectl 명령줄 도구를 사용하여 이 문제를 확인할 수 있습니다.

콘솔

다음 단계를 수행합니다.

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

    워크로드로 이동

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

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

  4. 포드의 메뉴에서 이벤트 탭을 클릭합니다.

kubectl

포드의 컨테이너 이미지에 대한 자세한 정보를 보려면 다음 명령어를 실행합니다.

kubectl describe pod POD_NAME

문제: 이미지를 찾을 수 없음

이미지를 찾을 수 없는 경우 다음 단계를 완료합니다.

  1. 이미지 이름이 올바른지 확인합니다.
  2. 이미지의 태그가 올바른지 확인합니다. (:latest를 사용하거나 태그를 사용하지 않으면 최신 이미지를 가져올 수 있습니다.)
  3. 이미지에 전체 레지스트리 경로가 있으면 사용 중인 Docker 레지스트리에 있는지 확인합니다. 이미지 이름만 제공하는 경우, Docker Hub 레지스트리를 확인합니다.
  4. GKE Standard 클러스터에서 Docker 이미지를 수동으로 가져옵니다.

    1. SSH를 사용하여 노드에 연결합니다.

      예를 들어 SSH를 사용하여 VM에 연결하려면 다음 명령어를 실행합니다.

      gcloud compute ssh VM_NAME --zone=ZONE_NAME
      

      다음을 바꿉니다.

    2. /home/[USER]/.docker/config.json에서 구성 파일을 생성합니다.

      docker-credential-gcr configure-docker
      

      /home/[USER]/.docker/config.json의 구성 파일에 credHelpers 필드의 이미지 레지스트리가 포함되어 있는지 확인합니다. 예를 들어 다음 파일에는 asia.gcr.io, eu.gcr.io, gcr.io, marketplace.gcr.io, us.gcr.io에 호스팅된 이미지의 인증 정보가 포함되어 있습니다.

      {
      "auths": {},
      "credHelpers": {
        "asia.gcr.io": "gcr",
        "eu.gcr.io": "gcr",
        "gcr.io": "gcr",
        "marketplace.gcr.io": "gcr",
        "us.gcr.io": "gcr"
      }
      }
      
    3. 이미지를 가져옵니다.

      docker pull IMAGE_NAME
      

    이미지를 수동으로 가져오는 것이 작동하는 경우 포드에서 ImagePullSecrets를 지정해야 할 수도 있습니다. 포드는 자체 네임스페이스에 있는 이미지 가져오기 보안 비밀만을 참조할 수 있으므로 이 프로세스는 네임스페이스당 한 번 수행해야 합니다.

오류: 권한 거부됨

"permission denied" 또는 "no pull access" 오류가 발생하면 로그인되어 있고 이미지에 대한 액세스 권한이 있는지 확인합니다. 이미지를 호스팅하는 레지스트리에 따라 다음 방법 중 하나를 시도합니다.

Artifact Registry

이미지가 Artifact Registry에 있으면 노드 풀의 서비스 계정에 이미지가 포함된 저장소에 대한 읽기 액세스 권한이 필요합니다.

서비스 계정에 artifactregistry.reader 역할을 부여합니다.

gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
    --location=REPOSITORY_LOCATION \
    --member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
    --role="roles/artifactregistry.reader"

다음을 바꿉니다.

  • REPOSITORY_NAME: Artifact Registry 저장소의 이름입니다.
  • REPOSITORY_LOCATION: Artifact Registry 저장소의 리전입니다.
  • SERVICE_ACCOUNT_EMAIL: 노드 풀과 연결된 IAM 서비스 계정의 이메일 주소입니다.

Container Registry

이미지가 Container Registry에 있으면 노드 풀의 서비스 계정에 이미지가 포함된 Cloud Storage 버킷에 대한 읽기 액세스 권한이 필요합니다.

버킷에서 읽을 수 있도록 서비스 계정에 roles/storage.objectViewer 역할을 부여합니다.

gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
    --member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
    --role=roles/storage.objectViewer

다음을 바꿉니다.

  • SERVICE_ACCOUNT_EMAIL: 노드 풀과 연결된 서비스 계정의 이메일입니다. gcloud iam service-accounts list를 사용하여 프로젝트의 모든 서비스 계정을 나열할 수 있습니다.
  • BUCKET_NAME: 이미지가 포함된 Cloud Storage 버킷의 이름입니다. gcloud storage ls를 사용하여 프로젝트의 모든 버킷을 나열할 수 있습니다.

레지스트리 관리자가 Container Registry 대신 gcr.io 도메인에 대해 이미지를 저장하도록 Artifact Registry에서 gcr.io 저장소를 설정한 경우 Container Registry 대신 Artifact Registry에 대해 읽기 액세스 권한을 부여해야 합니다.

비공개 레지스트리

이미지가 비공개 레지스트리에 있으면 이미지에 액세스하기 위해 키가 필요할 수 있습니다. 자세한 내용은 Kubernetes 문서의 비공개 레지스트리 사용을 참조하세요.

오류 401 승인되지 않음: 비공개 Container Registry 저장소에서 이미지를 가져올 수 없음

비공개 Container Registry 저장소에서 이미지를 가져올 때 다음과 비슷한 오류가 발생할 수 있습니다.

gcr.io/PROJECT_ID/IMAGE:TAG: rpc error: code = Unknown desc = failed to pull and
unpack image gcr.io/PROJECT_ID/IMAGE:TAG: failed to resolve reference
gcr.io/PROJECT_ID/IMAGE]:TAG: unexpected status code [manifests 1.0]: 401 Unauthorized

Warning  Failed     3m39s (x4 over 5m12s)  kubelet            Error: ErrImagePull
Warning  Failed     3m9s (x6 over 5m12s)   kubelet            Error: ImagePullBackOff
Normal   BackOff    2s (x18 over 5m12s)    kubelet            Back-off pulling image

이 오류를 해결하려면 다음 단계를 완료하세요.

  1. 포드를 실행 중인 노드를 식별합니다.

    kubectl describe pod POD_NAME | grep "Node:"
    
  2. 이전 단계에서 식별한 노드에 스토리지 범위가 있는지 확인합니다.

    gcloud compute instances describe NODE_NAME \
        --zone=COMPUTE_ZONE --format="flattened(serviceAccounts[].scopes)"
    

    노드의 액세스 범위에는 최소한 다음 범위 중 하나 이상이 포함되어야 합니다.

    serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/devstorage.read_only
    serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/cloud-platform
    

    노드에 이러한 범위 중 하나가 포함되어 있지 않으면 노드 풀을 다시 만듭니다.

  3. 충분한 범위를 사용해서 노드가 포함된 노드 풀을 다시 만듭니다. 기존 노드는 수정할 수 없고, 올바른 범위를 사용해서 노드를 다시 만들어야 합니다.

    • 권장사항: gke-default 범위를 사용해서 새 노드 풀을 만듭니다.

      gcloud container node-pools create NODE_POOL_NAME \
          --cluster=CLUSTER_NAME \
          --zone=COMPUTE_ZONE \
          --scopes="gke-default"
      
    • 스토리지 범위만 사용해서 새 노드 풀을 만듭니다.

      gcloud container node-pools create NODE_POOL_NAME \
          --cluster=CLUSTER_NAME \
          --zone=COMPUTE_ZONE \
          --scopes="https://www.googleapis.com/auth/devstorage.read_only"
      

오류: 예약할 수 없는 포드

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는 노드가 사용하려 하는 포트가 이미 사용 중임을 나타냅니다.

이 문제를 해결하려면 spec: containers: ports: hostPort에서 Pod 사양의 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를 사용 중이 아닌지 확인합니다. 자세한 내용은 GKE 지원 중단을 참조하세요.

다음 단계

추가 지원이 필요하면 Cloud Customer Care에 문의하세요.