mcpField
G
gke-ai-troubleshooting-jobset-interruption

gke-ai-troubleshooting-jobset-interruption

github.com/google云与 DevOps21.6k4.7k 次安装今天更新
代码仓库

关于 gke-ai-troubleshooting-jobset-interruption

此技能为在 GKE 上运行大型 AI/ML 工作负载的团队提供 JobSet 中断、重启和抢占的诊断流程。它将指标、日志与节点及 Pod 状态关联起来,并给出调度优化或故障主机隔离建议。

主要功能

  1. 01JobSet 重启指标分析
  2. 02节点池中断与日志检查
  3. 03节点状态和物理主机关联
  4. 04Pod 状态及容器日志检查
  5. 05按故障类型提供处置建议

适用场景

  1. 01调查训练任务反复重启
  2. 02区分 Spot 抢占与硬件故障
  3. 03定位反复故障的物理主机
  4. 04检查 Pod 未调度及协调器日志

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/google/skills --skill gke-ai-troubleshooting-jobset-interruption

安装后在 Claude Code 中输入/gke-ai-troubleshooting-jobset-interruption确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
attribution.md
failure_signatures.md
scripts/
validate_queries.sh

详细介绍

GKE JobSet 中断故障排查

使用此技能,系统地诊断并解决托管大规模 AI/ML 工作负载的 GKE 集群中的 JobSet 中断、重启和抢占问题。

致谢

必须阅读:执行任何 gcloud、REST API 或 MCP 命令之前,必须先阅读 使用归属信息。对于直接在终端中执行的命令(绝不可在生成的脚本、Terraform 或用户代码中执行),请在 gcloud 前加上 CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:gke-ai-troubleshooting-jobset-interruption)" ,并在 User-Agent 标头中追加 agent-skills/1.0 (skill:gke-ai-troubleshooting-jobset-interruption)。

⚠️ 前提条件和沙盒规则

  • 集群的 kube-state-metrics 中必须启用 JobSet 指标包。
  • Google Cloud 项目必须启用 Cloud Logging 和 Cloud Monitoring。
  • 自主执行与沙盒规则:如果 API 查询、工具或命令遇到 403 Permission Denied、身份验证错误或网络隔离,请勿陷入身份验证或凭据故障排查循环。使用已获取的变量({project_id}、{cluster_name}、{workload_name}、{start_time}、{end_time})填充查询模板;如果有本地暂存的遥测数据或模拟数据文件,请检查这些文件,并自主完成诊断工作流并给出解决建议。

🔍 诊断工作流

步骤 0:获取上下文并定义时间范围

使用工具、工作区文件、环境详情或用户提示词上下文,独立收集以下信息:

  • 项目 ID({project_id})
  • 集群名称({cluster_name})
  • 工作负载名称(JobSet 名称)({workload_name})
  • 工作负载命名空间({namespace})
  • 问题发生时间({issue_time})

如果用户未明确提供特定变量,请检查集群资源或日志以确定其值,或使用提供的 {variable} 占位符。

时间处理规则
  1. 自主确定时间范围:如果提供的是相对时间(例如“X 分钟前”)或未提供确切时间戳,请根据当前时间或可用日志时间戳计算查询时间范围。
  2. 计算时间范围:如果有 {issue_time} 时间戳(或将其计算为 T),则设置 {start_time} = T - 30m,{end_time} = T + 30m。

步骤 1:识别 JobSet 重启和尝试次数 [低风险]

确认 JobSet 是否陷入重启循环,并确定重启频率。

可视化图表 / MQL 查询 - 重启次数
  • MQL 查询规范:

    fetch prometheus_target
    | metric 'prometheus.googleapis.com/kube_jobset_restarts/gauge'
    | filter resource.cluster_name == '{cluster_name}' && metric.jobset_name == '{workload_name}'
    | align next_older(1m)
    | every 1m
    | group_by [metric.jobset_name], [val: max(value)]
    
PromQL 指标查询 - 重启次数
  • PromQL 查询规范:

    kube_jobset_restarts{jobset_name="{workload_name}", cluster="{cluster_name}"}
    
  • 诊断逻辑:重启次数非零或不断增加,表示控制器正在因工作节点故障或中断而主动重启 JobSet。

  • 自动化:报告发现结果后,自动继续执行步骤 2。


步骤 2:检查节点池中断 [低风险]

确定 JobSet 重启是否由节点池级别的物理事件触发(例如 Spot 抢占、维护或主机终止)。

A. 指标查询(节点池中断次数)
可视化图表 / MQL 查询 - 中断
  • MQL 查询规范:

    fetch k8s_node_pool
    | metric 'kubernetes.io/node_pool/interruption_count'
    | filter cluster_name == '{cluster_name}'
    | align next_older(10m)
    | every 10m
    | group_by [metric.interruption_type, metric.interruption_reason, metadata.system.node_pool_name], [val: sum(value)]
    
PromQL 查询 - 中断
  • PromQL 查询规范:

    sum by (interruption_type, interruption_reason, node_pool_name, cluster_name) (
      avg_over_time(kubernetes_io:node_pool_interruption_count{cluster_name="{cluster_name}"}[10m])
    )
    
B. 日志查询(节点池生命周期事件)
  • LQL 日志筛选规范:

    resource.type="gke_nodepool"
    AND resource.labels.cluster_name="{cluster_name}"
    AND timestamp >= "{start_time}"
    AND timestamp <= "{end_time}"
    
  • 诊断逻辑:

    • PreemptionEvent:Spot VM 被抢占,或节点已缩容。
    • MaintenanceEvent:节点池已更新,或 Google 安排了维护。
    • TerminationEvent:严重的主机故障。检查 interruption_reason 或日志中的主机问题。
    • 示例请参阅故障特征,了解节点终止日志和抢占事件。
  • 自动化:自动继续执行步骤 3。


