Pod被驱逐的根因分析与恢复操作
Pod Eviction是K8s最常见的告警之一。触发条件是节点资源压力——磁盘、内存或PID达到阈值时,kubelet按优先级驱逐Pod。处理之前,先搞清楚是哪种资源触发了驱逐。
定位步骤:
# 查看Pod驱逐事件
kubectl get events --field-selector type=Warning -A | grep Evict
# 查看节点资源压力详情
kubectl describe node <node-name> | grep -A 20 "Conditions"
# 检查磁盘压力
kubectl describe node <node-name> | grep -i "disk\|pressure"
# 查看被驱逐Pod的状态和原因
kubectl get pods -A -o json | jq '.items[] | select(.status.reason=="Evicted") | {name: .metadata.name, namespace: .metadata.namespace, message: .status.message}'
恢复操作:
# 1. 清理节点磁盘空间(最常见原因)
# 清理退出的容器
crictl rmp -a
# 清理无用镜像
crictl rmi -a
# 清理旧日志
journalctl --vacuum-size=200M
find /var/log -name "*.gz" -mtime +7 -delete
# 2. 删除已驱逐的Pod(它们不会自动重建)
kubectl get pods -A --field-selector="status.phase=Failed" -o json | kubectl delete -f -
# 3. 如果是Deployment/StatefulSet管理,删除后控制器会自动重建
kubectl delete pod <evicted-pod> -n <namespace>
节点NotReady的分层排查
节点变成NotReady,意味着kubelet与API Server的心跳中断。从底层往上逐层排查。
第一层:检查kubelet进程
# kubelet是否在运行
systemctl status kubelet
# 如果挂了,查看日志
journalctl -u kubelet --since "30 minutes ago" --no-pager | tail -50
# 常见问题:kubelet证书过期
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
第二层:检查网络连通性
# 从节点到API Server的连通性
curl -k https://<api-server-ip>:6443/healthz
# 检查DNS解析
nslookup kubernetes.default.svc.cluster.local
# 检查节点网络接口
ip addr show
ip route show
第三层:检查资源耗尽
# 是否OOM
dmesg | grep -i "oom\|killed process"
# 查看当前负载
top -bn1 | head -20
# 查看磁盘IO等待
iostat -x 1 3
恢复操作:如果是kubelet证书过期,用kubeadm重新生成;如果是资源耗尽,先杀掉异常进程再重启kubelet;如果是网络问题,先修复CNI插件。
Service网络不通的诊断路径
Pod到Service的网络不通是另一个高频问题。排查遵循固定路径。
# Step 1: Pod本身是否正常
kubectl exec -it <pod> -- curl -s http://localhost:<port>/healthz
# Step 2: Service的Endpoints是否就绪
kubectl get endpoints <svc-name> -n <ns>
# 如果为空,说明没有Pod匹配selector
# Step 3: 检查Service到Pod的转发
kubectl exec -it <client-pod> -- curl -s http://<svc-name>.<ns>.svc.cluster.local:<port>
# Step 4: 检查kube-proxy规则
iptables -t nat -L KUBE-SERVICES | grep <svc-cluster-ip>
# Step 5: 检查DNS解析
kubectl exec -it <pod> -- nslookup <svc-name>.<ns>.svc.cluster.local
最常见的原因排序:selector标签不匹配导致Endpoints为空 > readinessProbe失败导致Pod不在Endpoints中 > CNI插件配置错误 > kube-proxy异常。
集群级故障的SOP模板
规模化运维需要标准化的应急响应流程。以下是一个集群级故障SOP模板:
# 故障等级定义
P0: 集群不可用,影响全部业务
P1: 部分节点/命名空间不可用
P2: 单节点/单服务异常
# P0响应流程(目标:15分钟内开始恢复)
1. [0-2min] 确认故障范围:kubectl get nodes, kubectl get pods -A
2. [2-5min] 判断根因:API Server? etcd? 网络? 资源?
3. [5-10min] 执行对应恢复预案
4. [10-15min] 验证恢复效果
5. [15min+] 如未恢复,触发扩容或切换到备用集群
# etcd故障快速恢复
# 检查etcd健康
ETCDCTL_API=3 etcdctl endpoint health --cluster
# 查看leader
ETCDCTL_API=3 etcdctl endpoint status --write-out=table
# 如果quorum丢失,需要从snapshot恢复
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db
Chaos工程验证:主动注入故障验证韧性
应急预案写好了不代表能用。定期用Chaos工程验证系统在真实故障下的表现。
# 使用chaos-mesh注入网络延迟
apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
name: network-delay-test
namespace: chaos-testing
spec:
action: delay
mode: one
selector:
namespaces: ["production"]
labelSelectors:
app: "payment-service"
delay:
latency: "500ms"
jitter: "100ms"
duration: "5m"
# 注入Pod删除
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
name: pod-kill-test
namespace: chaos-testing
spec:
action: pod-kill
mode: fixed-percent
value: "30"
selector:
namespaces: ["production"]
labelSelectors:
app: "order-service"
duration: "2m"
每个季度至少做一次全链路Chaos演练,覆盖网络分区、节点宕机、磁盘写满三个场景。记录每次演练的发现和改进项,闭环追踪。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-ji-qun-gu-zhang-ying-ji-xiang-ying-shou-ce-pod/