Skip to main content
skill Claude Code Gemini CLI CX Codex official · Google

gke-node-notready — Claude Code skill for GKE node diagnosis

This skill investigates why GKE nodes show NotReady or Unknown and suggests remediation steps. Use it when kubelet stops reporting status or workloads are stuck Pending because of node health.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add google/skills --skill gke-node-notready -a claude-code
Open on GitHub

What gke-node-notready does

The skill checks node conditions and events, kubelet and containerd logs, and node metrics. It uses those clues to investigate runtime failures, resource pressure, networking, or control-plane connectivity. You need the project, cluster, location, and node details, plus credentials to access the cluster for gcloud commands.

Diagnostics are read-only. The skill gathers evidence and proposes a kubectl or gcloud command, or a GitOps manifest change, for a person to apply. It will not mutate the cluster, drain nodes, or delete and recreate them. First check whether NotReady is expected during provisioning, upgrades, repairs, or scale-down. Use this for GKE node health issues; pod-level application failures and autoscaler decisions call for different skills.

What it helps with

  • trace a GKE node's NotReady or Unknown status
  • match kubelet errors to containerd failures
  • check whether resource pressure or networking is behind node issues
  • find why workloads are Pending because of node health

Example prompts for the agent

  • Find out why this GKE node is NotReady and suggest safe remediation steps.
  • Check the kubelet logs and node events for the node that stopped reporting status.
  • Determine whether these Pending workloads are caused by GKE node health.

How to install gke-node-notready

1Skills CLI (Vercel)

npx skills add google/skills --skill gke-node-notready -a claude-code

2Manually: put the files in place

~/.claude/skills/gke-node-notready/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/gke-node-notready/

From the same set172

The whole set →
bigquery-basics official google Manages BigQuery resources and runs SQL queries. Use it to create datasets, tables and views, or handle basic data ingestion and analysis. Claude Code Gemini CLI CX Codex 17,678installs cloud-run-basics official google This skill helps an agent manage Cloud Run services, jobs, and worker pools when a project needs HTTP deployment, scheduled work, or pull-based background processing. Claude Code Gemini CLI CX Codex 17,532installs gemini-api official google Connects Gemini API from Google Cloud Agent Platform to the agent. Gives access to Gemini models, multimodal input, function calling, and context caching. Claude Code Gemini CLI CX Codex 17,116installs google-cloud-recipe-auth official Google LLC This skill explains Google Cloud authentication and permissions. Use it when setting up IAM, ADC, or service accounts for local code and production workloads. Claude Code Gemini CLI CX Codex 15,450installs google-cloud-recipe-onboarding official Google LLC Guides a developer through a first Google Cloud project: CLI checks, sign-in, project setup and billing. It fits a personal first project. Claude Code Gemini CLI CX Codex 15,390installs cloud-sql-basics official google This skill helps create and explain Cloud SQL resources for MySQL, PostgreSQL, and SQL Server. Use it when setting up a database in Google Cloud. Claude Code Gemini CLI CX Codex 14,679installs google-cloud-waf-security official google This skill reviews Google Cloud workloads against the security pillar of the Well-Architected Framework and suggests actions for IAM, networks, data, and operations. Claude Code Gemini CLI CX Codex 14,620installs google-cloud-waf-cost-optimization official google Reviews Google Cloud workloads through the Well-Architected Cost Optimization pillar. Use it to inspect spending, resize resources, assess discounts, or find idle capacity. Claude Code Gemini CLI CX Codex 14,266installs

Similar

linkerd-patterns Seth Hobson Set up Linkerd in Kubernetes with patterns for mTLS, traffic policies, canary releases, and multi-cluster networking. Useful when configuring a service mesh or troubleshooting its policies. Claude Code CX Codex Cursor 10,200installs terraform-skill Anton Babenko Guides Terraform and OpenTofu refactoring, state migrations, and CI workflows. Diagnoses risks like identity churn and blast radius before generating HCL. Claude Code CX Codex Cursor +1 7,400installs wizard Matt Pocock This skill creates an interactive bash wizard for manual setup steps, CI secrets, third-party dashboards, and one-off migrations. Claude Code 553,369installs hyperframes-cli heygen-com Controls HyperFrames video workflows from the CLI: audits layouts and contrast, edits timeline clips, captures snapshots, and renders locally or in cloud runtimes. Claude Code CX Codex Cursor +1 1,200,000installs setup-pre-commit Matt Pocock This skill configures pre-commit checks for a JavaScript repository, running Prettier, type checking, and tests before each commit. Claude Code 489,289installs using-git-worktrees Jesse Vincent Prepares an isolated workspace before feature work or plan execution. It checks the repository first, then uses native worktree support or Git. Claude Code CX Codex 217,153installs finishing-a-development-branch Jesse Vincent This skill checks the test suite and guides branch completion: merge locally, open a Pull Request, or leave the work in place. Claude Code CX Codex 214,439installs orca-cli stablyai The skill lets an agent manage Orca worktrees, terminals, artifacts and the built-in browser through the orca CLI. Useful when your work already runs inside Orca. Claude Code CX Codex Cursor +1 353,000installs

