生產事故覆盤:K8s叢集崩潰排查實錄,一次etcd資料庫100%碎片化的生死營救

🚨 生產事故覆盤:K8s叢集崩潰排查實錄,一次etcd資料庫100%碎片化的生死營救

事故級別:P0 | 影響範圍:全量業務 | 恢復時長:4小時23分鐘

💥 災難降臨:凌晨3點的奪命連環Call

2024年12月15日 03:17,正當我沉浸在溫暖的被窩裡時,手機瘋狂震動——監控告警如雪花般飛來:
CRITICAL: K8s API Server響應超時
CRITICAL: etcd叢集健康檢查失敗  
CRITICAL: 所有Pod狀態異常
CRITICAL: 業務服務全量下線
作為一名有著8年運維經驗的老司機,我瞬間意識到——這次玩大了

🔍 初步排查:症狀比想象中更嚴重

SSH連線到Master節點,第一時間檢查叢集狀態:
$ kubectl get nodes
The connection to the server localhost:8080 was refused

$ kubectl cluster-info
Unable to connect to the server: dial tcp 10.0.1.10:6443: i/o timeout

心涼了半截,API Server徹底無響應。立即檢查etcd叢集:
$ systemctl status etcd
● etcd.service - etcd
   Active: active (running) but degraded

$ etcdctl endpoint health --cluster
10.0.1.10:2379 is unhealthy: took too long
10.0.1.11:2379 is unhealthy: took too long  
10.0.1.12:2379 is unhealthy: took too long

所有etcd節點健康檢查超時!這絕對不是普通的網路問題。

🎯 深入診斷:發現驚人真相

第一步:檢查etcd日誌

$ journalctl -u etcd -n 100
Dec 15 03:15:23 etcd[1234]: apply entries took too long [2.357658s] for 1 entries
Dec 15 03:15:45 etcd[1234]: database space exceeded
Dec 15 03:16:02 etcd[1234]: mvcc: database space exceeded
關鍵詞出現:database space exceeded

第二步:檢查資料庫狀態

$ etcdctl endpoint status --write-out=table --cluster
+------------------+------------------+---------+---------+-----------+-----------+
|     ENDPOINT     |        ID        | VERSION | DB SIZE | IS LEADER | RAFT TERM |
+------------------+------------------+---------+---------+-----------+-----------+
| 10.0.1.10:2379   | 8e9e05c52164694d |  3.4.13 | 8.2 GB  |     true  |         5 |
| 10.0.1.11:2379   | 8e9e05c52164694e |  3.4.13 | 8.1 GB  |    false  |         5 |
| 10.0.1.12:2379   | 8e9e05c52164694f |  3.4.13 | 8.3 GB  |    false  |         5 |
+------------------+------------------+---------+---------+-----------+-----------+
震驚發現:etcd資料庫已經膨脹到8GB+!正常情況下應該只有幾百MB。

第三步:碎片化檢查

$ etcdctl defrag --data-dir=/var/lib/etcd
Failed to defrag etcd member: rpc error: database space exceeded

du -sh /var/lib/etcd/
8.4G    /var/lib/etcd/

使用專業工具深度分析:
$ etcdctl endpoint hashkv --cluster
10.0.1.10:2379, 3841678299 (rev 1847293)
10.0.1.11:2379, 3841678299 (rev 1847293) 
10.0.1.12:2379, 3841678299 (rev 1847293)

# 計算碎片率
實際資料大小: 156MB
資料庫檔案大小: 8.4GB
碎片化率: (8.4GB - 156MB) / 8.4GB = 98.1%

天哪!碎片化率竟然高達98.1%,幾乎接近100%!

🕵️ 根因分析:歷史事件的累積效應

透過日誌分析和監控資料回溯,我發現了問題的根本原因:

1. 頻繁的Pod重啟風暴

# 分析etcd操作頻率
$ grep "PUT /registry/pods" /var/log/etcd.log | wc -l
2847293

# 過去24小時Pod建立刪除次數
$ kubectl get events --all-namespaces --field-selector reason=Created | wc -l
45623

某個有bug的應用在過去一個月內瘋狂重啟,產生了284萬次Pod狀態變更!

2. 歷史版本堆積

$ etcdctl get --prefix --keys-only /registry/ | wc -l
1847293

# 檢查歷史版本數量
$ etcdctl compaction $(etcdctl endpoint status --write-out="json" | jq '.[0].Status.header.revision - 1000')

etcd中積累了184萬個key的歷史版本,從未進行過壓縮清理。

3. 配置不當

# /etc/etcd/etcd.conf.yml中的致命配置
auto-compaction-retention:"0"# 停用了自動壓縮!
quota-backend-bytes:8589934592# 8GB限制已觸發

🚑 緊急搶救:分步驟恢復策略

階段一:緊急擴容儲存空間(15分鐘)

# 臨時提升quota限制
$ etcdctl put quota-backend-bytes 12884901888  # 提升到12GB

# 重啟etcd服務
$ systemctl restart etcd

階段二:手動壓縮歷史資料(45分鐘)

# 獲取當前revision
$ rev=$(etcdctl endpoint status --write-out="json" | jq '.[0].Status.header.revision')
echo"Current revision: $rev"

# 執行壓縮(保留最近1000個版本)
$ etcdctl compact $((rev-1000))
compacted revision 1846293

# 等待壓縮完成
$ watch 'etcdctl endpoint status --write-out=table'

