运维部署
GKE 节点持续 NotReady/Unknown 时…
适用于 GKE 节点显示 NotReady 或 Ready: Unknown、kubelet 停止上报节点状态,或工作负载因节点健康被驱逐/卡 Pending 时,先证据后建议修复。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
GKE 节点持续 NotReady/Un特定
解决思路
- 非交互式运行并遵守只读诊断边界:先收集证据,再提出修复用的 kubectl/gcloud 命令或 GitOps manifest 变更供人工应用;绝不自动变更集群、drain、删除或重建节点。
- 先排除预期 NotReady:新建、升级、修复、cordon 或缩容中的节点会短暂 NotReady;只有超过预期窗口仍持续时才按故障处理。
- 非交互式提取 project_id、cluster_name、cluster_location、node_name:从用户 prompt、当前 SETTINGS.md 或环境默认值获取,可用 kubectl config current-context 和 gcloud config get-value project。
- 尝试运行 gcloud container clusters get-credentials {cluster_name} --location {cluster_location} --project {project_id} 获取凭据。
- 如果集群不可达或命令失败(sandbox/dry-run/offline),给出准确诊断命令供人工运行,并继续根据已报告症状分析。
- 确定 {issue_time}(显式、相对或 now),并围绕它取 1 小时窗口 start=issue_time-30m、end=issue_time+30m,用于所有日志和指标查询。
- 运行 kubectl get nodes -o wide 列出节点,发现 NotReady 状态、节点 IP 和 container-runtime 版本。
- 运行 kubectl describe node "{node_name}" 查看受影响节点的 Conditions 和 Events。
- 当 kubectl 访问受限或需要历史事件时,改用 Cloud Logging:打开 Logs Explorer deep link,对 query 做 URL 编码并附加 project 和 Step 0 时间窗口:https://console.cloud.google.com/logs/query;query={URL_ENCODED_QUERY};timeRange={start}%2F{end}?project={project_id}(将 / 编码为 %2F,或用 ;duration=PT1H 表示滚动一小时)。
- 在 Cloud Logging 中查询事件: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 且 reason 为 KubeletNotReady/NodeStatusUnknown(Kubelet stopped posting node status)表示 kubelet 或 runtime 问题,继续 Step 2。
- 解释 Conditions 表:MemoryPressure: True、DiskPressure: True 或 PIDPressure: True 表示资源耗尽,转到 Step 4b。
- 解释 Conditions 表:NetworkUnavailable: True 表示网络/CNI 问题,转到 Step 4d。
- 使用 Step 1 的 deep link 模式打开 kubelet 日志: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。
- 同时查看节点 serial-console 日志(log_id("serialconsole.googleapis.com/serial_port_1_output") 或 resource.type="gce_instance" serial logs),查找与 kubelet 故障相关的 kernel TaskHung、OOM-killer 或 disk I/O errors。
- 按决策表映射签名:runtime is down、Container runtime not ready、/run/containerd/containerd.sock 连接被拒或 DeadlineExceeded → containerd 宕机或无响应 → Step 4a。
- 按决策表映射签名:Got sys oom event from cadvisor 或 serial logs 中 kernel OOM-killer → 系统(节点级)OOM 杀死关键进程 → Step 4b。
- 按决策表映射签名:PLEG is not healthy → PLEG 卡住,通常因节点过载(CPU/磁盘)→ Step 4c。
- 按决策表映射签名:containerd/kubelet 出现 TaskHung、高磁盘延迟 → 磁盘限流/I/O 饥饿 → Step 4b。
- 按决策表映射签名:failed to ensure lease、leases.coordination.k8s.io ... namespace kube-node-lease ... terminating → kube-node-lease 终止导致 NotReady flapping → Step 4f。
- 按决策表映射签名:kubelet 无法访问 API server、TLS/dial timeouts → kubelet 与控制面连通性问题 → Step 4d。
- 按决策表映射签名:NetworkPluginNotReady、cni plugin not initialized、NetworkUnavailable → CNI 插件失败 → Step 4d。
- 按决策表映射签名:节点关键 DaemonSet Pods(CNI、kube-proxy、metadata)被阻止准入 → Admission webhook 干扰 → Step 4e。
- 按决策表映射签名:只有通用 NodeNotReady 且无其他签名 → 原因不清,先扩大到 Step 4d,再升级。
- Step 4a:确认 kubelet 无法与 containerd 通信(上述 socket 错误);在 serial logs 中检查 containerd 重启/崩溃;提出修复但不执行:重建/修复节点(先 kubectl drain 再让 node pool 重建,或 gcloud container clusters upgrade/node auto-repair);如果跨节点复现,怀疑 node image 或自定义 DaemonSet 干扰 containerd。
- Step 4b:运行 kubectl describe node "{node_name}" | sed -n '/Allocated resources/,/Events/p' 查看节点 allocatable 与 usage。
- Step 4b:只读查看 Cloud Monitoring 指标:kubernetes.io/node/memory/used_bytes、kubernetes.io/node/cpu/core_usage_time、kubernetes.io/node/ephemeral_storage/used_bytes。
- Step 4b:DiskPressure/disk throttling 时,启动盘满或 PD 慢 → 增加磁盘大小或使用更快 PD 类型,并减少 image/log churn。
- Step 4b:System OOM 时,节点内存耗尽 → 设置/提高 Pod memory requests/limits,减少 over-commit,或使用更大 machine types;区分 system OOM(节点级,杀死 kubelet/runtime)和 cgroup OOM(单容器)。
- Step 4b:PIDPressure 时,进程过多 → 限制 Pod PIDs 或降低工作负载密度。
- Step 4c:PLEG is not healthy 通常意味着节点过载(CPU 饱和、磁盘延迟、每节点 Pod/容器过多)导致 runtime 无法及时 relist;与 4b 指标关联;提出修复:降低节点密度、增加 CPU/磁盘 headroom 或分散工作负载。
- Step 4d:运行 kubectl get pods -n kube-system -o wide --field-selector spec.nodeName={node_name} 检查该节点上节点关键网络 Pods 是否健康。
- Step 4d:若 kubelet 到控制面出现 dial/TLS timeouts,检查 firewall rules、Private Google Access、authorized networks 以及 route/NAT 变更。
- Step 4d:若 CNI 失败(NetworkPluginNotReady),CNI DaemonSet(netd/calico/dataplane)未在该节点运行 → 检查这些 Pods 的 logs/events。
- Step 4e:运行 kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations 检查 webhook。
- Step 4e:查找拦截 kube-system/节点关键对象且 failurePolicy: Fail 的 webhooks;提出修复:将 webhook 作用域移出 kube-system/节点关键 namespaces,或设置合适的 namespaceSelector。
- Step 4f:若节点 flapping NotReady 且出现 leases.coordination.k8s.io ... namespace kube-node-lease ... is being terminated,说明 kube-node-lease namespace 被删除/正在终止;提出修复:不要删除 kube-node-lease namespace;若正在 terminating,找出持有它的 finalizer/actor 并恢复 namespace。
- Step 5:呈现根因和证据(观察到的精确 conditions、events、log lines 或 metrics);提供 Cloud Logging deep links(以及 Step 4b 指标的 Cloud Monitoring links)让人工直接打开证据,使用 Steps 1-2 的 deep-link 模式。
- Step 5:将修复作为命令或 GitOps manifest 变更提出供人工应用;绝不自动 apply、drain 或重建节点。
- Step 5 升级条件:相关日志不可用(被 logging filter 排除,或早于 log bucket retention;_Default bucket 默认 30 天,超过则永久删除),或 kubelet/event signature 不在 Step 3 表且分支调查后根因仍未确定。
- 升级时先明确说明限制(例如:该日期的 kubelet 日志已超过 30 天 _Default retention window 并永久删除)。
- 升级时汇总已收集发现(node conditions、events、metrics,以及仍在 _Required bucket(默认 400 天保留)中的任何 Admin Activity audit logs)。
- 升级时将上述发现路由到 GKE support/engineering escalation;不要继续提出更多自助调查,也不要在证据缺失时编造诊断。
适用边界 · 注意事项
- Pod 级应用故障(应使用 gke-workload-troubleshooting)
- GKE Cluster Autoscaler 的扩容/缩容决策(应使用 gke-cluster-autoscaler)
- 非 GKE 计算环境