Ceph+K8s 中间件实战 | 第 18 天:K8s 部署 RabbitMQ 集群(Ceph RBD + 高可用架构 + 登录巡检)

第 18/28 天

RabbitMQ 是应用最广的 AMQP 协议消息中间件,凭借多语言客户端、灵活路由模型、事务语义与插件生态,已经成为微服务异步解耦、削峰填谷、跨地域事件总线的标配。本篇承接第 17 天 MongoDB 三主三从集群的实战,继续在 Ceph + Kubernetes 底座上部署 RabbitMQ 联邦高可用集群,并通过 Ceph RBD 持久化保证磁盘队列数据安全,覆盖架构设计、Helm Chart 部署、登录验证与日常巡检四大主线。

K8s Logo

一、为什么 RabbitMQ 需要 Ceph 持久化

RabbitMQ 有两种队列模式:纯内存队列与磁盘队列。在微服务场景里,跨服务调用、订单异步落库、日志事件聚合都要求消息在 Broker 重启、Pod 漂移、节点宕机后不丢。一旦使用持久化队列(durable queue + persistent message),消息会写入 OS 文件系统;如果不做集群级持久卷管理,Pod 重建后队列数据将全部丢失,整个异步链路断裂。

在 Kubernetes 之上,Ceph RBD 提供了三种存储能力适配 RabbitMQ:①为每个 RabbitMQ Pod 创建独立 RBD 块设备,承载 /var/lib/rabbitmq 与 /etc/rabbitmq 配置;②配合 StatefulSet 的 volumeClaimTemplates 实现 Pod 与卷的强绑定;③通过 Ceph CSI 的快照、克隆、扩容能力,支持队列备份与在线迁移。本系列第 2 天已详细讲解 CSI Driver 与 StorageClass,本篇直接复用现成 ceph-rbd StorageClass 即可。

K8s Logo

二、RabbitMQ 高可用集群设计架构

2.1 组件拓扑

RabbitMQ 集群由三类角色组成:①RabbitMQ 节点(rabbitmq-server + rabbitmq-mgmt),承载 Erlang VM,处理消息收发;②Erlang Cookie 认证,跨节点信任通道;③外部协调存储,本篇用 MySQL 8 持久化集群元数据,配合 Bitnami 镜像自带的 rabbitmq Operator 初始化逻辑。

典型 3 节点拓扑:

节点 Erlang Cookie 角色 PVC 绑定 端口
rabbitmq-0 shared_secret_xxx cluster_node_0 data-rabbitmq-0(ceph-rbd, 20Gi) 5672/15672/25672
rabbitmq-1 同上 cluster_node_1 data-rabbitmq-1(ceph-rbd, 20Gi) 5672/15672/25672
rabbitmq-2 同上 cluster_node_2 data-rabbitmq-2(ceph-rbd, 20Gi) 5672/15672/25672

2.2 数据流向

💻 代码示例

Producer Pod ──AMQP──▶ Headless Service ──▶ RabbitMQ-0/1/2 任一节点

└─▶ Erlang Cluster (25672)

├─ 队列镜像 (Quorum/Mirrored)

├─ Raft 共识 (Quorum Queue)

└─ MySQL 元数据同步 (可选)

消息从 Producer 发出,经 Pod 内 AMQP 客户端连接到 rabbitmq-headless:5672,由 RabbitMQ 路由表选 Queue,Quorum Queue 通过 Raft 协议在 3 节点副本间达成一致后持久化到对应节点的 RBD 磁盘。

2.3 高可用机制

RabbitMQ 3.10 之后推荐使用 Quorum Queues 替代 Mirrored Queues,核心是 Apache Raft 共识:①每队列选举一个 Leader,其余为 Follower;②Leader 收到 publish 后广播到所有 Follower,多数派确认后返回 ack;③Leader 宕机自动选举,多数派存活时集群仍可用。配合 3 节点 Ceph RBD 持久化,任一节点故障或 Pod 重建,消息不丢失、零人工干预恢复。

关键容量规划:3 节点 × 20Gi Ceph RBD = 60Gi 总容量,可承载约 3000 万条 2KB 消息(含 Raft 副本开销约 1.5 倍),单条消息 TTL 建议 ≤ 24 小时。

三、部署实战(Bitnami Helm Chart)

3.1 添加 Helm 仓库与查看版本

💻 代码示例

# 添加 Bitnami Chart 仓库

helm repo add bitnami https://charts.bitnami.com/bitnami

helm repo update

 

# 查看 RabbitMQ Chart 最新版本

helm search repo bitnami/rabbitmq

