基于Kubernetes(k8s)的RabbitMQ 集群

简介: 目前,有很多种基于Kubernetes搭建RabbitMQ集群的解决方案。今天笔者今天将要讨论我们在Fuel CCP项目当中所采用的方式。这种方式加以转变也适用于搭建RabbitMQ集群的一般方法。所以如果你想要设计自己的解决方案,你应该收集一些更符合你定制化需求的文章。

目前,有很多种基于Kubernetes搭建RabbitMQ集群的解决方案。今天笔者今天将要讨论我们在Fuel CCP项目当中所采用的方式。这种方式加以转变也适用于搭建RabbitMQ集群的一般方法。所以如果你想要设计自己的解决方案,你应该 收集一些更符合你定制化需求的文章。

命名你的集群

在Kubernetes内部运行RabbitMQ集群会遇到一系列有意思的问题。最先会遇到的问题是为了使各个节点之间互相可见,我们应该如何命名各个节点。以下是一些符合规范的不同的命名方法:

  • rabbit@hostname
  • rabbit@hostname.domainname
  • rabbit@172.17.0.4

在你尝试着启动第一个节点之前,你需要确定容器之间可以通过选取名字的方式互通。例如,Ping命令可以访问@符号后面的节点名称。

Erlang分布式方案(RabbitMQ所基于的实现方式)可以运行在两种命名方案当中的一种:短节点名或者长节点名。区别的关键点在于:名字中如果存在“.”,就属于长节点名;否则就是短节点名。在以上节点名举例当中,第一个就属于短节点名;第二个和第三个则属于长节点名。

综合以上要求,我们可以有以下节点命名规则以供选择:

  • 使用Pet集合(或者叫有状态集合):我们可以使用相对固定的DNS名字。与一般可以“丢弃”的副本出故障时可以轻易的踢出集群相对应,Pet集合是一组有状态的Pod,每个Pod有着可以表示其状态的标识符。
  • 使用IP地址以及一些具有自动发现集群节点的工具(例如,autocluster插件可以使RabbitMQ节点自动发现集群子节点)。

以上的命名规则均需要采用长名字模式。但是DNS/节点名在K8S Pod内部配置的方式需要RabbitMQ 3.6.6以后版本才可以支持。所以如果你采用这种方式,请确认你的RabbitMQ的版本。

Erlang的Cookie问题

第二个成功的关键问题是RabbitMQ节点需要共享一个密钥Cookie。默认情况下RabbitMQ从一个文件当中读取这个Cookie(如果该文件不在,则自动生成一个)。为确保该Cookie在所有节点一致,我们有以下方案:

  • 在制作Docker镜像的时候生成该Cookie文件。这种方法并不推荐,因为该Cookie可以让你对整个RabbitMQ内部有完整的访问权限。
  • 用一个Entrypoint脚本文件来生成该Cookie文件。生成时可以用环境变量来传输密文。如果我们还需要Entrypoint脚本文件来做其他事情,这个方案和下一个方案都可以使用。
  • 通过环境变量的方式给RabbitMQ传递:
    RABBITMQ_CTL_ERL_ARGS=”-setcookie ”
    RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS=”-setcookie ”

集群的缺陷

于RabbitMQ集群另外一个必须知道是事情是当一个节点加入集群时,该节点的数据将会丢失,无论是什么样的数据。在常见的用例当中,这点可能无关紧要。例如,当一个空节点加入到集群当中的时候,这时候该节点不存在任何数据丢失的问题。但是,当我们有两个节点,他们已经相对独立的运行过一段时间之后,并且已经累积了一些数据时。这时候我们无法在不损失任何数据的前提下将他们合并(注意:在网络中断或者节点宕机后回复一个集群都会有同样的问题,同样会有数据丢失)。对于特殊的数据,你可以使用一些其他的解决方案。例如,把需要重置的节点中的数据先备份出来。但是,目前没有一个健壮的、自动的、全局的解决方案。

所以我们的自动化集群解决方案受到我们能容忍什么样的数据丢失这一方面的影响。

Cluster formation集群信息

假设你已经解决了所有命名规则相关的问题,并且用rabbitmqctl命令手工的建立了集群。现在是把我们的RabbitMQ封装成自动化集群的时候了。就像我们以前遇到的问题一样,没有一个解决方案可以解决所有的问题。

一个特定的解决方案只适合我们并不关心服务停止或者链接丢失时数据丢失的问题。这种场景的一个例子就是当你使用RPC发送请求时,客户端可以在超时或者收到错误时重发请求。当服务恢复之后,RPC请求将不再有效,相关数据也不再有任何意义。幸运的是各个OpenStack组件之间的RPC调用正是这种情况。

在思考过以上所有问题之后,现在我们可以搭建我们自己的解决方案了。无状态是我们的首选,所以我们选择了IP地址而不是Pet集合。Autocluster插件将是我们组织动态节点集群的首选。

