etcd磁盘超限已触发只读模式,集群控制面实质瘫痪;需立即停止写入操作,通过etcdctl watch定位高频写入资源(如endpoints/secrets),并压缩历史版本、清理过期对象止血。

当kubectl get pods频繁超时、etcd磁盘使用率在几小时内从30%飙升至95%、etcdctl endpoint status显示backend quota usage持续增长,说明APIServer高并发读写正在触发etcd存储暴涨,必须立刻定位源头写入行为。
确认etcd是否已触发空间告警
登录任意Master节点,执行健康检查命令,观察返回中是否有“database space exceeded”字样:
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key endpoint status --write-out=table
若输出中DB Size列数值接近或等于DB Quota(默认2GB),且Is Leader为false或Health为false,说明etcd已进入只读模式,【此时所有写入请求将被拒绝,集群控制面实质瘫痪】。立即停止任何kubectl apply/delete操作。
定位高频写入的资源类型
方法一:用etcdctl watch实时捕获写入热点
在etcd节点上运行以下命令,持续监听最近10秒内变化最剧烈的key前缀:
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key watch --prefix /registry/ --changes-only --rev=$(etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key get / --print-value-only | wc -c) 2>/dev/null | head -n 50 | cut -d' ' -f1 | sed 's|/registry/||' | cut -d'/' -f1 | sort | uniq -c | sort -nr
该命令会输出类似:18432 endpoints、9216 secrets、4096 configmaps——数字越大代表该资源类型写入越密集。注意:endpoints资源高频更新通常源于Service后端Pod频繁上下线;secrets/configmaps暴涨大概率是CI/CD流水线每轮构建都创建新版本却未清理旧对象。
方法二:检查APIServer访问日志中的高频请求路径
查看kube-apiserver容器日志(需先确认日志路径是否启用):
journalctl -u kube-apiserver -n 1000 --no-pager | grep -E 'POST|PUT' | grep -v '/healthz|/livez|/metrics' | awk '{print $13}' | sort | uniq -c | sort -nr | head -10
重点关注如/api/v1/namespaces/default/secrets、/apis/batch/v1/namespaces/default/jobs这类路径。若某条路径出现频率远高于其他(例如单条路径占全部写入请求的60%以上),它就是罪魁祸首。
快速止血:冻结源头写入并清理历史版本
第一步:临时禁用高频写入的控制器(以Job为例)
找到对应控制器管理器Pod,进入其容器执行:
kubectl -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].metadata.name}' | xargs -I{} kubectl -n kube-system exec {} -- sh -c 'kill -STOP $(pgrep -f "job")'
这会暂停Job控制器的reconcile循环,阻止新Job对象持续写入etcd。注意:此操作不影响已运行的Job,仅阻断新增。
第二步:压缩etcd历史版本,释放空间
执行以下命令强制压缩revision(保留最近1000个版本,可根据实际调整):
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key compact $(etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key endpoint status --write-out=json | jq -r '.header.revision') --physical
第三步:彻底删除无用的历史对象(如过期的Secret)
先查出创建超过7天且未被任何Pod引用的Secret:
kubectl get secret --all-namespaces -o wide --sort-by=.metadata.creationTimestamp | tail -n +100 | awk '{if ($5 /dev/null | grep -q "$name" || echo "$ns/$name"; done
对输出列表中的每个namespace/name执行kubectl delete secret -n $ns $name。这一步必须人工核对,避免误删生产密钥。


