# bitnami/rabbitmq 16.x.x 3.13.x RabbitMQ is an open-source message broker

 

# 拉取 Chart 到本地查看 values 默认值

helm pull bitnami/rabbitmq –version 16.9.0

tar -xf rabbitmq-16.9.0.tgz

cat rabbitmq/values.yaml | head -80

3.2 准备 MySQL 元数据库(可选)

RabbitMQ 3.13 官方推荐通过 MySQL/MariaDB 做集群拓扑持久化,避免重启后重新选举。Bitnami 镜像要求使用专用库 rabbitmq 和专用用户 rabbitmq_user。沿用本系列第 4 天 MySQL 集群的 Service 地址即可:

💻 代码示例

# 通过 kubectl exec 进入 MySQL Pod 创建用户与库

kubectl exec -it mysql-0 -n middleware — mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "

CREATE DATABASE IF NOT EXISTS rabbitmq CHARACTER SET utf8mb4;

CREATE USER IF NOT EXISTS 'rabbitmq_user'@'%' IDENTIFIED BY 'Rmq@2026Secure!';

GRANT ALL PRIVILEGES ON rabbitmq.* TO 'rabbitmq_user'@'%';

FLUSH PRIVILEGES;

"

3.3 编写 values.yaml(重点:Ceph RBD 持久化)

创建 rabbitmq-values.yaml,重点覆盖 StatefulSet 的 volumeClaimTemplates、资源、认证与集群策略:

💻 代码示例

# rabbitmq-values.yaml

# RabbitMQ 集群高可用配置(Ceph RBD 持久化)

 

# — 集群拓扑 —

replicaCount: 3

auth:

# 管理员账号密码(生产用随机字符串)

username: admin

password: "RabbitMQ@2026#Secure"

existingPasswordSecret: ""

 

# — Erlang Cookie(节点间信任)—

rabbitmq:

# 统一 secret,写入所有 Pod 的 /var/lib/rabbitmq/.erlang.cookie

erlangCookie: "SharedErlangCookie_2026!@#Secure"

# 自定义配置(挂载到 /etc/rabbitmq/rabbitmq.conf)

configuration: |

cluster_formation.peer_discovery_backend = rabbit_peer_discovery_k8s

cluster_formation.k8s.service_host = rabbitmq-headless.middleware.svc.cluster.local

quorum_queue_type = classic

disk_free_limit.absolute = 1GB

vm_memory_high_watermark.relative = 0.5

# 启用 management 插件(15672 端口)

plugins:

– rabbitmq_management

– rabbitmq_management_agent

 

# — Ceph RBD 持久化(核心)—

volumeClaimTemplates:

data:

storageClass: ceph-rbd # 复用第 2 天创建的 StorageClass

accessModes:

– ReadWriteOnce # RBD 块存储仅支持 RWO

resources:

requests:

storage: 20Gi

reclaimPolicy: Retain # 保留卷,便于数据恢复

 

# — 持久化开关 —

persistence:

enabled: true

existingClaim: "" # 空 = 使用 volumeClaimTemplates 自动创建

 

# — 资源限制 —

resources:

requests:

cpu: 500m

memory: 1Gi

limits:

cpu: "2"

memory: 4Gi

 

# — 高可用与调优 —

extraConfiguration: |

# Quorum Queue 推荐配置

quorum_queue_type = classic

# 磁盘预留

disk_free_limit.absolute = 1GB

# Erlang 内存高水位

vm_memory_high_watermark.relative = 0.5

vm_memory_high_watermark_paging_ratio = 0.5

# 心跳间隔

heartbeat = 60

# Channel 与 Connection 上限

channel_max = 2048

connection_high_watermark.relative = 0.9

 

# — Network Policies(生产建议开启)—

networkPolicy:

enabled: false

allowIngressFromAnywhere: true

allowEgressToAnywhere: true

 

# — Ingress(可选,仅调试)—

ingress:

enabled: false

 

# — Metrics(Prometheus 抓取)—

metrics:

enabled: true

serviceMonitor:

enabled: true

namespace: monitoring

labels:

release: prometheus

3.4 部署命名空间与执行 helm install

💻 代码示例

# 创建独立命名空间

kubectl create namespace middleware –dry-run=client -o yaml | kubectl apply -f –

 

# 执行安装(–wait 等待 Pod Ready,–timeout 防超时)

helm install rabbitmq bitnami/rabbitmq

–namespace middleware

-f rabbitmq-values.yaml

–version 16.9.0

–set image.registry=registry.cn-hangzhou.aliyuncs.com

–set image.repository=bitnami/rabbitmq

–wait

–timeout 10m0s

–debug