查看过Autocluster的文档之后,我们得出了以下配置项:

  • {backend, etcd}: 这几乎是我们唯一的选择。Consul或者K8S可以很好的工作。选择它的唯一理由也是因为测试起来很简单。你可以下载etcd的二进制版本,不需要任何参数就可以运行,这样可以搭建起一个基于本地的集群。
  • {autocluster_failure, stop}:如果一个pod无法加入集群对于我们来说就没有任何价值。这个pod将会被移除集群,并在一个相对安全的环境中重启。
  • {cluster_cleanup, true}, {cleanup_interval, 30},{cleanup_warn_only, false}, {etcd_ttl, 15}:一个节点只有在完全启动,并且成功加入集群之后才可以在etcd中注册。只要该节点还可用,注册用的TTL将会不间断的被更新。如果该节点停掉(或者由于某种原因无法更新TTL),他将会被强制从集群中删除。即使该节点重启后获得了相同的IP地址,它也会被认为是重新加入集群。

无法预料的竞争

如果你尝试着按照以上搭建了几次集群,你会发现有时整个集群会分裂成几个互相无法联通的小集群。问题产生的原因是启动时对于竞争问题的唯一保护措施在节点启动时会有随机的延迟现象。在最坏的情况下,每个节点会认为它是第一个节点(例如这时在etcd中没有任何记录),所以这个节点就以无集群模式启动了。

Autocluster最终为该问题提出了一个很大的补丁。它在启动的过程中增加了锁机制:节点在启动时最先申请启动锁资源,最后在该节点成功在后台注册之后才释放。目前只有etcd这个平台支持该功能。但是其它平台也可以很容易的支持该功能(在后台当中增加两个新的回调函数)。

另一个问题是:K8S、Pet集合他们可以在启动的时候进行编排工作;在任何时间都只有一个节点处于启动状态。 该功能只处于初期测试阶段。提供该功能的补丁不仅仅提供给K8S的用户,而是提供给所有平台的开发者。

监控

目前唯一遗留的问题就是为我们运行在非看管状态的集群增加一个监控系统。我们需要监控rabbitmq的健康状况以及它是否和集群其它节点良好的工作在一起。

你也许还记得以前可以通过运行rabbitmqctl list_queues或者rabbitmqctl list_channels来监控。但是这种方案并不完美,因为它无法区别本地和远程的问题。同时它又明显的增加了网络负载。为了弥补这个缺陷,3.6.4版本之后推出了新的、轻量级的rabbitmqctl node_health_check。这是检查rabbitmq集群当中单节点健康状况最好的方法。

检查一个节点是否正确的加入集群需要做几方面的检查:

  • 新加入的节点应当与Autocluster后台最优节点在一起注册成集群。这个最优节点是在注册成功列表里按字母顺序排在最前面的节点。
  • 即使当节点已经与现有节点形成了集群,但它的数据可能还是分开的。对于这个检查并不是分开的,我们需要在当前节点和新发现节点都检查分区列表。

所有的这些可以通过独立的检查完成,检查可以使用以下命令:
rabbitmqctl eval ‘autocluster:cluster_health_check_report().’

使用rabbitmqctl命令我们可以检测出rabbitmq节点的任何问题,也可以通过该命令将该节点停掉。因此,K8S可以有机会施展魔法重启该节点。

搭建你自己的RabbitMQ集群

如果你自己亲自按照这个方案搭建这个集群,你需要最新版本的RabbitMQ以及autocluster插件的定制化版本(目前启动锁机制这个补丁还没有合并到主版本当中)。

你可以查看Fuel CCP如何搭建集群,或者用你自己的实现方法使用独立的版本来搭建。

为了提示你该方案案如何实施,让我们假设你已经复制了第二个repository,并且你已经有了一个叫做“demo”的K8S的命名空间。Etcd的服务已经在K8S集群中运行,并且可以通过”etcd”这个名字访问。你可以通过以下命令来搭建环境:

kubectl create namespace demo
kubectl run etcd --image=microbox/etcd --port=4001 \
--namespace=demo -- --name etcd
kubectl --namespace=demo expose deployment etcd

完成以上步骤后,用以下命令搭建RabbitMQ:

1. 用合适的RabbitMQ和Autocluster版本创建Docker镜像,并设置相应配置文件。

$ docker build . -t rabbitmq-autocluster

2. 保存Erlang的Cookie到K8S当中。

$ kubectl create secret generic --namespace=demo erlang.cookie \
--from-file=./erlang.cookie

3. 创建3节点RabbitMQ集群。为了简化操作,你们可以从以下链接下载rabbitmq.yaml文件https://github.com/binarin/rabbit-on-k8s-standalone/blob/master/rabbitmq.yaml.

$ kubectl create -f rabbitmq.yaml

4. 检查集群是否正常工作

$ FIRST_POD=$(kubectl get pods --namespace demo -l 'app=rabbitmq' \
-o jsonpath='{.items[0].metadata.name }')
$ kubectl exec --namespace=demo $FIRST_POD rabbitmqctl \
cluster_status

你应该得到如下输出:

