RabbitMQ 从入门到精通:从工作模式到集群部署实战(二)

接上篇:《RabbitMQ 从入门到精通:从工作模式到集群部署实战(一)》

链接

文章目录

4.安装RabbitMQ Messaging Topology Operator

使用 cert-manager 安装Messaging Topology Operator

在k8s集群上安装 cert-manager 版本 1.2.0+。例如,对于版本 1.3.1,请运行:

复制代码
wget https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml

kubectl apply -f cert-manager.yaml

要安装 Operator,请运行以下命令:

复制代码
wget https://github.com/rabbitmq/messaging-topology-operator/releases/latest/download/messaging-topology-operator-with-certmanager.yaml

kubectl apply --f messaging-topology-operator-with-certmanager.yaml

使用生成的自有证书安装Messaging Topology Operator

此方式因涉及自建私有证书,具体步骤可以参考官方文档:

https://www.rabbitmq.com/kubernetes/operator/install-topology-operator#install-with-generated-certificates

使用Kubernetes 内部非默认域名

默认情况下,Kubernetes 内部域名为.cluster.local。kubeadm可以将其配置为其他名称,例如my.cluster.domain。在这种情况下,Messaging Topology Operator可以将自定义域名附加到用于与 RabbitMQ 交互的连接字符串中。

要配置消息传递拓扑操作员以在连接字符串中附加域名,请将环境变量设置MESSAGING_DOMAIN_NAME为您的域名,例如".my.cluster.domain"。

修改Messaging Topology Operator部署清单文件,在Deployment配置段中向spec. template... spec. container. Command增加一个env,名称MESSAGING_DOMAIN_NAME和值为您的域名如:messaging-topology-operator-with-certmanager.yaml

复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  [...]
  name: messaging-topology-operator
  namespace: rabbitmq-system
spec:
  template:
    [...]
    spec:
      containers:
      - command:
        - /manager
        env:
        - name: OPERATOR_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: MESSAGING_DOMAIN_NAME
          value: "my.cluster.domain"


Messaging Topology Operator使用

创建queue和Policy

以下清单将在namepace名为rabbitmq-test下,默认虚拟主机中创建一个名为"queue-t1-rabbitmq-test"的队列:

复制代码
cat queue-t1-rabbitmq-test.yaml

apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
  name: queue-t1
  namespace: rabbitmq-test
spec:
  name: queue-t1-rabbitmq-test
  autoDelete: false
  durable: true
  rabbitmqClusterReference:
    name: rabbitmq-cluster01
    namespace: rabbitmq-test
kubectl apply -f queue-t1-rabbitmq-test.yaml
queue.rabbitmq.com/queue-t1 created

kubectl get queue -n rabbitmq-test
NAME       AGE
queue-t1   17s

以下清单将在namepace名为rabbitmq-test下创建名为"policy-example"的policy

复制代码
cat policy.yaml

apiVersion: rabbitmq.com/v1beta1
kind: Policy
metadata:
  name: policy-example
  namespace: rabbitmq-test
spec:
  name: lazy-queue
  pattern: "^lazy-queue-" # matches any queue begins with "lazy-queue-"
  applyTo: "queues"
  definition:
    queue-mode: lazy
  rabbitmqClusterReference:
    name: rabbitmq-cluster01
    namespace: rabbitmq-test

kubectl apply -f policy.yaml
policy.rabbitmq.com/policy-example created

kubectl get policy -n rabbitmq-test
NAME             AGE
policy-example   54s


创建exchange和binding

以下清单将在namepace名为rabbitmq-test下创建名为"rabbitmq-test"的exchange

cat exchange.yaml

复制代码
cat exchange.yaml

apiVersion: rabbitmq.com/v1beta1
kind: Exchange
metadata:
  name: fanout
  namespace: rabbitmq-test
spec:
  name: fanout-exchange # name of the exchange
  type: fanout # default to 'direct' if not provided; can be set to 'direct', 'fanout', 'headers', and 'topic'
  autoDelete: false
  durable: true
  rabbitmqClusterReference:
    name: rabbitmq-cluster01
    namespace: rabbitmq-test

kubectl apply -f exchange.yaml
exchange.rabbitmq.com/fanout created

kubectl get exchange -n rabbitmq-test
NAME     AGE
fanout   13s

以下清单将在namepace名为rabbitmq-test下将名为"rabbitmq-test"的exchange与名为"queue-t1-rabbitmq-test"的queue 进行绑定

复制代码
cat binding.yaml

apiVersion: rabbitmq.com/v1beta1
kind: Binding
metadata:
  name: binding
  namespace: rabbitmq-test
