排查 GKE 中缺少日志的问题

Google Kubernetes Engine (GKE) 中的日志记录流水线出现问题可能会导致集群日志无法显示在 Cloud Logging 中,从而妨碍您进行监控和调试。

本文档介绍了如何验证配置和权限、解决资源和性能问题、调查过滤器和应用行为,以及解决影响日志的平台或服务问题。

对于负责维护集群可观测性的平台管理员和运维人员,以及使用 Cloud Logging 排查 GKE 运维问题的任何人员,此信息都非常重要。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务

如需详细了解如何使用日志排查工作负载和集群问题,请参阅使用 Cloud Logging 进行历史分析

按症状查找解决方案

如果您发现了与缺少日志相关的特定症状,请使用下表查找问题排查建议:

类别 症状或观察结果 可能的原因 问题排查步骤
配置 项目中的任何集群的日志都不可见。 系统对项目停用了 Cloud Logging API。 验证 Cloud Logging API 状态
特定集群中缺少日志,或者仅缺少某些日志类型。 系统对所需的日志类型停用了集群级日志记录。 验证集群日志记录配置
特定节点池中的节点缺少日志。 节点池的节点缺少所需的访问权限范围。 验证节点池访问权限范围
日志记录代理日志中显示权限错误(401403)。 节点的服务账号缺少所需的权限。 验证节点服务账号权限
资源和性能 日志间歇性缺失,或者您看到 RESOURCE_EXHAUSTED 错误。 项目超出了 Cloud Logging API 写入配额。 调查 Cloud Logging API 配额用量
缺少特定节点的某些日志,通常是在高流量或高负载期间。 节点超出日志记录代理吞吐量限制,或者缺少处理日志所需的资源(CPU 或内存)。 调查节点吞吐量和资源用量
过滤和应用行为 始终缺少与特定模式匹配的特定日志。 Cloud Logging 中的日志排除过滤条件意外丢弃了日志。 调查日志排除过滤条件
容器中的日志严重延迟或仅在容器退出后显示。 应用的输出完全缓冲,通常是由于通过管道输送 stdout 调查容器日志缓冲和延迟问题
预期日志未显示在搜索结果中。 Logs Explorer 中的查询过滤条件可能过于严格。 调查 Logs Explorer 查询
无法从特定应用 Pod 看到任何日志,但存在其他集群日志。 容器内的应用未写入 stdoutstderr 调查应用特有的日志记录行为
平台和服务 特定日期之前的日志不会显示。 日志已超过保留期限且已被 Cloud Logging 删除。 调查日志保留期限
多个项目或集群中出现大范围的日志丢失或延迟。 Cloud Logging 服务问题或注入延迟。 调查 Cloud Logging 服务问题和延迟
日志记录问题与集群版本限制有关。 GKE 版本不受支持。 调查集群版本

使用自动化诊断工具

以下部分介绍了可自动检查集群是否存在常见配置错误并帮助调查复杂问题的工具。

使用 gcpdiag 调试 GKE 日志记录问题

如果您的 GKE 集群缺少日志或是获取的日志不完整,可使用 gcpdiag 工具进行问题排查。

gcpdiag 是一种开源工具,不是官方支持的 Google Cloud 产品。您可以使用 gcpdiag 工具来帮助识别和修复 Google Cloud项目问题。如需了解详情,请参阅 GitHub 上的 gcpdiag 项目

如果 GKE 集群中的日志缺失或不完整,请重点检查以下核心配置设置,调查潜在原因:

  • 项目级日志记录:确保托管 GKE 集群的 Google Cloud项目已启用 Cloud Logging API。
  • 集群级日志记录:验证是否在 GKE 集群的配置中明确启用了日志记录。
  • 节点池权限:确认集群节点池中的节点已启用 Cloud Logging Write 范围,从而允许它们发送日志数据。
  • 服务账号权限:验证节点池使用的服务账号是否具有与 Cloud Logging 交互所需的 IAM 权限。具体而言,roles/logging.logWriter 角色通常是必需的。
  • Cloud Logging API 写入配额:验证指定时间范围内未超出 Cloud Logging API 写入配额。

Google Cloud 控制台

  1. 完成然后复制以下命令。
  2. gcpdiag runbook gke/logs \
        --parameter project_id=PROJECT_ID \
        --parameter name=CLUSTER_NAME \
        --parameter location=LOCATION
  3. 打开 Google Cloud 控制台并激活 Cloud Shell。
  4. 打开 Cloud 控制台
  5. 粘贴复制的命令。
  6. 运行 gcpdiag 命令以下载 gcpdiag Docker 映像,然后执行诊断检查。如果适用,请按照输出说明修复失败的检查。

Docker

您可以使用封装容器运行 gcpdiag,以在 Docker 容器中启动 gcpdiag。必须安装 Docker 或 Podman

  1. 在本地工作站上复制并运行以下命令。
    curl https://gcpdiag.dev/gcpdiag.sh >gcpdiag && chmod +x gcpdiag
  2. 执行 gcpdiag 命令:
    ./gcpdiag runbook gke/logs \
        --parameter project_id=PROJECT_ID \
        --parameter name=CLUSTER_NAME \
        --parameter location=LOCATION

查看此 Runbook 的可用参数

