google/gke-ai-troubleshooting-jobset-interruption
>- Diagnoses GKE JobSet interruptions, restarts, and preemptions for AI/ML training workloads autonomously. Use when troubleshooting JobSet restart loops, spot VM preemptions, node readiness failures, host VM issues, or coordinator worker crashes. Don't use for general GKE cluster creation, basic workload deployment, or non-JobSet application issues.
npx skills add https://github.com/google/skills --skill gke-ai-troubleshooting-jobset-interruption
Use this skill to systematically diagnose and resolve JobSet interruptions,
restarts, and preemptions on GKE clusters hosting large-scale AI/ML workloads.
kube-state-metrics for yourcluster.
encounter 403 Permission Denied, authentication errors, or network
isolation, **do NOT enter authentication or credential troubleshooting
loops**. Populate the query templates with the acquired variables
({project_id}, {cluster_name}, {workload_name}, {start_time},
{end_time}), inspect any locally staged telemetry or mock data files if
available, and complete the diagnostic workflow and resolution
recommendations autonomously.
Independently gather context using tools, workspace files, environment details,
or user prompt context:
{project_id}){cluster_name}){workload_name}){namespace}){issue_time})If specific variables are not explicitly provided by the user, inspect cluster
resources or logs to determine them, or use the {variable} placeholders
provided.
exact timestamp is provided, calculate the query window based on current
time or available log timestamps.
{issue_time} is available (orcalculated as T), set {start_time} = T - 30m and {end_time} = `T +
30m`.
--------------------------------------------------------------------------------
Verify if the JobSet is experiencing restart loops and determine the frequency
of restarts.
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)]
kube_jobset_restarts{jobset_name="{workload_name}", cluster="{cluster_name}"}
that the JobSet is being actively restarted by the controller due to worker
failure or interruption.
--------------------------------------------------------------------------------
Determine if the JobSet restarts were triggered by physical nodepool-level
events (such as spot preemptions, maintenance, or host terminations).
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)]
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])
)
resource.type="gke_nodepool"
AND resource.labels.cluster_name="{cluster_name}"
AND timestamp >= "{start_time}"
AND timestamp <= "{end_time}"
interruption_reasonor logs for host issues.
of node termination logs and preemption events.
--------------------------------------------------------------------------------
Correlate node readiness failures with physical host VMs to see if a single
faulty host repeatedly fails coordinator pods.
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)]
sum by (status, condition, node_pool_name) (
kubernetes_io:node_status_condition{cluster_name="{cluster_name}", condition="Ready", status="False"}
)
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)]
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 or Unknown) and correlate them to their GCE physical host
ID via metadata.user.gce_topology_host. Check if the same host is
repeatedly failing.
--------------------------------------------------------------------------------
Analyze pod status phases and retrieve coordinator worker logs to identify
application-level crashes or network deadlocks.
> Required Execution Order: You MUST analyze pod status phases (Section A)
> and unschedulable pod metrics (Section B) to assess overall workload health
> before inspecting specific worker container logs (Section C).
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()]
sum by (phase) (
avg_over_time(kube_pod_status_phase{cluster="{cluster_name}", pod=~"{workload_name}.*"}[10m])
)
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)]
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}"
for NCCL timeouts, collective communication issues, or MegaScale hangs.
--------------------------------------------------------------------------------
If Step 2 showed high preemption counts on Spot VMs:
GKE Reserved/On-Demand VMs or utilizing Compact Placement Policies
to minimize defragmentation interruptions.
restarts.
If Step 3 identified a specific host ID (gce-topology-host) that consistently
fails or triggers restarts across multiple attempts:
underlying GCE VM instance to trigger instance recreation, and opening a
support ticket with Google Cloud Support specifying the physical host ID.
physical hardware, preventing infinite restart loops.
--------------------------------------------------------------------------------
{start_time} ({issue_time} - 30m) and{end_time} ({issue_time} + 30m) window.
terminations).
quarantining.
Take google/gke-ai-troubleshooting-jobset-interruption from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.