spec:
  source: fanout-exchange # an existing exchange
  destination: queue-t1-rabbitmq-test # an existing queue
  destinationType: queue # can be 'queue' or 'exchange'
  routingKey: "queue-t1-rabbitmq-test"
  rabbitmqClusterReference:
    name: rabbitmq-cluster01
    namespace: rabbitmq-test

kubectl apply -f binding.yaml
binding.rabbitmq.com/binding created

创建的binding无法通过kubectl 命令列出,但通过RabbitMQ的管理UI可以看到。

创建用户及授权

可以使用 Messaging Topology Operator 创建 RabbitMQ 用户并分配用户权限

对账号(admin-user01)、密码(123123.com)进行base64加密:

复制代码
echo -n 'admin-user01' | base64
YWRtaW4tdXNlcjAx

echo -n '123123.com' | base64
MTIzMTIzLmNvbQ==

创建secret

复制代码
vim secret-admin-user01.yaml

apiVersion: v1
kind: Secret
metadata:
  name: admin-user-secret
  namespace: rabbitmq-test # 指定rabbitmq-cluster01的namespace
type: Opaque
data:
  username: YWRtaW4tdXNlcjAx  # base64 编码后的用户名
  password: MTIzMTIzLmNvbQ==  # base64 编码后的密码

kubectl apply -f secret-admin-user01.yaml
secret/admin-user01-secret created

创建Rabbitmq 账号资源,需要引用上面步骤创建的secret

复制代码
vim my-admin-user01.yaml

apiVersion: rabbitmq.com/v1beta1
kind: User
metadata:
  name: my-admin-user01
  namespace: rabbitmq-test
spec:
  tags:
  - administrator
  rabbitmqClusterReference:
    name: rabbitmq-cluster01 # rabbitmqCluster must exist in the same namespace as this resource
    namespace: rabbitmq-test

  importCredentialsSecret:
    name: admin-user01-secret  # must match the name of the Secret

kubectl apply -f my-admin-user01.yaml
user.rabbitmq.com/my-admin-user01 created

创建Rabbitmq 账号授权资源

复制代码
vim permission-admin-user10.yaml

apiVersion: rabbitmq.com/v1beta1
kind: Permission
metadata:
  name: admin-user01-permission
  namespace: rabbitmq-test
spec:
  vhost: "/"
  user: "admin-user01" # name of the RabbitMQ user
  permissions:
    write: ".*"
    configure: ".*"
    read: ".*"
  rabbitmqClusterReference:
    name: rabbitmq-cluster01
    namespace: rabbitmq-test

kubectl apply -f permission-admin-user10.yaml
permission.rabbitmq.com/admin-user01-permission created


创建虚拟主机

以下YAML将在名为"rabbitmq-cluster01"的 RabbitmqCluster 中创建名为"test"的虚拟主机:

复制代码
vim vhost01.yaml

apiVersion: rabbitmq.com/v1beta1
kind: Vhost
metadata:
  name: test-vhost01 # name of this custom resource
  namespace: rabbitmq-test
spec:
  name: test01 # name of the vhost
  rabbitmqClusterReference:
    name: rabbitmq-cluster01
    namespace: rabbitmq-test

kubectl apply -f vhost01.yaml
vhost.rabbitmq.com/test-vhost01 created

kubectl get vhost -n rabbitmq-test
NAME           AGE
test-vhost01   2s


更新

一些自定义资源属性是不可变的,Messaging Topology Operator 实现了验证 webhook 来阻止对不可变字段的更新。禁止的更新将被拒绝。例如:

复制代码
kubectl apply -f test-queue.yaml
Error from server (Forbidden):
...
Resource: "rabbitmq.com/v1beta1, Resource=queues", GroupVersionKind: "rabbitmq.com/v1beta1, Kind=Queue"
Name: "example", Namespace: "rabbitmq-system"
for: "test-queue.yaml": admission webhook "vqueue.kb.io" denied the request: Queue.rabbitmq.com "example" is forbidden: spec.name: Forbidden: updates on name, vhost, and rabbitmqClusterReference are all forbidden

无法更新的属性已记录在Messaging Topology Operator API 文档中,URL:https://github.com/rabbitmq/messaging-topology-operator/blob/main/docs/api/rabbitmq.com.ref.asciidoc

删除

删除自定义资源会删除 RabbitMQ 集群中相应的资源。Messaging Topology Operator 会在所有自定义资源上设置 kubernetes finalizers。如果对象已在 RabbitMQ 集群中删除,或者 RabbitMQ 集群已删除,Messaging Topology Operator 会删除自定义资源,而不会尝试删除 RabbitMQ 对象。

