排查 GKE Standard 节点池问题


本页面介绍如何解决 GKE Standard 模式节点池的问题。

如果您需要其他帮助,请与 Cloud Customer Care 联系。

节点池创建问题

本部分列出了在 Standard 集群中创建新节点池时可能出现的问题,并提供了有关如何解决这些问题的建议。

资源可用性导致节点池创建失败

当您在某个 Google Cloud 可用区中创建使用特定硬件的节点池,并且该可用区没有足够的硬件来满足您的要求时,会发生以下问题。

如需验证节点池创建是否由于某个可用区没有足够的资源而失败,请查看日志中是否有相关错误消息。

  1. 在 Google Cloud 控制台中打开 Logs Explorer。

    转到日志浏览器

  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 会继续尝试预配其余节点以满足原始请求。如需指示 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 中有 10 个挂接 NVIDIA A100 40GB GPU 的节点。根据 GPU 区域和可用区可用性表,此可用区支持 A100 GPU。为了避免在没有 10 个 GPU 机器可用时节点池创建失败,您可以使用尽力而为的预配。

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

即使 us-central1-c 中只有 5 个 GPU 可用,GKE 也会创建节点池。在随后的一段时间内,GKE 会尝试预配更多节点,直到节点池中有 10 个节点为止。

在节点池之间迁移工作负载

请按照以下说明将工作负载从一个节点池迁移到另一个节点池。如果要更改节点池中节点的机器属性,请参阅通过更改节点机器属性进行纵向扩缩

如何将 Pod 迁移到新节点池

如需将 Pod 迁移到新节点池,您必须执行以下操作:

  1. 封锁现有节点池:此操作会将现有节点池中的节点标记为无法安排。将它们标记为无法安排后,Kubernetes 会停止将新 Pod 安排到这些节点。

  2. 排空现有节点池:此操作会正常逐出正在现有节点池的节点上运行的工作负载。

这些步骤会导致在现有节点池中运行的 Pod 正常终止。Kubernetes 会将它们重新安排到其他可用的节点上。

为了确保 Kubernetes 正常终止您的应用,容器应该处理 SIGTERM 信号。使用此方法可以关闭与客户端的活跃连接,并干净地提交或回滚数据库事务。在 Pod 清单中,您可以使用 spec.terminationGracePeriodSeconds 字段指定 Kubernetes 必须等待多长时间才能停止 Pod 中的容器。默认值为 30 秒。 您可以在 Kubernetes 文档中详细了解终止 Pod

您可以使用 kubectl cordonkubectl drain 命令封锁和排空节点。

创建节点池并迁移工作负载

如需将工作负载迁移到新节点池,请创建新的节点池,然后封锁并排空现有节点池中的节点:

  1. 向集群添加节点池

    通过运行以下命令来验证新节点池已创建:

    gcloud container node-pools list --cluster CLUSTER_NAME
    
  2. 运行以下命令以查看 Pod 正在哪个节点上运行(请参阅 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 替换为上一个命令中的名称)。以下 shell 命令将遍历现有节点池中的每个节点,并将它们标记为无法安排:

    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 秒)内逐出 Pod,排空每个节点:

    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
    

    此外,您应该会看到 Pod 现正在新节点池中的节点上运行:

    kubectl get pods -o=wide
    
  8. 如果您不再需要现有节点池,请将其删除:

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

后续步骤

如果您需要其他帮助,请与 Cloud Customer Care 联系。