3.5 验证 Pod / Service / PVC 状态

💻 代码示例

# Pod 状态(应 3/3 Running 且 READY 为 3/3)

kubectl get pods -n middleware -l app.kubernetes.io/instance=rabbitmq

 

# PVC 绑定(应全部 Bound,storageClass 为 ceph-rbd)

kubectl get pvc -n middleware -o wide | grep rabbitmq

 

# Service 列表(Headless 供集群内连接,NodePort/ClusterIP 供外部)

kubectl get svc -n middleware | grep rabbitmq

 

# 查看 Ceph 后端实际 RBD 镜像

rbd ls ceph/rabbitmq-data –id admin

rbd du ceph/rabbitmq-data-rabbitmq-0

四、登录验证与集群状态检查

4.1 通过 kubectl exec 进入 Pod 操作 Erlang 节点

💻 代码示例

# 进入 rabbitmq-0 节点

kubectl exec -it rabbitmq-0 -n middleware — bash

 

# 列出所有集群节点(应看到 rabbitmq-0/1/2)

rabbitmqctl cluster_status

 

# 列出队列及其类型(quorum/classic)

rabbitmqctl list_queues name type durable messages state

 

# 列出所有 vhost

rabbitmqctl list_vhosts

 

# 列出用户与权限

rabbitmqctl list_users

rabbitmqctl list_permissions

 

# 查看节点运行状态

rabbitmqctl status | head -40

4.2 管理控制台 HTTP API(15672)

💻 代码示例

# 通过 kubectl port-forward 暴露 15672

kubectl port-forward -n middleware svc/rabbitmq 15672:15672 &

 

# 登录获取 cookie(curl -c 保存 session)

curl -c /tmp/cookie -X POST http://localhost:15672/api/login

-H "Content-Type: application/json"

-d '{"username":"admin","password":"RabbitMQ@2026#Secure"}'

 

# 列出所有队列(JSON)

curl -b /tmp/cookie http://localhost:15672/api/queues

-H "Accept: application/json" | python3 -m json.tool

 

# 列出所有连接

curl -b /tmp/cookie http://localhost:15672/api/connections

-H "Accept: application/json" | python3 -m json.tool

 

# 创建测试队列(持久化 + Quorum)

curl -b /tmp/cookie -X PUT http://localhost:15672/api/queues/%2F/test-queue

-H "Content-Type: application/json"

-d '{"durable":true,"type":"quorum","auto_delete":false}'

4.3 AMQP 客户端验证(Python 示例)

💻 代码示例

import pika

 

# 连接参数

params = pika.ConnectionParameters(

host='rabbitmq.middleware.svc.cluster.local',

port=5672,

credentials=pika.PlainCredentials('admin', 'RabbitMQ@2026#Secure'),

heartbeat=60,

connection_attempts=3,

)

 

conn = pika.BlockingConnection(params)

ch = conn.channel()

ch.queue_declare(queue='test-queue', durable=True)

 

# 发布消息

for i in range(10):

ch.basic_publish(

exchange='',

routing_key='test-queue',

body=f'hello rabbitmq message {i}',

properties=pika.BasicProperties(delivery_mode=2), # 2 = persistent

)

print('Published 10 messages')

conn.close()

五、日常巡检基础命令

5.1 健康巡检(每日执行)

💻 代码示例

# ① 节点存活

kubectl get pods -n middleware -l app.kubernetes.io/instance=rabbitmq

-o custom-columns=NAME:.metadata.name,READY:.status.containerStatuses[*].ready,RESTARTS:.status.containerStatuses[*].restartCount

 

# ② 集群节点列表

kubectl exec -n middleware rabbitmq-0 — rabbitmqctl cluster_status | grep -E "Nodes|Running"

 

# ③ 队列健康(消息堆积告警阈值)

kubectl exec -n middleware rabbitmq-0 — rabbitmqctl list_queues name messages ready unacknowledged

–formatter pretty_table

 

# ④ Erlang 进程内存与磁盘水位

kubectl exec -n middleware rabbitmq-0 — rabbitmqctl status |

grep -E "memory|disk|uptime" -A2

5.2 性能监控(对接 Prometheus)

💻 代码示例

# 抓取 RabbitMQ metrics endpoint(Pod 内暴露 9419)

kubectl exec -n middleware rabbitmq-0 — curl -s http://localhost:9419/metrics |

grep -E "^rabbitmq_messages_(published|delivered|redelivered|unacknowledged|ready|unacked)"

 

# Grafana 查询示例:过去 1 小时消息吞吐

rabbitmq_messages_published_total[1h] – rabbitmq_messages_published_total[1h offset 1h]

 

