aws 中的 rabbitmq 自动缩放集群:管理缩放事件

rabbitmq autoscaling cluster in aws: managing scaling events

我正在使用自动缩放组和负载均衡器(用于管理控制台 Web 访问和消息路由)在 aws 中部署 rabbitmq (3.8.0)。

用于 rabbitmq 自动缩放的 peer-discovery-aws 插件似乎非常适合让新节点自动加入集群。 (虽然我们只能让自动缩放模式工作)。

目标组健康检查将终止在 amq 端口 (5672) 上没有响应的实例,然后自动缩放组将替换它。当一个节点出现故障时,这很好。当 CPU 利用率超过某个阈值时,扩展策略也可用于增加集群大小(尽管我不知道这是否是一个现实的用例)。

所以我们 运行 进入了几个我不确定如何解决的测试场景:

  1. 我们遇到了一个问题,即 rabbitmqctl 应用程序在集群的所有节点上都死了。伸缩组杀死了无响应的实例,然后用新实例替换它。新实例不会自动加入集群,因为剩余的实例也已死亡。当 Auto Scaling 组杀死最后一个实例时,由于新实例无法加入,所有存储的消息都丢失了。所以这个问题是:如果最后一个集群节点因缩放事件而终止,我该如何保留数据? (我的假设是使用外部 EBS 卷来存储消息,并在启动时附加它,但是当该实例终止时,该卷也终止,并且没有附加到新实例 - 我感觉我正在尝试重新发明 Erlang 应该做的 HA 轮)。

  2. 另一个(相关)问题是:当我使用 rabbitmqctl start_app 重新启动服务时;并关闭新实例,缩放组替换新实例(因为旧实例现在正在通过健康检查) - - 无论出于何种原因,新实例无法加入集群。已终止的原始实例仍然是 "remembered" 作为集群节点。因此,当第二个新实例出现并尝试加入集群时——应用程序在原始节点上崩溃了。 (这是一种奇怪的行为——但我重复了三遍)。所以问题2是:当一个集群节点被自动伸缩组终止时,我如何自动从集群中删除这个节点,以便替换集群节点可以自动加入集群? (看来我应该做的是在每个集群节点上写一个运行s的服务,并使用aws cli持续监控其他集群节点的状态,当一个是"terminated"(这个状态只在实例消失之前持续几分钟)- 运行 已关闭节点上的删除节点命令)。还是我又在重新发明 Erlang 轮子?

  3. 最后一个问题是:我们最初使用 Terraform 部署了一个新的集群和资源。 rabbitmq 节点以 "initialized" 状态启动,配置没有队列或交换,只有管理员用户和默认密码等。我们从现有集群导出 json 配置文件,然后将其导入到新集群,然后将集群名称更改回其原始名称。当我们准备好停用旧集群时,我们只需将消息铲过并交换负载均衡器的 DNS 名称,我们就可以通过这种方式进行蓝绿部署升级。问题是:当一个新节点通过自动缩放实例化时,它处于初始状态,直到它加入集群。负载均衡器将路由到任何节点,因为它不知道该节点是否在 RabbitMQ 集群中。因此,没有生产者或消费者可以向 "initial-state" 节点进行身份验证,这很好。但是 Web 控制台会交替路由到旧的或新的集群节点;其中管理员密码与两个节点不同。 (即,在所有节点都加入之前无法管理集群)。问题 #3 是:我需要一种方法来告诉 Amazon ALB 不要将 15672(Web 控制台)流量路由到尚未加入集群的节点。看起来这应该是一个简单的问题,但这对我们的管理员造成了严重破坏。

免责声明我从未使用过 RabbitMQ 或使用它设置自动缩放

1) - 您可以将 EFS 用于共享的辅助数据存储[1]。 EFS 的性能确实比 EBS 差一点,因此您需要测试它是否专门适用于 RabbitMQ。 - 您还可以将辅助 EBS 卷附加到实例,但这会引入许多您必须编写脚本的烦人问题(EBS 特定于可用区,旧实例的运行状况检查替换上的竞争条件将消失及时启动新的,AZ 失败,其中实例全部移出 AZ,等等)。

2) - 您可以将终止生命周期挂钩 [2] 添加到组中。这将触发一个事件,并在 ASG 决定终止它之后,但在它实际终止之前,让实例 运行 在短时间内处于待处理状态。只要此生命周期挂钩启动,您就可以触发 CloudWatch 事件。 CW 事件可以触发诸如 Lambda 或 SSM 运行手册之类的东西,它们可以调用命令从集群中注销实例。 - 如果您不需要实例在从集群中注销时仍然是 运行,那么在 ASG 实例终止时任何时候都有一个 CloudWatch 事件[3],因此您可以触发该事件而无需设置ASG 上的生命周期挂钩。

3) - ALB 刚刚为进行 blue/green 部署的人员发布了一项新功能,您可以将 2 个目标组连接到一个侦听器操作,并为每个目标组分配多少流量 [4]。将旧 instances/ASG 附加到一个目标组,将新 instances/ASG 附加到另一目标组。在新节点启动并且 运行 之前,不要将流量发送到新节点。 - 或者,如果您一般想要这样做,而不仅仅是在部署期间,请利用 ELB 健康检查。设置默认情况下不存在的页面的自定义健康检查路径。一旦配置了实例并且您想要向它发送流量(我假设它是一个自动执行此操作的过程?)在该健康检查路径上创建一个文件,以便它开始通过健康检查并且 ALB 将发送该实例流量。 (我假设您现在有 2 个不同的目标组与 ASG 关联,两个 ports/types 流量中的每一个都有一个,每个都有自己的健康检查)。执行此操作时,请确保 ASG 的健康检查宽限期足够长,以免实例因不健康而终止。

[1] https://docs.aws.amazon.com/efs/latest/ug/mount-fs-auto-mount-onreboot.html

[2]https://docs.aws.amazon.com/autoscaling/ec2/userguide/lifecycle-hooks.html

[3] https://docs.aws.amazon.com/autoscaling/ec2/userguide/cloud-watch-events.html#terminate-successful

[4]https://aws.amazon.com/blogs/aws/new-application-load-balancer-simplifies-deployment-with-weighted-target-groups/