和面試官聊聊:那次讓我成長最快的 K8s 故障
引言
都不知道說啥了,我們直接開始吧。
開始
一、問題現象與背景
某電商平臺生產環境的Kubernetes集群在促銷活動期間突發大規模Pod驅逐,具體表現如下:
1. Pod頻繁重啟:超過30%的Pod進入Evicted
狀態,核心服務(如訂單支付、購物車)的Pod被反復驅逐。
2. 節點資源耗盡:多個Worker節點的內存使用率超過95%,kubelet日志持續輸出MemoryPressure
警告。
3. 監控告警:
? Prometheus觸發node_memory_available_bytes < 10%
告警。
? Grafana面板顯示部分節點的kubelet_evictions
指標飆升。
4. 業務影響:用戶支付失敗率從0.1%上升至15%,直接影響營收。
二、問題根因分析
1. 初步排查:節點與Pod狀態
# 查看節點資源使用情況(按內存排序)
kubectl top nodes --sort-by=memory
# 輸出示例:
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
worker-node-1 5800m 72% 6143Mi 98%
worker-node-2 4200m 52% 5892Mi 95%
worker-node-3 3800m 47% 4321Mi 70%
# 檢查被驅逐的Pod
kubectl get pods -A -o wide | grep Evicted | wc -l # 輸出:47
# 查看某個被驅逐Pod的詳細事件
kubectl describe pod payment-service-abcde -n production
關鍵日志:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Evicted 2m kubelet The node was low on resource: memory.
Normal Killing 2m kubelet Stopping container payment-service
結論:節點內存不足觸發kubelet的主動驅逐機制。
2. 深入定位:資源消耗來源
步驟1:識別高內存消耗Pod
# 按內存使用量排序所有Pod
kubectl top pods -A --sort-by=memory --use-protocol-buffers
# 輸出示例:
NAMESPACE POD_NAME MEMORY(Mi)
production recommendation-service-xyz 1024
production payment-service-abc 896
logging fluentd-7k8jh 512
發現:recommendation-service
的Pod內存占用異常高。
步驟2:檢查Pod資源限制配置
kubectl get pod recommendation-service-xyz -n production -o yaml | grep -A 5 resources
# 輸出示例:
resources:
requests:
cpu: "500m"
limits:
cpu: "1000m"
問題:該Pod未設置內存限制(limits.memory
缺失),導致內存泄漏時無約束。
步驟3:分析容器內存使用
# 進入節點查看容器級內存占用(需SSH登錄節點)
docker stats --format "table {{.Container}}\t{{.Name}}\t{{.MemUsage}}"
# 輸出示例:
CONTAINER NAME MEM USAGE
a1b2c3d4 recommendation-service 1.2GiB / 1.2GiB
發現:容器內存占用已突破1GiB,但未配置limits.memory
,導致節點內存耗盡。
三、緊急處理措施
1. 快速擴容與負載分流
? 橫向擴展節點:
# 使用Cluster Autoscaler自動擴容(假設配置了節點組)
kubectl scale deployment cluster-autoscaler --replicas=3 -n kube-system
? 臨時調整Pod副本數:
# 減少非核心服務副本數,釋放資源
kubectl scale deployment batch-job-processor --replicas=0 -n background
# 增加核心服務副本數,分散負載
kubectl scale deployment payment-service --replicas=10 -n production
2. 手動驅逐問題Pod
# 強制刪除高內存占用的Pod(觸發重新調度)
kubectl delete pod recommendation-service-xyz -n production --force --grace-period=0
# 觀察Pod重建后的內存使用
watch -n 1 "kubectl top pods -n production | grep recommendation-service"
3. 動態調整kubelet驅逐閾值
# 臨時修改kubelet配置(避免更多Pod被驅逐)
sudo vi /etc/kubernetes/kubelet.conf
# 添加參數:
evictionHard:
memory.available: "10%"
nodefs.available: "5%"
# 重啟kubelet
sudo systemctl restart kubelet
四、根因修復與長期優化
1. 資源配額規范化
? 為所有Pod添加內存限制:
# deployment.yaml示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: recommendation-service
spec:
template:
spec:
containers:
- name: app
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1024Mi" # 硬性限制內存上限
cpu: "2000m"
? 啟用命名空間級ResourceQuota:
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.memory: "100Gi"
limits.memory: "200Gi"
pods: "200"
2. 自動化彈性伸縮
? 配置HPA(基于內存):
kubectl autoscale deployment recommendation-service -n production \
--cpu-percent=70 \
--memory-percent=80 \
--min=3 \
--max=20
? 使用VPA(垂直擴縮容):
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: recommendation-service-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: recommendation-service
updatePolicy:
updateMode: "Auto"
3. 內存泄漏根治
? 使用pprof進行堆分析(以Go服務為例):
import _ "net/http/pprof"
func main() {
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
// 業務代碼
}
# 生成堆內存快照
go tool pprof http://localhost:6060/debug/pprof/heap
# 分析內存分配
(pprof) top 10
(pprof) list leakFunction
? 優化代碼邏輯:修復循環引用、緩存未釋放等問題。
五、監控與告警體系升級
1. Prometheus監控規則
# prometheus-rules.yaml
groups:
- name: Kubernetes-Resource
rules:
- alert: NodeMemoryPressure
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 85
for: 5m
labels:
severity: critical
annotations:
summary: "節點內存不足 ({{ $labels.instance }})"
description: "節點 {{ $labels.instance }} 內存使用率超過85%,當前值 {{ $value }}%"
- alert: PodEvictionRateHigh
expr: rate(kube_pod_status_evicted[1h]) > 0
for: 10m
labels:
severity: warning
2. Grafana可視化面板
? 關鍵面板配置:
a.節點資源視圖:node_memory_available_bytes
、node_cpu_usage
b.Pod驅逐統計:sum(kube_pod_status_evicted) by (namespace)
c.HPA伸縮歷史:kube_horizontalpodautoscaler_status_current_replicas
3. 日志聚合分析
? Fluentd + Elasticsearch配置:
<match kube.**>
@type elasticsearch
host elasticsearch.production.svc
port 9200
logstash_format true
logstash_prefix k8s
</match>
? 關鍵日志篩選:
# Kibana查詢被驅逐Pod的日志
kubernetes.labels.app: "payment-service" AND message: "Evicted"
六、預防與容災演練
1. 混沌工程實踐
? 模擬節點故障(使用Chaos Mesh):
apiVersion: chaos-mesh.org/v1alpha1
kind: NodeFailure
metadata:
name: node-failure-test
spec:
action: shutdown
duration: "10m"
selector:
nodes:
- worker-node-1
? 驗證集群自愈能力:
a.觀察Pod是否自動遷移到健康節點。
b.檢查HPA是否按負載自動擴展。
2. 定期壓力測試
? 使用Locust模擬流量高峰:
from locust import HttpUser, task
class PaymentUser(HttpUser):
@task
def create_order(self):
self.client.post("/api/order", json={"items": [...]})
locust -f load_test.py --headless -u 1000 -r 100
3. 架構優化
? 服務網格化:通過Istio實現熔斷和降級。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: payment-service
spec:
host: payment-service.production.svc.cluster.local
trafficPolicy:
outlierDetection:
consecutiveErrors: 5
interval: 1m
baseEjectionTime: 3m
七、總結與經驗
解決效果:
? 緊急措施在30分鐘內恢復核心服務,Pod驅逐率降至0。
? 通過內存限制和HPA配置,集群資源利用率穩定在70%-80%。
? 后續3個月未發生類似事件,故障MTTR(平均修復時間)從4小時縮短至15分鐘。
關鍵經驗:
1. 防御性編碼:所有服務必須設置資源limits
,并在CI/CD流水線中強制檢查。
2. 監控全覆蓋:從節點到Pod層級的資源監控需實現100%覆蓋。
3. 自動化優先:依賴Cluster Autoscaler、HPA等自動化工具,減少人工干預。
4. 定期演練:通過混沌工程暴露系統脆弱點,持續優化架構韌性。
通過系統化的故障處理與架構優化,Kubernetes集群的穩定性達到99.99% SLA,支撐了后續多次大促活動。