# 磁盘使用率

node_filesystem_avail_bytes{mountpoint="/var/lib/rabbitmq"} /

node_filesystem_size_bytes{mountpoint="/var/lib/rabbitmq"}

5.3 容量与日志巡检

💻 代码示例

# ① PVC 容量(应小于 80% 触发扩容)

kubectl get pvc -n middleware -o json | jq '.items[] | {name:.metadata.name, cap:.status.capacity.storage, sc:.spec.storageClassName}'

 

# ② Ceph 后端占用

ceph df | grep rabbitmq

rbd du ceph/rabbitmq-data-rabbitmq-0

 

# ③ 错误日志(近 100 行 ERROR)

kubectl logs -n middleware rabbitmq-0 –tail=100 | grep -iE "error|warn|refused|timeout"

 

# ④ 连接数突增告警

rabbitmqctl list_connections | wc -l

5.4 备份与恢复

💻 代码示例

# ① 全量备份队列元数据(含 vhost / user / policy)

kubectl exec -n middleware rabbitmq-0 —

rabbitmqctl dump_policies /tmp/policies.json

kubectl cp rabbitmq-0:/tmp/policies.json ./policies-backup.json -n middleware

 

# ② Ceph 快照(Ceph CSI 支持)

cat > /tmp/rmq-snapshot.yaml <<EOF

apiVersion: snapshot.storage.k8s.io/v1

kind: VolumeSnapshot

metadata:

name: rabbitmq-0-snap-20261019

namespace: middleware

spec:

source:

persistentVolumeClaimName: data-rabbitmq-0

volumeSnapshotClassName: ceph-rbd-snapshotclass

EOF

kubectl apply -f /tmp/rmq-snapshot.yaml

 

# ③ 验证快照状态

kubectl get volumesnapshot -n middleware

ceph rbd snap ls ceph/rabbitmq-data-rabbitmq-0

六、常见问题 FAQ

Q1:3 节点 RabbitMQ 集群启动时报 Error starting RabbitMQ: unable to join the cluster 怎么办?
A:通常是 Erlang Cookie 不一致或 Headless Service DNS 解析异常。①检查所有 Pod 的 /var/lib/rabbitmq/.erlang.cookie 内容是否完全一致(大小写敏感);②kubectl exec rabbitmq-0 -- ping -c 3 rabbitmq-headless.middleware.svc.cluster.local 验证 DNS;③检查 NetworkPolicy 是否放通 25672 Erlang 端口。

Q2:为什么 Ceph RBD PVC 显示 Pending?
A:Ceph RBD 是块存储,accessMode 必须为 ReadWriteOnce(不能 RWX);同时 StorageClass 名必须与 volumeClaimTemplates.storageClass 完全匹配。排查命令:kubectl describe pvc <name> -n middleware | grep -i event,若显示 provisioning failed 请检查 Ceph OSD 剩余容量。

Q3:RabbitMQ 队列消息堆积,怎么处理?
A:①确认 Consumer 是否在线:rabbitmqctl list_consumers;②检查 Quorum Queue 是否 Leader 漂移;③紧急扩容 Consumer 副本:kubectl scale deployment consumer-app -n middleware --replicas=8;④长期方案:调整 quorum_queue_type、扩容磁盘,并在 Grafana 设置 messages_ready > 100000 告警。

七、总结

本篇在 Ceph + K8s 底座上完成 RabbitMQ 3 节点高可用集群部署,通过 Bitnami Helm Chart 快速落地,关键交付点包括:

  • 架构设计:3 节点 Quorum Queue + Raft 共识,任一节点故障消息不丢失
  • 持久化方案:Ceph RBD 20Gi × 3 副本,StatefulSet + volumeClaimTemplates 自动创建
  • 登录验证:Erlang CLI、HTTP API、Python AMQP 客户端三种方式全覆盖
  • 日常巡检:健康检查、性能监控、容量备份四类命令模板,可直接纳入运维手册
  • 故障排查:Cookie 一致性、PVC Pending、队列堆积三大常见坑

RabbitMQ 与 Kafka 的选型差异详见第 12 天《K8s 部署 Kafka 集群》,本篇重点是 AMQP 协议与灵活路由。

八、下期预告

第 19 天将进入流式消息中间件领域,部署 Apache Pulsar 集群。Pulsar 采用分层存储架构(Broker + BookKeeper + ZooKeeper),支持百万级 Topic 与毫秒级延迟,与 Kafka 形成鲜明对比。届时将讲解 BookKeeper 账本管理、Ceph RBD 持久化、Helm Chart 部署与运维命令。敬请期待!

十、系列目录

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容