mcpField
G
gke-node-notready

gke-node-notready

github.com/google云与 DevOps21.6k2.9k 次安装今天更新
代码仓库

关于 gke-node-notready

用于诊断状态为 `NotReady` 或 `Ready: Unknown` 的 GKE 节点并提出修复建议的只读技能。它收集节点、日志和指标证据,所有修复操作均由人工执行。

主要功能

  1. 01检查节点状况和事件
  2. 02分析 kubelet 与串行日志
  3. 03追查常见运行时和资源问题
  4. 04排查网络与准入问题
  5. 05提出修复建议但不更改集群

适用场景

  1. 01调查持续处于 NotReady 的 GKE 节点
  2. 02结合 kubelet 错误与节点压力分析
  3. 03为人工处理准备证据和修复方案

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/google/skills --skill gke-node-notready

安装后在 Claude Code 中输入/gke-node-notready确认已加载。

附带文件references/attribution.md

详细介绍

GKE 节点 NotReady 故障排查技能

使用此技能系统地诊断一个或多个 GKE 节点报告 NotReady(或 Ready: Unknown)状态的原因,并提出安全的修复方案。NotReady 状态意味着节点的 kubelet 未能正确向控制平面报告,因此 Kubernetes 会停止在该节点上调度新 Pod,从而降低应用容量并可能导致停机。

此技能以非交互方式运行,并严格遵循只读诊断边界:先收集证据,再提出修复方案(供人工执行的 kubectl/gcloud 命令或 GitOps 清单变更)。绝不自动修改集群、排空、删除或重新创建节点。

重要

首先排除预期情况导致的 NotReady:正在新建、升级、修复、隔离或缩容的节点可能会暂时报告 NotReady。只有在超过预期时限后仍持续出现时,才将其视为故障。

归属信息

必须阅读:执行任何 gcloud、REST API 或 MCP 命令前,必须阅读 Usage Attribution。对于直接在终端中执行的命令(绝不能在生成的脚本、Terraform 或用户代码中执行),请在 gcloud 前添加前缀 CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:gke-node-notready)",并将 agent-skills/1.0 (skill:gke-node-notready) 添加到 User-Agent 标头。

🔍 诊断工作流

步骤 0:发现上下文并确定时间范围
  1. 提取参数 — 从用户提示、当前有效的 SETTINGS.md 或环境默认值(kubectl config current-context、gcloud config get-value project)中,以非交互方式获取 project_id、cluster_name、cluster_location 和 node_name。
  2. 凭据与回退方案 — 尝试执行 gcloud container clusters get-credentials {cluster_name} --location {cluster_location} --project {project_id}。如果无法访问集群或命令失败(沙盒、试运行或离线环境),请提供供人工运行的准确诊断命令,并根据报告的症状继续分析。
  3. 时间范围 — 确定 {issue_time}(明确指定、相对时间或当前时间),并以其为中心设定 1 小时时间范围(start = issue_time - 30m、end = issue_time + 30m),用于所有日志和指标查询。

步骤 1:识别 NotReady 节点并收集初始状态
# 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}"

也可以通过 Cloud Logging 查询(当 kubectl 访问受限或需要查看历史事件时优先使用)。请将其作为 Logs Explorer 深层链接打开——对查询进行 URL 编码,并附加项目和步骤 0 中的时间范围: https://console.cloud.google.com/logs/query;query={URL_ENCODED_QUERY};timeRange={start}%2F{end}?project={project_id} (将 / 编码为 %2F,或使用 ;duration=PT1H 表示滚动的一小时范围):

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

解读 Conditions 表:

  • Ready: False / Ready: Unknown,且原因是 KubeletNotReady / NodeStatusUnknown(“Kubelet stopped posting node status”)→ kubelet 或运行时问题;继续执行步骤 2。
  • MemoryPressure: True、DiskPressure: True、PIDPressure: True → 资源耗尽;转到步骤 4b。
  • NetworkUnavailable: True → 网络/CNI 问题;转到步骤 4d。

步骤 2:扫描 kubelet 日志,查找错误特征

使用与步骤 1 相同的 logs/query;query={URL_ENCODED_QUERY};timeRange=...?project=... 模式,将这些 kubelet 日志作为 Logs Explorer 深层链接打开。

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

还要查看节点的串行控制台日志(log_id("serialconsole.googleapis.com/serial_port_1_output") 或 resource.type="gce_instance" 串行日志),查找与 kubelet 故障相关的内核 TaskHung、OOM-killer 或磁盘 I/O 错误。


第 3 步:将特征映射到根因(决策表)
Kubelet / 事件特征可能的根因转到
runtime is down、Container runtime not ready、/run/containerd/containerd.sock 上的错误(connection refused / DeadlineExceeded)容器运行时(containerd)已停止或无响应第 4a 步
Got sys oom event from cadvisor / 串行日志中的内核 OOM-killer系统(节点级)OOM 终止了关键进程第 4b 步
PLEG is not healthyPLEG 停滞,通常由节点过载(CPU/磁盘)导致第 4c 步
containerd/kubelet 出现 TaskHung,磁盘延迟高磁盘限流 / I/O 资源不足第 4b 步
failed to ensure lease、leases.coordination.k8s.io ... namespace kube-node-lease ... terminatingkube-node-lease 终止 → NotReady 状态反复切换第 4f 步
Kubelet 无法访问 API 服务器,出现 TLS/拨号超时Kubelet ↔ 控制平面连接问题第 4d 步
NetworkPluginNotReady、cni plugin not initialized、NetworkUnavailableCNI 插件故障第 4d 步
节点关键 DaemonSet Pod(CNI、kube-proxy、metadata)无法通过准入准入 Webhook 干扰第 4e 步
只有通用的 NodeNotReady,没有其他特征原因不明 — 扩大排查范围至第 4d 步,然后升级处理升级处理

