RocketMQ - 高可用集群部署:K8s环境下的部署与调度
RocketMQ高可用集群部署指南 本文详细介绍了在Kubernetes(K8s)环境下部署高可用RocketMQ集群的完整方案。文章首先阐述了高可用集群的必要性,包括避免单点故障、提升吞吐量、保障数据安全等核心需求。随后提供了K8s环境准备指南,包括版本兼容性、资源要求和网络策略等。 文章深入剖析了RocketMQ集群的核心组件(NameServer和Broker)及其架构设计,并通过Merma

👋 大家好,欢迎来到我的技术博客!
💻 作为一名热爱 Java 与软件开发的程序员,我始终相信:清晰的逻辑 + 持续的积累 = 稳健的成长。
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕RocketMQ这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!
文章目录
RocketMQ - 高可用集群部署:K8s环境下的部署与调度 🚀
在现代微服务架构和云原生应用中,高可用性(High Availability, HA)是保障系统稳定、可靠运行的核心要素。Apache RocketMQ 作为业界领先的分布式消息中间件,其集群部署模式对于满足业务对高可用性的需求至关重要。特别是在 Kubernetes (K8s) 环境下,通过容器化和编排能力,可以实现 RocketMQ 集群的弹性伸缩、自动恢复和高效调度,从而最大化其可用性和可维护性。
本文将深入探讨如何在 Kubernetes 环境中部署和调度一个高可用的 RocketMQ 集群。我们将从 K8s 环境准备、RocketMQ 集群组件剖析、部署策略、核心配置、服务发现与负载均衡、健康检查、持久化存储、监控与日志、故障恢复与滚动升级等方面进行详细介绍,并提供具体的 YAML 配置示例和 Mermaid 图表,帮助读者构建一个健壮、高效的 RocketMQ 集群。
为什么需要高可用的 RocketMQ 集群? 🤔
在分布式系统中,任何一个单点故障都可能导致整个服务中断。RocketMQ 作为消息中间件,其可用性直接影响到依赖它的下游服务。一个典型的高可用需求场景包括:
- 避免单点故障 (Single Point of Failure):如果 NameServer 或 Broker 是单实例,一旦宕机,整个集群将无法正常工作。通过部署多个实例,即使其中一个实例失效,集群仍能继续提供服务。
- 提升吞吐量与性能:通过部署多个 Broker 实例,可以水平扩展消息处理能力,将消息负载分散到多个节点上,提高整体吞吐量。
- 保障数据安全与一致性:通过主从复制等机制,即使某个 Broker 节点发生故障,数据也不会丢失,确保了消息的持久化和一致性。
- 支持业务连续性:在面对流量高峰或突发情况时,高可用集群能够通过自动扩容或故障切换,保障业务的连续性和稳定性。
- 简化运维与管理:K8s 提供了强大的编排能力,可以自动化地管理集群的生命周期,包括部署、更新、回滚、扩缩容等,大大降低了运维复杂度。
Kubernetes 环境准备 🛠️
在部署 RocketMQ 集群之前,需要确保 Kubernetes 集群环境已经准备就绪。
1. Kubernetes 集群要求
- 版本兼容性:确保使用的 Kubernetes 版本与 RocketMQ 镜像及部署工具兼容。通常,较新的 Kubernetes 版本(如 v1.20+)能更好地支持 Pod 的高级功能。
- 资源充足:为 RocketMQ 组件预留足够的 CPU 和内存资源。NameServer 和 Broker 的资源需求会根据消息吞吐量和存储容量而变化。
- 网络策略:确保 Pod 间的网络通信畅通无阻,特别是 NameServer 与 Broker 之间的通信。可能需要配置 NetworkPolicy 来管理网络访问。
- 存储类 (StorageClass):需要配置合适的 StorageClass 来支持持久化存储(如 PV 和 PVC)。
2. 安装必要的 CLI 工具
- kubectl:Kubernetes 的命令行工具,用于与集群交互。
- helm(可选):Kubernetes 的包管理器,可以简化复杂应用的部署。本文也将展示使用 Helm 部署的方式。
- kustomize(可选):用于定制和管理 Kubernetes 清单文件的工具。
RocketMQ 集群核心组件与架构 🧱
在 Kubernetes 环境中部署 RocketMQ 集群,首先需要理解其核心组件及其在集群中的角色。
1. NameServer (命名服务)
- 职责:NameServer 是 RocketMQ 集群的无状态服务,负责维护 Broker 的路由信息。它不存储消息,也不参与消息的发送和消费过程。
- 高可用性:NameServer 通常部署多个实例,通过负载均衡器(如 Ingress、LoadBalancer Service)对外提供服务。客户端(Producer/Consumer)通过 NameServer 获取 Broker 的地址列表。
- 状态:无状态,重启后无需恢复数据。
2. Broker (消息代理)
- 职责:Broker 是 RocketMQ 的核心组件,负责接收、存储和转发消息。它管理 Topic、Queue 和消息存储。
- 主从模式:为了保证高可用和数据安全,Broker 通常以主从模式(Master-Slave)运行。一个 Master 对应一个或多个 Slave。
- 状态:有状态,需要持久化存储消息数据和元数据。主从之间通过同步或异步方式进行数据复制。
3. 集群拓扑示例
典型的 RocketMQ 集群结构如下所示:
graph TD
subgraph "Kubernetes Cluster"
subgraph "Namespace: rocketmq"
N1[NameServer-1]
N2[NameServer-2]
N3[NameServer-3]
M1[Broker-Master-1]
M2[Broker-Master-2]
S1[Broker-Slave-1]
S2[Broker-Slave-2]
end
end
subgraph "Client Applications"
P[Producer]
C[Consumer]
end
N1 -.->|NameServer Discovery| P
N2 -.->|NameServer Discovery| P
N3 -.->|NameServer Discovery| P
N1 -.->|NameServer Discovery| C
N2 -.->|NameServer Discovery| C
N3 -.->|NameServer Discovery| C
M1 -->|Message Store| S1
M2 -->|Message Store| S2
style N1 fill:#FFA500
style N2 fill:#FFA500
style N3 fill:#FFA500
style M1 fill:#4169E1
style M2 fill:#4169E1
style S1 fill:#4B0082
style S2 fill:#4B0082
style P fill:#228B22
style C fill:#228B22
linkStyle 0 stroke:#000000;
linkStyle 1 stroke:#000000;
linkStyle 2 stroke:#000000;
linkStyle 3 stroke:#000000;
linkStyle 4 stroke:#000000;
linkStyle 5 stroke:#000000;
linkStyle 6 stroke:#000000;
linkStyle 7 stroke:#000000;
linkStyle 8 stroke:#000000;
linkStyle 9 stroke:#000000;
linkStyle 10 stroke:#000000;
- NameServer 集群:部署了 3 个 NameServer 实例,通过负载均衡器对外提供服务。客户端连接到任意一个 NameServer 即可获取 Broker 列表。
- Broker 集群:部署了 2 个 Master Broker 实例(M1, M2)和 2 个 Slave Broker 实例(S1, S2)。每个 Master 配对一个 Slave,形成主从结构。Master 负责处理读写请求,Slave 从 Master 同步数据,提供备份和故障转移能力。
部署策略与架构选择 🧩
在 K8s 环境中部署 RocketMQ 集群,可以选择不同的部署策略:
1. 基于 StatefulSet 的部署 (推荐)
- 优势:
- 有状态管理:StatefulSet 为有状态应用(如 Broker)提供了稳定的网络标识符和持久化存储。
- 有序部署与删除:Pod 按序创建和删除,有利于主从关系的建立和维护。
- 稳定网络标识:每个 Pod 都有稳定的 DNS 名称和 IP 地址,便于 NameServer 和客户端发现。
- 持久化存储:易于绑定 PersistentVolume (PV) 和 PersistentVolumeClaim (PVC)。
- 适用场景:适用于需要稳定网络标识、持久化存储和主从模式的 RocketMQ Broker。
2. 基于 Deployment 的部署
- 优势:
- 简单易用:Deployment 更加通用,适用于无状态服务。
- 劣势:
- 无序性:Pod 无序部署和删除,不利于主从同步。
- 无稳定网络标识:Pod 的 DNS 名称和 IP 可能随重启而改变。
- 难以管理持久化:与持久化存储的绑定不如 StatefulSet 灵活。
- 适用场景:主要用于部署无状态的 NameServer,或者简单的测试环境。
3. 混合部署策略
- NameServer:使用 Deployment 或 StatefulSet 部署。通常使用 Deployment 即可,因为 NameServer 无状态。
- Broker:使用 StatefulSet 部署,以便管理其有状态特性。
核心配置详解 🛠️
1. NameServer 配置
NameServer 的配置相对简单,主要涉及启动参数和环境变量。
NameServer 配置文件 (namesrv.conf)
# namesrv.conf
# NameServer 监听地址和端口
listenPort=9876
# 集群名称 (可选,用于标识集群)
clusterName=DefaultCluster
# NameServer 的 IP 地址 (如果需要指定特定 IP)
# namesrvAddr=localhost:9876 # 通常由 K8s 自动注入或通过服务发现确定
# 服务端口 (可选)
# serverPort=9876
# 日志级别 (可选)
# logLevel=INFO
# 启用 ACL (可选,如果需要访问控制)
# aclEnable=false
# accessKey=
# secretKey=
NameServer Kubernetes Deployment 配置示例 (namesrv-deployment.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: rocketmq-namesrv
namespace: rocketmq
labels:
app: rocketmq-namesrv
spec:
replicas: 3 # 部署 3 个 NameServer 实例
selector:
matchLabels:
app: rocketmq-namesrv
template:
metadata:
labels:
app: rocketmq-namesrv
spec:
containers:
- name: namesrv
image: apache/rocketmq:5.1.0 # 使用官方镜像
ports:
- containerPort: 9876
name: namesrv-port
env:
- name: NAMESRV_ADDR
valueFrom:
fieldRef:
fieldPath: status.podIP # 通过 Pod IP 动态设置,方便内部通信
- name: ROCKETMQ_HOME
value: /opt/rocketmq
command:
- /bin/sh
- -c
- |
# 启动 NameServer
cd $ROCKETMQ_HOME
nohup bin/mqnamesrv > /dev/null 2>&1 &
# 等待 NameServer 启动
sleep 2
# 保持容器运行
tail -f /dev/null
volumeMounts:
- name: rocketmq-config
mountPath: /opt/rocketmq/conf
- name: rocketmq-data
mountPath: /opt/rocketmq/store
volumes:
- name: rocketmq-config
configMap:
name: rocketmq-namesrv-config
- name: rocketmq-data
emptyDir: {} # 临时存储,生产环境应使用 PersistentVolume
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
---
apiVersion: v1
kind: Service
metadata:
name: rocketmq-namesrv
namespace: rocketmq
labels:
app: rocketmq-namesrv
spec:
clusterIP: None # Headless Service,用于 StatefulSet 或者让客户端直接通过 Pod DNS 访问
ports:
- port: 9876
targetPort: 9876
name: namesrv-port
selector:
app: rocketmq-namesrv
---
apiVersion: v1
kind: ConfigMap
metadata:
name: rocketmq-namesrv-config
namespace: rocketmq
data:
namesrv.conf: |
# NameServer 配置
listenPort=9876
clusterName=DefaultCluster
# logLevel=INFO
说明:
replicas: 3:部署 3 个 NameServer 实例,实现高可用。clusterIP: None:创建 Headless Service,允许客户端直接通过 Pod DNS 名称访问,这对于 NameServer 集群的发现很重要。volumeMounts:挂载了配置文件和数据目录。emptyDir:这里使用了emptyDir作为数据存储,仅用于示例。生产环境中应使用 PersistentVolume。
2. Broker 配置
Broker 的配置更为复杂,因为它需要处理主从关系、存储、集群配置等。
Broker 配置文件 (broker.conf)
# broker.conf
# Broker 的监听地址和端口
listenPort=10911
# 集群名称
brokerClusterName=DefaultCluster
# Broker 名称 (在集群中唯一)
brokerName=Broker-A
# Broker 的角色 (MASTER or SLAVE)
brokerRole=MASTER
# Broker 的权重 (用于负载均衡)
brokerId=0
# NameServer 地址 (多个用分号分隔)
namesrvAddr=rocketmq-namesrv.rocketmq.svc.cluster.local:9876
# 存储路径
storePathCommitLog=/opt/rocketmq/store/commitlog
storePathConsumeQueue=/opt/rocketmq/store/consumequeue
storePathIndex=/opt/rocketmq/store/index
storePathMsgTrack=/opt/rocketmq/store/msgtrack
storePathDLeger=/opt/rocketmq/store/dledger
# 消息存储方式 (默认为 file)
# storeType=FILE
# 消息最大大小 (单位 bytes)
# maxMessageSize=1048576
# 消息保存时间 (单位分钟)
# messageStoreTimeToLive=1440
# 启用 ACL (可选)
# aclEnable=false
# accessKey=
# secretKey=
# 启用自动创建 Topic (可选)
# autoCreateTopicEnable=true
# 启用自动创建订阅组 (可选)
# autoCreateSubscriptionGroup=true
# 集群内通信端口 (用于主从同步)
# brokerIP1=127.0.0.1
# 日志级别
# logLevel=INFO
Broker Kubernetes StatefulSet 配置示例 (broker-statefulset.yaml)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: rocketmq-broker
namespace: rocketmq
labels:
app: rocketmq-broker
spec:
serviceName: rocketmq-broker
replicas: 2 # 部署 2 个 Broker 实例 (Master)
selector:
matchLabels:
app: rocketmq-broker
template:
metadata:
labels:
app: rocketmq-broker
spec:
containers:
- name: broker
image: apache/rocketmq:5.1.0
ports:
- containerPort: 10911
name: broker-port
- containerPort: 10909
name: broker-admin-port
env:
- name: BROKER_CONFIG_FILE
value: /opt/rocketmq/conf/broker.conf
- name: ROCKETMQ_HOME
value: /opt/rocketmq
- name: NAMESRV_ADDR
value: rocketmq-namesrv.rocketmq.svc.cluster.local:9876 # NameServer 服务地址
command:
- /bin/sh
- -c
- |
# 确保存储目录存在
mkdir -p /opt/rocketmq/store/commitlog
mkdir -p /opt/rocketmq/store/consumequeue
mkdir -p /opt/rocketmq/store/index
mkdir -p /opt/rocketmq/store/msgtrack
mkdir -p /opt/rocketmq/store/dledger
# 启动 Broker
cd $ROCKETMQ_HOME
nohup bin/mqbroker -n $NAMESRV_ADDR -c /opt/rocketmq/conf/broker.conf > /dev/null 2>&1 &
# 等待 Broker 启动
sleep 5
# 保持容器运行
tail -f /dev/null
volumeMounts:
- name: rocketmq-config
mountPath: /opt/rocketmq/conf
- name: rocketmq-data
mountPath: /opt/rocketmq/store
- name: rocketmq-logs
mountPath: /opt/rocketmq/logs
volumes:
- name: rocketmq-config
configMap:
name: rocketmq-broker-config
- name: rocketmq-logs
emptyDir: {}
volumeClaimTemplates:
- metadata:
name: rocketmq-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "standard" # 请根据你的集群配置调整
resources:
requests:
storage: 20Gi # 根据实际需求调整
---
apiVersion: v1
kind: Service
metadata:
name: rocketmq-broker
namespace: rocketmq
labels:
app: rocketmq-broker
spec:
clusterIP: None # Headless Service
ports:
- port: 10911
targetPort: 10911
name: broker-port
- port: 10909
targetPort: 10909
name: broker-admin-port
selector:
app: rocketmq-broker
---
apiVersion: v1
kind: ConfigMap
metadata:
name: rocketmq-broker-config
namespace: rocketmq
data:
broker.conf: |
# Broker 配置
listenPort=10911
brokerClusterName=DefaultCluster
brokerName=Broker-A
brokerRole=MASTER
brokerId=0
namesrvAddr=rocketmq-namesrv.rocketmq.svc.cluster.local:9876
storePathCommitLog=/opt/rocketmq/store/commitlog
storePathConsumeQueue=/opt/rocketmq/store/consumequeue
storePathIndex=/opt/rocketmq/store/index
storePathMsgTrack=/opt/rocketmq/store/msgtrack
storePathDLeger=/opt/rocketmq/store/dledger
# autoCreateTopicEnable=true
# logLevel=INFO
说明:
StatefulSet:用于管理有状态的 Broker Pod。serviceName: rocketmq-broker:与 Service 关联,确保 Pod 有稳定的 DNS 名称。volumeClaimTemplates:定义了持久化存储模板,每个 Pod 会获得一个独立的 PVC。brokerRole=MASTER:此配置适用于 Master Broker。对于 Slave Broker,需要在配置文件中修改brokerRole=SLAVE和brokerId。NAMESRV_ADDR:通过环境变量传递 NameServer 地址,K8s 服务发现机制会自动解析。storageClassName:需要根据集群实际提供的 StorageClass 进行配置。
3. 主从 Broker 配置
为了实现主从复制,需要为每个 Master Broker 配置对应的 Slave Broker。
示例:Slave Broker 配置 (slave-broker.conf)
# slave-broker.conf
# Broker 的监听地址和端口
listenPort=10911
# 集群名称
brokerClusterName=DefaultCluster
# Broker 名称 (与 Master 一致)
brokerName=Broker-A
# Broker 的角色 (SLAVE)
brokerRole=SLAVE
# Broker 的权重 (与 Master 不同)
brokerId=1
# NameServer 地址
namesrvAddr=rocketmq-namesrv.rocketmq.svc.cluster.local:9876
# 主 Broker 地址 (用于同步)
brokerIP1=rocketmq-broker-0.rocketmq-broker.rocketmq.svc.cluster.local
# 存储路径
storePathCommitLog=/opt/rocketmq/store/commitlog
storePathConsumeQueue=/opt/rocketmq/store/consumequeue
storePathIndex=/opt/rocketmq/store/index
storePathMsgTrack=/opt/rocketmq/store/msgtrack
storePathDLeger=/opt/rocketmq/store/dledger
# 日志级别
# logLevel=INFO
部署 Slave Broker 的 StatefulSet (部分配置)
# ... (省略前面的 Deployment 配置)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: rocketmq-broker-slave
namespace: rocketmq
labels:
app: rocketmq-broker-slave
spec:
serviceName: rocketmq-broker-slave
replicas: 2 # 部署 2 个 Slave Broker 实例
selector:
matchLabels:
app: rocketmq-broker-slave
template:
metadata:
labels:
app: rocketmq-broker-slave
spec:
containers:
- name: broker
image: apache/rocketmq:5.1.0
ports:
- containerPort: 10911
name: broker-port
- containerPort: 10909
name: broker-admin-port
env:
- name: BROKER_CONFIG_FILE
value: /opt/rocketmq/conf/slave-broker.conf
- name: ROCKETMQ_HOME
value: /opt/rocketmq
- name: NAMESRV_ADDR
value: rocketmq-namesrv.rocketmq.svc.cluster.local:9876
command:
- /bin/sh
- -c
- |
# 确保存储目录存在
mkdir -p /opt/rocketmq/store/commitlog
mkdir -p /opt/rocketmq/store/consumequeue
mkdir -p /opt/rocketmq/store/index
mkdir -p /opt/rocketmq/store/msgtrack
mkdir -p /opt/rocketmq/store/dledger
# 启动 Broker (Slave)
cd $ROCKETMQ_HOME
nohup bin/mqbroker -n $NAMESRV_ADDR -c /opt/rocketmq/conf/slave-broker.conf > /dev/null 2>&1 &
# 等待 Broker 启动
sleep 5
# 保持容器运行
tail -f /dev/null
volumeMounts:
- name: rocketmq-config
mountPath: /opt/rocketmq/conf
- name: rocketmq-data
mountPath: /opt/rocketmq/store
- name: rocketmq-logs
mountPath: /opt/rocketmq/logs
volumes:
- name: rocketmq-config
configMap:
name: rocketmq-slave-config # 使用 Slave 配置
- name: rocketmq-logs
emptyDir: {}
volumeClaimTemplates:
- metadata:
name: rocketmq-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "standard"
resources:
requests:
storage: 20Gi
---
apiVersion: v1
kind: Service
metadata:
name: rocketmq-broker-slave
namespace: rocketmq
labels:
app: rocketmq-broker-slave
spec:
clusterIP: None # Headless Service
ports:
- port: 10911
targetPort: 10911
name: broker-port
- port: 10909
targetPort: 10909
name: broker-admin-port
selector:
app: rocketmq-broker-slave
---
apiVersion: v1
kind: ConfigMap
metadata:
name: rocketmq-slave-config
namespace: rocketmq
data:
slave-broker.conf: |
# Slave Broker 配置
listenPort=10911
brokerClusterName=DefaultCluster
brokerName=Broker-A
brokerRole=SLAVE
brokerId=1
namesrvAddr=rocketmq-namesrv.rocketmq.svc.cluster.local:9876
brokerIP1=rocketmq-broker-0.rocketmq-broker.rocketmq.svc.cluster.local
storePathCommitLog=/opt/rocketmq/store/commitlog
storePathConsumeQueue=/opt/rocketmq/store/consumequeue
storePathIndex=/opt/rocketmq/store/index
storePathMsgTrack=/opt/rocketmq/store/msgtrack
storePathDLeger=/opt/rocketmq/store/dledger
# logLevel=INFO
关键点:
brokerRole=SLAVE:指定了角色。brokerId=1:与 Master 的brokerId=0区分。brokerIP1=...:指定了 Master Broker 的地址,用于数据同步。ConfigMap:使用了不同的配置文件名 (slave-broker.conf)。
服务发现与负载均衡 🌐
Kubernetes 提供了强大的服务发现和负载均衡机制,这对于 RocketMQ 集群至关重要。
1. NameServer 服务发现
NameServer 通常通过 Headless Service (无头服务) 提供服务。客户端通过 DNS 查询直接获取所有 NameServer Pod 的 IP 地址,然后选择其中一个进行连接。
# 在 namesrv-deployment.yaml 中
---
apiVersion: v1
kind: Service
metadata:
name: rocketmq-namesrv
namespace: rocketmq
labels:
app: rocketmq-namesrv
spec:
clusterIP: None # Headless Service
ports:
- port: 9876
targetPort: 9876
name: namesrv-port
selector:
app: rocketmq-namesrv
客户端(Producer/Consumer)配置 NameServer 地址时,可以使用服务名:
# 客户端配置
namesrvAddr=rocketmq-namesrv.rocketmq.svc.cluster.local:9876
K8s 会自动将这个域名解析为所有 NameServer Pod 的 IP 地址列表。
2. Broker 服务发现
Broker 通常通过 Headless Service 提供服务,以便客户端可以直接连接到具体的 Broker Pod。
# 在 broker-statefulset.yaml 中
---
apiVersion: v1
kind: Service
metadata:
name: rocketmq-broker
namespace: rocketmq
labels:
app: rocketmq-broker
spec:
clusterIP: None # Headless Service
ports:
- port: 10911
targetPort: 10911
name: broker-port
- port: 10909
targetPort: 10909
name: broker-admin-port
selector:
app: rocketmq-broker
3. 外部访问 (可选)
如果需要从 K8s 集群外部访问 RocketMQ,可以创建 LoadBalancer 或 Ingress 服务。
LoadBalancer Service 示例
# 为 Broker 创建 LoadBalancer 服务 (用于外部访问)
apiVersion: v1
kind: Service
metadata:
name: rocketmq-broker-lb
namespace: rocketmq
labels:
app: rocketmq-broker-lb
spec:
type: LoadBalancer # 外部负载均衡器
ports:
- port: 10911
targetPort: 10911
name: broker-port
selector:
app: rocketmq-broker
注意:
LoadBalancer类型的服务需要云提供商支持。在本地集群(如 Minikube)上可能不支持,或者需要模拟。
健康检查与就绪探针 🧪
Kubernetes 通过探针(Probes)来检查 Pod 的健康状况和就绪状态,这对于自动故障恢复和滚动升级至关重要。
1. Liveness Probe (存活探针)
检测 Pod 是否存活。如果探针失败,K8s 会重启 Pod。
# 在 StatefulSet 或 Deployment 的容器配置中
livenessProbe:
exec:
command:
- /bin/sh
- -c
- |
# 检查 RocketMQ 进程是否存在
if pgrep -f "mqbroker" > /dev/null; then
exit 0
else
exit 1
fi
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
2. Readiness Probe (就绪探针)
检测 Pod 是否准备好接收流量。如果探针失败,K8s 会将 Pod 从服务中移除。
# 在 StatefulSet 或 Deployment 的容器配置中
readinessProbe:
exec:
command:
- /bin/sh
- -c
- |
# 检查 NameServer 是否可达 (示例)
# 注意:这里只是一个简单的检查,实际应用中可能需要更复杂的逻辑
if nc -z rocketmq-namesrv.rocketmq.svc.cluster.local 9876; then
exit 0
else
exit 1
fi
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
3. 示例整合
# ... (省略前面的配置)
containers:
- name: broker
image: apache/rocketmq:5.1.0
ports:
- containerPort: 10911
name: broker-port
- containerPort: 10909
name: broker-admin-port
env:
- name: BROKER_CONFIG_FILE
value: /opt/rocketmq/conf/broker.conf
- name: ROCKETMQ_HOME
value: /opt/rocketmq
- name: NAMESRV_ADDR
value: rocketmq-namesrv.rocketmq.svc.cluster.local:9876
livenessProbe:
exec:
command:
- /bin/sh
- -c
- |
if pgrep -f "mqbroker" > /dev/null; then
exit 0
else
exit 1
fi
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- /bin/sh
- -c
- |
if nc -z rocketmq-namesrv.rocketmq.svc.cluster.local 9876; then
exit 0
else
exit 1
fi
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
command:
- /bin/sh
- -c
- |
# 确保存储目录存在
mkdir -p /opt/rocketmq/store/commitlog
mkdir -p /opt/rocketmq/store/consumequeue
mkdir -p /opt/rocketmq/store/index
mkdir -p /opt/rocketmq/store/msgtrack
mkdir -p /opt/rocketmq/store/dledger
# 启动 Broker
cd $ROCKETMQ_HOME
nohup bin/mqbroker -n $NAMESRV_ADDR -c /opt/rocketmq/conf/broker.conf > /dev/null 2>&1 &
# 等待 Broker 启动
sleep 5
# 保持容器运行
tail -f /dev/null
volumeMounts:
- name: rocketmq-config
mountPath: /opt/rocketmq/conf
- name: rocketmq-data
mountPath: /opt/rocketmq/store
- name: rocketmq-logs
mountPath: /opt/rocketmq/logs
持久化存储策略 📦
RocketMQ 的持久化存储是保证数据安全和高可用的关键。K8s 中通过 PersistentVolume (PV) 和 PersistentVolumeClaim (PVC) 来管理。
1. 持久化存储需求
- CommitLog:存储原始消息数据。
- ConsumeQueue:存储消费队列索引。
- IndexFile:存储消息索引。
- DLeger:如果启用了 DLedger 模式,则需要存储相关数据。
2. 创建 StorageClass
# storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/aws-ebs # 示例,根据云提供商调整
parameters:
type: gp2
fsType: ext4
reclaimPolicy: Retain # 或 Delete
allowVolumeExpansion: true
3. 配置 PVC (在 StatefulSet 中)
# 在 broker-statefulset.yaml 中的 volumeClaimTemplates 部分
volumeClaimTemplates:
- metadata:
name: rocketmq-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "fast-ssd" # 使用上面创建的 StorageClass
resources:
requests:
storage: 100Gi # 根据实际需求调整
4. 数据备份策略
- 定期快照:利用云提供商的存储快照功能,定期备份 PV。
- 应用层备份:通过 RocketMQ 自带的工具或第三方工具(如 Velero)进行应用级别的备份。
- 异地容灾:在不同区域部署集群,实现跨区域容灾。
监控与日志管理 📊
一个健壮的 RocketMQ 集群离不开有效的监控和日志管理。
1. Prometheus + Grafana 监控
- Prometheus Exporter:可以使用 RocketMQ 提供的 Prometheus Exporter 或社区开发的 exporter 来收集指标。
- Grafana Dashboard:创建自定义 Dashboard 来展示 Broker 的吞吐量、延迟、内存使用、磁盘 I/O 等关键指标。
示例:Prometheus 配置 (prometheus.yml)
scrape_configs:
- job_name: 'rocketmq'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
regex: rocketmq-broker
action: keep
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
regex: (.+)(?::\d+);(\d+)
target_label: __address__
replacement: ${1}:${2}
action: replace
2. 日志收集
- Fluentd/Fluent-bit:用于收集 Pod 日志并转发到集中式日志系统(如 ELK Stack)。
- ELK Stack (Elasticsearch, Logstash, Kibana):用于存储和可视化日志。
- Loki + Promtail:轻量级的日志收集和查询系统,适合与 Prometheus 集成。
示例:Promtail 配置 (promtail.yaml)
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: rocketmq
__path__: /var/log/pods/*/*/*.log
故障恢复与滚动升级 🔄
1. 故障恢复机制
Kubernetes 本身提供了强大的故障恢复能力:
- Pod 自动重启:当 Pod 因为健康探针失败或崩溃而终止时,K8s 会自动重启它。
- 节点故障处理:当节点宕机时,K8s 会将该节点上的 Pod 调度到其他健康的节点上。
- StatefulSet 保证:StatefulSet 保证了 Pod 的稳定网络标识和持久化存储,即使 Pod 被删除重建,也能维持其状态。
2. 滚动升级策略
滚动升级是一种平滑的更新方式,确保服务不中断。
示例:StatefulSet 滚动升级策略
# ... (省略前面的配置)
spec:
serviceName: rocketmq-broker
replicas: 2
selector:
matchLabels:
app: rocketmq-broker
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0 # 从第一个 Pod 开始更新
template:
# ... (Pod 模板)
更新流程
- 更新镜像:修改 StatefulSet 的镜像标签。
kubectl set image statefulset/rocketmq-broker broker=apache/rocketmq:5.2.0 - K8s 自动更新:K8s 会按照
updateStrategy策略,逐个更新 Pod。对于 StatefulSet,它会按顺序(从 0 开始)更新 Pod。 - 就绪检查:每个新 Pod 启动后,K8s 会等待其通过
readinessProbe检查,确认就绪后再更新下一个 Pod。 - 完成:所有 Pod 都被更新后,集群处于新版本状态。
3. 故障演练与恢复测试
- 模拟 Pod 故障:手动删除一个 Pod,观察 K8s 是否能自动恢复。
- 模拟节点故障:标记一个节点为不可调度,观察 Pod 是否会被驱逐并重新调度。
- 数据恢复测试:在备份的基础上,尝试恢复数据,验证其完整性。
使用 Helm 部署 RocketMQ 🧰
Helm 是 Kubernetes 的包管理器,可以简化复杂应用的部署。RocketMQ 社区或第三方提供了 Helm Chart。
1. 安装 Helm
# 下载 Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# 验证安装
helm version
2. 添加 RocketMQ Helm Repo
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
注意:Bitnami 的 RocketMQ Chart 可能不是官方 RocketMQ 的最完整实现。可以查找社区或官方提供的 Helm Chart。
3. 部署 RocketMQ
helm install my-rocketmq bitnami/rocketmq \
--namespace rocketmq \
--create-namespace \
--set persistence.enabled=true \
--set persistence.size=100Gi
说明:这只是一个示例,具体参数需要根据实际情况调整。
安全加固与访问控制 🔐
1. 启用 ACL (Access Control List)
RocketMQ 支持通过 ACL 机制进行访问控制。
启用 ACL 配置
在 broker.conf 中:
# broker.conf
aclEnable=true
accessKey=rocketmq
secretKey=12345678
在 namesrv.conf 中:
# namesrv.conf
aclEnable=true
accessKey=rocketmq
secretKey=12345678
客户端配置
// Producer/Consumer 配置
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroup");
producer.setNamesrvAddr("rocketmq-namesrv.rocketmq.svc.cluster.local:9876");
producer.setAccessChannel(AccessChannel.CLOUD);
producer.setCredentials(new Credentials("rocketmq", "12345678")); // 设置 AccessKey 和 SecretKey
2. 使用 Kubernetes Secrets 管理敏感信息
将 accessKey 和 secretKey 存储在 Kubernetes Secrets 中,避免硬编码。
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: rocketmq-acl-secret
namespace: rocketmq
type: Opaque
data:
accessKey: cm9ja3RtcXVl
secretKey: MTIzNDU2Nzg=
然后在 Pod 中引用:
# 在 StatefulSet 的容器中
env:
- name: ACCESS_KEY
valueFrom:
secretKeyRef:
name: rocketmq-acl-secret
key: accessKey
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: rocketmq-acl-secret
key: secretKey
总结与最佳实践 📝
通过本文的介绍,我们掌握了在 Kubernetes 环境下部署高可用 RocketMQ 集群的完整流程。关键要点包括:
- 架构设计:采用 NameServer 集群和 Broker 主从模式,确保高可用性。
- 部署方式:使用 StatefulSet 部署有状态的 Broker,使用 Deployment 部署无状态的 NameServer。
- 配置管理:通过 ConfigMap 管理配置文件,避免硬编码敏感信息。
- 持久化存储:使用 PVC 和 StorageClass 实现数据持久化。
- 服务发现:利用 K8s 的 Service 和 DNS 实现服务发现。
- 健康检查:配置 Liveness 和 Readiness Probe,确保 Pod 的健康状态。
- 监控与日志:集成 Prometheus、Grafana、Loki 等工具进行监控和日志分析。
- 安全加固:启用 ACL,使用 Kubernetes Secrets 管理敏感信息。
- 滚动升级与故障恢复:利用 K8s 的原生能力实现平滑升级和自动恢复。
遵循这些最佳实践,可以构建一个稳定、可靠、安全且易于维护的 RocketMQ 集群,充分满足现代分布式应用对高可用性的需求。
参考资料与延伸阅读
- Apache RocketMQ 官方文档
- Kubernetes 官方文档
- Helm 官方文档
- Prometheus 官方文档
- Grafana 官方文档
- Loki 官方文档
- Bitnami RocketMQ Helm Chart
- Kubernetes StatefulSet 文档
- Kubernetes Persistent Volumes 文档
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨
更多推荐



所有评论(0)