GKE Standard 노드 풀 문제 해결


이 페이지에서는 GKE Standard 모드 노드 풀의 문제를 해결하는 방법을 보여줍니다.

노드 풀 생성 문제

이 섹션에서는 Standard 클러스터에서 새 노드 풀을 만들 때 발생할 수 있는 문제를 나열하고 문제를 해결하는 방법에 대한 제안을 제공합니다.

리소스 가용성으로 인해 노드 풀 만들기 실패

요구 사항을 충족하는 데 사용할 수 있는 하드웨어가 충분하지 않은 Google Cloud 영역에서 특정 하드웨어로 노드 풀을 만들 때 다음 문제가 발생합니다.

영역에 리소스가 부족하여 노드 풀 만들기가 실패했는지 확인하려면 로그에서 관련 오류 메시지를 확인하세요.

  1. Google Cloud 콘솔의 로그 탐색기로 이동합니다.

    로그 탐색기로 이동

  2. 쿼리 필드에 다음 쿼리를 지정합니다.

    log_id(cloudaudit.googleapis.com/activity)
    resource.labels.cluster_name="CLUSTER_NAME"
    protoPayload.status.message:("ZONE_RESOURCE_POOL_EXHAUSTED" OR "does not have enough resources available to fulfill the request" OR "resource pool exhausted" OR "does not exist in zone")
    

    CLUSTER_NAME을 GKE 클러스터 이름으로 바꿉니다.

  3. 쿼리 실행을 클릭합니다.

다음 오류 메시지 중 하나가 표시될 수 있습니다.

  • resource pool exhausted
  • The zone does not have enough resources available to fulfill the request. Try a different zone, or try again later.
  • ZONE_RESOURCE_POOL_EXHAUSTED
  • ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS
  • Machine type with name '<code><var>MACHINE_NAME</var></code>' does not exist in zone '<code><var>ZONE_NAME</var></code>'

해결

이 문제를 해결하려면 다음을 제안을 시도해 보세요.

  • 선택한 Google Cloud 리전이나 영역에 필요한 특정 하드웨어가 있는지 확인합니다. Compute Engine 가용성 표를 사용하여 특정 영역이 특정 하드웨어를 지원하는지 확인합니다. 필요한 하드웨어 가용성을 높일 수 있는 노드에 대한 다른 Google Cloud 리전 또는 영역을 선택합니다.
  • 더 작은 머신 유형으로 노드 풀을 만듭니다. 총 컴퓨팅 용량이 동일하게 유지되도록 노드 풀의 노드 수를 늘립니다.
  • Compute Engine 용량 예약을 사용하여 미리 리소스를 예약합니다.
  • 다음 섹션에 설명된 대로 최선의 프로비저닝을 사용하여 노드 풀이 요청된 수 중에서 지정된 최소 노드 수를 프로비저닝할 수 있는 경우 해당 노드 풀이 성공적으로 생성됩니다.

최선의 프로비저닝

특정 하드웨어의 경우 최선의 프로비저닝을 사용하여 GKE가 지정된 최소 노드 수를 프로비저닝할 수 있는 경우 노드 풀을 성공적으로 만들도록 지정할 수 있습니다. GKE는 시간 경과에 따라 원래 요청을 충족하도록 나머지 노드를 프로비저닝하려고 계속 시도합니다. GKE에 최선의 프로비저닝을 사용하도록 지시하려면 다음 명령어를 사용합니다.

gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --node-locations=ZONE1,ZONE2,... \
    --machine-type=MACHINE_TYPE
    --best-effort-provision \
    --min-provision-nodes=MINIMUM_NODES

다음을 바꿉니다.

  • NODE_POOL_NAME: 새 노드 풀의 이름입니다.
  • ZONE1,ZONE2,...: 노드의 Compute Engine 영역입니다. 이 영역은 선택한 하드웨어를 지원해야 합니다.
  • MACHINE_TYPE: 노드의 Compute Engine 엔진 머신 유형입니다. 예를 들면 a2-highgpu-1g입니다.
  • MINIMUM_NODES: GKE가 노드 풀을 프로비저닝하고 성공적으로 만들기 위한 최소 노드 수입니다. 생략할 경우 기본값은 1입니다.

예를 들어 us-central1-c에 연결된 NVIDIA A100 40GB GPU가 있는 10개의 노드가 필요한 시나리오를 생각해 보십시오. GPU 리전 및 영역 가용성 표에 따라 이 영역은 A100 GPU를 지원합니다. GPU 머신 10개를 사용할 수 없는 경우 노드 풀 생성 실패를 방지하려면 최선의 프로비저닝을 사용합니다.

