K8s 懸案:當 Pod 集體故障而日志卻說一切正常,SRE 如何絕地翻盤?
引言
你平常的工作中有沒有遇到這些故障呢?如果沒有遇到過,那就提前預防下吧。
最后有相關的群。
開始
一、故障場景深度還原
現(xiàn)象描述:
? 時間:2024年8月20日 14:00(GMT+8)
? 影響范圍:
生產(chǎn)集群prod-cluster-01
中,payment-service
、order-service
等核心服務共32個Pod進入CrashLoopBackOff
狀態(tài)
服務可用性從99.99%驟降至83.5%,用戶支付失敗率上升至15%
? 初步觀察:
容器啟動日志顯示Application started successfully on port 8080
但kubectl describe pod
顯示Last State: Terminated with exit code 137
節(jié)點監(jiān)控顯示node-5
至node-8
內(nèi)存使用率超90%
二、SRE標準化應急響應流程(逐步拆解)
階段1:黃金5分鐘 - 快速定位問題邊界
1. 信息收集模板(群內(nèi)首發(fā))
@運維團隊 @開發(fā)團隊 @網(wǎng)絡團隊
【故障通告 - 2024-08-20 14:05】
**現(xiàn)象**:
- 生產(chǎn)集群prod-cluster-01出現(xiàn)32個Pod CrashLoopBackOff
- 影響服務:payment-service、order-service
**緊急行動項**:
1. [開發(fā)團隊] 請?zhí)峁┳罱?小時內(nèi)的發(fā)布記錄和配置變更(Git提交記錄+Helm版本)
2. [網(wǎng)絡團隊] 驗證以下端口連通性(示例命令):
- 節(jié)點間:`nc -zv 10.0.5.10 6443`(API Server)
- 跨命名空間:`kubectl run net-test --image=nicolaka/netshoot --command -- sleep 3600`
3. [存儲團隊] 檢查Ceph集群狀態(tài):`ceph -s`
4. [運維團隊] 正在收集以下數(shù)據(jù)(預計5分鐘同步):
- 異常Pod分布圖(見附件)
- 關鍵組件日志(API Server、kubelet、CNI插件)
**溝通紀律**:
- 所有結(jié)論需附帶日志片段或命令輸出
- 非緊急問題請通過工單系統(tǒng)提交
2. 初步診斷(命令詳解)
# 1. 確認故障范圍(按命名空間統(tǒng)計)
kubectl get pods -A -o wide | grep CrashLoopBackOff | awk '{print $1}' | sort | uniq -c
# 輸出示例:
# 15 payment-service
# 17 order-service
# 2. 檢查節(jié)點狀態(tài)(重點觀察資源水位)
kubectl top nodes --use-protocol-buffers
# 輸出示例:
# NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
# node-5 3800m 95% 6144Mi 98%
# node-6 4200m 92% 5892Mi 96%
# 3. 查看kubelet關鍵日志(過濾錯誤)
journalctl -u kubelet -n 200 --no-pager | grep -E 'error|fail|oom'
# 關鍵日志線索:
# Aug 20 13:58:23 node-5 kubelet[1123]: Error: failed to start container "payment": OOMKilled
階段2:根因分析 - 全鏈路排查
3. Pod生命周期深度檢查
# 1. 查看Pod完整事件鏈(重點關注Warning事件)
kubectl describe pod payment-service-abcde -n production | grep -A 30 Events:
# 輸出示例:
# Events:
# Type Reason Age From Message
# ---- ------ ---- ---- -------
# Warning Unhealthy 2m10s kubelet Liveness probe failed: HTTP probe failed...
# Normal Killing 2m10s kubelet Stopping container payment
# Warning BackOff 2m8s kubelet Back-off restarting failed container
# 2. 獲取前一次容器日志(關鍵?。?kubectl logs payment-service-abcde --previous --tail=200
# 日志片段:
# ERROR [main] o.s.boot.SpringApplication: Application run failed
# java.lang.OutOfMemoryError: Java heap space
# 3. 檢查容器退出碼(137=OOM)
kubectl get pod payment-service-abcde -o jsonpath='{.status.containerStatuses[].lastState.terminated.exitCode}'
# 輸出:137
4. 存儲與網(wǎng)絡專項驗證(分步驟)
? 存儲驗證流程:
# 1. 進入Pod驗證掛載點
kubectl exec -it payment-service-abcde -- df -h
# 輸出示例:
# Filesystem Size Used Avail Use% Mounted on
# /dev/rbd0 50G 50G 0 100% /data
# 2. 嘗試寫入測試文件
kubectl exec -it payment-service-abcde -- touch /data/test.txt
# 錯誤信息:
# touch: cannot touch '/data/test.txt': No space left on device
# 3. 檢查PVC狀態(tài)
kubectl get pvc -n production
# 輸出示例:
# NAME STATUS VOLUME CAPACITY ACCESS MODES
# payment-data Bound pvc-xyz 50Gi RWO
? 網(wǎng)絡驗證流程:
# 1. 創(chuàng)建臨時網(wǎng)絡診斷Pod
kubectl run net-test --image=nicolaka/netshoot -it --rm --restart=Never --command -- sh
# 2. 驗證服務發(fā)現(xiàn)
nslookup payment-service.production.svc.cluster.local
# 預期輸出:解析到ClusterIP
# 3. 測試跨命名空間通信
nc -zv redis.cache.svc.cluster.local 6379
# 錯誤示例:
# Connection to redis.cache.svc.cluster.local (10.100.50.10) 6379 port [tcp/*] failed: Connection timed out
5. 探針配置審計(常見錯誤模式)
# 錯誤配置示例:探針過于敏感
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 2 # 應用啟動需要10秒以上
periodSeconds: 5 # 檢測過于頻繁
failureThreshold: 3 # 失敗3次即重啟
# 優(yōu)化建議:
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30 # 根據(jù)應用啟動時間調(diào)整
periodSeconds: 10
failureThreshold: 5
三、典型故障模式與解決方案(附真實案例)
Case 1:存儲卷已滿導致容器啟動失敗
現(xiàn)象:
? kubectl describe pod
顯示Warning: FailedMount
? 存儲插件日志(Ceph CSI)報No space left on device
排查步驟:
1. 檢查存儲卷容量:
kubectl exec -it payment-service-abcde -- df -h /data
# 輸出:Use% 100%
2. 清理存儲或擴容PVC:
# 臨時清理(需開發(fā)確認)
kubectl exec -it payment-service-abcde -- rm -rf /data/logs/*.old
# 永久擴容
kubectl edit pvc payment-data -n production
# 修改spec.resources.requests.storage: "100Gi"
Case 2:節(jié)點內(nèi)存泄漏觸發(fā)OOM
現(xiàn)象:
? 容器退出碼137(OOMKilled)
? 節(jié)點dmesg
日志顯示Out of memory: Kill process
解決方案:
1. 調(diào)整Pod資源限制:
resources:
requests:
memory: "2Gi"
limits:
memory: "4Gi" # 原為2Gi
2. 優(yōu)化應用內(nèi)存配置:
# Java應用添加JVM參數(shù)
-XX:MaxRAMPercentage=80
Case 3:網(wǎng)絡策略阻斷服務發(fā)現(xiàn)
現(xiàn)象:
? 容器日志顯示java.net.UnknownHostException: redis.cache
? kubectl exec
執(zhí)行nslookup失敗
排查流程:
1. 檢查NetworkPolicy:
kubectl get networkpolicy -n production
# 發(fā)現(xiàn)存在default-deny-all策略
2. 添加允許規(guī)則:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- ports:
- protocol: UDP
port: 53
四、團隊協(xié)作與信息同步(實戰(zhàn)模板)
1. 多團隊協(xié)作框架(RACI矩陣)
角色 | 職責(Responsible) | 需批準(Accountable) | 需咨詢(Consulted) | 需告知(Informed) |
SRE | 根因分析、協(xié)調(diào)資源 | 故障處理方案 | 開發(fā)/網(wǎng)絡/存儲團隊 | 管理層 |
開發(fā)團隊 | 提供代碼變更信息 | 代碼回滾決策 | SRE | QA團隊 |
網(wǎng)絡團隊 | 驗證網(wǎng)絡策略 | 防火墻規(guī)則變更 | SRE | - |
存儲團隊 | 檢查存儲健康狀態(tài) | 存儲擴容/修復 | SRE | - |
2. 信息同步模板(每小時更新)
【故障處理進展 - 2024-08-20 15:00】
**當前狀態(tài)**:
- 已恢復25個Pod,剩余7個仍在處理
- 確認根因:Ceph存儲卷空間耗盡(OSD.12故障導致容量計算錯誤)
**行動記錄**:
1. [存儲團隊] 已完成OSD.12替換,存儲集群恢復健康
2. [運維團隊] 執(zhí)行以下操作:
- 擴容受影響PVC至100Gi
- 驅(qū)逐故障節(jié)點上的Pod
3. [開發(fā)團隊] 已回滾可能導致內(nèi)存泄漏的配置變更
**后續(xù)計劃**:
- 16:00前完成所有Pod恢復
- 今晚22:00進行存儲系統(tǒng)架構(gòu)評審
**遺留風險**:
- 節(jié)點node-5內(nèi)存使用率仍偏高(建議后續(xù)擴容)
3. 故障復盤模板
## 故障復盤報告 - 2024-08-20
**影響時長**:14:00-15:47(總1小時47分鐘)
**根本原因**:
1. 直接原因:Ceph OSD.12磁盤故障導致存儲卷容量計算錯誤
2. 深層原因:
- 存儲容量監(jiān)控未覆蓋OSD級指標
- PVC自動擴容策略未啟用
**改進項**:
| 改進措施 | 負責人 | 截止日期 |
|---------------------------|----------|-----------|
| 部署Ceph OSD健康監(jiān)控 | 存儲團隊 | 2024-08-25|
| 啟用PVC自動擴容(StorageClass) | 運維團隊 | 2024-08-23|
| 實施存儲多AZ副本策略 | 架構(gòu)組 | 2024-09-10|
**經(jīng)驗沉淀**:
- 新增《存儲故障應急手冊》第3.2節(jié)
- 開發(fā)團隊完成JVM內(nèi)存配置培訓
五、防御性設計與長效優(yōu)化
1. 集群健康檢查自動化腳本
#!/bin/bash
# check_k8s_health.sh
# 控制平面檢查
kubectl get componentstatuses
kubectl -n kube-system get pods -l tier=control-plane
# 節(jié)點狀態(tài)檢查
kubectl get nodes -o json | jq -r '.items[] | .metadata.name + " " + .status.conditions[] | select(.type=="Ready").status'
# 存儲健康檢查
if which ceph &>/dev/null; then
ceph -s
ceph osd tree
fi
# 網(wǎng)絡策略審計
calicoctl get networkpolicy -A -o wide
2. 混沌工程常態(tài)化測試方案
# chaos-mesh/network-loss.yaml
apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
name: simulate-network-loss
spec:
action: loss
mode: one
selector:
namespaces: [production]
loss:
loss: "50"
correlation: "50"
duration: "5m"
3. 架構(gòu)優(yōu)化措施
? 存儲多活架構(gòu):
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph-rbd-multi-az
parameters:
clusterID: ceph-primary
mirroringPool: replica-pool
dataPool: ec-data-pool
provisioner: rbd.csi.ceph.com
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
? Pod優(yōu)先級與搶占:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: mission-critical
value: 1000000
globalDefault: false
description: "用于核心業(yè)務Pod"
六、可視化輔助工具
1. 故障排查流程圖
圖片
2. 典型故障模式速查表
退出碼 | 常見原因 | 應急命令 |
137 | OOMKilled |
|
1 | 應用啟動失敗 |
|
143 | SIGTERM終止 | 檢查PreStop鉤子 |
255 | 容器運行時錯誤 |
|
通過這份深度指南,團隊可將平均故障恢復時間(MTTR)縮短40%以上,并顯著提升跨團隊協(xié)作效率。建議將此文檔納入SRE新員工培訓體系,并定期組織紅藍對抗演練以驗證流程有效性。