首页
Search
1
解决 docker run 报错 oci runtime error
49,608 阅读
2
WebStorm2025最新激活码
28,204 阅读
3
互点群、互助群、微信互助群
23,060 阅读
4
常用正则表达式
21,664 阅读
5
罗技鼠标logic g102驱动程序lghub_installer百度云下载windows LIGHTSYNC
20,037 阅读
自习室
互通有无
搞钱日记
养生记
包罗万象
Search
标签搜索
职场副业
职业发展
副业赚钱
后端开发
内容创作
微服务
分布式系统
效率提升
DevOps
技能提升
流量变现
性能优化
云原生
高并发
编程学习
深度学习
人工智能
架构设计
机器学习
前端开发
loong
累计撰写
3,206
篇文章
累计收到
4
条评论
首页
栏目
自习室
互通有无
搞钱日记
养生记
包罗万象
页面
搜索到
1
篇与
的结果
2026-01-21
深夜救火!我亲历的10大K8s诡异故障排查实录:这些坑你的集群可能正在经历
深夜救火!我亲历的10大大规模Kubernetes集群诡异故障排查实录凌晨三点,手机突然狂震。监控告警:线上核心服务Pod批量重启,CPU负载曲线像心电图一样狂跳,但日志里干净得像个乖孩子。这不是我第一次被这种‘症状清晰、病因模糊’的K8s故障从床上薅起来,也绝不会是最后一次。如果你正在管理或计划管理大规模K8s集群(比如几百个节点、上千个服务),这篇文章可能会让你少掉很多头发。我不会讲那些‘kubectl get pods’的基础操作,而是聚焦于那些真正让人抓狂、搜索无果、甚至反常识的诡异问题。这些都是我用真金白银的线上事故和无数个不眠之夜换来的经验。诡异的表象背后:我们到底在排查什么?大规模集群的复杂性呈指数级增长。问题往往不再是单个Pod起不来这么简单,而是表现为系统的、间歇的、难以复现的诡异行为。搜索这类问题的你,大概率已经过了‘新手村’,正处于‘深水区’:你懂基本操作,但面对集群级别的‘玄学’问题,仍然感到无从下手。你的痛点很明确:如何从海量噪音(metrics、日志、事件)中,精准定位那个导致业务抖动或中断的根因?下面这十大故障场景,每一个我都踩过坑,希望能成为你的排查地图。故障一:“幽灵”抢占:Pod明明资源充足,为何频繁被Evicted?现象:监控显示节点资源(CPU/Memory)远未用满,但某些Pod(尤其是低优先级的Batch Job)频繁被K8s驱逐(Evicted),报错‘Node pressure’。诡异点:kubectl describe node 看Allocatable和Allocated都对不上,总觉得有‘看不见’的资源被用了。根因与排查实录:检查Kubelet配置的System Reserved和Kube Reserved:这部分资源是预留给系统和K8s组件的,不体现在Allocatable里,但会占用实际物理资源。如果你的预留设置过高,或节点上系统/kubelet实际占用远超预留值,就会挤压Pod空间。排查隐形杀手——ephemeral-storage:这是最容易被忽略的资源!容器日志、镜像层、emptyDir卷都会快速消耗临时存储。用df -h和du命令深入节点,查看/var/lib/kubelet和/var/lib/docker(或containerd根目录)的大小。我遇到过因日志轮转配置错误,导致/var/log/pods目录暴涨触发驱逐的案例。警惕内存杀手——内存不可压缩资源:Pod的内存请求(request)如果设置过低,当Pod实际使用内存超过其Limit时,会被OOM Killer干掉。但更诡异的是,如果节点总的内存使用(包括缓存和Buffer)接近物理限制,即使Pod未超Limit,也可能因为整个节点的内存压力而‘躺枪’。关键命令:# 查看节点资源详情,重点关注Events和Allocatable kubectl describe node <node-name> # 登录节点,检查实际磁盘使用 df -h /var/lib/kubelet /var/lib/containerd du -sh /var/log/pods/* # 查看kubelet配置中的预留资源 ps aux | grep kubelet | grep -E "system-reserved|kube-reserved"故障二:网络“黑洞”:Service ClusterIP间歇性不通现象:从Pod A访问Service B的ClusterIP,大部分时间正常,但偶尔会超时或失败,直接访问Pod IP却一直正常。问题随机出现,难以捕捉。诡异点:核心网络组件(Calico/Flannel/Cilium)的日志和监控都‘岁月静好’,kubectl get endpoints也显示Endpoints正常。根因与排查实录:IPTables/IPVS的Conntrack表满:这是经典问题。在高连接数(特别是短连接)场景下,Linux连接跟踪表可能被迅速打满,导致新连接被丢弃。检查net.netfilter.nf_conntrack_count和net.netfilter.nf_conntrack_max。解决方法包括增大conntrack_max、减小conntrack_tcp_timeout_*,或者对于K8s 1.14+且使用IPVS模式的kube-proxy,其连接跟踪压力会小很多。节点级网络策略冲突:某些安全软件或手动配置的iptables规则,可能会干扰kube-proxy生成的规则链。用iptables-save | grep <service-ip>检查规则是否被意外丢弃。CoreDNS或kube-dns负载不均/缓存问题:Service域名解析失败。检查CoreDNS Pod的负载是否均衡,监控其QPS和延迟。我曾遇到CoreDNS Pod所在的节点网络异常,导致部分Pod解析超时。关键思路:这种间歇性问题,必须抓包。在客户端Pod和服务端Pod同时用tcpdump抓包,对比时间戳,看包在哪一环丢失了。故障三:调度“僵局”:高优Pod卡在Pending,节点却有空闲现象:一个关键Deployment扩缩容,新Pod一直Pending,kubectl describe显示调度失败的原因为‘0/XX nodes are available’。但明明有节点上有足够的空闲资源(kubectl top node)。诡异点:调度器日志No nodes available,但没说具体原因。根因与排查实录:NodeSelector/NodeAffinity/Affinity硬性约束不满足:这是最常见原因。仔细检查Pod的配置。Taints and Tolerations的‘潜规则’:即使Pod有Toleration能容忍节点的Taint,如果该Taint的effect是NoSchedule,且节点上还存在其他该Pod不能容忍的Taint,调度依然会失败。需要逐个核对。Pod拓扑分布约束(PodTopologySpread):这个用于实现Pod打散的特性,在结合selector时可能产生意想不到的调度死锁。例如,要求Pod在zone间均匀分布,但某个zone的节点都不满足其他选择器要求。资源碎片化:节点有空闲CPU,但可能都是‘碎片’。比如节点剩4个核,但Pod请求requests.cpu: 2.5,无法满足。kubectl describe node看的是总量,但调度器看的是可分配块。关键命令:# 查看调度失败的具体详情 kubectl describe pod <pending-pod-name> # 查看调度器日志(需开启相应日志级别) kubectl logs -n kube-system <scheduler-pod-name> --tail=100 | grep <pending-pod-name>故障四:存储“断联”:PVC突然只读,卷无法挂载现象:运行了很长时间的有状态应用(如数据库),突然报‘Read-only file system’或新Pod因‘Unable to mount volume’启动失败。使用云盘或Ceph等网络存储时尤其常见。诡异点:存储后端自身监控显示一切正常,节点dmesg或journalctl里可能有隐蔽的错误日志。根因与排查实录:云盘被意外卸载或节点漂移:在云环境中,节点VM发生维护性重启或迁移时,如果CSI驱动处理不当,可能导致磁盘从旧节点‘卸载’后,在新节点‘挂载’失败,状态卡住。iSCSI/FC连接中断与重连失败:网络闪断可能导致存储连接断开,重连协议超时后,卷被标记为故障。检查节点的multipath -ll状态和存储客户端日志。文件系统损坏:某些极端情况下(如节点突然断电),文件系统可能损坏,触发只读保护。需要fsck修复,但务必先完整备份数据!StorageClass的回收策略(reclaimPolicy)是Delete:这是高危配置! 删除PVC时,会联动删除后端PV和物理数据。务必确认生产环境StorageClass的reclaimPolicy设置为Retain。关键步骤:立即将业务切换到备用实例(如果有),然后对问题节点执行:dmesg -T | tail -100, journalctl -u kubelet --since "5 minutes ago",并与存储管理员联动。故障五:镜像“拉取”迷思:ImagePullBackOff背后的隐藏错误现象:Pod状态ImagePullBackOff,错误信息就是简单的‘pull access denied’。但用同样的imagePullSecret在其他命名空间或集群拉取都正常。诡异点:kubectl describe pod的错误信息过于笼统,掩盖了真实原因。根因与排查实录:私有仓库证书问题:节点时钟不同步,导致HTTPS证书验证失败。或者,仓库使用的自签名证书未添加到节点的Docker/Containerd信任链中。ImagePullSecret格式或挂载问题:Secret中的.dockerconfigjson格式错误,或Secret未被正确引用/挂载到Pod使用的ServiceAccount上。检查kubectl get secret <secret-name> -o yaml,确认data字段的.dockerconfigjson内容完整且为base64编码的合法JSON。仓库网络策略或防火墙:某些集群网络策略(NetworkPolicy)可能限制了Pod对特定外部IP(仓库地址)的访问。或者节点所在主机的防火墙规则阻止了443端口。镜像仓库限流或宕机:尤其是使用Docker Hub免费账号时,很容易触发限流。查看节点上容器运行时的拉取日志。关键命令:# 模拟节点拉取镜像,在节点上执行 crictl pull <your-image-name> # 查看容器运行时日志(以containerd为例) journalctl -u containerd --since "1 hour ago" | grep -i pull故障六:API“心跳”骤停:kube-apiserver间歇性高延迟或中断现象:kubectl命令间歇性变慢或超时,监控显示apiserver的P99延迟飙高,但CPU/内存使用率并不高。诡异点:问题周期性出现,与业务高峰不重合,重启apiserver Pod能暂时缓解。根因与排查实录:Etcd性能瓶颈:Apiserver的后端是etcd。etcd的磁盘IOPS/延迟是生命线。使用etcdctl endpoint status检查etcd集群健康度和leader状态。我曾遇到一个案例,是etcd所在的云盘性能达到上限,导致写请求堆积。Apiserver的请求过滤器(Filter)或认证/授权组件(Webhook)性能问题:如果启用了审计日志、动态准入控制(Mutating/Validating Webhook),这些外部Webhook服务响应慢会直接拖垮apiserver。检查apiserver日志中是否有大量超时警告。资源泄漏或客户端连接数暴增:某些失控的Controller或客户端可能会创建大量LIST/WATCH连接,耗尽apiserver资源。使用ss或netstat查看apiserver进程的连接数。关键工具:使用kubectl get --raw=/readyz和/livez检查apiserver健康状态,并使用kube-apiserver的metrics接口(通常是/metrics)分析请求延迟和错误码分布。故障七:DNS“风暴”:CoreDNS因解析请求过多而崩溃现象:集群内服务发现时好时坏,CoreDNS Pod的CPU使用率持续100%,频繁重启。nslookup间歇性失败。诡异点:业务流量并未显著增长,但DNS请求量异常飙升。根因与排查实录:应用程序的DNS查询策略不佳:某些Java应用(特别是使用JNDI的)或配置了不当DNS缓存的客户端,会对每个连接都发起一次DNS查询,产生海量请求。就绪探针(Readiness Probe)使用主机名而非IP:如果大量Pod的Readiness Probe配置为http://service-name:port/health,那么每次执行探针都会触发一次DNS查询。在Pod数量巨大时,DNS请求量将是(Pod数量 * 探针频率)的恐怖级别。CoreDNS缓存配置不当或内存不足:缓存太小(cache插件)或未启用缓存,导致所有请求都穿透到上游。CoreDNS Pod的内存Limit设置过低,在请求量大时可能OOM。解决方案:优化应用,使用连接池并缓存DNS结果。将就绪探针的地址改为ClusterIP或Pod IP。调整CoreDNS配置:增大缓存(cache [TTL] [ZONES...]),启用负载均衡(loadbalance),并适当增加其CPU/内存资源。故障八:节点“假死”:Kubelet状态为Ready,但Pod无法通信现象:kubectl get node显示节点状态为Ready,但节点上的Pod无法被访问(服务无响应),且kubectl exec进入Pod也失败。诡异点:节点看起来是健康的,但网络平面或容器运行时层面已“脑裂”。根因与排查实录:容器运行时(Docker/Containerd)无响应:运行时进程僵死或陷入内核死锁。systemctl status containerd或dockerd可能显示active (running),但实际已无法处理请求。需要重启容器运行时(但要做好Pod中断的准备)。CNI插件故障:网络插件(如Calico的calico-node、Flannel的kube-flannel)的Pod在该节点上CrashLoopBackOff,导致网络配置无法下发。检查kubectl get pods -n kube-system -o wide | grep <node-name>。节点负载极高,进程被Stall:由于磁盘IO、内存交换(Swap)或内核Bug导致系统完全无响应,虽然kubelet的心跳线程还能工作,但其他所有进程都已停滞。登录节点(如果还能登录)执行top,并查看dmesg。紧急处理:将该节点标记为不可调度并驱逐Pod:kubectl cordon <node-name> 然后 kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data。如果drain失败,再考虑重启节点。故障九:配置“漂移”:看似相同的YAML,在不同集群表现迥异现象:同一份Deployment YAML,在开发集群运行完美,到了生产集群就出各种问题(调度失败、启动错误等)。诡异点:Diff了YAML文件,确认完全相同。根因与排查实录:Kubernetes版本差异:不同版本(特别是跨Minor版本,如1.23 vs 1.25)的API默认值、行为可能发生变化。例如,securityContext的默认值、Pod优先级等。准入控制器(Admission Controllers)不同:生产集群可能启用了额外的Mutating Webhook(如Istio sidecar注入、Pod安全策略PSP的替代品等),它们动态修改了你的Pod Spec,而你没意识到。使用kubectl get pod <pod-name> -o yaml查看被实际创建的Pod的‘最终形态’。集群组件配置不同:kube-scheduler、kube-controller-manager的命令行参数(如--default-not-ready-toleration-seconds)可能不同,影响Pod的行为。黄金法则:基础设施即代码(IaC)。不仅应用YAML要代码化,集群的初始化配置、插件部署、策略配置也应全部代码化,确保环境一致性。故障十:日志“消失”:容器日志被神秘截断或丢失现象:应用抛出一个关键错误后崩溃,但kubectl logs只看到崩溃前的几条普通日志,关键的报错信息不见了。或者,日志文件在容器内明明存在且完整,但kubectl logs就是看不到最新部分。诡异点:日志像被一刀切断,不符合预期。根因与排查实录:容器运行时日志驱动配置:如果Docker/Containerd配置的日志驱动(如json-file)的max-size和max-file设置过小,当日志写满最大文件数后,会回滚删除最老的日志文件,造成日志丢失。Sidecar日志采集器的‘激进’读取:如果使用了Filebeat、Fluent-bit等Sidecar容器通过共享卷方式采集日志,它们可能以‘tail’方式读取文件。某些情况下,如果主容器和Sidecar对文件的读写存在竞争,可能导致日志被跳过或读取不完整。缓冲区未刷新:应用日志写入标准输出(stdout/stderr)时,如果未配置缓冲刷新(如Java的-XX:+DisableExplicitGC可能影响?不,这里更可能是-Xlog:async或日志框架的缓冲设置),在进程突然崩溃时,缓冲区中的数据来不及写入就被丢弃了。解决之道:调整容器运行时的日志轮转策略(如增大max-size)。对于关键应用,考虑让应用直接将日志写入持久化卷上的文件,而非仅依赖标准输出。确保日志采集器配置的可靠性。写在最后:诡异故障的通关秘籍处理大规模K8s集群的诡异问题,像法医破案,也像老中医问诊。你需要:全链路可观测性:Metrics(Prometheus)、Logs(Loki/ELK)、Traces(Jaeger)一个都不能少。让数据说话。清晰的排查层次:从宏观(集群状态)到微观(节点进程、内核日志),逐层下钻,隔离变量。怀疑一切默认配置:K8s默认配置是为通用性设计的,不一定适合你的规模和场景。资源配额、调度器参数、网络策略、日志轮转......都需要根据实际情况调整。建立自己的知识库和SOP:把每次踩坑和解决过程记录下来,形成内部排查手册。团队的知识共享能极大提升救火效率。最核心的一点:保持敬畏,保持好奇。Kubernetes生态庞大而复杂,没人能通晓所有细节。遇到问题时,敢于深入底层(容器运行时、Linux内核、网络协议),往往能找到最终答案。你的集群最近遇到了什么‘诡异’问题?欢迎分享,或许我能提供一些排查思路。
2026年01月21日
14 阅读
0 评论
0 点赞