了解 Google Kubernetes Engine (GKE) 的各个问题排查工具很有帮助,但看到它们一起用于解决实际问题可以帮助您巩固知识。
按照引导式示例操作,将 Google Cloud 控制台、kubectl
命令行工具、Cloud Logging 和 Cloud Monitoring 结合使用,以找出 OutOfMemory
(OOMKilled
) 错误的根本原因。
此示例适用于任何想要了解本系列文章中介绍的问题排查技巧的实际应用的人员,尤其是平台管理员和运维人员以及应用开发者。如需详细了解我们在Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务。
场景
假定您是 GKE 中运行的名为 product-catalog
的 Web 应用的一名值班工程师。
在您收到 Cloud Monitoring 发送的自动提醒时,便需要开始展开调查了:
Alert: High memory utilization for container 'product-catalog' in 'prod' cluster.
此提醒会告知您存在问题,并指出该问题与 product-catalog
工作负载有关。
在 Google Cloud 控制台中确认问题
首先,您需要大致了解工作负载,以确认问题。
- 在 Google Cloud 控制台中,前往工作负载页面,然后过滤出
product-catalog
工作负载。 - 查看 Pod 状态列。您看到的不是表明健康状况良好的
3/3
值,而是持续显示的2/3
值,而这是一种不健康的状态值。该值表示应用的某个 Pod 的状态不是Ready
。 - 您需要进一步调查,因而您点击
product-catalog
工作负载的名称以前往其详情页面。 - 在详情页面上,查看托管式 Pod 部分。您立即发现了一个问题:有 Pod 的
Restarts
列显示14
,这是一个异常高的数字。
如此高的重启次数证实了是该问题导致了应用不稳定,并表明有容器未通过健康检查或发生崩溃。
使用 kubectl
命令查找原因
既然您已了解应用反复重启的问题,那么就需要找出导致该问题的原因。kubectl describe
命令非常适合用来实现此目的。
您会获得不稳定 Pod 的确切名称:
kubectl get pods -n prod
输出如下所示:
NAME READY STATUS RESTARTS AGE product-catalog-d84857dcf-g7v2x 0/1 CrashLoopBackOff 14 25m product-catalog-d84857dcf-lq8m4 1/1 Running 0 2h30m product-catalog-d84857dcf-wz9p1 1/1 Running 0 2h30m
您描述了该不稳定的 Pod 以获取详细的事件记录:
kubectl describe pod product-catalog-d84857dcf-g7v2x -n prod
您查看了输出内容,并在
Last State
和Events
部分中找到线索:Containers: product-catalog-api: ... State: Waiting Reason: CrashLoopBackOff Last State: Terminated Reason: OOMKilled Exit Code: 137 Started: Mon, 23 Jun 2025 10:50:15 -0700 Finished: Mon, 23 Jun 2025 10:54:58 -0700 Ready: False Restart Count: 14 ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 25m default-scheduler Successfully assigned prod/product-catalog-d84857dcf-g7v2x to gke-cs-cluster-default-pool-8b8a777f-224a Normal Pulled 8m (x14 over 25m) kubelet Container image "us-central1-docker.pkg.dev/my-project/product-catalog/api:v1.2" already present on machine Normal Created 8m (x14 over 25m) kubelet Created container product-catalog-api Normal Started 8m (x14 over 25m) kubelet Started container product-catalog-api Warning BackOff 3m (x68 over 22m) kubelet Back-off restarting failed container
输出内容提供了两条关键线索:
- 首先,
Last State
部分显示容器已因Reason: OOMKilled
而终止,这表示它内存不足。Exit Code: 137
证实了这一原因,这是标准的 Linux 退出代码,表示进程因内存消耗过多而被终止。 - 其次,
Events
部分显示Warning: BackOff
事件以及相应的Back-off restarting failed container
消息。此消息证实了容器处于故障循环中,这是导致您之前看到的CrashLoopBackOff
状态的直接原因。
- 首先,
使用指标直观呈现行为
kubectl describe
命令会告知您发生了什么情况,但 Cloud Monitoring 可以显示您的环境在一段时间内的行为变化。
- 在 Google Cloud 控制台中,前往 Metrics Explorer。
- 选择
container/memory/used_bytes
指标。 - 您可以过滤输出以将结果范围缩小到针对特定的集群、命名空间和 Pod 名称。
该图表显现出一个明显的模式:最初内存用量稳步攀升,然后在容器因内存不足而被终止并重启后突然降至零。该直观证据证实了存在内存泄漏或内存限额不足的问题。
在日志中查找根本原因
现在,您知道容器内存不足,但仍不清楚具体原因。如要找出根本原因,您可以使用 Logs Explorer。
- 在 Google Cloud 控制台中,前往 Logs Explorer。
您可以编写查询,以过滤出特定容器自上次崩溃时间(您在
kubectl describe
命令的输出中看到的时间)之前片刻开始的日志内容:resource.type="k8s_container" resource.labels.cluster_name="example-cluster" resource.labels.namespace_name="prod" resource.labels.pod_name="product-catalog-d84857dcf-g7v2x" timestamp >= "2025-06-23T17:50:00Z" timestamp < "2025-06-23T17:55:00Z"
在日志中,您会发现每次崩溃前都有一系列重复的消息:
{ "message": "Processing large image file product-image-large.jpg", "severity": "INFO" }, { "message": "WARN: Memory cache size now at 248MB, nearing limit.", "severity": "WARNING" }
这些日志条目表明,应用正尝试通过将大型图片文件完全加载到内存中来处理这些文件,最终导致容器的内存限额耗尽。
发现结果
通过结合使用这些工具,您现已全面了解问题:
- 监控提醒通知您出现了问题。
- Google Cloud 控制台显示,该问题影响了用户(重启)。
kubectl
命令指出了重启的确切原因 (OOMKilled
)。- Metrics Explorer 直观呈现了一段时间内的内存泄漏变化情况。
- Logs Explorer 揭示了导致内存问题的具体行为。
现在,您可以开始实现解决方案了。您可以优化应用代码,以便更高效地处理大型文件;也可以在工作负载的 YAML 清单中暂时增加容器的内存限额(具体而言,即 spec.containers.resources.limits.memory
值),作为临时的解决方法。
后续步骤
如需有关解决特定问题的建议,请查看 GKE 的问题排查指南。
如果您在文档中找不到问题的解决方案,请参阅获取支持以获取进一步的帮助,包括以下主题的建议:
- 请与 Cloud Customer Care 联系,以提交支持请求。
- 通过在 StackOverflow 上提问并使用
google-kubernetes-engine
标记搜索类似问题,从社区获得支持。您还可以加入#kubernetes-engine
Slack 频道,以获得更多社区支持。 - 使用公开问题跟踪器提交 bug 或功能请求。