跨命名空间

默认情况下,Messaging Topology Operator 只协调使用RabbitMQ Cluster Kubernetes Operator 创建的RabbitMQ集群所在namespace下的创建消息拓扑资源请求。如果需要创建的建消息拓扑资源在其他的namesapce,需要在namespace 下添加相关注解annotations.rabbitmq.com/topology-allowed-namespaces

如下图,RabbitMQ集群所在的的namespace为rabbitmq-test,如果需要Messaging Topology Operator 额外协调rabbitmq-01和rabbitmq-02 两个namespace下消息拓扑资源,需要进行如下配置,多个namespace使用逗号分隔,中间不能有空格。可以设置为"*",则为协调所有namesapce

复制代码
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
  name: rabbitmq-cluster01
  namespace: rabbitmq-test
  annotations:
    rabbitmq.com/topology-allowed-namespaces: "rabbitmq-01,rabbitmq-02"

如果在没有允许的namespace中创建消息拓扑资源,如下图中为"my-app2",Topology Operator 的pod会有相关日志提示:

示例如下:

在namespace为my-app2下创建名称为queue-t1的queue, 在rabbitmq中的名称为queue-t1-my-app2

复制代码
apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
  name: queue-t1 # name of this custom resource; does not have to the same as the actual queue name
  namespace: my-app2
spec:
  name: queue-t1-my-app2 # name of the queue
  rabbitmqClusterReference:
    name: rabbitmq-cluster01
    namespace: rabbitmq-test

虽然使用kuberct 命令在namespace可以获取到列表,

但在rabbitmq中没有创建名字为queue-t1-my-app2的queue:

故障排查

如果无法创建某些 RabbitMQ 拓扑对象,可通过Messaging Topology Operator 的pod日志进行排查。

复制代码
kubectl -n rabbitmq-system logs -l app.kubernetes.io/name=messaging-topology-operator

另外还可以使用kubectl desribe命令查看资源的详细信息:

复制代码
kubectl describe queue queue-t1 -n rabbitmq-test

Name:         queue-t1
Namespace:    rabbitmq-test
Labels:       <none>
Annotations:  <none>
API Version:  rabbitmq.com/v1beta1
Kind:         Queue
Metadata:
  Creation Timestamp:  2024-10-25T09:46:27Z
  Finalizers:
    deletion.finalizers.queues.rabbitmq.com
...
  Vhost:        /
Status:
  Conditions:
    Last Transition Time:  2024-10-25T09:46:27Z
    Reason:                SuccessfulCreateOrUpdate
    Status:                True
    Type:                  Ready
  Observed Generation:     2
Events:
  Type    Reason             Age                 From              Message
  -                 -                -              -
  Normal  SuccessfulDeclare  7h2m (x6 over 47h)  queue-controller  Successfully declare queue

裸金属环境部署RabbitMQ

OS及内核:

复制代码
[root@rbt01 ~]# cat /etc/redhat-release
BigCloud Enterprise Linux For Euler release 21.10 (LTS-SP2)

[root@rbt01 ~]# uname -a
Linux rbt01 4.19.90-2107.6.0.0208.16.oe1.bclinux.x86_64 #1 SMP Tue Jul 18 10:06:28 CST 2023 x86_64 x86_64 x86_64 GNU/Linux

Erlang和RabbitMQ版本匹配关系参考官方文档:

https://www.rabbitmq.com/docs/3.13/which-erlang#redhat

本文档选用Erlang:v26.2.5.4和RabbitMQ: v3.13.7

部署单实例

关闭防火墙

复制代码
systemctl stop firewalld
systemctl disable firewalld

安装Erlang

Erlang官方推荐使用各系统平台预安装包进行安装,Euler 21.10使用以下rmp包进行安装,下载地址:https://github.com/rabbitmq/erlang-rpm/releases/download/v26.2.5.4/erlang-26.2.5.4-1.el7.x86_64.rpm

执行安装及通过验证版本号测试是否安装成功

复制代码
# 安装
yum install erlang-26.2.5.4-1.el7.x86_64.rpm

# 查看版本
erl -version
Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version 14.2.5.4

部署RabbitMQ

二进制包下载地址:

https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.13.7/rabbitmq-server-generic-unix-3.13.7.tar.xz

创建rabbitmq普通用户并设置密码,用于管理rabbitmq

复制代码
useradd rabbitmq
passwd rabbitmq

解压下载好的二进制安装包到/opt目录下,并做软连接

