1. 故障现象与初步排查
那天凌晨2点15分,我正盯着监控大屏上突然跳出的告警——ArgoCD控制台里两个关键Pod的状态变成了Unknown。作为负责生产环境稳定性的SRE,这种半夜告警早已是家常便饭,但每次处理都需要保持高度警惕。
首先确认了基础环境状态:
bash复制kubectl get nodes
输出显示三个工作节点都是Ready状态,这说明:
- 节点与Master的通信链路正常
- kubelet基础服务在运行
- 节点资源没有达到硬性限制
经验提示:节点Ready只能说明基础通信正常,不代表所有组件都健康。我曾遇到过节点显示Ready但CNI插件崩溃的情况。
通过以下命令定位问题Pod所在节点:
bash复制kubectl get pods -n argocd -o wide
kubectl get pods -n ai-services -o wide
发现异常的argocd-repo-server和ollama Pod都集中在node-3上。这给了我们重要线索——问题很可能出在这个节点的容器运行时层。
2. 深入诊断与根因分析
2.1 检查容器运行时状态
登录node-3后,首先检查containerd日志:
bash复制journalctl -u containerd -n 100 --no-pager
发现大量类似错误:
code复制ERRO[2023-05-17T01:58:23.123456Z] Failed to get pod status error="context deadline exceeded"
接着检查kubelet日志:
bash复制journalctl -u kubelet -n 50 --no-pager
发现关键报错:
code复制PLEG is not healthy: pleg was last seen active 5m12s ago
2.2 问题本质解析
结合现象和日志,可以确认这是典型的"PLEG不健康"问题。其根本原因是:
- Pod生命周期事件生成器(PLEG)超时:kubelet通过PLEG定期检查容器状态,当containerd响应变慢时会导致PLEG超时
- 状态同步中断:kubelet无法从containerd获取最新状态,因此将Pod标记为Unknown
- 连锁反应:长时间未恢复会导致Pod被驱逐,进而引发服务中断
根本诱因通常是:
- 节点资源不足(特别是IOPS)
- containerd内部状态不一致
- 内核资源竞争
3. 解决方案与操作实录
3.1 紧急恢复步骤
对于生产环境,我采用的恢复方案是:
- 重启容器运行时服务(谨慎操作):
bash复制systemctl restart containerd
systemctl restart kubelet
- 强制重建问题Pod:
bash复制# 对于ArgoCD组件
kubectl delete pod argocd-repo-server-59c8f4b684-487s8 -n argocd --grace-period=0 --force
# 对于AI服务组件
kubectl delete pod ollama-5c8bb8bb69-dkm6f -n ai-services --grace-period=0 --force
重要提示:强制删除(--force)会绕过正常的终止流程,可能导致数据不一致。仅在确定无状态服务时使用。
3.2 根治措施实施
为防止问题复发,我们实施了以下改进:
- 调整kubelet配置:
bash复制# /var/lib/kubelet/config.yaml
podPlegDuration: 10s -> 30s
runtimeRequestTimeout: 2m -> 5m
- 优化containerd参数:
toml复制# /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri"]
max_concurrent_downloads = 3 -> 1
snapshotter = "overlayfs" -> "stargz"
- 增加监控指标:
yaml复制# Prometheus监控规则
- alert: HighPLEGLatency
expr: kubelet_pleg_relist_duration_seconds{quantile="0.99"} > 30
for: 5m
4. 经验总结与避坑指南
4.1 关键教训
-
重启不是万能的:直接重启节点可能掩盖真正问题,应该先收集以下数据:
kubectl describe node <node>crictl inspect <container-id>dmesg -T | tail -n 100
-
状态同步的脆弱性:Kubernetes强依赖各组件状态同步,任何环节延迟都会放大影响。建议:
- 为关键组件设置独立的QoS类别
- 避免单个节点部署过多核心服务
-
日志收集的时效性:很多关键日志(如containerd)默认轮转很快,应该提前配置:
bash复制# /etc/systemd/journald.conf SystemMaxUse=1G -> 4G MaxRetentionSec=1month
4.2 推荐排查路线图
遇到Unknown Pod时,建议按此流程排查:
mermaid复制graph TD
A[Pod状态Unknown] --> B{节点是否Ready?}
B -->|是| C[检查kubelet日志]
B -->|否| D[排查节点基础设施]
C --> E{是否有PLEG错误?}
E -->|是| F[检查containerd状态]
E -->|否| G[检查网络插件]
F --> H[重启containerd/kubelet]
H --> I[重建问题Pod]
(注:实际处理时应替换为文字描述流程)
4.3 长效预防措施
-
资源预留:确保节点有足够资源余量
bash复制kubectl describe node | grep -A 10 "Allocatable" -
定期维护:每月执行一次预防性重启
bash复制# 使用kured实现安全重启 kubectl apply -f https://github.com/kubereboot/kured/releases/latest/download/kured.yaml -
版本管理:保持组件版本兼容
bash复制# 推荐版本组合 Kubernetes 1.25+ Containerd 1.6+
这个故障处理过程让我深刻体会到,在分布式系统中,状态同步问题往往比硬件故障更难排查。建议每个SRE团队都建立自己的《状态异常排查手册》,记录各种异常现象的诊断方法和处理经验。