gcloud container node-pools create a100-nodes \
    --cluster=ml-cluster \
    --node-locations=us-central1-c \
    --num-nodes=10 \
    --machine-type=a2-highgpu-1g \
    --accelerator=type=nvidia-tesla-a100,count=1 \
    --best-effort-provision \
    --min-provision-nodes=5

GKE는 us-central1-c에서 5개의 GPU만 사용할 수 있는 경우에도 노드 풀을 만듭니다. 시간 경과에 따라 GKE는 노드 풀에 노드가 10개가 될 때까지 더 많은 노드를 프로비저닝하려고 시도합니다.

노드 풀 간 워크로드 마이그레이션

다음 안내에 따라 한 노드 풀에서 다른 노드 풀로 워크로드를 마이그레이션합니다. 노드 풀에 있는 노드의 머신 속성을 변경하려면 노드 머신 속성을 변경하여 수직 확장을 참조하세요.

포드를 새 노드 풀로 마이그레이션하는 방법

포드를 새 노드 풀로 마이그레이션하려면 다음을 수행해야 합니다.

  1. 기존 노드 풀 차단: 이 작업은 기존 노드 풀에 있는 노드를 예약 불가능으로 표시합니다. 이를 예약 불가능으로 표시한 다음에는 Kubernetes가 이러한 노드에 대한 새 포드 예약을 중지합니다.

  2. 기존 노드 풀 드레이닝: 이 작업은 기존 노드 풀의 노드에서 실행 중인 워크로드를 정상적으로 제거합니다.

이러한 단계를 수행하면 기존 노드 풀에서 실행 중인 포드가 정상적으로 종료됩니다. Kubernetes는 이 포드를 다른 사용 가능한 노드에 다시 예약합니다.

Kubernetes가 애플리케이션을 정상적으로 종료하도록 하려면, 컨테이너가 SIGTERM 신호를 처리해야 합니다. 이 방법을 사용하면 클라이언트에 대한 활성 연결을 닫고 데이터베이스 트랜잭션을 깔끔한 방식으로 커밋하거나 롤백할 수 있습니다. 포드 매니페스트에서 spec.terminationGracePeriodSeconds 필드를 사용하여 Kubernetes가 포드의 컨테이너를 중지하기 전에 대기해야 하는 시간을 지정할 수 있습니다. 기본값은 30초입니다. 포드 종료에 대한 상세 설명은 Kubernetes 문서를 참조하세요.

kubectl cordonkubectl drain 명령어를 사용하여 노드를 차단 및 드레이닝할 수 있습니다.

노드 풀 만들기 및 워크로드 마이그레이션

워크로드를 새 노드 풀로 마이그레이션하려면 새 노드 풀을 만든 다음 기존 노드 풀에서 노드를 차단 및 드레이닝합니다.

  1. 클러스터에 노드 풀을 추가합니다.

    다음 명령어를 실행하여 새 노드 풀이 생성되었는지 확인합니다.

    gcloud container node-pools list --cluster CLUSTER_NAME
    
  2. 다음 명령어를 실행하여 포드가 실행 중인 노드를 확인합니다 (NODE 열 참조).

    kubectl get pods -o=wide
    
  3. 기존 노드 풀의 노드 목록을 가져오고 EXISTING_NODE_POOL_NAME을 이름으로 바꿉니다.

    kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME
    
  4. kubectl cordon NODE 명령어를 실행합니다(NODE를 이전 명령어 이름으로 대체). 다음 셸 명령어는 기존 노드 풀에서 각 노드를 반복하고 예약 불가능으로 표시합니다.

    for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do
      kubectl cordon "$node";
    done
    
  5. 선택적으로 기존 노드 풀에서 실행되는 워크로드를 업데이트하여 cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME 라벨의 nodeSelector를 추가합니다. 여기서 NEW_NODE_POOL_NAME은 새 노드 풀의 이름입니다. 이렇게 하면 GKE가 새 노드 풀의 노드에 이러한 워크로드를 배치합니다.

  6. 10초의 할당된 단계적 종료 시간에 따라 포드를 제거하여 각 노드를 드레이닝합니다.

    for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do
      kubectl drain --force --ignore-daemonsets --delete-emptydir-data --grace-period=GRACEFUL_TERMINATION_SECONDS  "$node";
    done
    

    GRACEFUL_TERMINATION_PERIOD_SECONDS를 단계적 종료에 필요한 시간으로 바꿉니다.

  7. 다음 명령어를 실행하여 기존 노드 풀의 노드가 노드 목록에서 SchedulingDisabled 상태인지 확인합니다.

    kubectl get nodes
    

    또한 이제 새 노드 풀의 노드에서 포드가 실행 중임을 확인할 수 있습니다.

    kubectl get pods -o=wide
    
  8. 더 이상 필요하지 않으면 기존 노드 풀을 삭제합니다.

    gcloud container node-pools delete default-pool --cluster CLUSTER_NAME