Etcd: NOSPACE 问题修复

共计 3137 个字符,预计需要花费 8 分钟才能阅读完成。

在生产环境集群中,运行一年多突然出现了 etcd 集群空间超过配额的问题。查看 etcd 的告警,发现有 NO SPACE 的信息,并且 etcdctl endpoints status 中的 DB SIZE 大于 2GiB。

版本信息

  • etcd 版本:3.3.10(运行方式为 Docker 容器)

解决步骤

1. 将 API 版本调整为 3

export ETCDCTL_API=3

2. 声明变量 ETCD_ENDPOINT

ETCD_ENDPOINT=(https://xx:xx:xx:xx:2379,https://xx:xx:xx:xx:2379,https://xx:xx:xx:xx:2379)
ETCD_CAFILE=/etc/ssl/etcd/ssl/ca.pem
ETCD_CERTFILE=/etc/ssl/etcd/ssl/node-master-1.pem
ETCD_KEYFILE=/etc/ssl/etcd/ssl/node-master-1-key.pem

提示:如果不清楚 etcd 证书存放的位置,可以使用 ps 命令查看:

ps -ef | grep -v grep | grep apiserver | sed 's/ /\n/g' | grep etcd

示例输出:

--etcd-cafile=/etc/ssl/etcd/ssl/ca.pem
--etcd-certfile=/etc/ssl/etcd/ssl/node-master-1.pem
--etcd-keyfile=/etc/ssl/etcd/ssl/node-master-1-key.pem
--etcd-servers=https://172.16.200.101:2379,https://172.16.200.102:2379,https://172.16.200.103:2379
--storage-backend=etcd3

3. 备份 etcd

etcdctl --endpoints=${ETCD_ENDPOINT} --cert=${ETCD_CERTFILE} --key=${ETCD_KEYFILE} --cacert=${ETCD_CAFILE} \
snapshot save /var/lib/etcd/my-snapshot.db

4. 获取当前的修订编号,选取需要截断的历史

rev=$(etcdctl --cert=${ETCD_CERTFILE} --key=${ETCD_KEYFILE} --cacert=${ETCD_CAFILE} endpoint status --write-out="json" | \
egrep -o '"revision":[0-9]*' | egrep -o '[0-9]*' | awk 'NR==1{print $1}')

5. 按第四步得到的编号进行压缩

etcdctl --endpoints=${ETCD_ENDPOINT} --cert=${ETCD_CERTFILE} --key=${ETCD_KEYFILE} --cacert=${ETCD_CAFILE} compact $rev

6. 释放物理空间

etcdctl --endpoints=${ETCD_ENDPOINT} --cert=${ETCD_CERTFILE} --key=${ETCD_KEYFILE} --cacert=${ETCD_CAFILE} defrag

注意:此步骤最好将 endpoints 列表中的节点拆开依次执行,否则容易引起集群震荡。

7. 解除告警

etcdctl --endpoints=${ETCD_ENDPOINT} --cert=${ETCD_CERTFILE} --key=${ETCD_KEYFILE} --cacert=${ETCD_CAFILE} alarm disarm

提示:此命令可能需执行两次,确保 etcdctl alarm list 再无输出。

8. 重启 kubelet

经过一段时间后,如果发现所有节点都是 Not Ready 状态,只需重启每个节点的 kubelet

for node in $(kubectl get node --no-headers | awk '{print $1}' | xargs); do
  ssh ${node} 'systemctl restart kubelet'
done

9. 观察 DB SIZE

确保 DB SIZE 无大幅度增长:

etcdctl --endpoints=${ETCD_ENDPOINT} --cert=${ETCD_CERTFILE} --key=${ETCD_KEYFILE} --cacert=${ETCD_CAFILE} endpoints status

参考:压缩完 DB SIZE 是 30MiB,一段时间后涨到 132MiB 后持续不动。

自动压缩机制

etcd 的自动压缩机制用于防止数据大量存入导致性能下降和空间耗尽。压缩完成后,指定 revision 版本之前的数据将不可访问,压缩过的空间将用于存放新键。

自动压缩周期

以 etcd 3.3.x 版本为例:

  • 参数

    • --auto-compaction-mode=periodic
    • --auto-compaction-retention=30m(每 30 分钟压缩一次,保留 30 分钟的数据)
  • 压缩逻辑

    • 当前 revision 为 7617,30 分钟后 revision 编号为 14221。
    • 压缩后,7617 之前的键不可访问。

默认配置

cat /etc/etcd.env
# Environment file for etcd v3.3.10
...
ETCD_AUTO_COMPACTION_RETENTION=8
...
  • 默认配置说明
    • ETCD_AUTO_COMPACTION_RETENTION=8(保留 8 小时的数据量)
    • --auto-compaction-mode=periodic(周期压缩)
    • 最大空间默认 2GiB

问题原因:测试环境中 8 小时的数据量超过 2GiB,导致 etcd 告警。

解决方案

修改 etcd.env 配置:

# 更新保留时间缩短为4小时
ETCD_AUTO_COMPACTION_RETENTION=4

# 添加 etcd 最大空间为8GiB的配置
ETCD_QUOTA_BACKEND_BYTES=8589934592

对于非 Docker 启动的 etcd 集群,添加启动参数:

--quota-backend-bytes=8589934592 --auto-compaction-retention=4

效果:经过几天观察,这两套 etcd 集群再未发生空间超限的问题。

KeySpace 与存储空间

在解决步骤的第 6 步,会执行 defrag 命令,用于释放碎片文件。碎片文件是 etcd 进行 compaction 操作后历史的数据,这部分空间可以用于存放新键。

注意:在进行完 compaction 操作后,如果不需要释放空间,不必执行 defrag。只有当 etcd 空间满时,才需要进行 defrag 操作。

如何查看 etcd 空间的实际使用量?

通过 etcdctl 命令查看的 DB SIZE 是 etcd 历史的最大数据量大小,而不是当前的数据量。要查看当前数据量,可以通过 etcd 的 metrics 获取,具体指标为 etcd_mvcc_db_total_size_in_use_in_bytes

查询方法

curl -s --cacert ${ETCD_CA_FILE} --cert ${ETCD_CERT_FILE} --key ${ETCD_KEY_FILE} \
$(echo ${ETCD_ENDPOINTS} | awk -F, '{print $1}')/metrics | \
egrep ^etcd_mvcc_db_total_size_in_use_in_bytes | awk '{print $2}' | awk '{printf("%.2fMiB",$0/1024/1024)}'

参考文档

etcd 官方维护文档
ETCD问题修复博客

正文完
 0
评论(没有评论)