节点异常时先确认调度和驱逐路径

📅 发布时间:2026/8/27 17:19:44
节点异常时先确认调度和驱逐路径
节点异常时先确认调度和驱逐路径节点进入NodeNotReady时先检查条件事件、磁盘水位和驱逐记录再判断是否需要迁移工作负载。不要直接把单个症状归因于某个服务。使用kubectl调取节点的 Event 事件与 Kubelet 日志进行分析kubectl describe node k8s-node-04 | grep -A 5 Conditions # Status: False, Reason: KubeletHasDiskPressure, Message: kubelet has disk pressure journalctl -u kubelet -n 100 --no-pager | grep -i eviction # 输出了 Attempting to evict pods due to disk pressure ...登录故障宿主机排查发现数据目录/var/lib/docker/containers的磁盘空间已耗尽。分析原因为某个 Python 业务 Pod 发生未捕获的重试异常持续向标准输出stdout写入日志而该 Pod 的 Deployment 未配置日志滚动策略与日志卷限制。磁盘空间满导致 Kubelet 无法正常更新 NodeLease 心跳进而被控制面判定为节点不可用。在 Kubernetes 的生产实践中类似的反模式若未能规避在特定边界条件下容易引发连锁服务异常。节点状态变为 NodeNotReady排查容器日志无限制导致的磁盘满。在容器化最佳实践中通常建议将应用日志输出至标准输出stdout/stderr由 DaemonSet 统一采集。但若忽略了容器引擎层Docker / Containerd的日志轮转Log Rotation配置将存在安全隐患。当业务代码出现无限重试并大量打印日志时宿主机的根分区或/var分区可能在短时间内被单个容器的日志文件填满。当磁盘可用空间低于 Kubelet 预设的阈值如imagefs.available15%或nodefs.available10%时Kubelet 会触发 DiskPressure 状态并开始驱逐 Pod。若驱逐速度滞后于日志写入速度Kubelet 进程将出现响应延迟。应根据运行时、日志采集链路和节点磁盘容量配置日志轮转与保留上限例如修改/etc/docker/daemon.json或对应的 Containerd 配置{ log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 } }避免默认命名空间滥用规范 ResourceQuota 与 HostPath 挂载。常见的反模式之一是将生产服务混杂部署于default命名空间且未配置 ResourceQuota 限制。这可能导致单一服务的内存泄漏消耗整个命名空间的资源配额。另一项高危配置是滥用hostPath挂载。部分开发者为了读取宿主机配置将宿主机的/或/etc目录直接通过hostPath挂载进容器。若容器存在安全漏洞被控制攻击者可能通过修改宿主机配置文件获取控制权限。规避hostPath的标准规范包括业务配置统一使用ConfigMap或Secret进行管理。临时文件存储使用emptyDir: { medium: Memory, sizeLimit: 512Mi }。有状态服务部署防误用避免共享存储并发写入导致的锁冲突。另一典型反模式是使用 Deployment 部署服务同时为其挂载允许并发读写的共享存储卷如 ReadWriteMany 的 NFS 或 CephFS并由多个 Pod 共同写入同一个文件或 SQLite 数据库。在 RollingUpdate滚动更新过程中新旧 Pod 会同时处于运行状态。在缺少分布式锁控制的情况下多个 Pod 并发写入同一文件易引发文件破坏或数据库文件锁死如database is locked进而导致服务不可用。工程规范要求有状态写操作必须使用StatefulSet结合volumeClaimTemplates为每个 Pod 绑定独立的 PVPersistentVolume。共享只读数据存储卷挂载模式应明确声明为ReadOnlyMany。优化 CoreDNS 域名解析瓶颈规避 ndots 检索域多次轮询损耗。在 Kubernetes 中Pod 默认的dnsConfig将ndots参数设为5。这意味着当应用发起针对api.example.com的域名解析请求时由于域名中的点号.数量小于 5Kubelet 会按照/etc/resolv.conf中的搜索域依次轮询查询api.example.com.prod.svc.cluster.local(返回 NXDOMAIN)api.example.com.svc.cluster.local(返回 NXDOMAIN)api.example.com.cluster.local(返回 NXDOMAIN)api.example.com(解析成功)每一次外部 HTTP 调用均产生了 4 次 DNS 查询。在高并发场景下可能导致 CoreDNS CPU 占用升高甚至丢包使应用出现i/o timeout解析超时。以下为一个基于 Python 编写的 Kubernetes 巡检脚本能够调用 K8s API 自动检测集群内部存在的反模式配置如未配置 Resource Limit、使用 HostPath 挂载、缺少存活性探针import sys from typing import List, Dict, Any from kubernetes import client, config from kubernetes.client.rest import ApiException class K8sAntiPatternChecker: def __init__(self, namespace: str default): self.namespace namespace try: config.load_kube_config() except Exception: config.load_in_cluster_config() self.v1 client.CoreV1Api() def audit_pods(self) - List[Dict[str, Any]]: issues [] try: pods self.v1.list_namespaced_pod(namespaceself.namespace) for pod in pods.items: pod_name pod.metadata.name # 1. 检查 HostPath 挂载 if pod.spec.volumes: for vol in pod.spec.volumes: if vol.host_path: issues.append({ pod: pod_name, level: HIGH, rule: HostPath Mounting, message: f使用了 HostPath 挂载: {vol.host_path.path} }) # 2. 检查 Resource Limits 与 Probes for container in pod.spec.containers: c_name container.name res container.resources if not res or not res.limits or cpu not in res.limits: issues.append({ pod: pod_name, level: MEDIUM, rule: Missing CPU Limit, message: f容器 {c_name} 未配置 CPU Limit 限制 }) if not res or not res.limits or memory not in res.limits: issues.append({ pod: pod_name, level: HIGH, rule: Missing Memory Limit, message: f容器 {c_name} 未配置 Memory Limit 限制 }) if not container.liveness_probe: issues.append({ pod: pod_name, level: LOW, rule: Missing LivenessProbe, message: f容器 {c_name} 未配置 LivenessProbe 探针 }) except ApiException as e: print(f[ERROR] 调用 Kubernetes API 失败: {e}, filesys.stderr) sys.exit(1) except Exception as e: print(f[ERROR] 巡检发生未预期错误: {str(e)}, filesys.stderr) sys.exit(1) return issues if __name__ __main__: ns sys.argv[1] if len(sys.argv) 1 else default checker K8sAntiPatternChecker(namespacens) audit_results checker.audit_pods() print(f K8s 配置反模式巡检报告 [Namespace: {ns}] ) if not audit_results: print(SUCCESS: 未检测到常见的 K8s 部署反模式) else: for item in audit_results: print(f[{item[level]}] Pod: {item[pod]} | 规则: {item[rule]} - {item[message]}) has_high any(i[level] HIGH for i in audit_results) if has_high: print(\n结论: 检测到高危配置项请修正后再部署。) sys.exit(2)通过限制标准日志输出、禁止非必要的宿主机挂载、规范存储卷类型以及优化 DNS 查询检索域能够有效提升 Kubernetes 集群的稳定性与容错能力。