Gke Workload Troubleshooting
GoogleOfficialPublished by Google
- Skill
- Review and audit
- Cloud and DevOps
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured, non-interactive diagnostic workflow for troubleshooting failing GKE workloads, such as those stuck in CrashLoopBackOff, OOMKilled, or ImagePullBackOff states. It operates within a read-only boundary, analyzing pod status, events, logs, and network policies to identify root causes. Instead of executing live mutations, it synthesizes findings and proposes remediation steps, such as manifest patches or configuration changes, following a GitOps approach.
What it does
- Extracts cluster and workload context from the environment or user input.
- Analyzes pod states and conditions to identify specific failure modes.
- Queries namespace events and Cloud Logging to pinpoint infrastructure or configuration issues.
- Inspects application logs for stack traces, OOM events, and liveness probe failures.
- Verifies service connectivity and network policy configurations.
- Generates actionable GitOps remediation proposals, such as manifest patches or PRs.
When to use it
- When a GKE pod fails to start or crashes repeatedly.
- When investigating OOMKilled or ImagePullBackOff errors in a Kubernetes cluster.
- When you need to identify why a workload is stuck in a Pending or ContainerCreating state.
- When you require a systematic, non-destructive analysis of workload failures.
Advantages
- Enforces a safe, read-only diagnostic boundary by proposing rather than executing changes.
- Provides a clear, step-by-step decision tree for common Kubernetes failure modes.
- Integrates with GitOps workflows by generating manifest patches and PRs.
- Reduces manual effort by automating the correlation of logs, events, and pod status.
Usage examples
- “My pod 'payment-api' in the 'prod' namespace is stuck in CrashLoopBackOff. Can you help?”
- The agent will inspect the pod's status, check the termination reason and exit code, analyze the logs for errors, and propose a fix (e.g., memory limit adjustment or config correction) via a GitOps PR.
- “Why is my deployment failing with ImagePullBackOff?”
- The agent will query namespace events to identify the specific pull error, determine if it is an authentication or configuration issue, and suggest the appropriate fix or IAM policy update.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/google/gke-workload-troubleshooting/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip gke-workload-troubleshooting.zip -d .agents/skills
Documentation by Google
GKE Workload Troubleshooting Skill
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.
Attribution
MUST READ: Before executing any gcloud, REST API, or MCP command, you
MUST read Usage Attribution. For commands executed
directly in the terminal (never in generated scripts, Terraform, or user code),
prefix gcloud with
CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:gke-workload-troubleshooting)"
and append agent-skills/1.0 (skill:gke-workload-troubleshooting) to User-Agent headers.
🔍 Diagnostic Workflow
Step 0: Non-Interactive Context Discovery & Time Window Definition
Parameter Extraction: Extract required context (
project_id,cluster_name,cluster_location,workload_name,workload_namespace) non-interactively from the user prompt, activeSETTINGS.md, or active environment defaults:Default
workload_namespacetodefaultif omitted.Infer missing cluster parameters from active environment (
kubectl config current-contextorgcloud config get-value project).Prioritize non-interactive context discovery from prompts and environment defaults to ensure autonomous execution flow.
Cluster Credentials & Fallback Mode:
Attempt credential fetch:
gcloud container clusters get-credentials {cluster_name} --region/--zone {cluster_location}Fallback / Dry-Run Mode: If the cluster is unreachable, non-existent, or live command execution fails (such as in sandboxed evaluations, dry-run mode, or offline analysis):
Limit retry attempts to avoid resource exhaustion and context overflow in unreachable cluster scenarios.
Immediately present the exact sequence of
kubectldiagnostic commands for the human operator to run.Synthesize the root cause analysis and output the proposed GitOps manifest fix based on the reported symptoms.
Time Handling & Fallbacks:
Determine Issue Timestamp ({issue_time}):
Specific Time Provided: If the user provides a specific timestamp, use it as
{issue_time}.Relative Time Provided (e.g., "5 minutes ago"): Dynamically calculate the corresponding UTC timestamp based on current system time, and use it as
{issue_time}.No Time Provided (Default): Use current system time as
{issue_time}.
Window Calculation: Center a 1-hour query window around
{issue_time}(start_time={issue_time} - 30m,end_time={issue_time} + 30m).
Step 1: Analyze Pod Status and Conditions
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 yamlDiagnostic Decision Tree:
Phase: Pending:
The Pod cannot schedule on any node. Proceed directly to Step 2 (Query Namespace Events).
State: CrashLoopBackOff / Error:
The container boots but exits repeatedly; the
kubeletrestarts it with an increasing back-off delay of up to five minutes. First read the terminated reason and exit code:
kubectl describe pod {pod_name} -n {workload_namespace} kubectl get pod {pod_name} -n {workload_namespace} -o jsonpath='{.status.containerStatuses[*].lastState.terminated}'Reason: OOMKilled (Exit Code 137): The container's memory limit was reached. Proceed to Step 3 (Inspect Logs) → OOM Analysis to classify container-level vs node-level, then Step 5 to propose fixes.
Exit Code 0 (successful exit): Unexpected for a long-running Deployment/StatefulSet —
restartPolicy: Alwaysrestarts the finished process, creating the loop. Common causes: thecommand/entrypointdoes not start a persistent process, a worker exits on an empty queue, or a missing/invalid config (e.g., an unattached or mis-keyedConfigMapvolume) makes the app exit cleanly. Proceed to Step 3 (Inspect Logs).Exit Code 128: Invalid
command/entrypoint— the executable path is wrong or absent in the image. Verify the container command in the manifest.Exit Code 1 or other non-zero: The application crashed — configuration errors, missing/invalid env vars or config files, unreachable dependencies, or auth failures (
401/403) on Google Cloud calls (check the Pod's IAM / Workload Identity Federation). Proceed directly to Step 3 (Inspect Logs).If the exit code looks healthy but the container keeps restarting, suspect a liveness probe failure (see Step 3).
State: ImagePullBackOff / ErrImagePull:
The kubelet cannot pull the container image.
ImagePullBackOffmeans it keeps retrying with back-off;ErrImagePullis 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:
The container is blocked during volume mount, networking setup, or image pulling. Proceed directly to Step 2 (Query Namespace Events).
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}"
# Or query specifically for image pull failures within the time window:
gcloud logging read 'log_id("events") AND resource.type="k8s_pod" AND resource.labels.cluster_name="{cluster_name}" AND jsonPayload.message=~"Failed to pull image"' --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.
Signature Identifiers:
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:Missing PersistentVolumeClaim (
PVC).Missing Secret (
Secret "{secret_name}" not found).Missing ConfigMap (
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.Identify the failing container image name and the invalid tag.
Check the Git history for the last known working image tag:
git log -p -S "{image_name}" -- {manifest_file_path}(or rungit logon the folder containing manifests).Propose reverting the image tag to the last working version (or correcting the tag) in the manifest patch.
Permission / authentication errors only (the message contains
403 Forbidden/denied, or401 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:gcloud artifacts repositories add-iam-policy-binding {repository} \ --location={repo_location} \ --member="serviceAccount:{node_service_account_email}" \ --role="roles/artifactregistry.reader"For Container Registry (
gcr.io), grantroles/storage.objectVieweron the backing bucket (or the Artifact Registry role ifgcr.iowas 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:gcloud container clusters describe {cluster_name} --location={cluster_location} \ --format="table(nodePools.name,nodePools.config.serviceAccount)" gcloud iam service-accounts list \ --filter="email:{node_service_account_email} AND disabled:true" --project={project_id} gcloud compute instances describe {node_name} --zone={node_zone} \ --format="flattened(serviceAccounts[].scopes)"Scopes must include
devstorage.read_onlyorcloud-platform(provided bygke-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
imagePullSecretexists and is referenced by the Deployment.
Other statuses:
RegistryUnavailable/i/o timeout/ DNSserver misbehaving→ registry network path (DNS, firewall egress, Google API connectivity);exec format erroror a deprecated schema-1 image → architecture/schema mismatch.
Step 3: Inspect Application Logs
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=100Signature Identifiers:
Out-of-Memory (OOM) Analysis: First confirm and classify the kill.
Container-level OOM (most common):
kubectl describe podshowsLast 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 exceedingresources.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 marksOOMKilled. Search node logs in Cloud Logging:gcloud logging read 'resource.type="k8s_node" AND resource.labels.cluster_name="{cluster_name}" AND jsonPayload.MESSAGE:("TaskOOM event" OR "ContainerDied")' --project="{project_id}"A
TaskOOMentry confirms an OOM kill; match its container ID to theContainerDiedentry to find the affected Pod. On the node,journalctl -kdistinguishes 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
kubeletmay be killing it on failed liveness probes (defaultfailureThreshold: 3). Confirm in Cloud Logging:gcloud logging read 'resource.type="k8s_node" AND log_id("kubelet") AND jsonPayload.MESSAGE:"failed liveness probe, will be restarted" AND resource.labels.cluster_name="{cluster_name}"' --project="{project_id}"Common fixes: correct the probe type/path/port, raise
initialDelaySecondsortimeoutSeconds/failureThresholdfor 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 deniedwhen writing to/tmpor/var/log). Propose adding anemptyDirvolume mount to that directory in the manifest.
Step 4: Verify Service Connectivity and Network Policies
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 yamlLogic & Dry-Run Fallback:
Live Cluster Mode:
If
kubectl get endpointsreturns an empty list, the target microservice itself is failing to schedule or boot (troubleshoot target service).If endpoints exist but logs show timeouts, analyze
NetworkPolicyegress blocks to verify if egress traffic to the target service's IP/port is allowed.
Sandboxed / Dry-Run Mode:
If live
kubectlqueries fail or cluster connection is unavailable, do NOT retry live cluster access or enter repetitive connection attempts.Immediately inspect the application source code (e.g.
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).Present the exact
kubectl get endpointsandkubectl get networkpoliciescommands for the user, and synthesize the requiredNetworkPolicyegress patch allowing traffic to the target service and port.
Step 5: Propose GitOps Correction
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.
Synthesize the root cause analysis for the human operator (e.g. "payment-api is failing with exit code 137 because its memory limit is set to 256Mi while actual usage spiked to 270Mi").
Generate the corrected YAML manifest patch (e.g. increase memory limits, add missing Secret mounts, or add tolerations for Spot nodes).
Check if a branch or Pull Request (PR) already exists for this 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).
References
Files
- ATTRIBUTION.mdAdded by AutoGineer874 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md18.3 KiB
- references/attribution.md1.9 KiB
references/attribution.md
Usage Attribution
MUST READ: Before executing any gcloud, REST API, or MCP command with
this skill, follow these usage attribution instructions. Tag every command you
execute directly in the terminal so usage can be attributed. The tag identifies
only the skill and its version; it carries no user data.
gcloudCLI Commands: Prefix everygcloudinvocation, whatever the subcommand, with the metrics environment variable. Set it inline on each command because shell state may not persist between commands:CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:gke-workload-troubleshooting)" \ gcloud <command> [flags]Do not use
gcloud config setfor this: it would persist beyond the current task and mislabel unrelated usage.Direct HTTP, REST, and MCP Requests: On direct HTTP calls to Google Cloud APIs (for example with
curl) or HTTP requests to a remote MCP server, includeagent-skills/1.0 (skill:gke-workload-troubleshooting)in theUser-Agentheader. If aUser-Agentheader is already specified, append this string to the end of it rather than overwriting existingUser-Agentdata — the collection pipeline parses theagent-skills/<version>andskill:<name>tokens, so any rewording breaks attribution:User-Agent: <existing_user_agent> agent-skills/1.0 (skill:gke-workload-troubleshooting)Constraint for Generated Code: The tracking prefix is strictly for commands you execute directly in the terminal. Do NOT include this tracking prefix in generated scripts, Terraform templates, or code provided to the user for their own repositories.
User Opt-Out: If the user asks to disable or remove tracking or attribution tags, omit the
CLOUDSDK_METRICS_REQUEST_ATTRIBUTIONvariable and customUser-Agentsuffix from all commands.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs a command-line tool, Needs Node.js
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Publisher
- Google (Official)
- Source
- google/skills · skills/cloud/gke-workload-troubleshooting · commit 2194d3b
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Google.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download gke-workload-troubleshooting.zip