凌晨三点,告警响了。
仪表盘上一个关键服务的Pod重启次数曲线像心电图一样剧烈跳动,业务接口超时率飙升。你睡眼惺忪地连上集群,面对几十个Pod和交织的日志流,第一反应是什么?是kubectl describe,还是立刻去翻日志?
坦白讲,在Kubernetes里排查微服务故障,很多时候就像在迷宫里找一只会隐身的猫。东西太多,线索太杂。今天不聊那些教科书式的步骤,就聊聊这几年我真正用顺手的那套方法,以及那些容易踩进去的坑。
别急着看日志,先看看Pod“死”得明不明白
这是我的铁律。Pod出问题,第一眼永远不是kubectl logs。
先 kubectl get pods -o wide,看看状态。是CrashLoopBackOff,Pending,还是ImagePullBackOff?状态本身已经泄露了一半的秘密。
如果是Pending,问题八成出在调度上。立刻 kubectl describe pod <pod-name>,重点看Events部分。是不是节点资源不足?有没有不满足的节点选择器或亲和性规则?我见过太多因为nodeSelector打错一个标签,导致Pod永远找不到家的案例。
如果是CrashLoopBackOff,说明容器在反复启动和崩溃。这时候kubectl logs --previous是你的救命稻草,它能抓到上一个崩溃实例的日志,很多时候根本原因就在里面。
日志不是文本,是带坐标的故事线
拿到日志后,最怕的就是淹没在细节里。微服务架构下,一个请求穿越多个Pod,你需要的是串联,而不是单点观察。
1. 给日志注入“追踪DNA”
确保你的应用在日志的每一行都输出统一的请求ID(比如OpenTelemetry的Trace ID)。没有这个,分布式排查就是噩梦。这比任何花哨的日志工具都重要。
2. 别只用kubectl logs
对于实时追踪,kubectl logs -f 很好。但对于历史分析,你需要集中式日志。ELK(Elasticsearch, Logstash, Kibana)或者Grafana Loki是标配。关键不在于工具多高级,而在于你能多快地用请求ID把跨越多个服务和Pod的日志串成一条完整的故事线。
3. 警惕“安静”的日志
有时候最可怕的不是错误日志刷屏,而是日志突然停了,或者变得异常规律但缓慢。这往往指向线程池耗尽、死锁或外部依赖(如数据库连接池)卡死。这时候需要结合监控指标看。
性能瓶颈?指标比感觉更靠谱
服务变慢,但没挂,这可能是最棘手的问题。感觉是“慢”,证据呢?
黄金指标四件套:延迟、流量、错误数、饱和度。这是Google SRE手册里的精华,在K8s里同样适用。
- 延迟:不光看P99,也要看P50。P99飙升可能只是个别慢请求,P50也涨了才是真的大面积问题。检查应用监控(如Prometheus中的
http_request_duration_seconds)和网络延迟(服务网格如Istio的指标很有用)。 - 流量:QPS或并发连接数是否到了瓶颈?检查HPA(水平Pod自动伸缩)的配置,是不是
metrics-server提供的CPU/内存指标不准确,导致该扩容时没扩?我遇到过节点内存压力导致metrics-server自己数据不准的滑稽情况。 - 饱和度:资源用满了。
kubectl top pod/node是快速查看方式。但CPU高不一定有问题,可能是正常计算;内存持续增长(OOMKilled的前兆)和磁盘IO打满才是更危险的信号。 - 错误数:5xx错误率上升是结果,不是原因。要结合延迟和日志,看错误是原因还是结果。
一个真实案例:一个服务响应时间偶尔飙高。看日志没问题,CPU/内存正常。最后查出来是某个Pod所在的节点,网络带宽被另一个批处理任务临时打满。工具?kubectl describe node 看事件,配合节点级的网络监控。问题往往在你的服务之外。
我的诊断工具箱(精简版)
下面这些命令和思路,已经帮我解决了90%的线上问题:
- 初步定位:
kubectl get pods -o wide --show-labels(看分布和状态) - 查看死因:
kubectl describe pod <pod-name>(重点看Events和状态变化) - 查看日志:
kubectl logs --previous <pod-name>(针对崩溃容器) - 进入Pod:
kubectl exec -it <pod-name> -- /bin/sh(检查文件、进程状态,慎用生产环境) - 检查服务与端点:
kubectl get svc,ep(确认Service是否正确关联到Pod Endpoints) - 检查配置:
kubectl get configmap,secret(确认环境变量、配置文件是否生效) - 资源视角:
kubectl top pod/node(快速定位资源热点) - 网络视角:
kubectl run debug-tool --image=nicolaka/netshoot -it --rm(启动一个临时网络诊断工具Pod)
最后几句大实话
- 可观测性不是上线后才加的:在设计微服务时,就把日志、指标、追踪的埋点想清楚。事后再补,痛苦十倍。
- 复杂问题简单化:遇到诡异问题,试着按最小化原则复现。能不能先缩减到单个Pod、去掉Sidecar、简化配置来排查?
- 文档你的排查过程:不仅是为了别人,下次你再遇到类似问题,那份记录了所有弯路和灵感的文档就是无价之宝。
故障诊断没有银弹,它更像是一种肌肉记忆,来自一次次深夜的折腾和复盘。最好的工具,永远是你对系统行为不断加深的理解。
你的排查流程里,最依赖的那个“杀手锏”命令或思路是什么?