3

考虑跨 3 个可用区的 Statefulset(Cassandra 使用官方 K8S 示例):

  • cassandra-0 -> 区域 a
  • cassandra-1 -> 区域 b
  • cassandra-2 -> 区域 c

每个 Cassandra pod 都使用一个 EBS 卷。所以自动地有一个亲和力。例如,cassandra-0 无法移动到“zone-b”,因为它的卷位于“zone-a”中。都好。

如果某些 Kubernetes 节点/worker 发生故障,它们将被替换。pod 将在新节点上重新启动并重新附加其 EBS 卷。看起来什么都没发生。

现在,如果整个 AZ “zone-a”出现故障并且在一段时间内不可用(这意味着 cassandra-0 由于与 EBS 在同一区域中的相关性而无法再启动)。你剩下:

  • cassandra-1 -> 区域 b
  • cassandra-2 -> 区域 c

只要“zone-a”不可用,Kubernetes 就永远无法启动 cassandra-0。这一切都很好,因为 cassandra-1 和 cassandra-2 可以处理请求。

现在,如果最重要的是,另一个 K8S 节点出现故障,或者您已经设置了基础架构的自动扩展,那么您最终可能需要移动到另一个 K8S 节点的 cassandra-1 或 cassandra-2。这不应该是一个问题。

但是根据我的测试,K8S 不会这样做,因为 pod cassandra-0 处于脱机状态。它永远不会自我修复 cassandra-1 或 cassandra-2(或任何 cassandra-X),因为它首先要返回 cassandra-0。并且 cassandra-0 无法启动,因为它的卷位于已关闭且未恢复的区域中。

因此,如果您使用Statefulset + VolumeClaim + 跨区域 并且您遇到整个 AZ 故障 并且您在另一个 AZ 中遇到 EC2 故障或者您的基础架构具有自动扩展

=> 那么你将失去所有的 Cassandra 豆荚。直到 zone-a 重新上线

这似乎是一个危险的情况。有没有办法让有状态的集合不关心订单并且仍然自我修复或在 cassandra-3、4、5、X 上启动更多 pod?

4

3 回答 3

2

两种选择:

选项 1:使用 podManagementPolicy并将其设置为 Parallel。pod-1 和 pod-2 会崩溃几次,直到种子节点(pod-0)可用。第一次创建有状态集时会发生这种情况。另请注意,Cassandra 文档曾经建议不要并行创建多个节点,但最近的更新似乎使这不是真的。可以同时向集群添加多个节点

发现的问题:如果使用 2 个种子节点,您将得到一个裂脑场景。每个种子节点将同时创建,并创建 2 个独立的逻辑 Cassandra 集群

选项 1 b:使用 podManagementPolicy并将其设置为 Parallel 并使用 ContainerInit。与选项 1 相同,但使用 initContainer https://kubernetes.io/docs/concepts/workloads/pods/init-containers/。init 容器是一个短暂的容器,它的作用是在启动实际容器之前检查种子节点是否可用。如果我们很高兴 pod 崩溃直到种子节点再次可用,这不是必需的。问题是 Init Container 将始终运行,这不是必需的。我们希望确保 Cassandra 集群在第一次创建时就已经形成。之后就无所谓了

选项 2:创建 3 个不同的 statefulets

每个可用区/机架 1 个状态集。每个 statefulset 都有约束,因此它只能在特定 AZ 中的节点上运行。我还有 3 个存储类(再次限制到特定区域),以确保 statefulset 不会在错误的区域中配置 EBS(statefulset 还没有动态处理)在每个 statefulset 中我都有一个 Cassandra 种子节点(定义为在运行时填充 SEED_PROVIDER 的环境变量 CASSANDRA_SEEDS)。这使得 3 种子是足够的。由于replication-factor = 3,我的设置可以在完全区域中断中幸存下来

提示:

  • 种子节点列表包含用逗号分隔的所有 3 个节点:“cassandra-a-0.cassandra.MYNAMESPACE.svc.cluster.local, cassandra-b-0.cassandra.MYNAMESPACE.svc.cluster.local, cassandra-c- 0.cassandra.MYNAMESPACE.svc.cluster.local"
  • 等到第一个种子 (cassandra-a-0) 准备好后再创建其他 2 个 statefulset。否则你会脑裂。这只是您创建集群时的问题。之后,您可以在没有影响的情况下松开一两个种子节点,因为第三个节点知道所有其他节点。
于 2018-02-20T22:59:02.093 回答
2

从 Kubernetes 1.7 开始,您可以使用podManagementPolicy选项(文档)告诉 Kubernetes 放宽 StatefulSet 排序保证。通过将该选项设置为ParallelKubernetes 将不再保证在启动或停止 pod 和并行启动 pod 时的任何顺序。这可能会对您的服务发现产生影响,但应该可以解决您正在谈论的问题。

于 2018-02-09T05:23:03.553 回答
0

我认为如果你可以控制每个 pod 的部署(cassandra-0、cassandra-1、cassandra-2 和三个不同的 yaml 部署文件),你可以使用 podAffinity 为每个 pod 设置一个特定的区域。

一旦 zone 上的一个节点发生故障并且必须重新调度在该服务器内运行的 pod,affinity 将强制 Kubernetes 将 pod 部署在同一 zone 的不同节点上,如果同一 zone 上没有可用的节点,Kubernetes 应该无限期地保持这个吊舱。

例如,您可以创建一个具有三个不同 managedNodeGroup 的 Kubernetes 集群,每个区域一个(标签“zone”:每个组的“a”、“b”、“c”),每个组至少有两个节点,并且使用 podAffinity。

注意:不要为节点使用 x1.32xlarge 机器 :-)

于 2022-02-24T18:14:32.637 回答