aws 中的 rabbitmq 自动缩放集群:管理缩放事件
Posted
技术标签:
【中文标题】aws 中的 rabbitmq 自动缩放集群:管理缩放事件【英文标题】:rabbitmq autoscaling cluster in aws: managing scaling events 【发布时间】:2020-03-29 16:51:42 【问题描述】:我正在使用自动缩放组和负载平衡器(用于管理控制台 Web 访问和消息路由)在 aws 中部署 rabbitmq (3.8.0)。
用于 rabbitmq 自动缩放的 peer-discovery-aws 插件似乎非常适合让新节点自动加入集群。 (虽然我们只能让自动缩放模式工作)。
目标组健康检查将杀死一个在 amq 端口 (5672) 上没有响应的实例,然后 Auto Scaling 组将替换它。当一个节点出现故障时,这很棒。当 CPU 利用率超过某个阈值时,也可以使用扩展策略来增加集群大小(尽管我不知道这是否是一个现实的用例)。
所以我们在测试中遇到了几个我不确定如何解决的场景:
我们遇到了一个问题,即 rabbitmqctl 应用程序在集群的所有节点上都死了。伸缩组将无响应的实例杀死,然后用新实例替换它。新实例不会自动加入集群,因为剩余的实例也已死亡。当 Auto Scaling 组杀死最后一个实例时,由于新实例无法加入,因此所有存储的消息都丢失了。所以这个问题是:如果最后一个集群节点被缩放事件终止,我如何保存数据? (我的假设是使用外部 EBS 卷来存储消息,并在启动时附加它,但是当该实例终止时,卷也被终止,而不是附加到新实例 - 我感觉我正在尝试重新发明 Erlang 应该做的 HA 轮)。
另一个(相关)问题是:当我使用rabbitmqctl start_app
重新启动服务时;并关闭新实例,伸缩组替换新实例(因为旧实例现在正在通过健康检查) - 但无论出于何种原因,新实例都无法加入集群。已终止的原始实例仍被“记住”为集群节点。因此,当第二个新实例出现并尝试加入集群时 - 应用程序在原始节点上崩溃了。 (这是奇怪的行为 - 但我重复了三遍)。那么问题2是:当一个集群节点被弹性伸缩组终止时,如何自动将该节点从集群中移除,以便替换的集群节点可以自动加入集群? (看来我应该做的是写一个服务在每个集群节点上运行,并使用aws cli持续监控其他集群节点的状态,当一个“终止”时(这种状态只持续几分钟之前实例消失) - 在出现故障的节点上运行删除节点命令)。还是我再次重新发明了 Erlang ***?
最后一个问题是:我们最初使用 Terraform 部署一个新的集群和资源。 rabbitmq 节点以“初始化”状态启动,没有配置队列或交换器,只有管理员用户和默认密码等。我们从现有集群导出 json 配置文件,然后将其导入新集群,然后更改集群名称恢复为原始名称。当我们准备好停用旧集群时,我们只需将消息铲入并交换负载均衡器的 DNS 名称,我们就可以通过这种方式进行蓝绿部署升级。问题是:当一个新节点通过自动缩放实例化时,它处于初始状态,直到它加入集群。负载均衡器将路由到任何节点,因为它不知道该节点是否在 RabbitMQ 集群中。因此,没有生产者或消费者可以对“初始状态”节点进行身份验证,这很好。但是 Web 控制台会交替路由到旧的或新的集群节点;其中管理员密码与两个节点不同。 (即,在所有节点都加入之前无法管理集群)。问题 #3 是:我需要一种方法来告诉 Amazon ALB 不要将 15672(Web 控制台)流量路由到尚未加入集群的节点。看起来这应该是一个简单的问题,但这对我们的管理员造成了严重破坏。
【问题讨论】:
【参考方案1】:免责声明我从未使用过 RabbitMQ 或设置自动缩放
1) - 您可以将 EFS 用于共享辅助数据存储[1]。 EFS 的性能确实比 EBS 差一些,因此您需要测试它是否特别适用于 RabbitMQ。 - 您还可以将辅助 EBS 卷附加到实例,但这会引入许多您必须编写脚本的烦人问题(EBS 特定于 AZ,旧实例的运行状况检查替换的竞争条件消失了及时启动新的,AZ 故障,实例全部移出 AZ,等等)。
2) - 您可以向组添加终止生命周期挂钩[2]。这将触发一个事件,并在 ASG 决定终止它之后,但在其实际终止之前,让实例在短时间内处于挂起状态。只要此生命周期挂钩启动,您就可以触发 CloudWatch 事件。 CW 事件可以触发诸如 Lambda 或 SSM Runbook 之类的东西,它们可以调用命令从集群中取消注册实例。 - 如果您在从集群中取消注册实例时不需要该实例仍在运行,那么在 ASG 实例终止时还会有一个 CloudWatch 事件[3],因此您可以触发该事件而无需设置生命周期挂钩ASG。
3) - ALB 刚刚为进行蓝/绿部署的人发布了一项新功能,您可以在其中将 2 个目标组连接到单个侦听器操作,并确定每个目标组应该有多少流量[4]。将旧实例/ASG 附加到一个目标组,将新实例/ASG 附加到另一个目标组。在新节点启动并运行之前,不要向它们发送流量。 - 或者,如果您通常需要此功能,而不仅仅是在部署期间,请利用 ELB 运行状况检查。为默认情况下不存在的页面设置自定义运行状况检查路径。一旦配置了实例并且您想要向它发送流量(我假设它是一个自动过程执行此操作?)在该运行状况检查路径上创建一个文件,以便它开始通过运行状况检查并且 ALB 将发送该实例流量。 (我假设您现在有 2 个与 ASG 关联的不同目标组,一个用于两个端口/流量类型中的每一个,每个都有自己的运行状况检查)。执行此操作时,请确保 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/
【讨论】:
以上是关于aws 中的 rabbitmq 自动缩放集群:管理缩放事件的主要内容,如果未能解决你的问题,请参考以下文章
Terraform 中的 ECS 服务如何连接到 AWS 自动缩放组