階段三:資料庫碎片整理(180分鐘)

# 依次對每個節點進行碎片整理
for endpoint in 10.0.1.10:2379 10.0.1.11:2379 10.0.1.12:2379; do
echo"Defragmenting $endpoint..."
    etcdctl --endpoints=$endpoint defrag
sleep 60
done

# 檢查整理效果
$ etcdctl endpoint status --write-out=table --cluster
+------------------+------------------+---------+---------+-----------+-----------+
|     ENDPOINT     |        ID        | VERSION | DB SIZE | IS LEADER | RAFT TERM |
+------------------+------------------+---------+---------+-----------+-----------+
| 10.0.1.10:2379   | 8e9e05c52164694d |  3.4.13 | 178 MB  |     true  |         5 |
| 10.0.1.11:2379   | 8e9e05c52164694e |  3.4.13 | 181 MB  |    false  |         5 |
| 10.0.1.12:2379   | 8e9e05c52164694f |  3.4.13 | 175 MB  |    false  |         5 |
+------------------+------------------+---------+---------+-----------+-----------+

奇蹟出現:資料庫大小從8.4GB驟降至180MB左右!

階段四:服務恢復驗證(23分鐘)

# 驗證API Server
$ kubectl cluster-info
Kubernetes master is running at https://10.0.1.10:6443

# 驗證節點狀態
$ kubectl get nodes
NAME           STATUS   ROLES    AGE   VERSION
k8s-master-1   Ready    master   45d   v1.19.3
k8s-master-2   Ready    master   45d   v1.19.3
k8s-master-3   Ready    master   45d   v1.19.3
k8s-worker-1   Ready    <none>   45d   v1.19.3

# 驗證Pod恢復
$ kubectl get pods --all-namespaces | grep -v Running | wc -l
0

完美!所有服務恢復正常執行。

🛡️ 防患未然:永久解決方案

1. 自動化壓縮配置

# 最佳化後的etcd配置
auto-compaction-mode:periodic
auto-compaction-retention:"5m"# 每5分鐘自動壓縮
quota-backend-bytes:8589934592
max-request-bytes:1572864

2. 監控告警升級

# Prometheus監控規則
groups:
-name:etcd-alerts
rules:
-alert:EtcdDatabaseQuotaLowSpace
expr:etcd_mvcc_db_total_size_in_bytes/etcd_server_quota_backend_bytes>0.8
for:5m

-alert:EtcdHighFragmentation
expr:(etcd_mvcc_db_total_size_in_bytes-etcd_mvcc_db_total_size_in_use_bytes)/etcd_mvcc_db_total_size_in_bytes>0.5
for:10m

3. 自動化運維指令碼

#!/bin/bash
# etcd-health-check.sh - 每日健康檢查指令碼

# 檢查碎片化率
check_fragmentation() {
for endpoint in$ETCD_ENDPOINTSdo
        frag_rate=$(etcdctl endpoint status --endpoints=$endpoint --write-out=json | jq '.[] | ((.Status.dbSize - .Status.dbSizeInUse) / .Status.dbSize * 100)')
if (( $(echo "$frag_rate > 50" | bc -l) )); then
echo"WARNING: $endpoint fragmentation rate: ${frag_rate}%"
# 自動執行碎片整理
            etcdctl defrag --endpoints=$endpoint
fi
done
}

📊 經驗總結:血淚教訓換來的寶貴財富

關鍵指標監控清單

  • • 資料庫大小:正常<500MB,告警>2GB,緊急>5GB
  • • 碎片化率:正常<30%,告警>50%,緊急>80%
  • • 壓縮頻率:建議每5-10分鐘自動壓縮一次
  • • 歷史版本數:建議保留1000-5000個版本

最佳實踐總結

  1. 1. 預防大於治療:定期巡檢比應急搶救更重要
  2. 2. 自動化運維:人工操作容易遺漏,自動化才是王道
  3. 3. 監控先行:完善的監控體系是運維的生命線
  4. 4. 應急預案:提前準備恢復指令碼,關鍵時刻救命

🎉 寫在最後

這次etcd資料庫100%碎片化的緊急恢復經歷,讓我深刻體會到了運維工作的挑戰性和重要性。4小時23分鐘的生死時速,不僅考驗技術能力,更考驗心理素質和應急決策能力。
作為運維人,我們是企業業務的最後一道防線。每一次故障都是成長的機會,每一次恢復都是經驗的積累。
如果這篇文章對你有幫助,請點贊👍、收藏⭐、轉發🔄支援!
你遇到過類似的etcd問題嗎?歡迎在評論區分享你的經歷和解決方案!

關注我,持續分享更多運維實戰經驗:
  • • K8s叢集最佳化調優實踐
  • • 雲原生架構設計與實現
  • • 大規模分散式系統運維
  • • DevOps工具鏈建設經驗
文末福利
就目前來說,傳統運維衝擊年薪30W+的轉型方向就是SRE&DevOps崗位。
為了幫助大家早日擺脫繁瑣的基層運維工作,給大家整理了一套高階運維工程師必備技能資料包,內容有多詳實豐富看下圖!
共有 20 個模組
1.38張最全工程師技能圖譜
2.面試大禮包
3.Linux書籍
4.go書籍
······
6.自動化運維工具
18.訊息佇列合集
 以上所有資料獲取請掃碼
備註:最新運維資料
100%免費領取
(後臺不再回復,掃碼一鍵領取)


相關文章