替换以下内容:

  • PROJECT_ID:资源所在项目的 ID。
  • CLUSTER_NAME:GKE 集群的名称。
  • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。

实用标志:

如需查看所有 gcpdiag 工具标志的列表和说明,请参阅 gcpdiag 使用说明

使用 Gemini Cloud Assist 调查

请考虑使用 Gemini Cloud Assist 调查来更深入了解日志并解决问题。如需详细了解如何使用 Logs Explorer 以不同方式发起调查,请参阅 Gemini 文档中的使用 Gemini Cloud Assist 调查排查问题

验证日志记录配置和权限

设置不正确是导致缺少 GKE 日志的常见原因。请按照以下部分中的说明验证 Cloud Logging 配置。

验证 Cloud Logging API 状态

如需从项目中的任何集群收集日志,Cloud Logging API 必须处于活跃状态。

症状

Cloud Logging 中未显示项目中的任何 GKE 资源的日志。

原因

系统对 Google Cloud 项目停用了 Cloud Logging API,导致节点上的日志记录代理无法发送日志。

解决方法

如需验证 Cloud Logging API 是否已启用,并在必要时启用该 API,请选择以下选项之一:

控制台

  1. 在 Google Cloud 控制台中,前往已启用的 API 和服务页面。

    前往“已启用的 API 和服务”

  2. 过滤条件字段中,输入 Cloud Logging API,然后按 Enter 键。

  3. 如果该 API 已启用,您会看到它列出。如果该 API 未列出,请启用它:

    1. 点击 启用 API 和服务
    2. 搜索字段中,输入 Cloud Logging API,然后按 Enter 键。
    3. 点击 Cloud Logging API 结果。
    4. 点击启用

gcloud

  1. 检查该 API 是否已启用:

    gcloud services list --enabled --filter="NAME=logging.googleapis.com"
    

    输出应如下所示:

    NAME: logging.googleapis.com
    TITLE: Cloud Logging API
    
  2. 如果该 API 未列在已启用的服务中,请启用它:

    gcloud services enable logging.googleapis.com \
        --project=PROJECT_ID
    

    PROJECT_ID 替换为您的 Google Cloud项目 ID。

验证集群日志记录配置

借助 GKE,您可以配置从集群收集哪些日志类型(例如 SYSTEMWORKLOAD)。

症状

Cloud Logging 中未显示特定 GKE 集群的任何日志,或者仅缺少某些类型的日志(例如 SYSTEM)。

原因

系统对所需的日志类型停用了集群级日志记录。如果您使用的是 Autopilot 集群,则这不是日志记录问题的原因。此设置对于 Standard 集群是可配置的,但在 Autopilot 集群中默认始终处于启用状态,且无法停用。

解决方法

如需检查和更新集群的日志记录配置,请选择以下选项之一:

控制台

  1. 在 Google Cloud 控制台中,前往 Kubernetes 集群页面。

    转到 KUBERNETES 集群

  2. 点击您要调查的集群的名称。

  3. 点击详细信息标签页,然后前往功能部分。

  4. Logging 行中,查看已启用的日志类型,例如系统工作负载

  5. 如果您要收集的日志类型处于停用状态或不正确,请点击 修改 Logging

  6. 组件列表中,选中要收集的日志类型对应的复选框,然后点击确定。如需详细了解可用的日志类型,请参阅 GKE 日志简介

  7. 点击保存更改

gcloud

  1. 如需检查日志记录配置,请描述集群:

    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --project=PROJECT_ID \
        --format="value(name,loggingConfig.componentConfig.enableComponents)"
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。
    • PROJECT_ID:您的 Google Cloud 项目 ID。

    如果已启用日志记录,则输出类似于以下内容:

    example-cluster    SYSTEM_COMPONENTS;WORKLOADS
    

    如果输出为 NONE,则表示日志记录已停用。

  2. 如果所需的日志类型处于停用状态或不正确,请更新日志记录配置:

    gcloud container clusters update CLUSTER_NAME \
        --location=LOCATION \
        --project=PROJECT_ID \
        --logging=LOGGING_TYPE
    

    LOGGING_TYPE 替换为 SYSTEMWORKLOAD 或两者兼有。如需收集任何日志,必须启用 SYSTEMWORKLOAD 日志无法单独收集。如需详细了解可用的日志类型,请参阅 GKE 日志简介

验证节点池访问权限范围

GKE 集群中的节点使用 OAuth 访问范围来获取与 Google Cloud API(包括 Cloud Logging)交互的权限。

症状

特定节点池中的节点缺少日志。

原因

节点池中的节点没有必要的 OAuth 访问权限范围。节点需要以下范围之一才能将日志写入 Cloud Logging:

  • https://www.googleapis.com/auth/logging.write:授予写入日志的权限。这是所需的最小范围。
  • https://www.googleapis.com/auth/logging.admin:授予对 Cloud Logging API 的完整访问权限,其中包括 logging.write 中的权限。
  • https://www.googleapis.com/auth/cloud-platform:授予对所有已启用的 Google Cloud API 的完整访问权限,其中包括 logging.write 中的权限。

解决方法

如需验证权限并在缺少权限时授予所需的角色,请选择以下选项之一:

