部署后使用 marathon-api 自动关闭 Akka 集群中的节点

问题描述

我有一个应用程序使用 marathon-api 和 ClusterBootstrap 部署 Akka 集群

当部署运行时,它会执行以下操作:

  • 使用新版本的应用程序添加新实例
  • 杀死一个旧实例
  • 重复直到完成

我们有一个由 4 个节点组成的集群

在进行部署后,集群看起来像这样(在这个例子中假设有 2 个实例):

{
  "leader": "akka.tcp://app@ip-10-0-5-15.eu-central-1.compute.internal:13655","members": [
    {
      "node": "akka.tcp://app@ip-10-0-4-8.eu-central-1.compute.internal:15724","nodeUid": "-1598489963","roles": [
        "dc-default"
      ],"status": "Up"
    },{
      "node": "akka.tcp://app@ip-10-0-5-15.eu-central-1.compute.internal:13655","nodeUid": "-1604243482","status": "Up"
    }
  ],"oldest": "akka.tcp://app@ip-10-0-4-8.eu-central-1.compute.internal:15724","oldestPerRole": {
    "dc-default": "akka.tcp://app@ip-10-0-4-8.eu-central-1.compute.internal:15724"
  },"selfNode": "akka.tcp://app@ip-10-0-5-15.eu-central-1.compute.internal:13655","unreachable": [
    {
      "node": "akka.tcp://app@ip-10-0-4-8.eu-central-1.compute.internal:15724","observedBy": [
        "akka.tcp://app@ip-10-0-5-15.eu-central-1.compute.internal:13655"
      ]
    }
  ]
}

有时leader仍然是WeaklyUp,但想法是一样的,而消失的节点可以是up或Leaving。

然后日志开始显示此消息:

Cluster Node [akka.tcp://app@ip-10-0-5-15.eu-central-1.compute.internal:13655] - leader can currently not perform its duties,reachability status: [akka.tcp://app@ip-10-0-5-15.eu-central-1.compute.internal:13655 -> akka.tcp://app@ip-10-0-4-8.eu-central-1.compute.internal:15724: Unreachable [Unreachable] (1)],member status: [
akka.tcp://app@ip-10-0-4-8.eu-central-1.compute.internal:15724 Up seen=false,akka.tcp://app@ip-10-0-5-15.eu-central-1.compute.internal:13655 Up seen=true]

部署更多次会使情况变得更糟

我想当一个节点被杀死时,它会改变集群的状态,因为它实际上无法访问,但我希望可以有某种功能可以解决这个问题

到目前为止,唯一可以解决此问题的方法是使用 Akka Cluster HTTP Management 执行 PUT /cluster/members/{address} operation:Down

我知道有一个名为 Auto-downing功能删除了,因为它弊大于利。

我也尝试了 Split Brain Resolver 使用那里提供的策略,但最终这些策略最终导致整个集群宕机,日志如下:

> Cluster Node [akka://app@ip-10-0-5-215.eu-central-1.compute.internal:43211] - leader can currently not perform its duties,reachability status: [akka://app@ip-10-0-5-215.eu-central-1.compute.internal:43211 -> akka://app@ip-10-0-4-146.eu-central-1.compute.internal:2174: Unreachable [Unreachable] (1)],member status: [akka://app@ip-10-0-4-146.eu-central-1.compute.internal:2174 Up seen=false,akka://app@ip-10-0-5-215.eu-central-1.compute.internal:43211 Up seen=true]
> Running CoordinatedShutdown with reason [ClusterDowningReason]
> SBR is downing
> SBR took decision DownReachable and is downing

也许我没有用正确的配置设置正确的策略,但我不知道该尝试什么,同样我有一个 4 节点集群,所以我猜认的 Keep Majority 应该这样做,尽管这案例与其说是网络分区,不如说是一个崩溃的节点

有没有办法使用 marathon-api 顺利部署 Akka 集群?我愿意接受建议

更新: 我还将 Akka 版本从 2.5.x 更新到 2.6.x,文档指出它不兼容,因此我需要手动干预第一次部署。最后使用认配置的 Split Brain Resolver 确实有效

解决方法

您需要使用像 Split Brain Resolver 这样的“真正的”downing 提供程序。这让集群可以安全地关闭无法访问的节点。 (与自动停机相反,它在不考虑安全与否的情况下将它们停机。)

还有一个单独的问题,即为什么 DC/OS 如此迅速地杀死节点,以至于他们没有机会正确关闭。但我不太了解 DC/OS,无法说明为什么会这样。而且,无论如何,停机提供程序对于集群环境至关重要,因此无论如何您都希望将其部署到位。

根据您对 SBR 的评论进行编辑:

  • 首先我想澄清一下,marathan-api 在这里几乎可以肯定是无关紧要的。 marathon-api 是节点发现 DC/OS 中其他节点的方式。您遇到的问题是基本的集群问题,即无法访问的节点。具有无法访问节点的集群将以相同的方式运行,无论它在哪里运行以及节点是如何被发现的。
  • 从根本上说,我最好的猜测是您在完全关闭时遇到了问题。如果 SBR 使您的整个集群宕机,那是因为无法访问的节点数量超过了实时集群。

举个例子,可能会发生什么:

  • 您有 4 个活动节点并且想要升级。
  • DC/OS 终止第一个节点。由于某些未知原因,您没有完全关闭,因此该节点被标记为无法访问。 (本质上是集群,因为它不是完全关闭,如果节点仍然存在但没有响应和/或在分区后面,则不会节点。)有 3 个活动节点和一个无法访问。
  • DC/OS 启动第二个节点。也许启动您的应用程序需要一些时间。因此,您有 3 个活动节点、1 个无法访问的节点和 1 个未就绪节点。
  • DC/OS 杀死了另一个节点。因此,您有 2 个活动节点、2 个无法访问的节点和 1 个未就绪节点。此时 SBR 不能再保证您没有网络分区,因为您没有多数。此时,为了防止损坏,必须停止集群。

所以,我会推荐以下内容:

  • 我不太了解 DC/OS 的详细信息,但您可能需要放慢滚动升级的速度。在 K8S 中,我会使用类似 MinReadySeconds 的东西。
  • 您可能需要考虑第五个节点。奇数更好,因为它更容易确定多数。
  • 如果您仍然遇到问题,则需要提供更多来自 SBR 决定的日志。

SBR 就是答案。我意识到您没有真正的网络分区,但是您拥有无法访问的节点这一事实意味着 Akka 集群无法判断是否存在网络分区,这就是问题的根本原因。