近日,腾讯云TKE团队的工程师在做混沌测试的过程中,定位并解决了一个存在3年之久的etcd3数据一致性bug。
在特定场景下,该bug会导致etcd集群多个节点之间的数据不一致,而且etcd日志无明显报错,并且继续向集群写入数据不会报错,但是会概率性读不出来,可能导致Kubernetes集群无法正常工作。
详细描述可见issue: https://github.com/etcd-io/etcd/issues/11651
etcd的鉴权模块,为了避免TOCTOU问题,引入了auth revision,每次在进行权限操作时,会增加当前的auth revision。在进行数据apply时,如果需要鉴权,会将请求header中的auth revision(取自raft请求发起的节点,即通过etcd api直接访问的节点)和当前的auth revision做比较。如果请求header中的auth revision小于当前节点的auth revision,则认为该授权已过期,不会进行实际的apply操作。正常情况下etcd每个节点之间的auth revision都是一致的,但如果触发了该bug,则会导致不同节点之间的auth revision出现不一致,从而导致在实际写入数据到后端时,部分节点认为鉴权过期写入失败,引发数据不一致。
而auth revision不一致的根本原因,是由于etcd3的权限模块本身未持久化consistentIndex导致。etcd在apply数据到后端存储时,依赖consistentIndex来保证同一条命令不会重复执行,即consistentIndex保证了etcd写操作的幂等性。每次实际执行apply操作后,etcd都会更新consistentIndex为当前apply数据的Index。etcd3的权限模块同样依赖consistentIndex,但是它身并未持久化consistentIndex,而是依赖mvcc模块的写请求来持久化consistentIndex。如果在权限操作(例如grant-permission)之后,没有其他数据写入,且此时重启了节点,那么已经更新的consistentIndex并不会持久化到后端存储。由于增量变更的consistentIndex未持久化,会导致这部分数据被重复apply,如果该apply操作有副作用,就可能会导致一系列的问题 —— 例如会导致该节点的auth revision被增加多次,从而和其他节点不一致。
目前我们已经向社区提了PR来修复该问题,并且已经合入master,将来会backport到etcd 3.2/3.3/3.4等不同版本: https://github.com/etcd-io/etcd/pull/11652。未避免升级重启时遇到该问题,升级前需要停止权限相关的写操作,并且手动触发一次写数据操作,然后重启节点。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。