Skip to content

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 $rev

2.3 碎片整理

bash
etcdctl defrag

2.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 table

3.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 原生自动压缩:

环境配置方式
RKEcluster.yml 中 etcd 服务的 extra_args 添加:auto-compaction-mode: periodicauto-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 exceededNOSPACE 告警,写入被拒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 检查集群状态