第 4 步:分支排查
4a. 容器运行时(containerd)已停止

确认 kubelet 无法与 containerd 通信(参见上述套接字错误)。检查串行日志中是否有 containerd 重启/崩溃记录。修复措施(提出建议,不要执行): 重建/修复节点(运行 kubectl drain,然后让节点池重建节点;或运行 gcloud container clusters upgrade/节点自动修复);如果多个节点都反复出现此问题, 则怀疑是节点映像或自定义 DaemonSet 干扰了 containerd。

4b. 资源压力与 OOM
# Node allocatable vs. usage.
kubectl describe node "{node_name}" | sed -n '/Allocated resources/,/Events/p'

要检查的 Cloud Monitoring 指标(只读):kubernetes.io/node/memory/used_bytes、 kubernetes.io/node/cpu/core_usage_time、kubernetes.io/node/ephemeral_storage/used_bytes。

  • DiskPressure / 磁盘限流:启动磁盘已满或 PD 速度较慢 → 增大磁盘 容量 / 使用速度更快的 PD 类型;减少映像/日志的频繁变更。
  • 系统 OOM:节点内存耗尽 → 设置/提高 Pod 内存 requests/limits, 减少超额分配,或使用更大规格的机器。区分系统 OOM (影响整个节点,会终止 kubelet/运行时)与 cgroup OOM(仅影响单个容器)。
  • PIDPressure:进程过多 → 限制 Pod 的 PID 数量 / 降低工作负载密度。
4c. PLEG 不健康

PLEG is not healthy 几乎总是意味着节点过载(CPU 饱和、 磁盘延迟,或每个节点上的 Pod/容器过多),导致运行时无法及时重新列出。 将其与第 4b 步中的指标进行关联。**修复措施:**降低节点密度,增加 CPU/磁盘余量,或分散工作负载。

4d. 网络
# Are node-critical networking Pods healthy on this node?
kubectl get pods -n kube-system -o wide --field-selector spec.nodeName={node_name}
  • Kubelet ↔ 控制平面:连接 API 服务器时出现拨号/TLS 超时 → 检查 防火墙规则、Private Google Access、授权网络以及路由/NAT 变更。
  • CNI 故障(NetworkPluginNotReady):节点上的 CNI DaemonSet (netd/calico/dataplane)未运行 → 检查这些 Pod 的日志/事件。
4e. 准入 Webhook 干扰

配置错误或发生故障且作用范围较广的验证型或变更型 Webhook,可能会 阻止节点关键系统 Pod 通过准入,导致节点保持 NotReady 状态。

kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations

查找拦截 kube-system / 节点关键对象且设置了 failurePolicy: Fail 的 Webhook。**修复措施(提出建议):**将 Webhook 的作用范围排除 kube-system/节点关键命名空间,或设置适当的 namespaceSelector。

4f. kube-node-lease 终止状态反复

如果节点反复变为 NotReady,并出现 leases.coordination.k8s.io ... namespace kube-node-lease ... is being terminated,则 kube-node-lease 命名空间已被删除或正在终止。修复建议: 不要删除 kube-node-lease 命名空间;如果它正在终止,请确定阻止其终止的 finalizer/操作者,并恢复该命名空间。


第 5 步:修复边界与升级处理
  • 提供根本原因 + 证据(观察到的确切条件、事件、日志行 或指标)。提供相关条目的 Cloud Logging 深层链接(以及第 4b 步指标对应的 Cloud Monitoring 链接), 使用第 1-2 步中的深层链接格式,方便人工直接打开证据。
  • 将修复方案作为命令或 GitOps 清单变更提出,供人工应用 — 绝不要自动应用修复、排空节点或重新创建节点。 以下情况需要升级处理(此时不要再提出自助诊断):

出现以下任一情况时,请升级处理:

  • 相关日志不可用 — 已被日志过滤器排除,或超出 日志存储桶的保留期限(_Default 存储桶默认保留 30 天,因此超过该期限的事故日志会被永久删除);或
  • kubelet/事件特征不在第 3 步的表格中,且分支调查后仍无法确定根本原因。

在这些情况下,请完成以下三项:

  1. 明确说明限制(例如:“该日期的 kubelet 日志已超出 30 天的 _Default 保留期限窗口,现已永久删除”)。
  2. 总结已收集的调查结果(节点条件、事件、指标,以及 _Required 存储桶中仍可用的任何 Admin Activity 审计日志;默认保留 400 天)。
  3. 根据这些调查结果转交 GKE 支持团队/升级给工程团队处理。 不要 继续提出更多自助调查,也不要在缺少证据时编造诊断结论。

参考资料

此技能源自 Google Cloud 公开文档:

  • 排查状态为 NotReady 的节点 — 节点条件,以及 kubelet / PLEG / system-OOM / containerd / kube-node-lease / CNI / admission-webhook 特征及相应修复方法。
  • 排查节点注册问题 — 适用于始终无法完成注册的节点的 Node Registration Checker。
  • 查看 GKE 日志 和 Cloud Logging 路由概览 — 日志查询(resource.type="k8s_node"、log_id("kubelet"))以及日志存储桶 的保留期限(_Default 为 30 天,_Required 为 400 天)。
  • Logs Explorer 界面 — 通过 URL 构建和分享查询(上文使用的 logs/query;query=... 深层链接 格式)。

评论

支持 Markdown