google/gke-workload-troubleshooting
>- Diagnoses GKE workload failures (CrashLoopBackOff, OOMKilled, ImagePullBackOff, Pending, etc.) via logs and events. Use when pods fail to start or crash repeatedly. Don't use for GKE cluster infrastructure provisioning, node pool creation, or non-Kubernetes Google Cloud services.
npx skills add https://github.com/google/skills --skill gke-workload-troubleshooting
Use this skill to systematically diagnose and resolve failures in application
workloads deployed in GKE clusters. This skill operates non-interactively and
enforces a read-only diagnostics boundary before proposing manifest or config
corrections.
project_id,cluster_name, cluster_location, workload_name, workload_namespace)
non-interactively from the user prompt, active SETTINGS.md, or active
environment defaults:
workload_namespace to default if omitted.config current-context or gcloud config get-value project`).
environment defaults to ensure autonomous execution flow.
{cluster_name} --region/--zone {cluster_location}`
non-existent, or live command execution fails (such as in sandboxed
evaluations, dry-run mode, or offline analysis):
overflow in unreachable cluster scenarios.
kubectl diagnosticcommands for the human operator to run.
manifest fix based on the reported symptoms.
timestamp, use it as {issue_time}.
calculate the corresponding UTC timestamp based on current system
time, and use it as {issue_time}.
{issue_time}.
{issue_time} (start_time = {issue_time} - 30m, end_time =
{issue_time} + 30m).
--------------------------------------------------------------------------------
Inspect the workload's active pod states and controller status.
Diagnostic Commands:
# 1. Inspect the deployment's actual selector labels:
kubectl get deployment {workload_name} -n {workload_namespace} -o jsonpath='{.spec.selector.matchLabels}'
# 2. Query the pods using the returned labels, for example:
kubectl get pods -l {selector_labels} -n {workload_namespace}
kubectl get deploy/{workload_name} -n {workload_namespace} -o yaml
Namespace Events)**.
using:
kubectl get pod {pod_name} -n {workload_namespace} -o jsonpath='{.status.containerStatuses[*].lastState.terminated}'
(Inspect Logs)** and inspect container startup command to differentiate
between an application-level memory leak/loop vs an infrastructure
capacity limit mismatch, then proceed to Step 5 to propose fixes.
Proceed directly to Step 3 (Inspect Logs).
pulling. Proceed directly to Step 2 (Query Namespace Events).
--------------------------------------------------------------------------------
Look for infrastructure, volume, image, or scheduling alerts in GKE.
Diagnostic Command:
kubectl get events -n {workload_namespace} --sort-by='.metadata.creationTimestamp'
# Or query Cloud Logging for historical GKE events within the time window:
gcloud logging read "resource.type=\"k8s_cluster\" AND logName=\"projects/{project_id}/logs/events\" AND jsonPayload.involvedObject.namespace=\"{workload_namespace}\"" --start-time="{start_time}" --end-time="{end_time}" --project="{project_id}"
*Note: Retrieve the sorted events list and manually inspect the event timestamps
(CreationTimestamp/LastSeen) to identify failures occurring within the
{start_time} and {end_time} window.*
FailedScheduling: Node resource exhaustion. Look for messages like0/3 nodes are available: 3 Insufficient memory. or missing node affinity
tolerations (e.g. Spot VM taints).
FailedMount:PVC).Secret "{secret_name}" not found).ConfigMap "{configmap_name}" not found).Failed / BackOff (Image Pull):ImagePullBackOff).
for this workload. Run `git log -p -S "{image_name}" --
{manifest_file_path} (or use git log` on the folder containing
manifests) to identify the previous working tag in Git.
tag from the last successful commit.
correcting the tag version in the manifest patch.
--------------------------------------------------------------------------------
Extract exceptions and stack traces from the application runtime.
Diagnostic Commands:
# Check current active log stream (handles multi-container pods)
kubectl logs {pod_name} -n {workload_namespace} --all-containers --tail=100
# Check logs from previously terminated container instances (handles multi-container pods)
kubectl logs {pod_name} -n {workload_namespace} --all-containers -p --tail=100
commands (spec.containers[*].command). Differentiate between an
Application Code Leak/Loop (unbounded array appending, memory leak
signatures) vs an Infrastructure Capacity Ceiling Mismatch (legitimate
workload demand exceeding limits).
traces (e.g., panic:, NullPointerException, `Traceback (most recent
call)`). This indicates an application bug.
timed out, dial tcp: i/o timeout`). Proceed to **Step 4 (Verify
Connectivity)**.
Read-only file system, Permission denied when writing to /tmp or
/var/log). Propose adding an emptyDir volume mount to that directory in
the manifest.
--------------------------------------------------------------------------------
Troubleshoot connection drops to other services.
Diagnostic Commands:
# Verify target endpoint is active
kubectl get endpoints {target_service_name} -n {target_namespace}
# Query network policies inside namespace
kubectl get networkpolicies -n {workload_namespace} -o yaml
kubectl get endpoints returns an empty list, the targetmicroservice itself is failing to schedule or boot (troubleshoot target
service).
NetworkPolicyegress blocks to verify if egress traffic to the target service's
IP/port is allowed.
kubectl queries fail or cluster connection is unavailable, doNOT retry live cluster access or enter repetitive connection attempts.
worker.py,app.go, DB connection strings) or Deployment manifests to identify the
target service hostname (e.g. account-db) and destination port (e.g.
5432).
kubectl get endpoints and `kubectl getnetworkpolicies` commands for the user, and synthesize the required
NetworkPolicy egress patch allowing traffic to the target service and
port.
--------------------------------------------------------------------------------
Following the GitOps boundary, do not apply patches directly to the cluster.
*"payment-api is failing with exit code 137 because its memory limit is set
to 256Mi while actual usage spiked to 270Mi"*).
missing Secret mounts, or add tolerations for Spot nodes).
workload/failure. If so, update the existing branch/PR or notify the user
instead of creating a duplicate. Otherwise, create a branch, commit the
change, open a Pull Request (PR) on GitHub, and conclude the workflow (do
not wait for human merge).
Take google/gke-workload-troubleshooting 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.