Kubernetes 部署高可用 RocketMQ 集群

6,355 阅读3分钟

一、现状分析

传统方式通过物理机或虚拟机部署一套高可用的 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

image.png

实现细节

把每个 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 节点

作者简介

八戒,来自杭州晓宇科技,技术中台运维工程师。

| 本文系晓宇科技技术团队出品,著作权归属晓宇科技技术团队。欢迎出于分享和交流等非商业目的转载或使用本文内容,敬请注明“内容转载自晓宇科技技术团队”。本文未经许可,不得进行商业性转载或者使用。