引言
最近仔细看了下 Elasticsearch Operator,感觉它的设计有点别出心裁,在集群更新方面,比我所知道的 TiDB Operator 和 Prometheus Operator 做的更好。所以在这里做一个 Elasticsearch Operator 和 TiDB Operator 的对比。
ES Operator 滚动更新
ES 作为搜索存储组件,也是一种有状态应用。ES Operator 在19年的有一个 issue #1173 ,确定了基于Statefulset
做 ES 的部署。最近阅读完 ES Operator的代码,我发现它虽然基于Statefulset
做集群管理,但是节点更新的逻辑脱离了 Statefulset
的倒序更新。ES Operator 将需要部署的Statefulset
更新策略设置为OnDelete
策略,然后自定义了一套 节点更新 策略,这套更新策略简化为:
ES Operator 自定义了一套 Pod 预选机制,预选机制是可扩展的,当前已有多个预选规则,我总结了一下。
预选规则:
- 不得重启大于 MaxUnAvailable 的节点数。
- 只有当集群是 green 或者 yellow 的时候,才可以重启节点。
- 跳过正在重启的Pod。
- 在集群是 yellow 状态的时候,如果重启这个点,必须满足 shard 不会出现无 started 状态分片的情况。
- 一次只重启一个 master。
- 如果 data 节点没有更新完,不会更新 master 节点。
- 不会同时更新两个Pod 包含相同的 shard。
ES Operator 在更新 Pod
之前,会经过一系列的验证才会去操作集群,我觉得更加稳定。举个例子,[0,1,2] 三个 data 节点,如果 0 节点损坏宕机了,这个时候Operator 更新集群,如果按照Statefulset 的倒序策略,需要先重启 2 号节点,这个时候会让集群陷入更糟糕的场景。我们应该先重启 0 号节点,让它先恢复。所以 ES Operator 虽然脱离于Statefulset
重新写了一套更新策略,但是这套机制更灵活,让应用更稳定。
我画了一张更详细的流程图,描述 ES Operator 的滚动更新逻辑。
TiDB Operator 滚动更新
TiDB Operator 采用 Statefulset Partition 的方式滚动更新,这种方式可以控制节点依次更新,但是必须按照倒序的方式,在极端情况下,由于中间节点的损坏,倒序更新的方式会让集群陷入更加糟糕的地步。TiDB Operator 更新集群的时候,没有考虑到集群层面的可用性,只是对当前更新节点进行驱逐 region。这一点我们可以从TiDB Operator 更新 TiKV 的一段核心代码看出来。
代码如下:
画个图描述下依次更新的过程:
基于 TiDB Operator 当前的实现,我也提出来了自定义一套更新策略,增强在发布过程中的稳定性。参考 issue 4130。
总结
从 ES Operator 的实现可以看出,有状态存储用Statefulset
还是有很多问题点,所以大家会对它做很多增强,比如 AdvanceStatefulset。但是我觉得或许我们需要一款新的基于 Pod 重新组装的CRD,他需要更加灵活可扩展,来应对 TiDB ,ES 等复杂类型的组件。