总结:问题排查场景示例


了解 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 控制台中确认问题

首先,您需要大致了解工作负载,以确认问题。

  1. 在 Google Cloud 控制台中,前往工作负载页面,然后过滤出 product-catalog 工作负载。
  2. 查看 Pod 状态列。您看到的不是表明健康状况良好的 3/3 值,而是持续显示的 2/3 值,而这是一种不健康的状态值。该值表示应用的某个 Pod 的状态不是 Ready
  3. 您需要进一步调查,因而您点击 product-catalog 工作负载的名称以前往其详情页面。
  4. 在详情页面上,查看托管式 Pod 部分。您立即发现了一个问题:有 Pod 的 Restarts 列显示 14,这是一个异常高的数字。

如此高的重启次数证实了是该问题导致了应用不稳定,并表明有容器未通过健康检查或发生崩溃。

使用 kubectl 命令查找原因

既然您已了解应用反复重启的问题,那么就需要找出导致该问题的原因。kubectl describe 命令非常适合用来实现此目的。

  1. 您会获得不稳定 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
    
  2. 您描述了该不稳定的 Pod 以获取详细的事件记录:

    kubectl describe pod product-catalog-d84857dcf-g7v2x -n prod
    
  3. 您查看了输出内容,并在 Last StateEvents 部分中找到线索:

    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 可以显示您的环境在一段时间内的行为变化。

  1. 在 Google Cloud 控制台中,前往 Metrics Explorer
  2. 选择 container/memory/used_bytes 指标。
  3. 您可以过滤输出以将结果范围缩小到针对特定的集群、命名空间和 Pod 名称。

该图表显现出一个明显的模式:最初内存用量稳步攀升,然后在容器因内存不足而被终止并重启后突然降至零。该直观证据证实了存在内存泄漏或内存限额不足的问题。

在日志中查找根本原因

现在,您知道容器内存不足,但仍不清楚具体原因。如要找出根本原因,您可以使用 Logs Explorer。

  1. 在 Google Cloud 控制台中,前往 Logs Explorer
  2. 您可以编写查询,以过滤出特定容器自上次崩溃时间(您在 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"
    
  3. 在日志中,您会发现每次崩溃前都有一系列重复的消息:

    {
      "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 值),作为临时的解决方法。

后续步骤