Questions about gke-node-notready

How do I install gke-node-notready in Claude Code?

Run npx skills add google/skills --skill gke-node-notready -a claude-code.

What does gke-node-notready do?

It examines GKE node conditions, events, kubelet and containerd logs, and metrics, then proposes remediation steps.

Does the skill make changes to the cluster?

No. It performs read-only diagnostics and suggests commands or a GitOps manifest change for a human to apply.

Source text

SKILL.md · Apache-2.0
---
name: gke-node-notready
metadata:
  version: "1.0.1"
  category: Containers
description: >-
  Diagnoses GKE nodes reporting NotReady or Unknown status by inspecting node conditions, events, kubelet/containerd logs, and node metrics, then proposing safe remediations. Use when nodes show NotReady, when the kubelet stops posting node status, or when workloads are evicted or stuck Pending due to node health. Don't use for pod-level application failures (use gke-workload-troubleshooting), autoscaler scale-up/scale-down decisions (use gke-cluster-autoscaler), or non-GKE compute.
---

# GKE Node NotReady Troubleshooting Skill

Use this skill to systematically diagnose why one or more GKE nodes report a
`NotReady` (or `Ready: Unknown`) status and to propose safe remediations. A
`NotReady` status means the node's kubelet is not reporting to the control plane
correctly, so Kubernetes stops scheduling new Pods on the node, which can reduce
application capacity and cause downtime.

This skill operates **non-interactively** and enforces a **read-only diagnostics
boundary**: gather evidence first, then propose a fix (a `kubectl`/`gcloud`
command or a GitOps manifest change) for a human to apply. **Never** mutate the
cluster, drain, delete, or recreate nodes automatically.

> [!IMPORTANT]
> First rule out an **expected** `NotReady`: a node that is newly provisioning,
> upgrading, being repaired, cordoned, or scaling down will transiently report
> `NotReady`. Only treat it as a fault if it persists beyond the expected window.

## Attribution

**MUST READ**: Before executing any `gcloud`, REST API, or MCP command, you
MUST read [Usage Attribution](references/attribution.md). 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-node-notready)"`
and append `agent-skills/1.0 (skill:gke-node-notready)` to `User-Agent` headers.

## 🔍 Diagnostic Workflow

### Step 0: Context discovery & time window

1.  **Parameter extraction** — obtain `project_id`, `cluster_name`,
    `cluster_location`, and `node_name` non-interactively from the user prompt,
    active `SETTINGS.md`, or environment defaults (`kubectl config current-context`,
    `gcloud config get-value project`).
2.  **Credentials & fallback** — attempt
    `gcloud container clusters get-credentials {cluster_name} --location {cluster_location} --project {project_id}`.
    If the cluster is unreachable or commands fail (sandbox/dry-run/offline),
    present the exact diagnostic commands for a human to run and continue the
    analysis from the reported symptoms.
3.  **Time window** — determine `{issue_time}` (explicit, relative, or now) and
    center a 1-hour window around it (`start = issue_time - 30m`,
    `end = issue_time + 30m`) for all log/metric queries.

--------------------------------------------------------------------------------

### Step 1: Identify NotReady nodes and gather initial status

```bash
# List nodes and spot NotReady status, node IPs, and container-runtime version.
kubectl get nodes -o wide

# Inspect the affected node's Conditions and Events (the primary clues).
kubectl describe node "{node_name}"
```

