為什麼高IO會導致Pod重啓?
當節點IO使用率超過90%時,會直接導致Pod運行異常,包括重啓。
1. 直接原因:節點壓力驅逐
當節點磁盤IO壓力過大時,kubelet會監測到並觸發節點壓力驅逐:
bash
# 查看節點狀態,通常會看到 DiskPressure
kubectl describe node <node-name>
# 輸出示例:
Conditions:
Type Status LastHeartbeatTime Reason Message
---- ------ ----------------- ------ -------
DiskPressure True Thu, 16 May 2024 10:23:45 +0800 KubeletHasDiskPressure kubelet has disk pressure
MemoryPressure False Thu, 16 May 2024 10:23:45 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
PIDPressure False Thu, 16 May 2024 10:23:45 +0800 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Thu, 16 May 2024 10:23:45 +0800 KubeletReady kubelet is posting ready status
2. 間接原因:探針超時
高IO導致容器響應緩慢:
- 存活探針 超時失敗
- 就緒探針 超時失敗
- kubelet認為應用不健康,重啓容器
3. 系統級影響
- 容器啓動慢:新的Pod無法快速啓動
- 日誌寫入失敗:容器日誌無法及時寫入
- 鏡像拉取失敗:無法下載新的容器鏡像
緊急處理措施
1. 立即識別問題Pod
# 查看所有Pod狀態,重點關注Evicted狀態
kubectl get pods --all-namespaces -o wide | grep -E "Evicted|Pending|Error"
# 查看節點磁盤壓力情況
kubectl top nodes # 如果有metrics-server
df -h # 在節點上直接查看磁盤使用
iostat -x 1 # 查看實時IO狀態
2. 快速緩解IO壓力
bash
# 1. 清理Docker/Containerd舊鏡像和容器
docker system prune -f
# 或者
crictl rmi --prune
# 2. 清理日誌文件
# 查看大文件
find /var/log/ -type f -size +100M -exec ls -lh {} \;
# 清理Kubernetes日誌
echo "" > /var/log/pods/*/*/*.log
# 3. 臨時擴容(如果有云平台)
# 增加節點磁盤空間或使用更高速的磁盤
根本原因排查
1. 找出IO密集型Pod
bash
# 方法1:使用kubectl top(如果支持IO監控)
kubectl top pods --containers --all-namespaces
# 方法2:在節點上使用iotop
iotop -o -P
# 方法3:使用pidstat
pidstat -d 1
2. 檢查Pod的IO配置
yaml
apiVersion: v1
kind: Pod
spec:
containers:
- name: app
image: my-app:latest
resources:
requests:
memory: "256Mi"
cpu: "250m"
ephemeral-storage: "1Gi" # 臨時存儲請求
limits:
memory: "512Mi"
cpu: "500m"
ephemeral-storage: "2Gi" # 臨時存儲限制
3. 檢查存儲配置
bash
# 查看PVC和PV使用情況
kubectl get pvc --all-namespaces
kubectl get pv
# 查看是否有大量數據讀寫
kubectl describe pvc <pvc-name>
長期解決方案
1. 優化應用IO模式
yaml
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
# 添加IO控制註解
annotations:
container.alpha.kubernetes.io/io-throttle: "true"
resources:
limits:
# 設置IOPS限制(如果存儲後端支持)
storage.io/iops: "1000"
storage.io/throughput: "100Mi"
2. 配置合理的資源限制
yaml
resources:
limits:
ephemeral-storage: "5Gi" # 根據實際需求設置
requests:
ephemeral-storage: "2Gi"
3. 優化探針配置
yaml
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30 # 適當延長初始延遲
periodSeconds: 20 # 延長檢查間隔
timeoutSeconds: 5 # 設置合理的超時時間
failureThreshold: 3 # 增加失敗閾值
4. 使用更合適的存儲
yaml
# 對於IO密集型應用,使用高性能存儲
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: high-iops-pvc
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: high-iops-pvc
spec:
storageClassName: "ssd" # 使用SSD存儲類
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
5. 監控和告警
yaml
# Prometheus監控規則示例
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: io-alert
spec:
groups:
- name: io.rules
rules:
- alert: HighDiskIO
expr: rate(node_disk_written_bytes_total[5m]) > 100e6 # 100MB/s
for: 5m
labels:
severity: warning
annotations:
summary: "High disk IO on {{ $labels.instance }}"
預防措施
- 定期維護:
- 清理無用鏡像和容器
- 輪轉和歸檔日誌
- 監控磁盤使用趨勢
- 容量規劃:
- 預估應用IO需求
- 選擇合適存儲類型
- 預留足夠緩衝空間
- 應用優化:
- 使用緩存減少磁盤IO
- 批量寫入操作
- 異步處理大文件操作
通過以上方法,你可以快速定位並解決高IO導致的Pod重啓問題,同時建立長期的預防機制。