本页面介绍如何解决 Google Kubernetes Engine (GKE) Autopilot 集群的问题。
集群问题
无法创建集群:已注册 0 个节点
您在尝试通过已停用或没有所需权限的 IAM 服务账号创建 Autopilot 集群时会发生以下问题。集群创建失败,并显示以下错误消息:
All cluster resources were brought up, but: only 0 nodes out of 2 have registered.
如需解决此问题,请执行以下操作:
检查默认 Compute Engine 服务账号或您要使用的自定义 IAM 服务账号是否已停用:
gcloud iam service-accounts describe SERVICE_ACCOUNT
将
SERVICE_ACCOUNT
替换为服务账号电子邮件地址,例如my-iam-account@my-first-project.iam.gserviceaccount.com
。如果服务账号已停用,则输出类似于以下内容:
disabled: true displayName: my-service-account email: my-service-account@my-project.iam.gserviceaccount.com ...
如果服务账号已停用,请启用它:
gcloud iam service-accounts enable SERVICE_ACCOUNT
如果在启用该服务账号后仍然出现该错误,请向该服务账号授予 GKE 所需的最低权限:
gcloud projects add-iam-policy-binding PROJECT_ID \
--member "serviceAccount:SERVICE_ACCOUNT" \
--role roles/container.defaultNodeServiceAccount
当集群有 0 个节点时,命名空间卡在终止状态
当您在集群缩减至零个节点后删除集群中的命名空间时,会出现以下问题。metrics-server
组件无法接受命名空间删除请求,因为该组件没有副本。
如需诊断此问题,请运行以下命令:
kubectl describe ns/NAMESPACE_NAME
将 NAMESPACE_NAME
替换为命名空间的名称。
输出如下所示:
Discovery failed for some groups, 1 failing: unable to retrieve the complete
list of server APIs: metrics.k8s.io/v1beta1: the server is currently unable to
handle the request
如需解决此问题,请扩容任何工作负载以触发 GKE 来创建新节点。节点准备就绪后,命名空间删除请求会自动完成。在 GKE 删除命名空间后,请缩减工作负载。
扩缩问题
节点纵向扩容失败:Pod 存在不被安排的风险
当您在Google Cloud 项目中停用串行端口日志记录功能时,会出现以下问题。GKE Autopilot 集群需要串行端口日志记录功能才能有效调试节点问题。如果停用串行端口日志记录功能,则 Autopilot 无法预配节点来运行工作负载。
Kubernetes 事件日志中的错误消息类似于以下内容:
LAST SEEN TYPE REASON OBJECT MESSAGE
12s Warning FailedScaleUp pod/pod-test-5b97f7c978-h9lvl Node scale up in zones associated with this pod failed: Internal error. Pod is at risk of not being scheduled
通过实施 compute.disableSerialPortLogging
限制条件的组织政策,可以在组织级层停用串行端口日志记录功能。您也可以在项目或虚拟机 (VM) 实例级层停用串行端口日志记录功能。
如需解决此问题,请执行以下操作:
- 要求您的 Google Cloud 组织政策管理员在您的 Autopilot 集群中移除项目中的
compute.disableSerialPortLogging
限制条件。 - 如果您没有强制执行此限制条件的组织政策,请尝试在项目元数据中启用串行端口日志记录。此操作需要
compute.projects.setCommonInstanceMetadata
IAM 权限。
节点纵向扩容失败:GCE 资源不足
如果您的工作负载请求的资源超过该 Compute Engine 区域或可用区中可供使用的资源,则会出现以下问题。您的 Pod 可能会保持 Pending
状态。
检查您的 Pod 事件:
kubectl events --for='pod/POD_NAME' --types=Warning
将
RESOURCE_NAME
替换为待处理 Kubernetes 资源的名称。例如pod/example-pod
。输出类似于以下内容:
LAST SEEN TYPE REASON OBJECT Message 19m Warning FailedScheduling pod/example-pod gke.io/optimize-utilization-scheduler 0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling. 14m Warning FailedScheduling pod/example-pod gke.io/optimize-utilization-scheduler 0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling. 12m (x2 over 18m) Warning FailedScaleUp cluster-autoscaler Node scale up in zones us-central1-f associated with this pod failed: GCE out of resources. Pod is at risk of not being scheduled. 34s (x3 over 17m) Warning FailedScaleUp cluster-autoscaler Node scale up in zones us-central1-b associated with this pod failed: GCE out of resources. Pod is at risk of not being scheduled.
如需解决此问题,请尝试执行以下操作:
- 在其他区域或可用区中部署 Pod。如果您的 Pod 具有可用区级限制(例如拓扑选择器),请尽可能移除该限制。如需了解相关说明,请参阅将 GKE Pod 放置在特定的可用区中。
- 在其他区域中创建集群并重试部署。
- 尝试使用其他计算类。由较小的 Compute Engine 机器类型提供支持的计算类更有可能具有可用资源。例如,Autopilot 的默认机器类型具有最高可用性。如需查看计算类和相应机器类型的列表,请参阅何时使用特定计算类。
- 如果您运行 GPU 工作负载,则请求的 GPU 可能在您的节点位置不可用。请尝试在其他位置部署工作负载或请求其他类型的 GPU。
如需避免将来发生由资源可用性导致的纵向扩容问题,请考虑以下方法:
- 使用 Kubernetes PriorityClass 在集群中一致地预配额外的计算容量。如需了解详情,请参阅预配额外的计算容量以实现快速 Pod 扩缩。
- 将 Compute Engine 容量预留与性能或加速器计算类搭配使用。如需了解详情,请参阅使用预留的可用区级资源。
节点无法纵向扩容:已超出 Pod 可用区级资源
当 Autopilot 未在特定可用区为 Pod 预配新节点时,会发生以下问题,因为新节点会违反资源限制。
日志中的错误消息类似于以下内容:
"napFailureReasons": [
{
"messageId": "no.scale.up.nap.pod.zonal.resources.exceeded",
...
此错误指的是 noScaleUp
事件,其中节点自动预配功能未为可用区中的 Pod 预配任何节点组。
如果遇到此错误,请确认以下内容:
- 您的 Pod 具有足够的内存和 CPU。
- Pod IP 地址 CIDR 范围足够大,可以支持您预期的集群大小上限。
工作负载问题
工作负载因临时存储错误而卡住
如果您的 Pod 临时存储请求超过 GKE 1.28.6-gke.1317000 版及更高版本中的 Autopilot 最大值 10GiB,GKE 将不会创建 Pod。
如需诊断此问题,请描述工作负载控制器,例如 Deployment 或 Job:
kubectl describe CONTROLLER_TYPE/CONTROLLER_NAME
替换以下内容:
CONTROLLER_TYPE
:工作负载控制器的类型,如replicaset
或daemonset
。如需查看控制器类型列表,请参阅工作负载管理。CONTROLLER_NAME
:卡住的工作负载的名称。
如果由于临时存储请求超出最大值而未创建 Pod,则输出类似于以下内容:
# lines omitted for clarity
Events:
{"[denied by autogke-pod-limit-constraints]":["Max ephemeral-storage requested by init containers for workload '' is higher than the Autopilot maximum of '10Gi'.","Total ephemeral-storage requested by containers for workload '' is higher than the Autopilot maximum of '10Gi'."]}
如需解决此问题,请更新您的临时存储请求,以使工作负载容器和 webhook 注入的容器所请求的临时存储总量小于或等于允许的最大值。如需详细了解最大值,请参阅 Autopilot 中的资源请求以了解正确的工作负载配置。
Pod 卡滞在“待处理”状态
如果您为 Pod 选择了特定节点,但 Pod 和 DaemonSet 中必须在该节点上运行的资源请求总和超过该节点的可分配容量上限,则 Pod 可能会卡在 Pending
状态。这可能会导致您的 Pod 变为 Pending
状态并保持未安排状态。
为避免此问题,请评估已部署的工作负载的大小,以确保它们不超过受支持的 Autopilot 资源请求上限。
您还可以尝试在安排常规工作负载 Pod 之前安排 DaemonSet。
特定节点上的工作负载性能持续不可靠
在 GKE 1.24 及更高版本中,如果特定节点上的工作负载持续出现中断、崩溃或类似不可靠的行为,您可以使用以下命令封锁有问题的节点,从而将此节点告知 GKE:
kubectl drain NODE_NAME --ignore-daemonsets
将 NODE_NAME
替换为有问题的节点的名称。您可以通过运行 kubectl get nodes
找到节点名称。
GKE 会执行以下操作:
- 从节点逐出现有工作负载并停止在该节点上调度工作负载。
- 在其他节点上自动重新创建由控制器(例如 Deployment 或 StatefulSet)管理的任何被逐出的工作负载。
- 终止保留在节点上的所有工作负载,并随着时间的推移修复或重新创建节点。
- 如果您使用 Autopilot,GKE 会立即关闭并替换节点,并忽略任何已配置的 PodDisruptionBudget。
Pod 在空集群上进行调度所花的时间超过预期时间
当您将工作负载部署到没有其他工作负载的 Autopilot 集群时,会发生此事件。Autopilot 集群会从零个可用节点开始,如果集群为空,则缩减至零个节点以避免集群中有未使用的计算资源。在具有零个节点的集群中部署工作负载会触发纵向扩容事件。
如果您遇到这种情况,则 Autopilot 会按预期运行,无需执行任何操作。新节点启动后,您的工作负载将按预期部署。
检查您的 Pod 是否正在等待新节点:
描述待处理 Pod:
kubectl describe pod POD_NAME
将
POD_NAME
替换为待处理 Pod 的名称。检查输出的
Events
部分。如果 Pod 正在等待新节点,则输出类似于以下内容:Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 11s gke.io/optimize-utilization-scheduler no nodes available to schedule pods Normal TriggeredScaleUp 4s cluster-autoscaler pod triggered scale-up: [{https://www.googleapis.com/compute/v1/projects/example-project/zones/example-zone/instanceGroups/gk3-example-cluster-pool-2-9293c6db-grp 0->1 (max: 1000)} {https://www.googleapis.com/compute/v1/projects/example-project/zones/example-zone/instanceGroups/gk3-example-cluster-pool-2-d99371e7-grp 0->1 (max: 1000)}]
TriggeredScaleUp
事件显示您的集群正在从零个节点纵向扩容到运行已部署的工作负载所需的节点数量。
系统 Pod 无法在空集群上进行调度
当您自己的工作负载都未在集群中运行时,就会发生此事件,从而导致集群缩减至零个节点。Autopilot 集群会从零个可用节点开始,如果您未在集群中运行任何工作负载,则缩减至零个节点。此行为可最大限度地减少集群中浪费的计算资源。
当集群缩减至零个节点时,GKE 系统工作负载将不会调度,并保持 Pending
状态。这是预期行为,无需采取任何措施。下次将工作负载部署到集群时,GKE 会扩容集群,且待处理的系统 Pod 将在这些节点上运行。
如需检查系统 Pod 是否因集群为空而处于待处理状态,请执行以下操作:
检查集群是否具有任何节点。
kubectl get nodes
输出如下所示,表明集群没有节点:
No resources found
检查系统 Pod 的状态:
kubectl get pods --namespace=kube-system
输出类似于以下内容:
NAME READY STATUS RESTARTS AGE antrea-controller-horizontal-autoscaler-6d97f7cf7c-ngfd2 0/1 Pending 0 9d egress-nat-controller-84bc985778-6jcwl 0/1 Pending 0 9d event-exporter-gke-5c5b457d58-7njv7 0/2 Pending 0 3d5h event-exporter-gke-6cd5c599c6-bn665 0/2 Pending 0 9d konnectivity-agent-694b68fb7f-gws8j 0/2 Pending 0 3d5h konnectivity-agent-7d659bf64d-lp4kt 0/2 Pending 0 9d konnectivity-agent-7d659bf64d-rkrw2 0/2 Pending 0 9d konnectivity-agent-autoscaler-5b6ff64fcd-wn7fw 0/1 Pending 0 9d konnectivity-agent-autoscaler-cc5bd5684-tgtwp 0/1 Pending 0 3d5h kube-dns-65ccc769cc-5q5q7 0/5 Pending 0 3d5h kube-dns-7f7cdb9b75-qkq4l 0/5 Pending 0 9d kube-dns-7f7cdb9b75-skrx4 0/5 Pending 0 9d kube-dns-autoscaler-6ffdbff798-vhvkg 0/1 Pending 0 9d kube-dns-autoscaler-8b7698c76-mgcx8 0/1 Pending 0 3d5h l7-default-backend-87b58b54c-x5q7f 0/1 Pending 0 9d metrics-server-v1.31.0-769c5b4896-t5jjr 0/1 Pending 0 9d
检查系统 Pod 处于
Pending
状态的原因:kubectl describe pod --namespace=kube-system SYSTEM_POD_NAME
将
SYSTEM_POD_NAME
替换为上一个命令的输出中任何系统 Pod 的名称。输出类似于以下内容:
... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 4m35s (x27935 over 3d5h) default-scheduler no nodes available to schedule pods ...
在输出中,
FailedScheduling
事件的Message
字段中的no nodes available to schedule pods
值表示系统 Pod 未安排,因为集群为空。
尝试从 GKE Autopilot 中的 Pod 运行 tcpdump 时与权限相关的错误
禁止访问 GKE Autopilot 集群中的底层节点。因此,需要在 Pod 中运行 tcpdump
实用程序,然后使用 kubectl cp 命令进行复制。如果您通常从 GKE Autopilot 集群的 Pod 中运行 tcpdump 实用程序,则可能会看到以下错误:
tcpdump: eth0: You don't have permission to perform this capture on that device
(socket: Operation not permitted)
这是因为默认情况下,GKE Autopilot 会将丢弃 NET_RAW
功能的安全上下文应用于所有 Pod,以缓解潜在漏洞。例如:
apiVersion: v1
kind: Pod
metadata:
labels:
app: tcpdump
name: tcpdump
spec:
containers:
- image: nginx
name: nginx
resources:
limits:
cpu: 500m
ephemeral-storage: 1Gi
memory: 2Gi
requests:
cpu: 500m
ephemeral-storage: 1Gi
memory: 2Gi
securityContext:
capabilities:
drop:
- NET_RAW
作为解决方案,如果您的工作负载需要 NET_RAW
功能,则可以重新启用它:
将
NET_RAW
功能添加到 Pod 的 YAML 规范的securityContext
部分:securityContext: capabilities: add: - NET_RAW
从 Pod 中运行
tcpdump
:tcpdump port 53 -w packetcap.pcap tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
使用
kubectl cp
命令将其复制到本地机器以供进一步分析:kubectl cp POD_NAME:/PATH_TO_FILE/FILE_NAME/PATH_TO_FILE/FILE_NAME
使用
kubectl exec
运行tcpdump
命令以执行网络数据包捕获并重定向输出:kubectl exec -it POD_NAME -- bash -c "tcpdump port 53 -w -" > packet-new.pcap
后续步骤
如果您在文档中找不到问题的解决方案,请参阅获取支持以获取进一步的帮助,包括以下主题的建议:
- 请与 Cloud Customer Care 联系,以提交支持请求。
- 通过在 StackOverflow 上提问,并使用
google-kubernetes-engine
标记搜索类似问题,来从社区获得支持。您还可以加入#kubernetes-engine
Slack 频道,以获得更多社区支持。 - 使用公开问题跟踪器提交 bug 或功能请求。