Equivalent via Cloud Logging (preferred when kubectl access is limited or for
historical events). Open it as a **Logs Explorer deep link** — URL-encode the
query and append the project and Step 0 time window:
`https://console.cloud.google.com/logs/query;query={URL_ENCODED_QUERY};timeRange={start}%2F{end}?project={project_id}`
(encode `/` as `%2F`, or use `;duration=PT1H` for a rolling hour):

```
resource.type="k8s_node"
log_id("events")
resource.labels.node_name="{node_name}"
resource.labels.cluster_name="{cluster_name}"
resource.labels.location="{cluster_location}"
```

**Interpret the `Conditions` table:**

- `Ready: False` / `Ready: Unknown` with reason `KubeletNotReady` /
  `NodeStatusUnknown` ("Kubelet stopped posting node status") → kubelet or
  runtime problem; continue to Step 2.
- `MemoryPressure: True`, `DiskPressure: True`, `PIDPressure: True` → resource
  exhaustion; go to Step 4b.
- `NetworkUnavailable: True` → networking/CNI problem; go to Step 4d.

--------------------------------------------------------------------------------

### Step 2: Scan kubelet logs for error signatures

Open these kubelet logs as a **Logs Explorer deep link** using the same
`logs/query;query={URL_ENCODED_QUERY};timeRange=...?project=...` pattern as Step 1.

```
resource.type="k8s_node"
resource.labels.node_name="{node_name}"
resource.labels.cluster_name="{cluster_name}"
resource.labels.location="{cluster_location}"
log_id("kubelet")
severity>=WARNING
```

Also review the node's serial-console logs (`log_id("serialconsole.googleapis.com/serial_port_1_output")`
or the `resource.type="gce_instance"` serial logs) for kernel `TaskHung`,
OOM-killer, or disk I/O errors that correlate with the kubelet failures.

--------------------------------------------------------------------------------

### Step 3: Map the signature to a root cause (decision table)

| Kubelet / event signature | Likely root cause | Go to |
| --- | --- | --- |
| `runtime is down`, `Container runtime not ready`, errors on `/run/containerd/containerd.sock` (connection refused / DeadlineExceeded) | Container runtime (`containerd`) down or unresponsive | Step 4a |
| `Got sys oom event from cadvisor` / kernel OOM-killer in serial logs | System (node-level) OOM killed critical processes | Step 4b |
| `PLEG is not healthy` | PLEG stalled, usually node overload (CPU/disk) | Step 4c |
| `TaskHung` for `containerd`/`kubelet`, high disk latency | Disk throttling / I/O starvation | Step 4b |
| `failed to ensure lease`, `leases.coordination.k8s.io ... namespace kube-node-lease ... terminating` | `kube-node-lease` termination → NotReady flapping | Step 4f |
| Kubelet cannot reach API server, TLS/dial timeouts | Kubelet ↔ control-plane connectivity | Step 4d |
| `NetworkPluginNotReady`, `cni plugin not initialized`, `NetworkUnavailable` | CNI plugin failure | Step 4d |
| Node-critical DaemonSet Pods (CNI, kube-proxy, metadata) blocked from admission | Admission webhook interference | Step 4e |
| Only generic `NodeNotReady`, no other signature | Cause unclear — widen to Step 4d, then escalate | Escalation |

--------------------------------------------------------------------------------

### Step 4: Branch investigations

#### 4a. Container runtime (`containerd`) down

