本页面介绍如何解决 GKE Standard 模式节点池的问题。
如果您需要其他帮助,请与 Cloud Customer Care 联系。节点池创建问题
本部分列出了在 Standard 集群中创建新节点池时可能出现的问题,并提供了有关如何解决这些问题的建议。
资源可用性导致节点池创建失败
当您在某个 Google Cloud 可用区中创建使用特定硬件的节点池,并且该可用区没有足够的硬件来满足您的要求时,会发生以下问题。
如需验证节点池创建是否由于某个可用区没有足够的资源而失败,请查看日志中是否有相关错误消息。
在 Google Cloud 控制台中打开 Logs Explorer。
在查询字段中,指定以下查询:
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 集群的名称。点击运行查询。
您可能会看到以下某条错误消息:
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 迁移到新节点池,您必须执行以下操作:
封锁现有节点池:此操作会将现有节点池中的节点标记为无法安排。将它们标记为无法安排后,Kubernetes 会停止将新 Pod 安排到这些节点。
排空现有节点池:此操作会正常逐出正在现有节点池的节点上运行的工作负载。
这些步骤会导致在现有节点池中运行的 Pod 正常终止。Kubernetes 会将它们重新安排到其他可用的节点上。
为了确保 Kubernetes 正常终止您的应用,容器应该处理 SIGTERM 信号。使用此方法可以关闭与客户端的活跃连接,并干净地提交或回滚数据库事务。在 Pod 清单中,您可以使用 spec.terminationGracePeriodSeconds
字段指定 Kubernetes 必须等待多长时间才能停止 Pod 中的容器。默认值为 30 秒。
您可以在 Kubernetes 文档中详细了解终止 Pod。
您可以使用 kubectl cordon
和 kubectl drain
命令封锁和排空节点。
创建节点池并迁移工作负载
如需将工作负载迁移到新节点池,请创建新的节点池,然后封锁并排空现有节点池中的节点:
向集群添加节点池。
通过运行以下命令来验证新节点池已创建:
gcloud container node-pools list --cluster CLUSTER_NAME
运行以下命令以查看 Pod 正在哪个节点上运行(请参阅
NODE
列):kubectl get pods -o=wide
获取现有节点池中的节点列表,并将
EXISTING_NODE_POOL_NAME
替换为名称:kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME
运行
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
(可选)更新现有节点池上运行的工作负载,以为标签
cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME
添加 nodeSelector,其中NEW_NODE_POOL_NAME
是新节点池的名称。这可以确保 GKE 将这些工作负载放置在新节点池中的节点上。通过在分配的正常终止时间段(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
替换为正常终止所需的时间。运行以下命令,查看现有节点池中的节点在节点列表中是否具有
SchedulingDisabled
状态:kubectl get nodes
此外,您应该会看到 Pod 现正在新节点池中的节点上运行:
kubectl get pods -o=wide
如果您不再需要现有节点池,请将其删除:
gcloud container node-pools delete default-pool --cluster CLUSTER_NAME