步骤 3:检查节点和底层主机 VM [低风险]

将节点就绪状态故障与物理主机 VM 关联起来,确认是否有单台故障主机反复导致协调器 Pod 失败。

A. 指标查询(节点就绪状态检查)
可视化图表 / MQL 查询 - 节点状态
  • MQL 查询规范:

    fetch k8s_node
    | metric 'kubernetes.io/node/status_condition'
    | filter cluster_name == '{cluster_name}' && metric.condition == 'Ready' && metric.status == 'False'
    | align next_older(1m)
    | every 1m
    | group_by [node_name, metadata.user.gke_nodepool], [val: max(value)]
    
PromQL 查询 - 节点状态
  • PromQL 查询规范:

    sum by (status, condition, node_pool_name) (
      kubernetes_io:node_status_condition{cluster_name="{cluster_name}", condition="Ready", status="False"}
    )
    
B. 指标查询(节点与主机元数据拓扑关联)
  • MQL 查询规范:

    fetch k8s_node
    | metric 'kubernetes.io/node/cpu/total_cores'
    | filter cluster_name == '{cluster_name}'
    | align next_older(1m)
    | every 1m
    | group_by [node_name, metadata.user.gce_topology_host, metadata.user.gke_nodepool], [val: max(value)]
    
C. 日志查询(节点故障日志)
  • LQL 日志筛选规范:

    resource.type="k8s_node"
    AND resource.labels.cluster_name="{cluster_name}"
    AND (textPayload:"host error" OR textPayload:"kernel panic" OR textPayload:"hardware failure" OR textPayload:"NodeNotReady")
    AND timestamp >= "{start_time}"
    AND timestamp <= "{end_time}"
    
  • 诊断逻辑:确定特定节点是否不健康 (Ready=False 或 Unknown),并通过 metadata.user.gce_topology_host 将其与 GCE 物理主机 ID 关联。检查是否有同一台主机反复发生故障。

  • 自动化:自动继续执行步骤 4。


步骤 4:检查 Pod 和 Worker / 容器故障 [低风险]

分析 Pod 状态阶段,并获取协调器 worker 日志,以识别应用级崩溃或网络死锁。

执行顺序要求:在检查特定 worker 容器日志(C 节)之前,必须先分析 Pod 状态阶段(A 节)和无法调度的 Pod 指标(B 节),以评估整体工作负载健康状况。

A. 指标查询(Pod 生命周期阶段)
可视化图表 / MQL 查询 - Pod 阶段
  • MQL 查询规范:

    fetch k8s_pod
    | metric 'kubernetes.io/pod/status/phase'
    | filter cluster_name == '{cluster_name}' && pod_name ==~ '{workload_name}.*'
    | align next_older(10m)
    | every 10m
    | group_by [metric.phase], [val: count()]
    
PromQL 查询 - Pod 阶段
  • PromQL 查询规范:

    sum by (phase) (
      avg_over_time(kube_pod_status_phase{cluster="{cluster_name}", pod=~"{workload_name}.*"}[10m])
    )
    
B. 指标查询(无法调度的 Pod 数量)
  • MQL 查询规范:

    fetch k8s_pod
    | metric 'kubernetes.io/pod/status/unschedulable'
    | filter cluster_name == '{cluster_name}' && pod_name ==~ '{workload_name}.*'
    | align next_older(10m)
    | every 10m
    | group_by [pod_name], [val: max(value)]
    
C. 日志查询(工作器容器日志)
  • LQL 日志筛选规范:

    resource.type="k8s_container"
    AND resource.labels.cluster_name="{cluster_name}"
    AND labels."k8s-pod/jobset_sigs_k8s_io/jobset-name"="{workload_name}"
    AND timestamp >= "{start_time}"
    AND timestamp <= "{end_time}"
    
  • 诊断逻辑:

    1. 检查 Pod 时间线,找出处于待处理或无法调度状态的 Pod。
    2. 使用工作器容器日志分析切片 0 中的工作器 0(协调器),排查 NCCL 超时、集体通信问题或 MegaScale 挂起。
  • 自动化:继续执行解决方案。


🛠️ 解决方案工作流

解决方案 1:抢占与自动扩缩优化 [低风险]

如果步骤 2 显示 Spot VM 的抢占次数较多:

  • 操作:建议将关键的长时间运行训练工作负载切换到 GKE 预留型 / 按需 VM,或使用 紧凑放置策略 来最大限度减少碎片整理中断。
  • 理由:消除 Spot 市场抢占,减少训练重启。
解决方案 2:隔离故障主机 VM [高风险]

如果步骤 3 确认某个特定主机 ID(gce-topology-host)在多次尝试中持续 发生故障或触发重启:

  • 操作:建议隔离 / 排空 GKE 节点,删除底层 GCE VM 实例以触发实例重建,并向 Google Cloud Support 提交支持工单,注明物理主机 ID。
  • 理由:GKE 自动修复会在正常的物理硬件上重建 VM 实例,避免无限重启循环。

📋 复制粘贴清单

  • 收集上下文,并计算 {start_time}({issue_time} - 30m)和 {end_time}({issue_time} + 30m)时间范围。
  • 查询 JobSet 重启尝试次数。
  • 检查 Nodepool 中断情况(Spot 抢占与硬件终止)。
  • 查询节点到主机的映射,并检查节点日志中的物理主机错误。
  • 检查 Pod 时间线状态和协调器工作器容器日志。
  • 建议合适的调度策略(按需或 Spot),或隔离主机 VM。

评论

支持 Markdown