控制台

  1. 验证节点池的访问权限范围:

    1. 在 Google Cloud 控制台中,前往 Kubernetes 集群页面。

      转到 KUBERNETES 集群

    2. 如需打开集群的详情页面,请点击要调查的集群的名称。

    3. 点击节点标签页。

    4. 节点池部分中,点击要调查的节点池的名称。

    5. 前往安全部分。

    6. 查看访问权限范围字段中列出的范围。确保至少存在一个所需范围:

      • Stackdriver Logging API - 只写
      • Stackdriver Logging API - 完整
      • Cloud Platform - 已启用

      如果缺少所需范围,请重新创建节点池。您无法更改现有节点池的访问权限范围。

  2. 如果需要,请创建具有所需范围的新节点池:

    1. 返回到要修改的集群的集群详情页面。
    2. 点击节点标签页。
    3. 点击 创建用户管理的节点池
    4. 填写节点池详情部分。
    5. 在左侧导航栏中,点击安全性
    6. 访问权限范围部分中,选择要添加的角色:
      • 如需添加特定范围,请选择针对每个 API 设置访问权限
      • 如需授予完整访问权限,请选择授予对所有 Cloud API 的完整访问权限
    7. 根据需要配置任何其他部分。
    8. 点击创建
  3. 将您的工作负载迁移到新节点池。。 将工作负载迁移到新节点池后,您的应用会在具有必要范围的节点上运行,以便将日志发送到 Cloud Logging。

  4. 删除旧节点池:

    1. 返回到集群详情页面,然后选择节点标签页。
    2. 节点池部分中,找到旧节点池。
    3. 点击节点池旁边的 删除
    4. 出现提示时,输入节点池名称以确认删除,然后点击删除

