关于 gke-ai-troubleshooting-jobset-interruption
此技能为运行大型 AI/ML 工作负载的 GKE 集群提供 JobSet 中断排查流程,供集群运维人员定位重启、抢占和节点故障。它按顺序检查指标、日志、节点与容器,并区分建议操作和需确认的高风险处置。
主要功能
- 01获取集群与故障时间信息
- 02检查 JobSet 重启指标
- 03排查节点池中断事件
- 04关联节点与物理主机
- 05检查 Pod 状态及工作容器日志
- 06提供分级处置建议
适用场景
- 01分析 JobSet 重启循环
- 02定位 Spot VM 抢占或维护事件
- 03排查节点及底层主机故障
- 04诊断工作 Pod 未调度或容器异常
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ googlecloudplatform/ gke-mcp --skill gke-ai-troubleshooting-jobset-interruption安装后在 Claude Code 中输入/gke-ai-troubleshooting-jobset-interruption确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
BUILDEVAL.yamlREADME.mdTEST.mdevals/faulty_physical_host_detected/task.yamlevals/missing_context/task.yamlevals/no_active_nodes_fallback_or_clean_telemetry/task.yamlevals/no_jobset_restarts_detected/task.yamlevals/single_node_unready_no_host_correlation/task.yamlevals/spot_preemption_detected/task.yamlevals/unschedulable_pods_resource_exhaustion/task.yamlreferences/failure_signatures.mdscripts/validate_queries.sh详细介绍
GKE JobSet 中断问题排查
使用此技能,系统地诊断和解决托管大规模 AI/ML 工作负载的 GKE 集群上的 JobSet 中断、重启和抢占问题。
⚠️ 先决条件
- 必须在集群的
kube-state-metrics中启用 JobSet 指标包(请参阅 KSM JobSet Metrics)。 - 必须为 Google Cloud 项目启用 Cloud Logging 和 Cloud Monitoring。
🔍 诊断工作流
步骤 0:获取上下文并定义时间范围
开始排查前,请向用户获取以下信息:
- 项目 ID(例如,
customer-ai-project-123) - 集群名称(例如,
tpu-cluster-prod) - 工作负载名称(JobSet 名称)(例如,
llama3-70b-training) - 工作负载命名空间(例如,
default) - 问题发生时间(例如,
2026-05-20T08:15:00Z)
时间处理规则
- 拒绝相对时间:如果用户说“X 分钟前”或“刚才”,请停止排查,并要求提供准确的时间戳或具体的时间范围。
- 计算时间范围:如果用户提供单个时间戳
T,请将查询时间范围设为[T - 30m]至[T + 30m]。- 令
Start_Time=T - 30m - 令
End_Time=T + 30m
- 令
步骤 1:识别 JobSet 重启和尝试次数 [低风险]
确认 JobSet 是否陷入重启循环,并确定重启频率。
选项 A:可视化图表(MQL)- 重启
- 使用的工具:
monitoring_time_series_chart - 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)]
选项 B:PromQL 查询 - 重启
- 方法:通过 shell 命令执行(需要
BypassSandbox: true)。 - 命令模板:
curl -sSf -H "Authorization: Bearer \$(gcloud auth print-access-token)" \ "https://monitoring.googleapis.com/v1/projects/<project_id>/location/global/prometheus/api/v1/query?query=kube_jobset_restarts%7Bjobset_name%3D%22<workload_name>%22%2Ccluster%3D%22<cluster_name>%22%7D" - 逻辑:重启次数非零或不断增加,表示控制器正在因工作节点故障或中断而主动重启 JobSet。
- 自动化:报告调查结果后自动继续步骤 2。
步骤 2:检查节点池中断 [低风险]
确定 JobSet 重启是否由节点池级别的物理事件触发(例如 Spot 抢占、维护或主机终止)。
A. 指标查询(节点池中断次数)
选项 A:可视化图表(MQL)- 中断
- 使用的工具:
monitoring_time_series_chart - 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)]
选项 B:PromQL 查询 - 中断
- 方法:通过 shell 命令执行(需要
BypassSandbox: true)。 - 命令模板:
curl -sSf -H "Authorization: Bearer \$(gcloud auth print-access-token)" \ "https://monitoring.googleapis.com/v1/projects/<project_id>/location/global/prometheus/api/v1/query?query=sum%20by%20%28interruption_type%2C%20interruption_reason%2C%20node_pool_name%2C%20cluster_name%29%20%28avg_over_time%28%7B__name__%3D%22kubernetes.io%2Fnode_pool%2Finterruption_count%22%2C%20monitored_resource%3D%22k8s_node_pool%22%2C%20cluster_name%3D%22<cluster_name>%22%7D%5B10m%5D%29%29"
B. 日志查询(节点池生命周期事件)
- 使用的工具:
query_logs - 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. 指标查询(节点 Ready 状态检查)
选项 A:可视化图表(MQL)- 节点状态
- 使用的工具:
monitoring_time_series_chart - 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)]
选项 B:PromQL 查询 - 节点状态
- 方法:通过 shell 命令执行(需要
BypassSandbox: true)。 - 命令模板:
curl -sSf -H "Authorization: Bearer \$(gcloud auth print-access-token)" \ "https://monitoring.googleapis.com/v1/projects/<project_id>/location/global/prometheus/api/v1/query?query=sum%20by%20%28status%2C%20condition%2C%20node_pool_name%29%20%28%7B__name__%3D%22kubernetes.io%2Fnode%2Fstatus_condition%22%2C%20monitored_resource%3D%22k8s_node%22%2C%20cluster_name%3D%22<cluster_name>%22%2C%20condition%3D%22Ready%22%2C%20status%3D%22False%22%7D%29"
B. 指标查询(节点到主机的元数据拓扑关联)
- 使用的工具:
monitoring_time_series_chart - 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. 日志查询(节点故障日志)
- 使用的工具:
query_logs - 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 日志,以识别应用级崩溃或网络死锁。
A. 指标查询(Pod 生命周期阶段)
选项 A:可视化图表(MQL)- Pod 阶段
- 使用工具:
monitoring_time_series_chart - 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()]
选项 B:PromQL 查询 - Pod 阶段
- 方法:通过 Shell 命令执行(需要
BypassSandbox: true)。 - 命令模板:
curl -sSf -H "Authorization: Bearer \$(gcloud auth print-access-token)" \ "https://monitoring.googleapis.com/v1/projects/<project_id>/location/global/prometheus/api/v1/query?query=sum%20by%20%28phase%29%20%28avg_over_time%28%7B__name__%3D%22kube_pod_status_phase%22%2C%20cluster%3D%22<cluster_name>%22%2C%20pod%3D~%22<workload_name>.*%22%7D%5B10m%5D%29%29"
B. 指标查询(不可调度 Pod 数量)
- 使用工具:
monitoring_time_series_chart - 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. 日志查询(Worker 容器日志)
- 使用工具:
query_logs - 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>" - 逻辑:
- 检查 Pod 时间线,找出待处理或不可调度的 Pod。
- 使用 Worker 容器日志分析切片 0 中的 Worker 0(协调器),排查 NCCL 超时、集合通信问题或 MegaScale 卡死。
- 自动化:继续执行解决流程。
🛠️ 解决流程
解决方案 1:抢占与自动扩缩容优化 [低风险]
如果步骤 2 显示 Spot VM 的抢占次数较高:
- 操作:建议将关键的长时间运行训练工作负载切换到 GKE Reserved/On-Demand VM,或使用 Compact Placement Policies,以尽量减少碎片整理中断。
- 理由:消除 Spot 市场抢占,并减少训练重启。
解决方案 2:隔离故障 Host VM [高风险]
如果步骤 3 确认某个特定主机 ID(gce-topology-host)在多次尝试中持续发生故障或触发重启:
- 操作:起草建议,隔离并排空 GKE 节点、删除底层 GCE VM 实例以触发实例重建,并向 Google Cloud Support 提交支持工单,注明物理主机 ID。
- 理由:GKE 自动修复会在健康的物理硬件上重建 VM 实例,避免无限重启循环。
- 自动化:在隔离或排空任何节点之前停止操作,并请求用户明确确认。
📋 复制粘贴检查清单
- 获取上下文并计算
[T - 30m, T + 30m]时间窗口。 - 查询 JobSet 重启尝试次数。
- 检查 Nodepool 中断(Spot 抢占与硬件终止)。
- 查询节点到主机的映射,并检查节点日志中的物理主机错误。
- 检查 Pod 时间线状态和协调器 Worker 容器日志。
- 建议合适的调度策略(On-demand 或 Spot),或隔离 Host VM。
评论
支持 Markdown