复制代码
tar xf rabbitmq-server-generic-unix-3.13.7.tar.xz -C /opt/
cd /opt/
ln -s /opt/rabbitmq_server-3.13.7/ /opt/rabbitmq
ln -s /opt/rabbitmq/sbin/* /usr/local/sbin/

安装完成后,默认没有配置文件,可以从官网下载示例,放到/opt/rabbitmq/etc/rabbitmq下,

https://github.com/rabbitmq/rabbitmq-server/blob/main/deps/rabbit/docs/rabbitmq.conf.example

可以根据实际需要参考下面的官方文档进行参数配置:

https://www.rabbitmq.com/docs/3.13/configure#config-items

修改rabbitmq 目录权限

复制代码
chown --R rabbitmq:rabbitmq /opt/rabbitmq*

使用rabbitmq账号并启动服务:

复制代码
su -- rabbitmq
rabbitmq-server -detached

查看服务进程及监听端口号,默认会监听5672,25672 两个端口

5672用于接受rabbitmq 客户端连接请求

25672 用于集群模式下集群间通信

关闭服务命令:

复制代码
rabbitmqctl shutdown

启动web管理插件,实现web 浏览器图形界面管理。

复制代码
rabbitmq-plugins enable rabbitmq_management

启动web管理插件插件后,RabbitMQ会另外启动15672端口用户web服务。

使用服务器IP和15672端口访问web管理页面。

创建账号密码并设置权限

以下命令创建了admin账号并设置密码为:Admin.123,将其标记为administrator,并设置了对/ 有所有权限

复制代码
rabbitmqctl add_user admin Admin.123
rabbitmqctl set_user_tags admin administrator
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"

使用admin账号登录web管理页面

解决web管理界面提示:

⚠ All stable feature flags must be enabled after completing an upgrade. [Learn more]

  1. 导航到特性标志页面:
    在RabbitMQ管理界面的左侧菜单中,找到并点击"Admin"选项。
    在"Admin"页面中,找到并点击"Feature Flags"选项。

  2. 启用特性标志:
    在"Feature Flags"页面中,你会看到一个列表,其中包含了所有可用的特性标志。
    检查每个特性标志的状态,确保所有标记为"stable"(稳定)的特性标志都被启用。如果发现有未启用的稳定特性标志,请将其启用。

    列出功能标志:

    rabbitmqctl list_feature_flags

要启用功能标志(或所有当前禁用的标志):

rabbitmqctl enable_feature_flag <all | name>

开启detailed_queues_endpoint 功能标志

复制代码
rabbitmqctl enable_feature_flag detailed_queues_endpoint

Feature Flags介绍:

官方文档:https://www.rabbitmq.com/docs/3.13/feature-flags

功能标记是一种机制,用于控制哪些功能在所有集群节点上被视为已启用或可用。如果启用了功能标记,则其相关功能(或行为)也会启用。如果没有启用,则集群中的所有节点都将禁用该功能(行为)。

功能标志子系统允许不同版本的 RabbitMQ 节点确定它们是否兼容,然后相互通信,尽管它们具有不同的版本,因此可能具有不同的功能集或实现细节。

引入此子系统是为了允许在不关闭整个集群的情况下对集群成员进行滚动升级。

至此RabbitMQ单实例部署完成。

部署集群

服务器列表

(3个节点保持一致)

复制代码
[root@rbt01 ~]# tail -n 3 /etc/hosts
192.168.18.11 rbt01
192.168.18.12 rbt02
192.168.18.13 rbt03

分别在3个节点按照"单实例部署"步骤部署完成

参考上面章节
所有节点配置主机域名解析

复制代码
vim /etc/hosts
192.168.18.11 rbt01
192.168.18.12 rbt02
192.168.18.13 rbt03

节点间同步cookie文件

Erlang cookie 是用于RabbitMQ 节点和CLI 工具之间身份验证的共享密钥。该值存储在通常称为 Erlang cookie 文件的文件中。

服务帐户和运行用户使用的 Cookie 文件rabbitmqctl必须同步,CLI 工具才能rabbitmqctl正常运行。集群中的所有节点必须具有相同的 Cookie 值(Cookie 文件内容)。

同步cooker前确保rabbitmq进程是关闭状态。

复制代码
[root@rbt01 ~]# rabbitmqctl shutdown

[root@rbt02 ~]# rabbitmqctl shutdown

[root@rbt03 ~]# rabbitmqctl shutdown

在 UNIX 系统上,cookie 通常位于$HOME/.erlang.cookie

如果使用rabbitmq普通用户启动rabbitmq服务,.erlang.cookie文件的路径为:/home/rabbitmq/.erlang.cookie

.erlang.cookie 文件内容可以是自定义的字符串

将rbt01节点上/home/rabbitmq/.erlang.cookie 文件复制到rbt02,rbt03

复制代码
[root@rbt01 ~]# scp .erlang.cookie rbt02:$PWD
.erlang.cookie                                                                              

[root@rbt01 ~]# scp .erlang.cookie rbt03:$PWD
.erlang.cookie                            

并确保所有节点/home/rabbitmq/.erlang.cookie的属主,属组是rabbitmq

权限是400

复制代码
chown --R rabbit:rabbit /home/rabbitmq/.erlang.cookie
chmod 400 /home/rabbitmq/.erlang.cookie

配置集群方式一,在配置文件中增加如下配置:

/opt/rabbitmq/etc/rabbitmq/rabbitmq.conf

复制代码
cluster_name = rbt-cluster01
cluster_formation.peer_discovery_backend     = rabbit_peer_discovery_classic_config

cluster_formation.classic_config.nodes.1 = rabbit@rbt01
cluster_formation.classic_config.nodes.2 = rabbit@rbt02
cluster_formation.classic_config.nodes.3 = rabbit@rbt03

在所有节点启动服务,集群将自动形成

复制代码
[rabbitmq@rbt01 ~]$ rabbitmq-server --detached

[rabbitmq@rbt02 ~]$ rabbitmq-server --detached

[rabbitmq@rbt03 ~]$ rabbitmq-server --detached

在rbt01节点日志中查看有相关日志:

复制代码
2024-11-05 11:23:41.793897+08:00 [info] <0.734.0> node rabbit@rbt02 up
2024-11-05 11:23:43.066480+08:00 [info] <0.734.0> rabbit on node rabbit@rbt02 up
2024-11-05 11:24:01.294927+08:00 [info] <0.734.0> node rabbit@rbt03 up
2024-11-05 11:24:02.705850+08:00 [info] <0.734.0> rabbit on node rabbit@rbt03 up

配置集群方式二,不需在rabbitmq.conf配置文件定义,使用以下命令配置集群

将rbt02节点加入集群

复制代码
[rabbitmq@rbt02 ~]$  rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rbt02 ...

[rabbitmq@rbt02 ~]$  rabbitmqctl join_cluster rabbit@rbt01
Clustering node rabbit@rbt02 with rabbit@rbt01

[rabbitmq@rbt02 ~]$  rabbitmqctl start_app
Starting node rabbit@rbt02 ...

将rbt03节点加入集群

复制代码
[rabbitmq@rbt03 ~]$ rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rbt03 ...

[rabbitmq@rbt03 ~]$ rabbitmqctl join_cluster rabbit@rbt01
Clustering node rabbit@rbt03 with rabbit@rbt01

[rabbitmq@rbt03 ~]$ rabbitmqctl start_app
Starting node rabbit@rbt03 ...

查看集群状态

复制代码
[rabbitmq@rbt01 ~]$ rabbitmqctl cluster_status
Cluster status of node rabbit@rbt01 ...
Basics

Cluster name: rabbit@rbt01
Total CPU cores available cluster-wide: 12

Disk Nodes

rabbit@rbt01
rabbit@rbt02
rabbit@rbt03

Running Nodes

rabbit@rbt01
rabbit@rbt02
rabbit@rbt03

Versions

rabbit@rbt01: RabbitMQ 3.13.7 on Erlang 26.2.5.4
rabbit@rbt02: RabbitMQ 3.13.7 on Erlang 26.2.5.4
rabbit@rbt03: RabbitMQ 3.13.7 on Erlang 26.2.5.4
...
相关推荐
跟着珅聪学java9 小时前
在电商系统中,如何确保库存扣减的原子性
分布式
JH307311 小时前
Redisson 看门狗机制:让分布式锁“活”下去的智能保镖
分布式
一点 内容12 小时前
深入理解分布式共识算法 Raft:从原理到实践
分布式·区块链·共识算法
8Qi812 小时前
分布式锁-redission
java·redis·分布式·redisson
13 小时前
鸿蒙——分布式数据库
数据库·分布式
jiayong2313 小时前
微服务架构与 Spring 生态完全指南
kafka·rabbitmq·rocketmq
Hui Baby13 小时前
分布式多阶段入参参数获取
分布式
阿拉斯攀登16 小时前
Spring Cloud Alibaba 生态中 RocketMQ 最佳实践
分布式·微服务·rocketmq·springcloud·cloudalibaba
无锡布里渊16 小时前
感温光纤 DTS 系统 vs 感温电缆 对比分析报告
分布式·实时监测·分布式光纤测温·线型感温火灾监测·感温电缆
g323086316 小时前
分布式框架seata AT模式源码分析
java·数据库·分布式