Etcd 坑了多少公司?
前几天影视飓风分享的 Pigsty / PostgreSQL 高可用案例里面踩的一个雷在 X 上引起网友热议。“因为 etcd 未开启自动压实功能,且默认仅为 2GB 容量”, ayanamist 评论到:“我倒要看看 etcd 这个傻逼 2G 的设计可以坑多少公司”。
etcd 的 slogan 是:“一个分布式的、可靠的键-值存储,用于存放系统中最为关键的配置数据”。目前最常见的场景是用于存储 K8S 的元数据。当然类似 Patroni 这样的 PostgreSQL 高可用方案也可能会用到 etcd 作为 DCS。
在 Ayanamist 这条推的评论下,可以看到许多人都踩过这个雷。大部分是 K8S 用户,也有在 PG 高可用场景上翻车的例子。
etcd 的缺陷
ETCD 有一个非常傻逼的设计,就是在默认配置下,写满 2GB 数据就挂了。
具体来说,etcd 每次写入都会创建一个新的版本,当这些数据/版本超过 2GB 之后,etcd 就会进入维护模式(挂了)。 想象一个没有启用 GC 垃圾回收的 Java JDK,就可以理解 etcd 有多坑了。
当然,其实是有参数配置项可以解决这个问题的,例如使用以下配置项,可以让 etcd 只保留最近 24 小时的版本,从而避免了存储空间的无限增长。
auto-compaction-retention: "24h"
但坑就坑在,这并不是一个默认配置,这个参数的默认值是 0
,也就是保留所有历史版本。
更坑的是,在 etcd “维护” 部分的文档里的语句很有误导性,例如在 Maintenance 部分是这么说的:
为了保持稳定性,etcd 集群需要定期维护。根据 etcd 应用的需求,这些维护通常可以自动化执行,且不会导致停机或显著性能下降。
而且在下面的 “Auto Compaction” 部分,一眼看过去,给人的感觉就是 auto compact 设置了很好的默认值嘛: 每小时垃圾回收一次,保留10个小时,这不是挺好的?应该不需要我操心了。
但如果你没去看那个 Configuration Options 参考文档,那完犊子了
最后,这个问题还不会在 etcd 开始服务时立即暴露,而是会在使用几个月之后突然爆雷。
PostgreSQL 的例子
其实在很早的时候(8.0, 2005 年前) PostgreSQL 也有这个问题。 PostgreSQL 使用与 etcd 类似的 MVCC 逻辑,每次写入也都是创建新版本/标记删除,所以会留下许多历史版本。 当垃圾版本积累的太多而没有清理时,数据库就炸了,而这个操作是需要管理员手工执行的,所以成为了 PG 广为诟病的一个问题。
不过后来 PostgreSQL 引入了 AutoVacuum 机制,也就是自动垃圾回收,会有守护进程不断扫描清理回收,免去了人工操作的烦恼。 因此在现代硬件上,默认参数下的 PostgreSQL 基本不会再因为这个问题而头疼了。
然而,并非所有数据库都像 PostgreSQL 这样 “靠谱贴心”,给用户设置了足够好的 “默认值”,可以开箱即用。etcd 就是一个非常典型的例子。
Pigsty 的例子
Pigsty 也在这个问题上翻过车。从 2023-02-28 发布的 v2.0.0 首次引入 etcd 作为 DCS 开始,到 2024-02-13 v2.6.0 修复 etcd 的这个问题, 整整一年的版本都受到 etcd 这个问题的影响。对影视飓风踩雷 etcd 的这个案例,老冯感到汗颜,因为他们也是因为 Pigsty (v2.3)