hello云胜

技术与生活

0%

etcdserver: mvcc: database space exceeded

它是指当前 etcd db 文件大小超过了配额,当出现此错误后,你的整个集群将不可写入,只读,对业务的影响非常大。

原因:

当 etcd server 收到 put/txn 等写请求的时候,会首先检查下当前 etcd db 大小加上你请求的 key-value 大小之和是否超过了配额(quota-backend-bytes)。

一方面默认 db 配额仅为 2G,当你的业务数据、写入 QPS、Kubernetes 集群规模增大后,你的 etcd db 大小就可能会超过 2G。

另一方面我们知道 etcd v3 是个 MVCC 数据库,保存了 key 的历史版本,当你未配置压缩策略的时候,随着数据不断写入,db 大小会不断增大,导致超限。

最后你要特别注意的是,如果你使用的是 etcd 3.2.10 之前的旧版本,请注意备份可能会触发 boltdb 的一个 Bug,它会导致 db 大小不断上涨,最终达到配额限制。

解决:

首先当然是调大配额。具体多大合适呢?etcd 社区建议不超过 8G

但是,当你把配额(quota-backend-bytes)调大后,集群依然拒绝写入

原因是

当发现超过了配额时,etcd会产生一个告警(Alarm)请求,告警类型是 NO SPACE,并通过 Raft 日志同步给其它节点,告知 db 无空间了,并将告警持久化存储到 db 中

etcd的Apply 模块在执行每个命令的时候,都会去检查当前是否存在 NO SPACE 告警,如果有则拒绝写入。所以还需要你额外发送一个取消告警(etcdctl alarm disarm)的命令,以消除所有告警。

我们还需要检查 etcd 的压缩(compact)配置是否开启、配置是否合理。etcd 保存了一个 key 所有变更历史版本,如果没有一个机制去回收旧的版本,那么内存和 db 大小就会一直膨胀,在 etcd 里面,压缩模块负责回收旧版本的工作。

压缩模块支持按多种方式回收旧版本,比如保留最近一段时间内的历史版本。不过你要注意,它仅仅是将旧版本占用的空间打个空闲(Free)标记,后续新的数据写入的时候可复用这块空间,而无需申请新的空间。如果你需要回收空间,减少 db 大小,得使用碎片整理(defrag), 它会遍历旧的 db 文件数据,写入到一个新的 db 文件。但是它对服务性能有较大影响,不建议你在生产集群频繁使用。

最后你需要注意配额(quota-backend-bytes)的行为,默认’0’就是使用 etcd 默认的 2GB 大小,你需要根据你的业务场景适当调优。如果你填的是个小于 0 的数,就会禁用配额功能,这可能会让你的 db 大小处于失控,导致性能下降,不建议你禁用配额。