gcloud

  1. 验证节点池的访问权限范围:

    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --project=PROJECT_ID \
        --format="value(nodePools[].name,nodePools[].config.oauthScopes)"
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。
    • PROJECT_ID:您的 Google Cloud 项目 ID。

    查看每个节点池的输出。确保至少列出一个所需范围(https://www.googleapis.com/auth/logging.writehttps://www.googleapis.com/auth/cloud-platformhttps://www.googleapis.com/auth/logging.admin)。如果缺少所需范围,请重新创建节点池。您无法更改现有节点池的访问权限范围。

  2. 如果需要,请创建具有所需范围的新节点池:

    gcloud container node-pools create NEW_NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --project=PROJECT_ID \
        --scopes=https://www.googleapis.com/auth/logging.write,OTHER_SCOPES
    

    替换以下内容:

    • NEW_NODE_POOL_NAME:新节点池的名称。
    • OTHER_SCOPES:节点所需的任何其他范围的英文逗号分隔列表。如果您不需要其他范围,请省略此占位符和前面的英文逗号。
  3. 将您的工作负载迁移到新节点池。。 将工作负载迁移到新节点池后,您的应用会在具有必要范围的节点上运行,以便将日志发送到 Cloud Logging。

  4. 删除旧节点池:

    gcloud container node-pools delete OLD_NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --project=PROJECT_ID
    

验证节点服务账号权限

节点使用服务账号向 Google Cloud 服务进行身份验证,该账号需要具有特定的 IAM 权限才能写入日志。

症状

  • 节点缺少日志。
  • 检查日志记录代理日志(例如 Fluent Bit)可能会显示与权限相关的错误,例如尝试写入 Cloud Logging 时出现的 401403 代码。
  • 您可能会在 Google Cloud 控制台中看到有关集群的 Grant Critical Permissions to Node Service Account 通知。

原因

节点池的节点使用的服务账号缺少将日志写入 Cloud Logging 所需的 IAM 权限。节点需要具有 logging.logWriter 角色的服务账号,该角色可提供 logging.logEntries.create 权限。

此外,对于 GKE 1.33 版或更高版本,GKE Default Node Service Agent (service-PROJECT_NUMBER@gcp-sa-gkenode.iam.gserviceaccount.com) 必须至少具有 Kubernetes Default Node Service Agent (roles/container.defaultNodeServiceAgent) 角色。此角色可让 GKE 管理节点资源和操作,包括日志记录组件。

解决方法

如需验证权限并在缺少权限时授予所需角色,请执行以下操作:

  • 验证节点的服务账号权限。
  • 验证 GKE 服务代理是否具有所需角色。

验证节点服务账号权限

节点服务账号是节点用于进行身份验证和发送日志的账号。如需确定此服务账号并验证其是否具有所需的 roles/logging.logWriter 权限,请执行以下操作:

  1. 如需确定节点池使用的服务账号,请选择以下选项之一:

    控制台

    1. 在 Google Cloud 控制台中,前往 Kubernetes 集群页面。

      转到 KUBERNETES 集群

    2. 在集群列表中,点击您要检查的集群的名称。

    3. 根据操作的集群模式,执行以下操作之一:

      • 对于 Standard 集群,请执行以下操作:

        1. 点击节点标签页。
        2. 节点池表格中,点击节点池名称。系统会打开节点池详情页面。
        3. 安全部分中,找到服务账号字段。
      • 对于 Autopilot 集群,请执行以下操作:

        1. 点击详细信息标签页。
        2. 安全部分中,找到服务账号字段。

      如果服务账号字段中的值为 default,则表示节点使用 Compute Engine 默认服务账号。如果此字段中的值不是 default,则表示节点使用自定义服务账号。如需向自定义服务账号授予所需的角色,请参阅使用最小权限 IAM 服务账号

    gcloud

    根据您使用的集群类型,运行以下命令:

    Standard 集群

    gcloud container node-pools describe NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --project=PROJECT_ID \
        --format="value(config.serviceAccount)"
    

    替换以下内容:

    • NODE_POOL_NAME:节点池的名称。
    • CLUSTER_NAME:Standard 集群的名称。
    • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。
    • PROJECT_ID: Google Cloud项目 ID。

    如果输出为 default,则表示节点池使用 Compute Engine 默认服务账号。如果该值不是 default,则表示节点使用自定义服务账号。如需向自定义服务账号授予所需的角色,请参阅使用最小权限 IAM 服务账号

    Autopilot 集群

    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --project=PROJECT_ID \
        --format="value(nodePoolDefaults.nodeConfigDefaults.serviceAccount)"
    

    替换以下内容:

    • CLUSTER_NAME:Autopilot 集群的名称。
    • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。
    • PROJECT_ID:您的 Google Cloud 项目 ID。

    如果输出为 default,则表示节点池使用 Compute Engine 默认服务账号。如果该值不是 default,则表示节点使用自定义服务账号。如需向自定义服务账号授予所需的角色,请参阅使用最小权限 IAM 服务账号

    如需查看更详细的脚本以识别缺少权限,请参阅识别所有缺少权限的节点服务账号

  2. GKE 会自动扫描是否缺少权限并提供建议。如需使用建议来检查是否缺少权限,请选择以下选项之一:

    控制台

    1. Kubernetes 集群页面中,找到通知列。
    2. 查看通知列是否存在授予关键权限建议。此建议表示 NODE_SA_MISSING_PERMISSIONS 检查失败。
    3. 如果存在该建议,请点击它。系统会打开一个详细信息面板,其中说明了缺少的权限,并提供了解决步骤。

    gcloud

    1. 列出有关缺少服务账号权限的建议:

      gcloud recommender recommendations list \
          --recommender=google.container.DiagnosisRecommender \
          --location LOCATION \
          --project PROJECT_ID \
          --format yaml \
          --filter="recommenderSubtype:NODE_SA_MISSING_PERMISSIONS"
      
    2. 分析命令输出:

      • 如果该命令返回一个空列表,则表示 Recommender 未找到任何有效的 NODE_SA_MISSING_PERMISSIONS 建议。它检查的服务账号可能具有所需的权限。

      • 如果该命令返回一个或多个 YAML 块,则表示 Recommender 已发现权限问题。查看输出中以下关键字段:

        • description:提供问题摘要,例如指定节点服务账号缺少 roles/logging.logWriter 角色,或者 GKE 服务代理缺少 roles/container.defaultNodeServiceAgent 角色。
        • resource:指定受影响的集群。
        • content.operations:包含建议的解决方法。 此部分提供了授予特定缺失角色所需的确切 gcloud projects add-iam-policy-binding 命令。

    Recommender 最多可能需要 24 小时才能反映近期的更改。

  3. 如果您想立即验证权限,请选择以下选项之一来检查权限并授予角色:

    控制台

    1. 在 Google Cloud 控制台中,前往 IAM 页面。

      进入 IAM

    2. 找到节点池使用的服务账号。

    3. 角色列中,检查该服务账号是否具有 Logs Writer (roles/logging.logWriter) 角色。

    4. 如果缺少相应权限,请添加该权限:

      1. 点击 修改主账号
      2. 点击 添加其他角色
      3. 在搜索字段中,输入 Logs Writer
      4. 选中 Logs Writer 复选框,然后点击应用
      5. 点击保存

    gcloud

    1. 检查节点服务账号的当前角色:

      gcloud projects get-iam-policy PROJECT_ID \
          --flatten="bindings[].members" \
          --format='table(bindings.role)' \
          --filter="bindings.members:serviceAccount:SERVICE_ACCOUNT_EMAIL"
      
    2. 如果缺少 logging.logWriter 角色,请授予该角色:

      gcloud projects add-iam-policy-binding PROJECT_ID \
          --member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
          --role="roles/logging.logWriter"
      

验证 GKE 服务代理权限

如果日志仍然缺失,并且您使用的是 1.33 版或更高版本,请验证 GKE 用于管理节点组件的 Google 管理的代理是否具有所需权限:

  1. 如需标识服务代理的邮箱,请获取您的项目编号:

    gcloud projects describe PROJECT_ID --format="value(projectNumber)"
    

    PROJECT_ID 替换为您的项目 ID。请注意输出。

    GKE 服务代理的邮箱为:service-PROJECT_NUMBER@gcp-sa-gkenode.iam.gserviceaccount.com

  2. 如需使用建议来检查是否缺少权限,请选择以下选项之一:

    控制台

    1. Kubernetes 集群页面中,找到通知列。
    2. 查看该列是否存在授予关键权限建议。
    3. 如果存在该建议,请点击它。系统会打开一个详细信息面板,其中说明了缺少的权限,并提供了解决步骤。

    gcloud

    1. 列出有关缺少服务账号权限的建议:

      gcloud recommender recommendations list \
          --recommender=google.container.DiagnosisRecommender \
          --location LOCATION \
          --project PROJECT_ID \
          --format yaml \
          --filter="recommenderSubtype:NODE_SA_MISSING_PERMISSIONS"
      
    2. 分析命令输出。查看输出中的说明,指明 GKE 服务代理 (gcp-sa-gkenode) 缺少 roles/container.defaultNodeServiceAgent 角色。

  3. 如需立即检查权限并授予该角色,请选择以下选项之一:

    控制台

    1. 在 Google Cloud 控制台中,前往 IAM 页面。

      进入 IAM

    2. 过滤条件字段中,输入 GKE 服务代理的邮箱,然后按 Enter 键。

    3. 在过滤后的列表中,检查服务代理是否至少具有 Kubernetes Default Node Service Agent (roles/container.defaultNodeServiceAgent) 角色。

    4. 如果缺少该角色,请授予该角色:

      1. 点击服务代理旁边的 修改主账号
      2. 点击 添加角色
      3. 在搜索字段中,输入 Kubernetes Default Node Service Agent 并选择该角色。
      4. 点击保存

    gcloud

    1. 验证 roles/container.defaultNodeServiceAgent 角色是否已绑定到服务代理:

      gcloud projects get-iam-policy PROJECT_ID \
          --flatten="bindings[].members" \
          --format='table(bindings.role)' \
          --filter="bindings.members:serviceAccount:service-PROJECT_NUMBER@gcp-sa-gkenode.iam.gserviceaccount.com"
      

      在输出中,查找 roles/container.defaultNodeServiceAgent

    2. 如果缺少该角色,请授予 Kubernetes Default Node Service Agent 角色:

      gcloud projects add-iam-policy-binding PROJECT_ID \
          --member="serviceAccount:service-PROJECT_NUMBER@gcp-sa-gkenode.iam.gserviceaccount.com" \
          --role="roles/container.defaultNodeServiceAgent"
      

排查资源和性能问题

如果日志间歇性缺失或从高流量节点中丢弃,原因可能不是配置错误,而是性能问题。请参阅以下部分,了解如何调查您的项目是否超出 API 配额,或者高日志量是否使特定节点上的代理不堪重负。

调查 Cloud Logging API 配额用量

为了保护服务,Cloud Logging 会对所有项目强制实施写入配额,从而限制 Cloud Logging 每分钟可注入的总日志量。

症状

  • 日志间歇性或完全缺失。
  • 您在节点或日志记录代理日志中看到与 logging.googleapis.com 相关的 RESOURCE_EXHAUSTED 错误。

原因

项目超出了 Cloud Logging API 写入请求配额。此问题会导致日志记录代理无法发送日志。

解决方法

如需查看配额用量并申请增加配额,请执行以下操作:

  1. 在 Google Cloud 控制台中,进入配额页面。

    转到“配额”

  2. 过滤条件字段中,输入 Cloud Logging API,然后按 Enter 键。

  3. 在过滤后的列表中,找到集群所在区域的每个区域每分钟的日志写入字节数的配额。

  4. 查看当前用量百分比列中的值。如果用量达到或接近限制,则您可能已超出配额。

  5. 如需申请增加配额,请点击修改配额,然后按照提示操作。如需了解详情,请参阅查看和管理配额

如需减少用量,请考虑排除日志或降低应用的日志详细程度。您还可以设置提醒政策,以便在达到限制之前收到通知。

调查节点吞吐量和资源用量

每个节点上的 GKE 日志记录代理都有自己的吞吐量限制,可能会超出此限制。

症状

特定节点的日志间歇性缺失或延迟,尤其是在集群活动频繁或节点资源用量较高时。

原因

GKE 日志记录代理具有默认吞吐量限制(每个节点大约 100 KBps)。如果节点上的应用生成日志的速度超过此限制,则即使未超出项目的总体 API 配额,代理也可能会丢弃日志。您可以使用 Metrics Explorer 中的 kubernetes.io/node/logs/input_bytes 指标监控节点日志记录吞吐量。

如果节点承受繁重的 CPU 或内存压力,导致代理没有足够的资源来处理日志,则日志也可能会缺失。

解决方法

如需降低吞吐量,请选择以下选项之一:

Standard 集群

请尝试按以下解决方法操作:

  • 启用高吞吐量日志记录:此功能可提高每个节点的容量。如需了解详情,请参阅调整 Cloud Logging 代理吞吐量

  • 减少日志量:分析应用日志记录模式。减少不必要或过于冗长的日志记录。

  • 部署自定义日志记录代理:您可以部署和管理自己的自定义 Fluent Bit DaemonSet,但您需要负责其配置和维护。

  • 检查节点资源用量:即使日志量在限制范围内,也要确保节点不会承受繁重的 CPU 或内存压力。节点资源不足可能会导致日志记录代理无法处理和发送日志。您可以在 Metrics Explorer 中查看 kubernetes.io/node/cpu/core_usage_timekubernetes.io/node/memory/used_bytes 等指标。

Autopilot 集群

请尝试按以下解决方法操作:

  • 减少日志量:分析应用日志记录模式。减少不必要或过于冗长的日志记录。尽可能确保日志结构化,因为这些类型的日志有助于高效处理。排除不必要的日志。

  • 优化应用性能:由于节点资源在 Autopilot 集群中管理,因此请确保应用不会过度消耗 CPU 或内存,这可能会间接影响日志记录代理等节点组件的性能。虽然您不会直接管理节点,但应用效率会影响节点的整体健康状况。

排查过滤和应用问题

如果您的应用成功生成了日志,但这些日志仍未显示在 Cloud Logging 中,则问题通常是由过滤或应用的日志记录行为导致的。以下部分探讨了日志排除过滤条件、容器级缓冲、限制性搜索查询以及应用未写入 stdoutstderr 等问题。

调查日志排除过滤条件

Logs Explorer 仅显示与查询中的所有过滤条件和所选时间范围匹配的日志。

症状

Cloud Logging 中缺少符合某些条件的特定日志,但存在来自同一来源的其他日志。

原因

日志排除过滤条件是在 Cloud Logging 接收器(通常是 _Default 接收器)中定义的。这些规则会静默丢弃符合特定条件的日志,即使节点已成功发送这些日志也是如此。

解决方法

如需查看和修改排除过滤条件,请选择以下选项之一:

控制台

  1. 在 Google Cloud 控制台中,前往日志路由器页面。

    转至日志路由器

  2. 找出有问题的过滤条件:

    1. 对于每个接收器(_Required 接收器除外,该接收器不能有排除过滤条件),点击 更多操作,然后选择查看接收器详情
    2. 查看排除过滤条件部分中的查询。将过滤条件逻辑与缺失日志的属性(例如资源类型、标签或关键字)进行比较。
    3. 复制排除过滤条件查询。
    4. 转到日志浏览器页面。

      转到日志浏览器

    5. 将排除过滤条件查询粘贴到查询窗格中,然后点击运行查询

    6. 查看结果。显示的日志是过滤条件会排除的日志。如果缺失的日志显示在这些结果中,则很可能是此过滤条件导致了该问题。

  3. 停用或修改过滤条件:

    1. 返回日志路由器页面。
    2. 点击具有可疑过滤条件的接收器对应的 更多操作,然后选择修改接收器
    3. 找到选择要从接收器中过滤掉的日志部分,然后找到排除过滤条件。
    4. 您可以点击停用以停用过滤条件,也可以修改其查询以使其更具体。
    5. 点击更新接收器。 更改适用于新日志。

gcloud

  1. 列出项目中的所有接收器:

    gcloud logging sinks list --project=PROJECT_ID
    
  2. 查看每个接收器的排除过滤条件:

    gcloud logging sinks describe SINK_NAME --project=PROJECT_ID
    

    在输出中,查看 exclusions 部分。将过滤条件逻辑与缺失日志的属性(例如资源类型、标签或关键字)进行比较。

  3. 如需修改排除项,请更新接收器的配置:

    1. 将接收器的配置导出到本地文件(例如 sink-config.yaml):

      gcloud logging sinks describe SINK_NAME \
          --format=yaml > sink-config.yaml
      
    2. 通过文本编辑器打开 sink-config.yaml 文件。

    3. 找到 exclusions: 部分,然后移除或修改有问题的过滤条件。

    4. 更新修改后的接收器:

      gcloud logging sinks update SINK_NAME sink-config.yaml \
          --project=PROJECT_ID
      

      如需详细了解此命令,请参阅 gcloud logging sinks update 文档。

调查容器日志缓冲和延迟

应用和操作系统通常使用缓冲来按块写入数据,而不是逐行写入,这样可以提高性能。

症状

  • 来自特定容器的日志仅在容器退出后才会显示在 Cloud Logging 中,或者日志显示明显延迟。
  • 有时,日志不完整。

原因

此问题通常是由日志缓冲导致的。虽然标准输出 (stdout) 在连接到终端时通常采用行缓冲,但当输出通过管道输送时,此行为会发生更改。如果容器中的应用日志或启动脚本通过管道 stdout 输送到其他命令(例如 my-app | grep ...),则输出可能会完全缓冲。因此,日志会一直保留,直到缓冲区已满或管道关闭。如果容器意外终止,此行为可能会导致延迟或数据丢失。应用内部缓冲也可能会导致延迟。

解决方法

如需解决此问题,请尝试以下解决方案:

  • 避免通过管道输送 stdout:如果可能,请修改容器入口点或应用命令,以将日志直接写入 stdoutstderr,而无需通过容器内的 grepsed 等其他命令进行管道输送。
  • 确保行缓冲
    • 如果管道输送不可避免,请使用支持行缓冲的工具。例如,使用 grep --line-buffered
    • 对于自定义应用,请确保它们在写入 stdout 时频繁刷新日志,最好是在每行之后刷新。许多日志记录库都有用于控制缓冲的设置。
  • 测试缓冲行为:部署以下 Pod 清单,并使用 kubectl logs -f buffered-pod 命令观察日志中的效果。通过在 buffered-container 清单中注释和取消注释不同的 command 数组来进行实验:

    # buffered.yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: run-script
    data:
    run.sh: |
        #!/bin/bash
        echo "Starting..."
        for i in $(seq 3600); do
        echo "Log ${i}"
        sleep 1
        done
        echo "Exiting."
    ---
    apiVersion: v1
    kind: Pod
    metadata:
    name: buffered-pod
    spec:
    containers:
        - name: buffered-container
        image: ubuntu  # Or any other image with bash
    
        # Case 1: Direct execution - line buffered by default to TTY
        # Logs appear immediately.
        command: ['/bin/bash', '-c', '/mnt/run.sh']
    
        # Case 2: Piped to grep - fully buffered by default
        # Logs might be delayed or appear in chunks.
        # command: ['/bin/bash', '-c', '/mnt/run.sh | grep Log']
    
        # Case 3: Piped to grep with --line-buffered
        # Logs appear immediately.
        # command: ['/bin/bash', '-c', '/mnt/run.sh | grep --line-buffered Log']
    
        volumeMounts:
            - name: scripts
            mountPath: /mnt
    volumes:
        - name: scripts
        configMap:
            name: run-script
            defaultMode: 0777
    restartPolicy: Never
    

调查 Logs Explorer 查询

如果您确信系统正在收集日志,但您找不到这些日志,则可能是搜索查询或时间范围存在问题。

症状

即使您知道应用正在生成预期日志,但这些日志并未显示在搜索结果中。

原因

Logs Explorer 中的查询可能包含过滤条件(例如,针对命名空间、标签、资源类型或文本的过滤条件),这些过滤条件可能会无意中排除您要查找的日志。

解决方法

  1. 在 Google Cloud 控制台中,前往 Logs Explorer 页面。

    转到日志浏览器

  2. 点击选择时间范围。即使您认为自己知道日志的发生时间,也请尝试使用更广的时间范围,以排除时间问题。

  3. 简化查询:

    1. 清除所有过滤条件。
    2. 尝试仅按集群过滤:

      resource.type="k8s_container"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      

      替换以下内容:

      • CLUSTER_NAME:您的集群的名称。
      • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。
    3. 点击运行查询

  4. 如果宽泛查询有效,请逐个重新添加原始过滤条件:

    • 资源类型:确保您使用的是正确的资源类型。例如,您是否在应该按 k8s_node 过滤时按 k8s_container 过滤?
    • 标签:仔细检查 resource.labels 的拼写,例如 namespace_namecontainer_name 或自定义标签。
    • 严重程度:确保严重程度级别(例如 severity=ERROR)不会过于严格。
    • 文本载荷:检查搜索字词中是否存在拼写错误和过于严格的字符串。例如,使用 : 表示“包含”,而不是使用 = 表示完全匹配(jsonPayload.message:"error" 而不是 jsonPayload.message="error")。
  5. 验证您的过滤条件是否考虑了区分大小写(文本通常不区分大小写,但标签可能区分大小写),确保值不包含隐藏字符或多余的空格,并检查包含特殊字符的字词是否需要用英文引号括起来。

  6. 查看时间轴。添加过滤条件后突然出现下降,有助于您确定查询中存在问题的部分。

如需查看有关有效日志记录日志的更多建议,请参阅 Cloud Logging 文档中的快速查找日志条目

如果您在优化查询后仍然找不到日志,问题可能不在于查询,而是本文档其他部分中描述的问题。

调查应用特有的日志记录行为

GKE Logging 代理仅会收集写入 stdoutstderr 流的日志。

症状

即使集群中的其他日志存在,Cloud Logging 中也看不到特定 Pod 或容器的日志。

原因

应用未写入 stdoutstderr。它可能配置错误,导致将日志写入容器内的文件,而日志记录代理无法在其中收集这些日志。

应用可能还在其输出中混合了 JSON 和非 JSON 文本。日志记录代理的解析器需要单个流中的格式保持一致(JSON 或文本)。如果配置为 JSON 日志记录的应用输出纯文本行,则可能会破坏解析器,导致日志被丢弃或错误地注入。

解决方法

  1. 确定缺少日志的应用的 Pod 名称和命名空间:

    kubectl get pods -n NAMESPACE_NAME
    
  2. 检查容器日志:

    • 如果 Pod 只有一个容器,请运行以下命令:

      kubectl logs POD_NAME \
          -n NAMESPACE_NAME
      

      替换以下内容:

      • POD_NAME:您的 pod 的名称。
      • NAMESPACE_NAME:您的 pod 的命名空间。
    • 如果 Pod 有多个容器,请指定容器名称:

      kubectl logs POD_NAME \
          -c CONTAINER_NAME \
          -n NAMESPACE_NAME
      

      CONTAINER_NAME 替换为 Pod 中容器的名称。

    • 如需实时跟踪日志,请运行以下命令:

      kubectl logs -f POD_NAME \
          -c CONTAINER_NAME \
          -n NAMESPACE_NAME
      

      替换以下内容:

      • POD_NAME:您的 pod 的名称。
      • CONTAINER_NAME:Pod 中容器的名称。
      • NAMESPACE_NAME:您的 pod 的命名空间。
  3. 分析输出:

    • 如果 kubectl logs 命令没有输出,或者命令输出不包含预期日志,则问题出在应用本身。kubectl logs 命令会直接从容器运行时捕获的 stdoutstderr 流中读取数据。如果日志不在此处,GKE 的日志记录代理就无法看到它们。

      更改应用的代码或配置,以停止将数据写入文件,而是将所有消息直接记录到 stdout(对于常规日志)和 stderr(对于错误日志)。

    • 如果您看到 JSON 字符串和纯文本行混合,则此输出表明存在混合格式问题。将应用配置为仅将有效的单行 JSON 对象写入 stdoutstderr

    • 如果 kubectl logs 命令确实显示了预期日志,则问题可能出在日志记录流水线的下游(例如,代理、权限或 Cloud Logging 服务)。

排查平台和服务问题

以下部分可帮助您调查即时配置外部的问题,例如日志保留政策、Cloud Logging 健康状况或不受支持的 GKE 版本。

调查日志保留期限

日志存储在存储桶中,每个存储桶都有一个保留期限,用于定义日志在被自动删除之前保留的时长。

症状

早于某个日期的日志缺失。

原因

您要搜索的日志早于其路由到的日志存储桶的保留期限。

解决方法

如需确定和更新保留期限,请选择以下选项之一:

控制台

  1. 确定 GKE 日志路由到的存储桶:

    1. 在 Google Cloud 控制台中,前往日志路由器页面。

      转至日志路由器

    2. 查看目标位置列,其中显示了日志的路由位置。

      目标位置如下所示:

      logging.googleapis.com/projects/PROJECT_ID/locations/LOCATION/buckets/BUCKET_ID
      

      请注意 PROJECT_IDLOCATIONBUCKET_ID

      日志通常会路由到 _Default 存储桶,但如果您配置了自定义接收器,日志也可能会路由到其他存储桶。

  2. 检查日志存储桶保留期限:

    1. 在 Google Cloud 控制台中,前往日志存储页面。

      转到“日志存储”

    2. 从接收器的目标位置查找与 BUCKET_IDLOCATIONPROJECT_ID 匹配的存储桶。

    3. 对于每个相关存储桶,查看保留期限列。

    4. 如果您要查看的日志早于保留期限,则 Cloud Logging 已将其删除。如果您需要更长的保留期限,请执行以下操作:

      1. 对于要延长其保留期限的存储桶,点击 更多操作
      2. 选择修改存储桶,然后更新保留期限。 请注意可能产生的费用影响

gcloud

  1. 确定 GKE 日志路由到的存储桶:

    gcloud logging sinks list --project=PROJECT_ID
    

    查看输出。每个接收器的 destination 字段显示了日志的路由位置。日志存储桶的目标位置格式为:

    logging.googleapis.com/projects/PROJECT_ID/locations/LOCATION/buckets/BUCKET_ID
    

    请注意 PROJECT_IDLOCATIONBUCKET_ID

    日志通常会路由到 _Default 存储桶。

  2. 检查日志存储桶保留期限:

    gcloud logging buckets describe BUCKET_ID \
        --location=LOCATION \
        --project=PROJECT_ID
    

    在输出中,查找 retentionDays 字段。 如果您需要的日志早于 retentionDays 列出的值,则 Cloud Logging 已将其删除。

  3. 如果您需要更长的保留期限,请更新该期限:

    gcloud logging buckets update BUCKET_ID \
        --location=LOCATION \
        --retention-days=RETENTION_DAYS \
        --project=PROJECT_ID
    

    替换以下内容:

    • BUCKET_ID:日志存储桶的 ID。
    • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。
    • RETENTION_DAYS:保留日志的天数。请注意延长保留期限可能产生的费用影响
    • PROJECT_ID:您的 Google Cloud 项目 ID。

调查 Cloud Logging 服务问题和注入延迟

有时,日志记录流水线本身可能会遇到问题,例如服务范围的中断或暂时大规模的注入延迟。

症状

  • 多个项目或集群中出现大范围或间歇性日志丢失。
  • 日志在 Logs Explorer 中显示的时间明显延迟。

原因

  • Cloud Logging 服务中断:极少发生的服务范围中断可能会阻止日志注入,导致大范围延迟或日志完全丢失。
  • 日志量较大:即使没有正式的中断,项目或区域的日志量较大也可能会暂时使注入服务不堪重负,导致日志延迟显示。

解决方法

  • 通过访问Google CloudService Health 信息中心查看 Google Cloud 服务的状态。查找与 Cloud Logging 或 GKE 相关的任何未解决的突发事件。

  • 考虑可能出现的数据注入延迟。如果日志未立即显示,并且没有尚未解决的突发事件,请等待一段时间以完成注入,尤其是在日志量较高的情况下。请过几分钟后再次查看。

调查集群版本

GKE 会定期发布新版本,其中包含针对组件(包括日志记录代理)的 bug 修复和性能改进。

症状

日志记录问题与集群版本限制有关。

原因

集群可能正在运行旧版或不受支持的 GKE 版本,该版本存在已知的日志记录代理问题或缺少某些日志记录功能。

解决方法

如需解决此问题,请执行以下操作:

  1. 检查集群的版本:

    gcloud container clusters describe CLUSTER_NAME \
        --location LOCATION \
        --format="value(currentMasterVersion)"
    

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:集群的 Compute Engine 区域或可用区(例如 us-central1us-central1-a)。
  2. 为确保该版本是受支持的版本,请将该版本与 GKE 发布时间表进行比较。

  3. 如果集群使用的是不受支持的版本,请升级集群

后续步骤