一、现状分析
传统方式通过物理机或虚拟机部署一套高可用的 RocketMQ 集群,假设 2 Master 2 Slave,再加 2 个 nameserver,一共需要 6 台机器。如果把 nameserver 跟 broker 部署在一起,那也需要 4 台机器。这种方式硬件成本很高,另外维护成本也相当高。
Kubernetes 部署
基于 Kubernetes 部署应用可以大幅度降低硬件成本和运维成本。RocketMQ 官方提供了 operator 部署,我们公司已经用这种方式部署了好几套集群,使用过程中发现了一些问题:
- nameserver 重新调度后 pod ip 会改变,此时 operator 会逐个修改 broker statefulset 配置,这意味着所有 broker 都需要重启,会造成业务中断。
- 配置不够灵活,比如不方便添加节点亲和性;副节点跟主节点使用同样的资源配额,不方便单独配置。
- 部署操作不够简洁,operator 比 helm 的复杂度高很多。
RocketMQ 官方没有提供 helm,谷歌搜一下 rocketmq helm
也没有找到可用的资源。bitnami 提供了超级丰富的 helm 资源,其中覆盖了 Kafka 和 RabbitMQ,但是没有 RocketMQ.
因此,有必要自己开发 helm 来部署高可用集群。
二、helm 开发
难点分析
因为 k8s pod ip 都是动态的,这给一些有状态的应用带来了麻烦。
broker 必须静态添加每个 nameserver 地址 (ip或域名),它不能依靠服务发现。这里使用 pod ip 肯定不合理,需要把每个 nameserver 的 pod 域名配置到 broker. <pod域名>
= <pod名>.<statefulSet服务名>.<namespace>.svc.cluster.local
,同命名空间下可以去掉后缀: <pod名>.<statefulSet服务名>
。
以下截取了部分关于 nameserver 高可用的配置:
apiVersion: v1
kind: Service
metadata:
name: rocketmq-nameserver
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: rocketmq-nameserver
spec:
replicas: 3
serviceName: rocketmq-nameserver
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: rocketmq-broker-0-master
spec:
template:
spec:
containers:
- env:
- name: NAMESRV_ADDR
# NAMESRV_ADDR 错误配置:value: rocketmq-nameserver:9876
# 正确操作是把所有 nameserver 节点加入 NAMESRV_ADDR,如下:
value: rocketmq-nameserver-0.rocketmq-nameserver:9876;rocketmq-nameserver-1.rocketmq-nameserver:9876;rocketmq-nameserver-2.rocketmq-nameserver:9876
实现细节
把每个 nameserver 的 pod 域名配置到 broker,以下截取了实现这个需求的部分模板配置:
nameserver statefulset.yaml
模板:
{{- $fullName := include "rocketmq.nameserver.fullname" . -}}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ $fullName | quote }}
spec:
replicas: {{ .Values.nameserver.replicaCount }}
serviceName: {{ $fullName | quote }}
broker statefulset.yaml
模板:
{{- $nameserverFullName := include "rocketmq.nameserver.fullname" . -}}
{{- $nameserverReplicaCount:= int .Values.nameserver.replicaCount }}
env:
- name: NAMESRV_ADDR
value: {{ range $i := until $nameserverReplicaCount }}{{ if gt $i 0 }}{{ printf ";" }}{{ end }}{{ printf "%s-%d.%s:9876" $nameserverFullName $i $nameserverFullName }}{{ end }}
三、部署
参考 GitHub 文档: github.com/itboon/rock…
git clone https://github.com/itboon/rocketmq-helm.git
cd rocketmq-helm
kubectl create namespace rocketmq
# 部署测试集群, 单 Master
helm -n rocketmq install rocketmq -f examples/test.yml ./
# 部署生产集群, 多 Master 多 Slave
helm -n rocketmq install rocketmq -f examples/production.yaml ./
Broker 集群架构
单 Master 模式
broker:
size:
master: 1
replica: 0
多 Master 模式
一个集群无Slave,全是Master,例如2个Master或者3个Master,这种模式的优缺点如下:
- 优点:配置简单,单个Master宕机或重启维护对应用无影响,性能最高;
- 缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到影响。
broker:
size:
master: 3
replica: 0
多 Master 多 Slave 模式
每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟(毫秒级),这种模式的优缺点如下:
- 优点:Master宕机后,消费者仍然可以从Slave消费,而且此过程对应用透明,不需要人工干预,性能同多Master模式几乎一样;
- 缺点:Master宕机,磁盘损坏情况下会丢失少量消息 (已经同步到 Slave 的数据不受影响)
broker:
size:
master: 3
replica: 1
# 3个 master 节点,每个 master 具有1个副节点,共6个 broker 节点
作者简介
八戒,来自杭州晓宇科技,技术中台运维工程师。
| 本文系晓宇科技技术团队出品,著作权归属晓宇科技技术团队。欢迎出于分享和交流等非商业目的转载或使用本文内容,敬请注明“内容转载自晓宇科技技术团队”。本文未经许可,不得进行商业性转载或者使用。