如果 Google Kubernetes Engine (GKE) 控制平面或节点池升级失败、卡住或导致意外的工作负载行为,您可能需要对该过程进行问题排查。及时更新控制平面和节点池对于安全性和性能至关重要,解决任何问题有助于确保环境保持稳定。
如需解决常见的升级问题,首先应监控集群升级过程。然后,您可以找到有关解决问题的建议:
对于希望诊断升级卡住或失败的根本原因、管理维护政策以及解决版本不兼容问题的平台管理员和运维人员,此信息非常重要。应用开发者可以找到有关解决升级后工作负载问题的指南,并了解工作负载配置(例如 PodDisruptionBudgets
)如何影响升级时长。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务。
监控集群升级流程
为了更有效地解决升级问题,请先了解升级过程中发生了什么情况。GKE 提供了多种工具,可让您了解此过程。
在 Google Cloud 控制台中,升级信息中心会提供项目范围内的视图,其中包含所有正在进行的集群升级、近期事件的时间轴,以及有关潜在阻碍因素(例如有效的维护排除项或即将弃用的版本)的警告。对于命令行或自动化检查,您可以使用 gcloud
container operations list
命令获取特定升级操作的状态。如需了解详情,请参阅了解集群升级情况。
如需进行更详细的调查,Cloud Logging 是您的主要信息来源。GKE 会在 Cloud Logging 中记录有关控制平面和节点池升级过程的详细信息。这包括跟踪主要升级操作的高级审核日志,以及更精细的日志(例如 Kubernetes 事件和来自节点组件的日志),这些日志可以显示有关特定错误的更多信息。
以下部分介绍了如何使用 Logs Explorer 或 gcloud CLI 查询这些日志。如需了解详情,请参阅检查升级日志。
通过审核日志识别升级操作
如果您不知道哪个升级操作失败,可以使用 GKE 审核日志。审核日志会跟踪管理操作,并提供有关升级何时启动及其最终状态的权威记录。在Logs Explorer中使用以下查询来查找相关操作。
事件类型 | 日志查询 |
---|---|
控制平面自动升级 |
resource.type="gke_cluster" protoPayload.methodName="google.container.internal.ClusterManagerInternal.UpdateClusterInternal" log_id("cloudaudit.googleapis.com/activity") protoPayload.metadata.operationType="UPGRADE_MASTER" resource.labels.cluster_name="CLUSTER_NAME" 将 此查询显示了目标控制平面版本和之前的控制平面版本。 |
控制平面手动升级 |
resource.type="gke_cluster" log_id("cloudaudit.googleapis.com/activity") protoPayload.response.operationType="UPGRADE_MASTER" resource.labels.cluster_name="CLUSTER_NAME"
|
节点池自动升级(仅限目标版本) |
resource.type="gke_nodepool" protoPayload.methodName="google.container.internal.ClusterManagerInternal.UpdateClusterInternal" log_id("cloudaudit.googleapis.com/activity") protoPayload.metadata.operationType="UPGRADE_NODES" resource.labels.cluster_name="CLUSTER_NAME" resource.labels.nodepool_name="NODEPOOL_NAME" 将 |
节点池手动升级 |
resource.type="gke_nodepool" protoPayload.methodName="google.container.v1.ClusterManager.UpdateNodePool" log_id("cloudaudit.googleapis.com/activity") protoPayload.response.operationType="UPGRADE_NODES" resource.labels.cluster_name="CLUSTER_NAME" resource.labels.nodepool_name="NODEPOOL_NAME" 如需查找之前的节点池版本,请检查 Kubernetes API 日志: resource.type="k8s_cluster" resource.labels.cluster_name="CLUSTER_NAME" protoPayload.methodName="nodes.patch" |
在 GKE 日志中查找详细的错误消息
在审核日志显示哪个操作失败以及失败时间后,您可以搜索同一时间段内来自 GKE 组件的更详细的错误消息。这些日志可以包含升级失败的具体原因,例如 PodDisruptionBudget
对象配置错误。
例如,在审核日志中发现失败的 UPGRADE_NODES
操作后,您可以使用其时间戳来缩小搜索范围。在Logs Explorer中,输入以下查询,然后使用时间范围选择器重点查看发生故障的时间:
resource.type="k8s_node"
resource.labels.cluster_name="CLUSTER_NAME"
resource.labels.node_name="NODE_NAME"
severity=ERROR
替换以下内容:
CLUSTER_NAME
:您的集群的名称。NODE_NAME
:您要检查是否存在错误的集群中节点的名称。
使用 gcloud CLI 查看升级事件
除了Logs Explorer之外,您还可以使用 gcloud CLI 命令查看升级事件。
如需查找控制平面升级,请运行以下命令:
gcloud container operations list --filter="TYPE=UPGRADE_MASTER"
输出类似于以下内容:
NAME: operation-1748588803271-cfd407a2-bfe7-4b9d-8686-9f1ff33a2a96
TYPE: UPGRADE_MASTER
LOCATION: LOCATION
TARGET: CLUSTER_NAME
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2025-05-30T07:06:43.271089972Z
END_TIME: 2025-05-30T07:18:02.639579287Z
此输出包括以下值:
LOCATION
:集群的 Compute Engine 区域或可用区(例如us-central1
或us-central1-a
)。CLUSTER_NAME
:您的集群的名称。
如需查找节点池升级,请运行以下命令:
gcloud container operations list --filter="TYPE=UPGRADE_NODES"
输出类似于以下内容:
NAME: operation-1748588803271-cfd407a2-bfe7-4b9d-8686-9f1ff33a2a96
TYPE: UPGRADE_NODES
LOCATION: LOCATION
TARGET: CLUSTER_NAME
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2025-05-30T07:06:43.271089972Z
END_TIME: 2025-05-30T07:18:02.639579287Z
示例:使用日志排查控制平面升级问题
以下示例展示了如何使用日志排查控制平面升级失败的问题:
在 Google Cloud 控制台中,前往 Logs Explorer 页面。
在查询窗格中,输入以下查询,过滤控制平面升级日志:
resource.type="gke_cluster" protoPayload.metadata.operationType=~"(UPDATE_CLUSTER|UPGRADE_MASTER)" resource.labels.cluster_name="CLUSTER_NAME"
将
CLUSTER_NAME
替换为您要调查的集群的名称。点击运行查询。
查看日志输出,了解以下信息:
确认升级已开始:查找您启动升级时附近最近的
UPGRADE_MASTER
事件。如果存在这些事件,则表明您或 GKE 已触发升级流程。验证版本:检查以下字段,确认之前的版本和目标版本:
protoPayload.metadata.previousMasterVersion
:显示升级之前的控制平面版本。protoPayload.metadata.currentMasterVersion
:显示 GKE 尝试将控制平面升级到的版本。例如,如果您打算升级到 1.30.1-gke.1234 版,但意外指定了 1.30.2-gke.4321(一个较新且可能与您的工作负载不兼容的版本),那么查看这两个字段会突出显示此差异。或者,如果
currentMasterVersion
字段在很长一段时间后仍显示旧版本,则表明升级未能应用新版本。
查找错误:检查是否有重复的
UPGRADE_MASTER
事件或其他错误消息。如果操作日志在未指示完成或失败的情况下停止,则此发现表示存在问题。
从日志中发现特定错误或行为后,您可以使用该信息在本指南中找到相应的解决方案。
排查节点池升级时间过长的问题
如果节点池升级所用的时间超出预期,请尝试以下解决方案:
- 检查 Pod 清单中的
terminationGracePeriodSeconds
值。此值定义了 Kubernetes 等待 Pod 正常关闭的最长时间。较高的值(例如几分钟)可能会显著延长升级时长,因为 Kubernetes 会等待每个 Pod 的完整时间段。如果此延迟导致问题,请考虑减小该值。 检查您的
PodDisruptionBudget
对象。当节点正在排空时,GKE 最多会等待一小时,以便正常逐出其工作负载。如果PodDisruptionBudget
对象过于严格,可能会导致正常逐出永远无法成功。在这种情况下,GKE 会使用整个一小时的宽限期来尝试排空节点,直到最终超时并强制升级继续进行。当多个节点都出现这种延迟时,就会导致整个集群升级缓慢。如需确认限制性PodDisruptionBudget
对象是否是升级缓慢的原因,请使用 Logs Explorer:在 Google Cloud 控制台中,前往 Logs Explorer 页面。
在查询窗格中,输入以下查询:
resource.type=("gke_cluster" OR "k8s_cluster") resource.labels.cluster_name="CLUSTER_NAME" protoPayload.response.message="Cannot evict pod as it would violate the pod's disruption budget." log_id("cloudaudit.googleapis.com/activity")
点击运行查询。
查看日志输出。如果
PodDisruptionBudget
对象是导致问题的原因,则输出类似于以下内容:resourceName: "core/v1/namespaces/istio-system/pods/POD_NAME/eviction" response: { @type: "core.k8s.io/v1.Status" apiVersion: "v1" code: 429 details: { causes: [ 0: { message: "The disruption budget istio-egressgateway needs 1 healthy pods and has 1 currently" reason: "DisruptionBudget" } ] } kind: "Status" message: "Cannot evict pod as it would violate the pod's disruption budget." metadata: { } reason: "TooManyRequests" status: "Failure" }
确认
PodDisruptionBudget
对象是原因所在后,列出所有PodDisruptionBudget
对象,并确保设置合适:kubectl get pdb --all-namespaces
输出类似于以下内容:
NAMESPACE NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE example-app-one one_pdb 3 0 1 12d
在此示例中,名为
one_pdb
的PodDisruptionBudget
需要至少三个可用的 Pod。由于在升级期间逐出 Pod 会导致只有两个 Pod 可用,因此该操作违反了预算,并导致升级停滞。如果您的
PodDisruptionBudget
对象按您希望的方式运行,则无需执行任何操作。如果不是,请考虑在升级窗口期间放宽PodDisruptionBudget
设置。
检查节点亲和性。如果可用节点与所需的标签不匹配,限制性规则会阻止将 Pod 重新调度到这些节点,从而减慢升级速度。在超额配置升级期间,此问题尤为严重,因为如果具有正确标签的节点没有足够的集群容量来托管新 Pod,节点亲和性可能会限制可同时升级的节点数量。
检查您是否使用了短期升级策略。 GKE 会对灵活启动节点以及在运行 GKE 1.32.2-gke.1652000 版或更高版本的集群上仅使用已排队的预配的节点使用短期升级策略。如果您使用此升级策略,升级操作最多可能需要 7 天时间。
检查您是否使用了延长时长的 Pod(适用于 Autopilot 集群)。在升级期间,GKE 必须先排空节点中的所有 Pod,然后才能完成升级流程。不过,在 GKE 发起的升级期间,GKE 不会逐出延长运行时间的 Pod,最长可达七天。此保护措施可防止节点被排空。GKE 仅在此期限结束后强制终止 Pod,而单个节点出现如此长达数天的延迟可能会导致 Autopilot 集群中更多节点升级延迟。
由于管理这些卷的生命周期需要时间,因此附加的持久卷可能会导致升级过程比平时更长。
检查集群自动升级状态。 如果原因是
SYSTEM_CONFIG
,则表示由于技术或业务原因,自动升级已暂停。如果您看到此原因,我们建议您仅在必要时执行手动升级。
排查节点池升级未完成的问题
有时,GKE 无法完成节点池升级,导致节点池仅部分升级。导致升级不完整的原因有多种:
- 升级已手动取消。
- 升级失败,原因可能是新节点无法注册、IP 地址用尽或资源配额不足等问题。
- GKE 已暂停升级。暂停升级可能是为了防止升级到存在已知问题的版本,也可能是在 Google 发起的某些维护期间。
- 如果您使用自动升级,则维护窗口在升级完成之前已结束。或者,维护排除期在升级完成之前开始。如需了解详情,请参阅维护窗口阻止节点更新完成。
当节点池部分升级时,节点会运行不同的版本。如需解决此问题并验证节点池中的所有节点是否都运行在同一版本上,请继续升级或回滚升级。
不过,超额配置升级策略和蓝绿升级策略与维护窗口的互动方式有所不同:
- 超额配置升级:如果升级操作在维护期之外运行,则会暂停。升级会在下一个预定的维护窗口自动恢复。
- 蓝绿升级:升级操作会一直持续到完成,即使超出维护窗口也是如此。蓝绿升级可提供对升级速度的精细控制,并具有批次和节点池过渡时间等功能,而额外的节点池有助于确保工作负载保持运行状态。
排查意外的自动升级行为
有时,集群自动升级可能不会按您预期的方式进行。以下部分将帮助您解决以下问题:
启用节点自动升级时,集群无法升级
如果您未停用节点自动升级,但未发生升级,请尝试以下解决方案:
如果您使用发布渠道,请验证节点自动升级是否未被阻止。对于已在发布渠道中注册的集群,
maintenancePolicy
是控制自动升级的主要方式。它可以阻止升级开始或中断正在进行的升级。有效的维护排除项可能会完全阻止升级,而维护窗口的时间可能会导致中断。检查您的maintenancePolicy
,确定以下任一设置是否是导致此问题的原因:gcloud container clusters describe CLUSTER_NAME \ --project PROJECT_ID \ --location LOCATION
替换以下内容:
CLUSTER_NAME
:要描述的节点池集群的名称。PROJECT_ID
:集群的项目 ID。LOCATION
:集群的 Compute Engine 区域或可用区(例如us-central1
或us-central1-a
)。
输出类似于以下内容:
… maintenancePolicy: maintenanceExclusions: - exclusionName: critical-event-q4-2025 startTime: '2025-12-20T00:00:00Z' endTime: '2026-01-05T00:00:00Z' scope: noUpgrades: true # This exclusion blocks all upgrades window: dailyMaintenanceWindow: startTime: 03:00 # Daily window at 03:00 UTC …
在输出中,查看
maintenancePolicy
部分,了解是否存在以下两种情况:- 如需查看升级是否被屏蔽,请查找具有
NO_MINOR_OR_NODE_UPGRADES
范围的有效maintenanceExclusion
。此设置通常会阻止 GKE 启动新的升级。 - 查看升级是否中断:检查
dailyMaintenanceWindow
或maintenanceExclusions
的时间表。如果升级运行时间超出预定窗口,GKE 会暂停升级,从而导致部分升级。如需详细了解部分升级,请参阅排查不完整的升级部分。
如需解决这些问题,您可以等待排除期结束、移除排除期,或调整维护窗口,以便为升级留出更多时间。
如果您不使用发布渠道,请验证是否仍为节点池启用了自动升级:
gcloud container node-pools describe NODE_POOL_NAME \ --cluster CLUSTER_NAME \ --location LOCATION
将
NODE_POOL_NAME
替换为要描述的节点池的名称。如果为相应节点池启用了节点池自动升级,则
autoUpgrade
字段中的输出如下所示:management: autoUpgrade: true
如果
autoUpgrade
设置为false
,或者该字段不存在,则启用自动升级。即使版本说明中提到了升级,升级也可能尚未发布到您的集群所在的区域或可用区。GKE 升级会在数天内(通常为四天或更长时间)逐步发布。升级到达您的区域或可用区后,只有在获得批准的维护窗口期间才会开始升级。例如,某项发布可能在发布的第一天就到达了集群的可用区,但集群的下一个维护窗口要到第七天才会出现。在这种情况下,GKE 不会在第七天之前升级集群。如需了解详情,请参阅 GKE 发布时间表。
未启用自动升级时,集群会自动升级
为了帮助您保持 GKE 环境的可靠性、可用性、安全性和性能,即使您不使用自动升级,GKE 也可能会自动升级您的集群。
出于以下几个关键原因,GKE 可能会绕过您的维护窗口、排除项或已停用的节点池自动升级功能,以执行必要的升级:
- 控制平面运行的 GKE 版本已达到支持终止日期的集群。如需确认您的集群是否即将达到支持终止日期,请参阅发布渠道的预计时间表。
- 集群中运行的 GKE 版本已达到支持终止日期的节点。
- 处于运行状态但长时间未显示任何活动的集群。例如,GKE 可能会认为没有 API 调用、没有网络流量且没有有效使用子网的集群已被放弃。
- 表现出持续不稳定状态且反复循环通过各种运行状态的集群。例如,状态在“正在运行”“已降级”“正在修复”或“已暂停”之间不断循环,但问题始终未得到解决。
如果您发现系统意外自动升级,并且担心此升级可能会对集群产生影响,请与 Cloud Customer Care 联系以获取帮助。
排查升级失败问题
如果升级失败,GKE 会生成错误消息。以下部分介绍了以下错误的原因及解决方法:
错误:kube-apiserver
不健康
有时,当您开始手动升级集群的 GKE 版本时,可能会看到以下错误消息:
FAILED: All cluster resources were brought up, but: component
"KubeApiserverReady" from endpoint "readyz of kube apiserver is not successful"
is unhealthy.
此消息会显示在 gcloud CLI 以及 gke_cluster
和 gke_nodepool
资源类型日志条目中。
如果某些用户部署的准入webhook阻止系统组件创建正常运行所需的宽松 RBAC 角色,就会出现此问题。
在控制平面升级期间,GKE 会重新创建 Kubernetes API 服务器 (kube-apiserver
) 组件。如果webhook阻止 API 服务器组件的 RBAC 角色,则 API 服务器将不会启动,并且集群升级也不会完成。即使 webhook 正常运行,也可能会导致集群升级失败,因为新创建的控制平面可能无法访问 webhook。
Kubernetes 会将默认系统 RBAC 角色与最新次要版本中的默认政策自动协调。系统角色的默认政策有时会在新的 Kubernetes 版本中发生变化。
为了执行此协调,GKE 会在集群中创建或更新 ClusterRole 和 ClusterRoleBinding。如果您的网络钩子因默认 RBAC 政策使用的权限范围而拦截或拒绝创建请求或更新请求,则 API 服务器无法在新的次要版本上运行。
如需确定失败的webhook,请检查 GKE 审核日志中是否具有包含以下信息的 RBAC 调用:
protoPayload.resourceName="RBAC_RULE"
protoPayload.authenticationInfo.principalEmail="system:apiserver"
在此输出中,RBAC_RULE
是 RBAC 角色的全名,例如 rbac.authorization.k8s.io/v1/clusterroles/system:controller:horizontal-pod-autoscaler
。
失败的webhook的名称以如下格式显示在日志中:
admission webhook WEBHOOK_NAME denied the request
如需解决此问题,请尝试以下解决方案:
- 检查您的 ClusterRole,确保它们不会过于严格。
您的政策不应阻止 GKE 创建或更新具有默认
system:
前缀的 ClusterRole 的请求。 - 调整网络钩子,不拦截用于创建和更新系统 RBAC 角色的请求。
- 停用网络钩子。
错误:DeployPatch 失败
有时,集群升级操作会失败,并显示以下错误:
DeployPatch failed
如果 Kubernetes 控制平面在 20 分钟内一直处于不健康状态,则可能会发生此错误。
此错误通常是暂时性的,因为控制平面会重试操作,直到成功为止。如果升级继续失败并显示此错误,请与 Cloud Customer Care 联系。
排查升级完成后出现的问题
如果您在升级完成后遇到意外行为,请参阅以下部分,了解针对以下常见问题的问题排查指南:
因破坏性更改而导致意外行为
如果升级成功完成,但您在升级后发现意外行为,请查看 GKE 版本说明,了解与集群升级到的版本相关的 bug 和破坏性更改。
标准集群升级后逐出的工作负载
如果满足以下所有条件,则集群升级后您的工作负载可能面临驱出的风险:
- 当集群的控制平面运行新的 GKE 版本时,系统工作负载需要更多空间。
- 现有节点没有足够的资源来运行新的系统工作负载和现有工作负载。
- 为集群停用了集群自动扩缩器。
如需解决此问题,请尝试以下解决方案:
配置“节点可分配”后,Pod 卡在 Pending
状态
如果您已配置节点可分配资源,则节点版本升级有时会导致处于 Running
状态的 Pod 卡在 Pending
状态。此更改通常是因为升级后的节点消耗的系统资源略有不同,或者因为重新调度的 Pod 现在必须在新的或修改后的节点上符合节点可分配的资源限制,这可能会受到更严格的条件限制。
如果您的 Pod 在升级后处于 Pending
状态,请尝试以下解决方案:
- 验证 Pod 的 CPU 和内存请求是否未超出其峰值使用量。如果 GKE 为开销预留了 CPU 和内存,则 Pod 无法请求这些资源。如果 Pod 请求的 CPU 或内存超出其使用量,则会阻止其他 Pod 请求这些资源,而且可能会导致集群利用率过低。如需了解详情,请参阅 Kubernetes 文档中的如何安排具有资源请求的 Pod。
- 考虑增加集群的大小。
- 如需验证升级是否是导致此问题的原因,请通过降级节点池来回滚升级。
- 配置集群以将 Kubernetes 调度器指标发送到 Cloud Monitoring,并查看调度器指标。 通过监控这些指标,您可以确定是否有足够的资源供 Pod 运行。
排查版本和兼容性问题
为了确保集群的稳定性和性能,您必须为集群的所有组件维护受支持的兼容版本。以下部分提供了有关如何识别和解决可能影响升级过程的版本控制和兼容性问题的指导。
检查控制平面和节点版本是否不兼容
控制平面与节点之间的版本偏差可能会导致集群不稳定。GKE 版本倾斜政策指出,控制平面仅与最多比其低两个次要版本的节点兼容。例如,1.19 控制平面可与 1.19、1.18 和 1.17 节点搭配使用。
如果您的节点不在支持的窗口期内,则可能会遇到严重的兼容性问题。这些问题通常与 API 相关;例如,旧节点上的工作负载可能使用在较新的控制平面中已弃用或移除的 API 版本。这种不兼容性还可能导致更严重的故障,例如网络路径中断,如果某个不兼容的工作负载中断了通信,则会导致节点无法向集群注册。
GKE 团队会代表您定期升级集群控制平面。控制平面将升级到较新的 Kubernetes 稳定版本。为确保节点与升级后的控制平面保持兼容,您还必须使节点保持最新状态。默认情况下,GKE 会处理此升级,因为集群的节点已启用自动升级,我们建议您不要将其停用。如果集群的节点已停用自动升级,并且您未手动升级这些节点,则控制平面最终会与节点不兼容。
如需确认控制平面和节点版本是否不兼容,请检查集群的控制平面和节点池正在运行的 Kubernetes 版本:
gcloud container clusters describe CLUSTER_NAME \
--project PROJECT_ID \
--location LOCATION
替换以下内容:
CLUSTER_NAME
:要描述的节点池集群的名称。PROJECT_ID
:集群的项目 ID。LOCATION
:集群的 Compute Engine 区域或可用区(例如us-central1
或us-central1-a
)。
输出类似于以下内容:
…
currentMasterVersion: 1.32.3-gke.1785003
…
currentNodeVersion: 1.26.15-gke.1090000
…
在此示例中,控制平面版本与节点池版本不兼容。
要解决此问题,请手动将节点池版本升级到与控制平面兼容的版本。
如果您担心升级过程会导致受影响节点上运行的工作负载出现中断情况,请完成以下步骤,将您的工作负载迁移到新节点池:
- 使用兼容版本创建新节点池。
- 封锁现有节点池的节点。
- 可选:更新现有节点池上运行的工作负载,以为标签
cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME
添加 nodeSelector。将NEW_NODE_POOL_NAME
替换为新节点池的名称。此操作可以确保 GKE 将这些工作负载放置在新节点池中的节点上。 - 排空现有节点池。
- 检查工作负载是否在新节点池中成功运行。 如果是,您可以删除旧节点池。如果您发现工作负载中断,请通过解除现有节点池中的节点封锁并排空新节点,重新安排现有节点上的工作负载。
节点 CPU 使用率高于预期
您可能会遇到一些节点的 CPU 使用率高于正在运行的 Pod 的预期使用率的问题。
如果您使用手动升级,并且您的集群或节点尚未升级到受支持的版本,则可能会发生此问题。查看版本说明,确保您使用的版本可用且受支持。
后续步骤
如果您在文档中找不到问题的解决方案,请参阅获取支持以获取进一步的帮助,包括以下主题的建议:
- 请与 Cloud Customer Care 联系,以提交支持请求。
- 通过在 StackOverflow 上提问并使用
google-kubernetes-engine
标记搜索类似问题,从社区获得支持。您还可以加入#kubernetes-engine
Slack 频道,以获得更多社区支持。 - 使用公开问题跟踪器提交 bug 或功能请求。