0%

看Elasticsearch-Operator-有感

引言

最近仔细看了下 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 预选机制,预选机制是可扩展的,当前已有多个预选规则,我总结了一下。

预选规则:

  1. 不得重启大于 MaxUnAvailable 的节点数。
  2. 只有当集群是 green 或者 yellow 的时候,才可以重启节点。
  3. 跳过正在重启的Pod。
  4. 在集群是 yellow 状态的时候,如果重启这个点,必须满足 shard 不会出现无 started 状态分片的情况。
  5. 一次只重启一个 master。
  6. 如果 data 节点没有更新完,不会更新 master 节点。
  7. 不会同时更新两个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 等复杂类型的组件。