k8s集群部署rabbitmq集群
1、构建rabbitmq镜像
RabbitMQ提供了一个Autocluster插件,可以自动创建RabbitMQ集群。下面我们将基于RabbitMQ的官方docker镜像,添加这个autocluster插件,构建我们自己的Rabbit镜像,以便在Kubernetes上使用这个镜像。
首选需要从这里下载autocluster和rabbitmq_aws插件,我这里下载的是0.8.0的最新版本。
mkdir -p rabbitmq/plugins
cd rabbitmq/plugins
wget https://github.com/rabbitmq/rabbitmq-autocluster/releases/download/0.8.0/autocluster-0.8.0.ez
wget https://github.com/rabbitmq/rabbitmq-autocluster/releases/download/0.8.0/rabbitmq_aws-0.8.0.ez
cd ..
我的Dockerfile内容如下:
FROM rabbitmq:3.6.11-management-alpine
MAINTAINER yangyuhang
RUN apk update && apk add ca-certificates && \
apk add tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
ADD plugins/*.ez /opt/rabbitmq/plugins/
RUN rabbitmq-plugins enable --offline autocluster
- 这里选择是rabbitmq:3.6.11-management-alpine作为基础镜像
- 添加了autocluster插件
制作镜像并推送至阿里云个人仓库:
docker build -t registry.cn-zhangjiakou.aliyuncs.com/beibei_dtstack/cashier_rabbitmq:base .
docker push registry.cn-zhangjiakou.aliyuncs.com/beibei_dtstack/cashier_rabbitmq:base
2、以statefulset部署rabbitmq集群
在部署集群之前需要为集群创建一个Storage Class(存储类)来作为集群数据的持久化后端。本例中使用nfs作为后端存储,在创建存储类之前需要先搭建好nfs,并保证在k8s集群各个节点上均能挂载该nfs存储。搭建好nfs后,需要先创建一个存储类,yaml文件如下:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: first-storage
parameters:
archiveOnDelete: "false"
provisioner: nfs-first-storage
reclaimPolicy: Retain
volumeBindingMode: Immediate
然后需要再创建一个PersistentVolumeClaim(PVC,存储卷),作为rabbitmq集群的后端存储:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rabbitmq
namespace: cashier
spec:
accessModes:
- ReadWriteMany #可被多节点读写
resources:
requests:
storage: 5Gi
storageClassName: first-storage #声明pv
volumeMode: Filesystem
相继执行kubectl apply -f 即可将后端存储建好。
前面在构建RabbitMQ的Docker镜像时,我们添加了autocluster插件,这个插件基于很多种backend做服务发现自动发现的RabbitMQ节点添加到RabbitMQ集群中,autocluster当前支持如下几种backend:
- AWS EC2 tags
- AWS Autoscaling Groups
- Kubernetes
- DNS A records
- Consul
- etcd
Kubernetes赫然在列,实际上当使用Kubernetes作为rabbitmq-autocluster的backend时,autocluster会通过访问Kubernetes的API Server获取RabbitMQ服务的endpoints,这样就能拿到Kubernete集群中的RabbitMQ的Pod的信息,从而可以将它们添加到RabbitMQ的集群中去。 这里也就是说要在autocluster实际上是在RabbitMQ Pod中要访问Kubernetes的APIServer。
可是然后呢?因为已经对Kubernetes的API Server启用了TLS认证,同时也为API Server起到用了RBAC,要想从Pod中访问API Server需要借助Kubernetes的Service Account。 Service Account是Kubernetes Pod中的程序用于访问Kubernetes API的Account(账号),它为Pod中的程序提供访问Kubernetes API的身份标识。下面我们创建rabbitmq Pod的ServiceAccount,并针对Kubernetes的endpoint资源做授权,创建相关的role和rolebinding。
先说明一下,我们的部署是在cashier这个namespace下的。创建如下的rabbitmq.rbac.yaml文件:
---
apiVersion: v1
kind: ServiceAccount #集群访问apiserver的凭证
metadata:
name: rabbitmq
namespace: cashier
---
kind: Role #创建sa角色
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: rabbitmq
namespace: cashier
rules:
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
kind: RoleBinding #将角色绑定
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: rabbitmq
namespace: cashier
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: rabbitmq
subjects:
- kind: ServiceAccount
name: rabbitmq
namespace: cashier
在Kubernetes上创建rabbitmq这个ServiceAccount以及相关的role和rolebinding:
kubectl create -f rabbitmq.rbac.yaml
然后创建访问rabbitmq集群的service,创建rabbitmq.service.yaml:
---
apiVersion: v1
kind: Service
metadata:
name: rabbitmq-management
namespace: cashier
labels:
app: rabbitmq
spec:
ports:
- port: 15672
name: http
nodePort: 32001 #集群外访问rabbitmq管理web界面,http://nodeip:32001
- port: 5672
name: amqp
nodePort: 32002
selector:
app: rabbitmq
type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: rabbitmq
namespace: cashier
labels:
app: rabbitmq
spec:
clusterIP: None
ports:
- port: 5672
name: amqp
selector:
app: rabbitmq
在Kubernetes上创建rabbitmq的service:
kubectl create -f rabbitmq.service.yaml
然后通过statefulset类型创建rabbitmq集群,创建rabbitmq.statefulset.yaml:
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: rabbitmq
k8s.eip.work/layer: cloud
k8s.eip.work/name: rabbitmq
name: rabbitmq
namespace: cashier
spec:
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: rabbitmq
k8s.eip.work/layer: cloud
k8s.eip.work/name: rabbitmq
serviceName: rabbitmq
template:
metadata:
labels:
app: rabbitmq
k8s.eip.work/layer: cloud
k8s.eip.work/name: rabbitmq
spec:
containers:
- env:
- name: RABBITMQ_DEFAULT_USER
valueFrom:
secretKeyRef:
key: rabbitDefaulUser
name: devsecret #登陆用户名和密码都存储在一个secret对象中
- name: RABBITMQ_DEFAULT_PASS
valueFrom:
secretKeyRef:
key: rabbitDefaultPass
name: devsecret
- name: RABBITMQ_ERLANG_COOKIE
valueFrom:
secretKeyRef:
key: erlang.cookie
name: devsecret
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: K8S_SERVICE_NAME
value: "rabbitmq"
- name: RABBITMQ_USE_LONGNAME
value: 'true'
- name: RABBITMQ_NODENAME
value: "rabbit@$(MY_POD_NAME).$(K8S_SERVICE_NAME)"
- name: RABBITMQ_NODE_TYPE
value: "disc"
- name: AUTOCLUSTER_TYPE
value: "k8s"
- name: AUTOCLUSTER_DELAY
value: '10'
- name: AUTOCLUSTER_CLEANUP
value: 'true'
- name: CLEANUP_WARN_ONLY
value: 'false'
- name: K8S_ADDRESS_TYPE
value: "hostname"
- name: K8S_HOSTNAME_SUFFIX
value: ".$(K8S_SERVICE_NAME)"
image: "registry.cn-zhangjiakou.aliyuncs.com/beibei_dtstack/cashier_rabbitmq:base"
imagePullPolicy: IfNotPresent
name: rabbitmq
ports:
- containerPort: 5672
name: amqp
protocol: TCP
resources:
limits:
cpu: 250m
memory: 512Mi
requests:
cpu: 150m
memory: 256Mi
volumeMounts:
- mountPath: /var/lib/rabbitmq
name: rabbitmq-volume
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: aliyunsecret
restartPolicy: Always
schedulerName: default-scheduler
serviceAccount: rabbitmq
serviceAccountName: rabbitmq
volumes:
- name: rabbitmq-volume
persistentVolumeClaim:
claimName: rabbitmq #绑定pvc
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
在创建之前还需要创建一个secret对象,用来存储rabbitmq的用户名、密码及erlang.cookie,具体创建步骤如下:
#首先需要生成一个erlang.cookie的文件:
echo $(openssl rand -base64 32) > erlang.cookie
#然后将该文件的内容复制下来,编写一个secret对象yaml:
apiVersion: v1
kind: Secret
metadata:
name: devsecret
namespace: cashier
type: Opaque
data:
rabbitDefaulUser: "cmFiYml0dXNlcgo="
rabbitDefaultPass: "cmFiYml0cGFzcwo="
erlang.cookie: "ClmQ9uk2OYk/e+F6wxQEj49rcWT0XzJFWvWIC8RHOiA="
- secret对象不允许存储明码的内容,必须将data下所有的数据转换为base64数据才ok,然后create一下:
kubectl creat -f secret.yaml
- 通过环境变量RABBITMQ_USE_LONGNAME, RABBITMQ_NODENAME, AUTOCLUSTER_TYPE, AUTOCLUSTER_DELAY, K8S_ADDRESS_TYPE, AUTOCLUSTER_CLEANUP等环境变量配置了autocluster插件,具体可以参考 RabbitMQ Autocluster中的文档内容
- 通过RABBITMQ_ERLANG_COOKIE指定了Erlang cookie。RabbitMQ的集群是通过Erlang OTP实现的,而Erlang节点间通信的认证通过Erlang cookie来允许通信,这里从devsecret这个Secret中挂载。关于devsecret这个Secret这里不再给出。
- 通过RABBITMQ_DEFAULT_USER和RABBITMQ_DEFAULT_PASS指定了RabbitMQ的管理员用户名和密码,也是从devsecret这个Secret中挂载的
- 通过RABBITMQ_NODE_TYPE设置集群所有节点类型为disc,即为磁盘节点
为了在Kubernetes上运行RabbitMQ集群,必须保证各个RabbitMQ节点之间可以通信,也就是SatefulSet的Pod可以通信。 采用的RabbitMQ节点的命名方式为rabbit@hostdomainname的形式:
rabbit@rabbitmq-0.rabbit (rabbit@rabbitmq-0.rabbit.cashier.svc.cluster.local)
rabbit@rabbitmq-1.rabbit (rabbit@rabbitmq-1.rabbit.cashier.svc.cluster.local)
rabbit@rabbitmq-2.rabbit (rabbit@rabbitmq-2.rabbit.cashier.svc.cluster.local)
可以看出采用的是长节点名的命名方式,因此设置了RABBITMQ_USE_LONGNAME为true。为了保证节点间可以通过访问rabbitmq-0.rabbit, rabbitmq-1.rabbit, rabbitmq-2.rabbit这些域名通信,必须使用Headless Service,上面rabbitmq Service的clusterIP: None这个必须设置。
在Kubernetes上创建Service和StatefulSet:
kubectl create -f rabbitmq.statefulset.yaml
[root@k8s-master1 ~]# kubectl get statefulset rabbitmq -n cashier
NAME READY AGE
rabbitmq 3/3 5h15m
最后可以在RabbitMQ Management中查看RabbitMQ的3个节点已经组成了集群:
参考资料
- RabbitMQ Autocluster
- Highly Available (Mirrored) Queues
- RabbitMQ File and Directory Locations
- Expose Pod Information to Containers Through Environment Variables
- Kubernetes Headless Services
- kubernetes中文网
k8s集群部署rabbitmq集群的更多相关文章
- RabbitMQ系列(五)使用Docker部署RabbitMQ集群
概述 本文重点介绍的Docker的使用,以及如何部署RabbitMQ集群,最基础的Docker安装,本文不做过多的描述,读者可以自行度娘. Windows10上Docker的安装 因为本人用的是Win ...
- Docker swarm结合Openresty部署rabbitmq集群
Docker swarm结合Openresty部署rabbitmq集群 大家好,年底了,年味儿越来越浓了.2019年的寒冬被定义为未来10年中最好的一年,对于这一说法悲观的人和乐观的人的理解是不一样的 ...
- rabbitMQ集群部署以及集群之间同步
MQ集群部署 期待的部署架构 其中,一个机房有两台机器部署MQ,并组成集群,有一个机房的MQ集群作为中心集群,其他机房的MQ集群将消息同步到中心MQ集群中. 安装erlang,略.. 安装rabbit ...
- Linux 部署 rabbitMQ集群
1. 部署Erlang 1.1 RabbitMQ依赖于Erlang,版本对应请查看 https://www.rabbitmq.com/which-erlang.html 1.2 下载安装Erlang ...
- Docker环境下的前后端分离项目部署与运维(八)使用Docker部署RabbitMQ集群
下载RabbitMQ镜像 镜像地址RabbitMQ Docker官方认证镜像地址:https://hub.docker.com/_/rabbitmq 安装命令安装之前,切记把Docker Hub设置为 ...
- docker部署rabbitmq集群
docker版本:18.09.6 或以上 rabbitmq镜像版本:rabbitmq:3.9.5-management 一.拉镜像: docker pull rabbitmq:3.9.5-manage ...
- kubernetes容器集群部署Etcd集群
安装etcd 二进制包下载地址:https://github.com/etcd-io/etcd/releases/tag/v3.2.12 [root@master ~]# GOOGLE_URL=htt ...
- CentOS 部署RabbitMQ集群
1. 准备两台CentOS,信息如下: node1:10.0.0.123 node2:10.0.0.124 修改hostname请参照: $ hostname # 查看当前的hostname $ ho ...
- Elasticsearch7.6 集群部署、集群认证及使用、数据备份
window 环境部署集群 注意:window下载解压elasticsearch一定需要解压多次.例如搭建的3节点的,需要解压3次,防止生成 cluster UUID 一致导致只能看到一个节点 1.e ...
随机推荐
- ArcPy批量选择指定属性的要素
在GIS数据处理中,选择数据是十分频繁的操作,常用的是"按属性选择"和"按位置选择",这两个功能虽然比较强大,但有时也不能满足实际需求.比如可能时常会遇到这样一 ...
- 1,web项目工作流程
1.1 了解web程序工作流程 .1.2django生命周期
- 正式班D21
2020.11.03星期二 正式班D21 目录 11.5 源码包 11.5.1 预先安装编译安装依赖的库 11.5.2 官网下载源码包 11.5.3 解压.编译.编译安装 11.5 源码包 11.5. ...
- 水题挑战1:NOIP 2013 选择客栈
丽江河边有\(n\) 家很有特色的客栈,客栈按照其位置顺序从 \(1\) 到 \(n\) 编号.每家客栈都按照某一种色调进行装饰(总共 \(k\) 种,用整数 \(0 \sim k-1\) 表示),且 ...
- 【快速因数分解】Pollard's Rho 算法
Pollard-Rho 是一个很神奇的算法,用于在 $O(n^{\frac{1}4}) $的期望时间复杂度内计算合数 n 的某个非平凡因子(除了1和它本身以外能整除它的数).事书上给出的复杂度是 \( ...
- Python Tkinter小实例——模拟掷骰子
什么是Tkinter? Tkinter 是 Python 的标准 GUI 库.Python 使用 Tkinter 可以快速的创建 GUI 应用程序. 由于 Tkinter 是内置到 python 的安 ...
- 1.1 Prism安装
Prism框架有很多安装包,即便用了很长一段时间,也可能会不知道如何安装框架.细心分析包的依赖关系,发现所有包均依赖与依赖注入扩展插件,以使用Unity为例,Prism.Unity依赖Prism.Wp ...
- Luogu P6833 【[Cnoi2020]雷雨】
这道题赛时的时候想了一个奇怪的做法但是没过,后来经过Stay_hungry的提示就码了这道题. 雷电必定会在一点处分叉,分别电击地上的两个点,我们只需要枚举这个分叉点.那么怎么算出这个点和目标点的距离 ...
- nginx&http 第六章 http 协议学习 1
1.HTTP方法 GET :获取资源 ,GET 方法用来请求访问已被 URI 识别的资源 POST:传输(上传和下载)实体主体 ,POST 方法用来传输实体的主体.虽然用 GET 方法也可以传输实体的 ...
- epoll内核源码详解(转 作者:赛罗·奥特曼 来源:牛客网)
发现自己发的一篇面经后,很多小伙伴向我索要epoll的内核源码实现,那我就在牛客网发下这源码还有自己总结的流程. 另外 网上很多博客说epoll使用了共享内存,这个是完全错误的 ,可以阅读源码,会发现 ...