Confirm the kubelet cannot talk to containerd (socket errors above). Check for
`containerd` restarts/crashes in serial logs. **Remediation (propose, don't run):**
recreate/repair the node (`kubectl drain` then let the node pool recreate it, or
`gcloud container clusters upgrade`/node auto-repair); if it recurs across nodes,
suspect a node image or custom DaemonSet interfering with containerd.

#### 4b. Resource pressure & OOM

```bash
# Node allocatable vs. usage.
kubectl describe node "{node_name}" | sed -n '/Allocated resources/,/Events/p'
```
Cloud Monitoring metrics to inspect (read-only): `kubernetes.io/node/memory/used_bytes`,
`kubernetes.io/node/cpu/core_usage_time`, `kubernetes.io/node/ephemeral_storage/used_bytes`.
- **DiskPressure / disk throttling**: full boot disk or slow PD → increase disk
  size / use a faster PD type; reduce image/log churn.
- **System OOM**: node memory exhausted → set/raise Pod memory `requests`/`limits`,
  reduce over-commit, or use larger machine types. Distinguish **system OOM**
  (node-wide, kills kubelet/runtime) from **cgroup OOM** (single container).
- **PIDPressure**: too many processes → cap Pod PIDs / reduce workload density.

#### 4c. PLEG is not healthy

`PLEG is not healthy` almost always means the node is overloaded (CPU saturation,
disk latency, or too many Pods/containers per node) so the runtime can't relist
in time. Correlate with 4b metrics. **Remediation:** reduce node density, add
CPU/disk headroom, or spread workloads.

#### 4d. Networking

```bash
# Are node-critical networking Pods healthy on this node?
kubectl get pods -n kube-system -o wide --field-selector spec.nodeName={node_name}
```
- **Kubelet ↔ control-plane**: dial/TLS timeouts to the API server → check
  firewall rules, Private Google Access, authorized networks, and route/NAT
  changes.
- **CNI failure** (`NetworkPluginNotReady`): the CNI DaemonSet
  (`netd`/`calico`/dataplane) is not running on the node → inspect those Pods'
  logs/events.

#### 4e. Admission webhook interference

A misconfigured/failing validating or mutating webhook with a broad scope can
block node-critical system Pods from being admitted, keeping the node NotReady.

```bash
kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations
```
Look for webhooks that intercept `kube-system` / node-critical objects with
`failurePolicy: Fail`. **Remediation (propose):** scope the webhook out of
`kube-system`/node-critical namespaces or set an appropriate `namespaceSelector`.

#### 4f. `kube-node-lease` termination flapping

If the node flaps NotReady with `leases.coordination.k8s.io ... namespace
kube-node-lease ... is being terminated`, the `kube-node-lease` namespace was
deleted/terminating. **Remediation (propose):** do not delete the
`kube-node-lease` namespace; if terminating, identify the finalizer/actor holding
it and restore the namespace.

--------------------------------------------------------------------------------

### Step 5: Remediation boundary & escalation

- Present the **root cause + evidence** (the exact conditions, events, log lines,
  or metrics observed). Provide **Cloud Logging deep links** (and Cloud Monitoring
  links for the Step 4b metrics) to the supporting entries — using the deep-link
  pattern from Steps 1-2 — so a human can open the evidence directly.
- Propose the fix as a **command or GitOps manifest change** for a human to apply
  — never apply, drain, or recreate nodes automatically.
**When to escalate (do this instead of proposing more self-service diagnostics):**

Escalate when either:

- the relevant logs are **unavailable** — excluded by a logging filter, or older
  than the log bucket's retention (the `_Default` bucket defaults to 30 days, so
  incidents older than that are permanently deleted); or
- the kubelet/event signature is **not in the Step 3 table** and the root cause
  remains **undetermined** after the branch investigations.

In those cases, do all three:

1.  **State the limitation plainly** (for example, "kubelet logs for that date are
    past the 30-day `_Default` retention window and are permanently deleted").
2.  **Summarize the findings you did gather** (node conditions, events, metrics,
    and any Admin Activity audit logs still in the `_Required` bucket, default
    400-day retention).
3.  **Route to GKE support / engineering escalation with those findings.** Do
    **not** keep proposing further self-service investigation, and do **not**
    fabricate a diagnosis when the evidence is missing.

--------------------------------------------------------------------------------

## References

This skill is derived from public Google Cloud documentation:

- [Troubleshoot nodes with the NotReady status](https://cloud.google.com/kubernetes-engine/docs/troubleshooting/node-notready)
  — node conditions and the kubelet / PLEG / system-OOM / containerd /
  `kube-node-lease` / CNI / admission-webhook signatures and their remediations.
- [Troubleshoot node registration](https://cloud.google.com/kubernetes-engine/docs/troubleshooting/node-registration)
  — Node Registration Checker for nodes that never finish registering.
- [View GKE logs](https://cloud.google.com/kubernetes-engine/docs/how-to/view-logs)
  and [Cloud Logging routing overview](https://cloud.google.com/logging/docs/routing/overview)
  — log queries (`resource.type="k8s_node"`, `log_id("kubelet")`) and log-bucket
  retention (`_Default` 30 days, `_Required` 400 days).
- [Logs Explorer interface](https://cloud.google.com/logging/docs/view/logs-explorer-interface)
  — building and sharing a query by URL (the `logs/query;query=...` deep-link
  format used above).

© google · Apache-2.0 · google/skills

See also

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor