主题
RKE / RKE2 etcd 空间告警处理与证书轮换手册
etcd 是 Kubernetes 集群的唯一数据源,默认存储配额为 2GB。随着集群对象、事件、变更历史不断累积,一旦写入量超过配额,etcd 会触发 NOSPACE 告警并拒绝后续写入,表现为集群无法创建或更新任何资源,属于必须立即处理的高危故障。本文面向 RKE / RKE2 集群运维工程师,覆盖告警原理、compact + defrag + disarm 的完整处理流程、日常自动压缩预防配置,以及集群证书有效期检查与轮换操作。
一、告警原理
etcd 默认的存储配额为 2GB(--quota-backend-bytes=2147483648)。需要理解两个关键点:
- etcd 采用多版本并发控制(MVCC),每一次对象更新都会产生一个新的修订版本(revision),旧版本数据并不会立即删除,而是不断堆积。
- 删除数据只是打标记,物理空间不会自动回收。必须通过 compact(压缩历史版本)+ defrag(碎片整理)两步才能真正释放磁盘与配额空间。
当数据库文件超过配额时,etcd 进入告警状态(alarm: NOSPACE),所有写请求被拒绝,只保留读和删除权限。此时 kubectl 的任何 create/update 操作都会报类似错误:
text
etcdserver: mvcc: database space exceeded处理思路固定为三步:compact 压缩旧版本 → defrag 整理碎片释放空间 → disarm 解除告警。所有 etcd 节点都需要处理。
二、RKE 集群处理流程
RKE 集群中 etcd 以静态 Pod / 容器方式运行,节点上自带 etcdctl 环境(etcd 容器内提供)。在每个 etcd 节点上执行:
2.1 查看状态与告警
bash
etcdctl endpoint status --write-out=table
etcdctl alarm list重点关注输出中的 DB SIZE(数据库大小)和告警列表。当 DB SIZE 接近或达到 2GB,且 alarm list 中存在 NOSPACE,即确认触发配额告警。
2.2 压缩历史版本
bash
# 获取当前修订版本号
rev=$(etcdctl endpoint status --write-out=json | grep -o '"revision":[0-9]*' | grep -o '[0-9]*')
# 删除所有早于该版本的历史数据
etcdctl compact $rev2.3 碎片整理
bash
etcdctl defrag2.4 解除告警
bash
etcdctl alarm disarm解除后再次执行 etcdctl endpoint status --write-out=table 确认 DB SIZE 已回落,然后验证集群可正常写入(例如创建一个测试 ConfigMap 再删除)。
2.5 定时自动压缩脚本(临时手段)
对于变更频繁、容易再次触顶的集群,可先在节点上部署定时压缩脚本作为过渡:
bash
cat <<'EOF' > /opt/etcd-compact.sh
#!/bin/bash
while true; do
rev=$(etcdctl endpoint status --write-out=json | grep -o '"revision":[0-9]*' | grep -o '[0-9]*')
etcdctl compact $rev
etcdctl defrag
sleep 1h
done
EOF
chmod +x /opt/etcd-compact.sh建议通过 systemd 或 crontab 托管运行。注意这只是临时手段,长期方案见第五节「日常预防」。
三、RKE2 集群处理流程
RKE2 中 etcd 的控制面证书位于 /var/lib/rancher/rke2/server/tls/etcd/,所有 etcdctl 操作必须携带 TLS 证书,并通过本机 2379 端点访问。
3.1 定位 etcdctl 并设置环境
bash
ETCDCTL_PATH=$(find /var/lib/rancher/rke2 -name "etcdctl" -type f)
echo $ETCDCTL_PATH
export ETCDCTL_API=3
TLS_PATH="/var/lib/rancher/rke2/server/tls/etcd/"3.2 查看状态
bash
$ETCDCTL_PATH \
--cacert=$TLS_PATH/server-ca.crt \
--cert=$TLS_PATH/server-client.crt \
--key=$TLS_PATH/server-client.key \
--endpoints=https://127.0.0.1:2379 \
endpoint status -w table3.3 压缩与碎片整理
bash
# 获取当前修订版本号
rev=$($ETCDCTL_PATH \
--cacert=$TLS_PATH/server-ca.crt \
--cert=$TLS_PATH/server-client.crt \
--key=$TLS_PATH/server-client.key \
--endpoints=https://127.0.0.1:2379 \
endpoint status -w json | grep -o '"revision":[0-9]*' | grep -o '[0-9]*')
# 压缩历史版本
$ETCDCTL_PATH \
--cacert=$TLS_PATH/server-ca.crt \
--cert=$TLS_PATH/server-client.crt \
--key=$TLS_PATH/server-client.key \
--endpoints=https://127.0.0.1:2379 \
compact $rev
# 碎片整理
$ETCDCTL_PATH \
--cacert=$TLS_PATH/server-ca.crt \
--cert=$TLS_PATH/server-client.crt \
--key=$TLS_PATH/server-client.key \
--endpoints=https://127.0.0.1:2379 \
defrag
# 解除告警
$ETCDCTL_PATH \
--cacert=$TLS_PATH/server-ca.crt \
--cert=$TLS_PATH/server-client.crt \
--key=$TLS_PATH/server-client.key \
--endpoints=https://127.0.0.1:2379 \
alarm disarm说明:defrag 是阻塞操作,多节点 etcd 集群建议逐台执行,避免同时进行影响集群可用性。
四、证书有效期检查与轮换
RKE 集群各类组件证书默认有效期为 10 年,但客户端 kubeconfig 证书及历史版本集群中的证书可能更早到期。证书过期会导致 kubectl 及组件间 TLS 握手失败,表现为 x509: certificate has expired。
4.1 检查客户端证书有效期
bash
kubectl config view --raw -o jsonpath='{.users[*].user.client-certificate-data}' | base64 -d | openssl x509 -noout -dates输出中的 notAfter 即为过期时间。建议将证书到期检查纳入日常巡检,提前 30 天安排轮换。
4.2 执行证书轮换
bash
rke cert rotate --config /path/to/cluster.yml轮换后 rke 会自动重新生成各类组件证书并下发新的 kubeconfig 文件(kube_config_cluster.yml),需将新文件分发给所有使用方。轮换过程中 API Server 会短暂重启,建议在业务低峰期操作,轮换前先备份集群状态:
bash
# 轮换前对 etcd 做快照备份
rke etcd snapshot-save --config /path/to/cluster.yml --name pre-cert-rotate五、日常预防
5.1 启用 etcd 自动压缩
相比定时脚本,更规范的做法是开启 etcd 原生自动压缩:
| 环境 | 配置方式 |
|---|---|
| RKE | cluster.yml 中 etcd 服务的 extra_args 添加:auto-compaction-mode: periodic、auto-compaction-retention: "8h" |
| RKE2 | /etc/rancher/rke2/config.yaml 添加:etcd-arg: ["auto-compaction-mode=periodic","auto-compaction-retention=8h"],重启 rke2-server |
自动压缩只负责 compact,defrag 仍需定期手动或通过脚本执行。
5.2 监控与巡检项
| 巡检项 | 命令 / 指标 | 阈值建议 |
|---|---|---|
| etcd DB 大小 | endpoint status -w table 的 DB SIZE | 超过 1.5GB(配额 75%)即预警 |
| 告警状态 | etcdctl alarm list | 应始终为空 |
| 磁盘空间 | /var/lib/etcd 所在分区 | 剩余空间低于 20% 预警 |
| 证书有效期 | openssl 检查 notAfter | 提前 30 天安排轮换 |
| 定期快照 | rke etcd snapshot-save / k3s etcd-snapshot save | 每日至少一次,异地留存 |
故障速查
| 现象 | 原因 | 处理 |
|---|---|---|
etcdserver: mvcc: database space exceeded | NOSPACE 告警,写入被拒 | compact → defrag → alarm disarm,全部 etcd 节点执行 |
| defrag 后 DB SIZE 未下降 | 未先 compact,或 defrag 未在对应节点执行 | 确认顺序,逐节点执行 |
| etcdctl 报 TLS 证书错误 | RKE2 未携带 etcd 客户端证书 | 使用 /var/lib/rancher/rke2/server/tls/etcd/ 下三件套 |
x509: certificate has expired | 集群 / 客户端证书过期 | rke cert rotate 轮换并更新 kubeconfig |
| alarm disarm 后很快再次告警 | 写入量大且无自动压缩 | 启用 auto-compaction,排查事件 / 大对象洪峰 |
| compact 命令卡住 | revision 获取异常或 etcd 不健康 | 先 endpoint health 检查集群状态 |