npx skills add ...
npx skills add google/skills --skill 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 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: it only proposes fixes — whether
Kubernetes manifest/config patches or Google Cloud changes (for example gcloud
IAM bindings or node-pool recreation) — and never executes live mutations
itself.
Parameter Extraction: Extract required context (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.kubectl config current-context or gcloud config get-value project).Cluster Credentials & Fallback Mode:
gcloud container clusters get-credentials {cluster_name} --region/--zone {cluster_location}kubectl diagnostic
commands for the human operator to run.Time Handling & Fallbacks:
{issue_time}.{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:
Phase: Pending:
State: CrashLoopBackOff / Error:
kubelet restarts it with
an increasing back-off delay of up to five minutes. First read the
terminated reason and exit code:restartPolicy: Always restarts the finished
process, creating the loop. Common causes: the command/entrypoint
does not start a persistent process, a worker exits on an empty queue,
or a missing/invalid config (e.g., an unattached or mis-keyed
ConfigMap volume) makes the app exit cleanly. Proceed to Step 3
(Inspect Logs).command/entrypoint — the executable path
is wrong or absent in the image. Verify the container command in the
manifest.401/403) on Google Cloud
calls (check the Pod's IAM / Workload Identity Federation). Proceed
directly to Step 3 (Inspect Logs).State: ImagePullBackOff / ErrImagePull:
ImagePullBackOff means it
keeps retrying with back-off; ErrImagePull is a general,
non-recoverable pull error. Related statuses: InvalidImageName,
RegistryUnavailable, SignatureValidationFailed, ImageInspectError.
Proceed to Step 2 (Query Namespace Events) to read the exact pull
error message.State: ContainerCreating:
Look for infrastructure, volume, image, or scheduling alerts in GKE.
Diagnostic Command:
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 like
0/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): First read the exact event message
(Failed to pull image "IMAGE": ...) and triage by what it actually says.
Do not jump to IAM / node service-account investigation unless the
message is genuinely a permission or authentication error.
Wrong image name/tag — start here (not found, manifest unknown,
InvalidImageName): the most common cause — the tag or path is wrong,
or the image was deleted, frequently introduced by a recent deployment
change.
git log -p -S "{image_name}" -- {manifest_file_path} (or run git log on
the folder containing manifests).Permission / authentication errors only (the message contains 403 Forbidden / denied, or 401 Unauthorized / unauthorized): the node
cannot authorize or authenticate to the registry. Pursue the checks
below only when the message matches.
403 Forbidden (authorization) — the node pool service account
(or the imagePullSecret's service account) is missing registry read
access. Suggest granting it by presenting the following command
for the user to review and run; do not execute it. For Artifact
Registry:
For Container Registry (gcr.io), grant
roles/storage.objectViewer on the backing bucket (or the Artifact
Registry role if gcr.io was migrated). Also check that any VPC
Service Controls perimeter allows Artifact Registry.
401 Unauthorized (authentication) — the node service account
is disabled or the node lacks the required OAuth scope:
Scopes must include devstorage.read_only or cloud-platform
(provided by gke-default). Nodes are immutable, so suggest
recreating the node pool with --scopes="gke-default" if the scope
is missing — present it as a proposed command for the user to run,
do not execute it.
Private / self-hosted registry: ensure a valid imagePullSecret
exists and is referenced by the Deployment.
Other statuses: RegistryUnavailable / i/o timeout / DNS server misbehaving → registry network path (DNS, firewall egress, Google API
connectivity); exec format error or a deprecated schema-1 image →
architecture/schema mismatch.
Extract exceptions and stack traces from the application runtime.
Diagnostic Commands:
Out-of-Memory (OOM) Analysis: First confirm and classify the kill.
Container-level OOM (most common): kubectl describe pod shows
Last State: Terminated, Reason: OOMKilled, Exit Code: 137. The
container exceeded its cgroup memory limit. Differentiate an
application memory leak/loop (unbounded growth in logs and startup
command) from an infrastructure capacity mismatch (legitimate demand
exceeding resources.limits.memory).
Node-level (system) OOM: the entire node ran out of memory; look for evicted Pods and node-pressure eviction. The combined memory of all Pods exceeded node capacity.
"Invisible" OOM (cgroup v1): a child process is killed but the
main process (PID 1) keeps running, so Kubernetes never marks
OOMKilled. Search node logs in Cloud Logging:
A TaskOOM entry confirms an OOM kill; match its container ID to the
ContainerDied entry to find the affected Pod. On the node, journalctl -k distinguishes container-level kills (memory cgroup, memcg) from
system-level kills (Out of memory: Killed process).
Do not rely solely on sampled memory metrics — they often miss the spike that triggers the kill. Then proceed to Step 5 to propose fixes (raise limits, fix the leak, or right-size the node pool).
Liveness Probe Failure (CrashLoop with no application error): if the
container restarts but its logs show no crash, the kubelet may be killing
it on failed liveness probes (default failureThreshold: 3). Confirm in
Cloud Logging:
Common fixes: correct the probe type/path/port, raise initialDelaySeconds
or timeoutSeconds/failureThreshold for slow starts, or relieve CPU/disk
I/O contention causing probe timeouts. Keep probe commands lightweight.
Stack Trace / Unhandled Exception: Look for language-specific stack
traces (e.g., panic:, NullPointerException, Traceback (most recent call)). This indicates an application bug.
Egress Network Timeout: Look for connection timeouts (e.g., Connection timed out, dial tcp: i/o timeout). Proceed to Step 4 (Verify
Connectivity).
Permission Errors (ReadOnlyRootFilesystem): Look for write errors (e.g.,
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:
Live Cluster Mode:
kubectl get endpoints returns an empty list, the target
microservice itself is failing to schedule or boot (troubleshoot target
service).NetworkPolicy
egress blocks to verify if egress traffic to the target service's
IP/port is allowed.Sandboxed / Dry-Run Mode:
kubectl queries fail or cluster connection is unavailable, do
NOT 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 get networkpolicies 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 changes directly — this includes
both cluster manifest/config patches and any Google Cloud mutations (for example
gcloud IAM bindings or node-pool recreation). Present every change as a
reviewable suggestion: a manifest patch / PR, or a command for the user to run.