Cluster status of node 'rabbit@172.17.0.3' ... [{nodes,[{disc,['rabbit@172.17.0.3','rabbit@172.17.0.4', 'rabbit@172.17.0.7']}]}, {running_nodes,['rabbit@172.17.0.4','rabbit@172.17.0.7','rabbit@172.17.0.3']}, {cluster_name,<<"rabbit@rabbitmq-deployment-861116474-cmshz">>}, {partitions,[]}, {alarms,[{'rabbit@172.17.0.4',[]}, {'rabbit@172.17.0.7',[]}, {'rabbit@172.17.0.3',[]}]}]

这里最关键的一点是nodes与running nodes集合均有三个节点。

本文转自中文社区-基于Kubernetes(k8s)的RabbitMQ 集群

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
7天前
|
消息中间件 监控 RocketMQ
Docker部署RocketMQ5.2.0集群
本文详细介绍了如何使用Docker和Docker Compose部署RocketMQ 5.2.0集群。通过创建配置文件、启动集群和验证容器状态,您可以快速搭建起一个RocketMQ集群环境。希望本文能够帮助您更好地理解和应用RocketMQ,提高消息中间件的部署和管理效率。
162 91
|
1月前
|
存储 运维 Kubernetes
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
飞轮科技推出了 Doris 的 Kubernetes Operator 开源项目(简称:Doris Operator),并捐赠给 Apache 基金会。该工具集成了原生 Kubernetes 资源的复杂管理能力,并融合了 Doris 组件间的分布式协同、用户集群形态的按需定制等经验,为用户提供了一个更简洁、高效、易用的容器化部署方案。
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
|
1月前
|
缓存 容灾 网络协议
ACK One多集群网关:实现高效容灾方案
ACK One多集群网关可以帮助您快速构建同城跨AZ多活容灾系统、混合云同城跨AZ多活容灾系统,以及异地容灾系统。
|
2月前
|
存储 Kubernetes Docker
Kubernetes(k8s)和Docker Compose本质区别
理解它们的区别和各自的优势,有助于选择合适的工具来满足特定的项目需求。
234 19
|
2月前
|
Kubernetes Ubuntu 网络安全
ubuntu使用kubeadm搭建k8s集群
通过以上步骤,您可以在 Ubuntu 系统上使用 kubeadm 成功搭建一个 Kubernetes 集群。本文详细介绍了从环境准备、安装 Kubernetes 组件、初始化集群到管理和使用集群的完整过程,希望对您有所帮助。在实际应用中,您可以根据具体需求调整配置,进一步优化集群性能和安全性。
152 12
|
2月前
|
Prometheus Kubernetes 监控
OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。
|
2月前
|
Kubernetes 应用服务中间件 nginx
二进制安装Kubernetes(k8s)v1.32.0
本指南提供了一个详细的步骤,用于在Linux系统上通过二进制文件安装Kubernetes(k8s)v1.32.0,支持IPv4+IPv6双栈。具体步骤包括环境准备、系统配置、组件安装和配置等。
699 10
|
2月前
|
Kubernetes 网络协议 应用服务中间件
Kubernetes Ingress:灵活的集群外部网络访问的利器
《Kubernetes Ingress:集群外部访问的利器-打造灵活的集群网络》介绍了如何通过Ingress实现Kubernetes集群的外部访问。前提条件是已拥有Kubernetes集群并安装了kubectl工具。文章详细讲解了Ingress的基本组成(Ingress Controller和资源对象),选择合适的版本,以及具体的安装步骤,如下载配置文件、部署Nginx Ingress Controller等。此外,还提供了常见问题的解决方案,例如镜像下载失败的应对措施。最后,通过部署示例应用展示了Ingress的实际使用方法。
87 2
|
2月前
|
消息中间件 存储 运维
2024最全RabbitMQ集群方案汇总
本文梳理了RabbitMQ集群的几种方案,主要包括普通集群、镜像集群(高可用)、Quorum队列(仲裁队列)、Streams集群模式(高可用+负载均衡)和插件方式。重点介绍了每种方案的特点、优缺点及适用场景。搭建步骤包括安装Erlang和RabbitMQ、配置集群节点、修改hosts文件、配置Erlang Cookie、启动独立节点并创建集群,以及配置镜像队列以提高可用性和容错性。推荐使用Quorum队列与Streams模式,其中Quorum队列适合高可用集群,Streams模式则同时支持高可用和负载均衡。此外,还有Shovel和Federation插件可用于特定场景下的集群搭建。
336 2
|
2月前
|
消息中间件 RocketMQ
2024最全RocketMQ集群方案汇总
在研究RocketMQ集群方案时,发现网上存在诸多不一致之处,如组件包含NameServer、Broker、Proxy等。通过查阅官方文档,了解到v4.x和v5.x版本的差异。v4.x部署模式包括单主、多主、多主多从(异步复制、同步双写),而v5.x新增Local与Cluster模式,主要区别在于Broker和Proxy是否同进程部署。Local模式适合平滑升级,Cluster模式适合高可用需求。不同模式下,集群部署方案大致相同,涵盖单主、多主、多主多从等模式,以满足不同的高可用性和性能需求。
351 0