Loading

在k8s中部署rabbitmq镜像集群

1 环境说明

主机名 系统版本 IP地址 cpu/内存/磁盘 用途 软件版本
k8s_nfs CentOS7.5 172.16.1.60 2核/2GB/60GB nfs存储 nfs-utils-1.3.0-0.68
k8s-master1 CentOS7.5 172.16.1.81 2核/2GB/60GB kubernetes master1节点 k8s v1.20.0
k8s-master2 CentOS7.5 172.16.1.82 2核/2GB/60GB kubernetes master2节点 k8s v1.20.0
k8s-node1 CentOS7.5 172.16.1.83 4核/8GB/60GB kubernetes node1节点 k8s v1.20.0
k8s-node2 CentOS7.5 172.16.1.84 4核/8GB/60GB kubernetes node2节点 k8s v1.20.0

补充: kubernetes集群的控制节点我打了污点不能被pod调度使用。

1 nfs服务部署
节点: k8s_nfs
用途: k8s pod 数据持久化存储
说明: nfs服务的搭建过程不再赘述
验证:
[root@k8s_nfs ~]# showmount -e 172.16.1.60
Export list for 172.16.1.60:
/ifs/kubernetes *

2 nfs-subdir-external-provisioner插件部署
节点: kubernetes集群
用途: 为中间件pod提供pvc自动供给
说明: nfs pvc自动供给插件的部署过程不再赘述。修改"deployment.yaml"文件中连接nfs服务的地址和nfs共享目录参数;修改"class.yaml"
文件中"archiveOnDelete"(删除时是否存档)参数为 archiveOnDelete: "true",删除pod时保留pod数据,默认为false时为不保留数据。
注意: 在部署前需要在k8s各个节点上部署nfs的客户端(yum install nfs-utils -y),否则无法部署成功。

补充:
(1) gitlab项目地址: https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
(2) 下载 deploy 目录如下文件
class.yaml、deployment.yaml、rbac.yaml

查看:
[root@k8s-master1 nfs-subdir-external-provisioner-master]# ls | xargs -i kubectl apply -f {}
[root@k8s-master1 nfs-subdir-external-provisioner-master]# kubectl get deployment,pod,svc,sc -n default

image-20220214160856064

2 rabbitmq集群部署(镜像)

2.1 rabbitmq介绍
1 简介
RabbitMQ是一个开源的消息代理的队列服务器,用来通过普通协议在完全不同的应用之间共享数据。支持异步处理、流量削峰、日志处理、应用解耦。

2 RabbitMQ集群节点之间的认证方式
(1) 通过Erlang Cookie,相当于共享秘钥的概念,长度任意,只要所有节点都一致即可。
(2) rabbitmq server在启动的时候,erlang VM会自动创建一个随机的cookie文件。
cookie文件的位置是/var/lib/rabbitmq/.erlang.cookie 或者 /root/.erlang.cookie,为保证cookie的完全一致,采用从一个节点
copy的方式。
(3) Erlang Cookie是保证不同节点可以相互通信的密钥,要保证集群中的不同节点相互通信必须共享相同的Erlang Cookie。具体的目录存放
在/var/lib/rabbitmq/.erlang.cookie。
(4) 从rabbitmqctl命令的工作原理说起,RabbitMQ底层是通过Erlang架构来实现的,所以rabbitmqctl会启动Erlang节点,并基于Erlang
节点来使用Erlang系统连接RabbitMQ节点,在连接过程中需要正确的Erlang Cookie和节点名称,Erlang节点通过交换Erlang Cookie以获得
认证。

3 RabbitMQ集群模式
(1) 单机模式
(2) 普通集群模式(无高可用性)
(3) 镜像集群模式(高可用性),最常用的集群模式

4 RabbitMQ节点类型
(1) RAM node
只保存状态到内存。内存节点将所有的队列、交换机、绑定、用户、权限和vhost的元数据定义存储在内存中,好处是可以使得像交换机和队列声明等操
作更加的快速。
(2) Disk node
将元数据存储在磁盘中。单节点系统只允许磁盘类型的节点,防止重启RabbitMQ的时候,丢失系统的配置信息。
(3) 内存节点虽然不写入磁盘,但是它执行比磁盘节点要快。RabbitMQ集群中,只需要一个磁盘节点来保存状态就足够了;如果集群中只有内存节点,
那么不能停止它们,否则所有的状态,消息等都会丢失。
(4) RabbitMQ要求在集群中至少有一个磁盘节点,所有其他节点可以是内存节点,当节点加入或者离开集群时,必须要将该变更通知到至少一个磁盘
节点。如果集群中唯一的一个磁盘节点崩溃的话,集群仍然可以保持运行,但是无法进行其他操作(增删改查),直到节点恢复。解决方案:设置两个磁
盘节点,至少有一个是可用的,可以保存元数据的更改。
(5) 为保证数据持久性,当前实验所有node节点跑在disk模式。
2.2 yaml配置文件
1 说明
rabbitmq集群运行在rabbitmq-cluster命名空间下,采用StatefulSet与Headless Service模式部署有状态的RabbitMQ集群。
[root@k8s-master1 ~]# mkdir -p rabbitmq-cluster
[root@k8s-master1 ~]# cd rabbitmq-cluster/
[root@k8s-master1 rabbitmq-cluster]# ls -l
total 0
# rabbitmq集群部署文件
-rw-r--r-- 1 root root 0 Feb 16 14:38 rabbitmq-cluster.yml

2 rabbitmq-cluster.yml
[root@k8s-master1 rabbitmq-cluster]# cat rabbitmq-cluster.yml
---
apiVersion: v1
kind: Service
metadata:
  name: rabbitmq-cluster-management
  namespace: rabbitmq-cluster
  labels:
    app: rabbitmq
spec:
  ports:
  - port: 15672
    name: http
    nodePort: 30072
  selector:
    app: rabbitmq
  type: NodePort
---
apiVersion: v1
kind: Service
metadata:
  name: rabbitmq-cluster
  namespace: rabbitmq-cluster
  labels:
    app: rabbitmq
spec:
  ports:
  - port: 5672
    name: amqp
  - port: 4369
    name: epmd
  - port: 25672
    name: rabbitmq-dist
  clusterIP: None
  selector:
    app: rabbitmq
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  namespace: rabbitmq-cluster
  name: rabbitmq-cluster
spec:
  serviceName: rabbitmq-cluster
  replicas: 3
  selector:
    matchLabels:
      app: rabbitmq
  template:
    metadata:
      labels:
        app: rabbitmq
    spec:
      containers:
      - name: rabbitmq
        image: rabbitmq:3.7.26-management
        lifecycle:
          postStart:
            exec:
              command:
              - /bin/sh
              - -c
              - >
                if [ -z "$(grep rabbitmq-cluster.rabbitmq-cluster.svc.cluster.local /etc/resolv.conf)" ]; then
                  cp -a /etc/resolv.conf /etc/resolv.conf.bak;
                  sed "s/^search \([^ ]\+\)/search rabbitmq-cluster.\1 \1/" /etc/resolv.conf > /etc/resolv.conf.new;
                  cat /etc/resolv.conf.new > /etc/resolv.conf;
                  rm /etc/resolv.conf.new;
                fi;
                until rabbitmqctl node_health_check; do sleep 1; done;
                if [ -z "$(rabbitmqctl cluster_status | grep rabbitmq-cluster-0)" ]; then
                  touch /gotit
                  rabbitmqctl stop_app;
                  rabbitmqctl reset;
                  rabbitmqctl join_cluster rabbit@rabbitmq-cluster-0;
                  rabbitmqctl start_app;
                else
                  touch /notget
                fi;
        env:
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: RABBITMQ_ERLANG_COOKIE
          value: "YZSDHWMFSMKEMBDHSGGZ"
        - name: RABBITMQ_NODENAME
          value: "rabbit@$(MY_POD_NAME)"
        ports:
        - name: http
          protocol: TCP
          containerPort: 15672
        - name: amqp
          protocol: TCP
          containerPort: 5672
        livenessProbe:
          tcpSocket:
            port: amqp
          initialDelaySeconds: 5
          timeoutSeconds: 5
          periodSeconds: 10
        readinessProbe:
          tcpSocket:
            port: amqp
          initialDelaySeconds: 15
          timeoutSeconds: 5
          periodSeconds: 20
        volumeMounts:
        - name: rabbitmq-data
          mountPath: /var/lib/rabbitmq
  volumeClaimTemplates:
  - metadata:
      name: rabbitmq-data
      #annotations:
      #  volume.beta.kubernetes.io/storage-class: "rabbitmq-nfs-storage"
    spec:
      storageClassName: "managed-nfs-storage"
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 10Gi

(1) rabbitmq端口号说明
4369    # erlang 发现端口
5672    # client 端通信端口
15672   # 管理界面 ui 端口
25672   # server 间内部通信端口
访问 RabbitMQ 管理界面:  http://IP:15672/
连接 RabbitMQ 用client端通信端口:  amqp://guest:guest@localhost:5672/

(2) yml文件中的脚本说明
1) 修改域名解析
if [ -z "$(grep rabbitmq-cluster.rabbitmq-cluster.svc.cluster.local /etc/resolv.conf)" ]; then
  cp -a /etc/resolv.conf /etc/resolv.conf.bak;
  sed "s/^search \([^ ]\+\)/search rabbitmq-cluster.\1 \1/" /etc/resolv.conf > /etc/resolv.conf.new;
  cat /etc/resolv.conf.new > /etc/resolv.conf;
  rm /etc/resolv.conf.new;
fi;

说明:
因为rabbitmq节点加入集群需要使用主机名,添加rabbitmq集群所在svc的域名配置,方便rabbitmq直接使用主机名进行访问,/etc/resolv.conf
文件修改前后变化如下图:

图示: image-20220218123552455

2) 将rabbitmq节点加入集群
until rabbitmqctl node_health_check; do sleep 1; done;
if [ -z "$(rabbitmqctl cluster_status | grep rabbitmq-cluster-0)" ]; then
  touch /gotit
  rabbitmqctl stop_app;
  rabbitmqctl reset;
  rabbitmqctl join_cluster rabbit@rabbitmq-cluster-0;
  rabbitmqctl start_app;
else
  touch /notget
fi;

说明:
rabbitmq服务启动并且健康检查通过后,将该rabbitmq节点以rabbitmq-cluster-0主机名为基准加入集群中。

2.3 部署
1 创建命名空间
[root@k8s-master1 rabbitmq-cluster]# kubectl create namespace rabbitmq-cluster

2 应用配置文件
[root@k8s-master1 rabbitmq-cluster]# kubectl apply -f rabbitmq-cluster.yml
service/rabbitmq-cluster-management created
service/rabbitmq-cluster created
statefulset.apps/rabbitmq-cluster created
3 查看 rabbitmq 集群 pod
[root@k8s-master1 rabbitmq-cluster]# kubectl get pod -n rabbitmq-cluster

图示: image-20220217175224900

4 查看 rabbitmq 集群 pvc、pv
[root@k8s-master1 rabbitmq-cluster]# kubectl get pvc -n rabbitmq-cluster
[root@k8s-master1 rabbitmq-cluster]# kubectl get pv

图示: image-20220217175350113

5 查看 rabbitmq 集群 svc
[root@k8s-master1 rabbitmq-cluster]# kubectl get svc,ep -n rabbitmq-cluster

图示: image-20220217175504676

6 查看 rabbitmq 集群 nfs 共享存储
[root@k8s_nfs ~]# ls -l /ifs/kubernetes/
[root@k8s_nfs ~]# ls -l /ifs/kubernetes/*/

# RabbitMQ的三个容器节点的.erlang.cookie内容是一致的
[root@k8s_nfs ~]# cat /ifs/kubernetes/*/.erlang.cookie

图示: image-20220217175726540

7 验证RabbitMQ集群
登录 rabbitmq-0|1|2 容器查看集群状态
[root@k8s-master1 rabbitmq-cluster]# kubectl exec -it pod/rabbitmq-cluster-0 -n rabbitmq-cluster -- bash
root@rabbitmq-cluster-0:/# rabbitmqctl cluster_status

说明: 可以看到rabbitmq集群三节点运行正常。

图示: image-20220217180048078

8 访问 rabbitmq 集群的 web 界面,查看集群的状态
访问 http://<nodeip>:30072,用户名和密码都是 guest。

图示: image-20220217180548962

2.4 测试
1 说明
模拟RabbitMQ节点故障,重启其中的一个node节点,比如rabbitmq-cluster-0,然后观察集群状态。

2 删除rabbitmq-cluster-0节点
[root@k8s-master1 rabbitmq-cluster]# kubectl delete pod rabbitmq-cluster-0 -n rabbitmq-cluster
pod "rabbitmq-cluster-0" deleted

说明:
此时在web界面查看集群的状态,先后经历了三个状态,红色表示节点故障,黄色表示节点恢复中(暂不可用),绿色表示节点运行正常。

3 查看pod,发现rabbitmq-cluster-0节点30s左右重启成功
[root@k8s-master1 rabbitmq-cluster]# kubectl get pod -n rabbitmq-cluster
NAME                 READY   STATUS   RESTARTS   AGE
rabbitmq-cluster-0   1/1     Running   0         30s
rabbitmq-cluster-1   1/1     Running   0         30m
rabbitmq-cluster-2   1/1     Running   0         30m

4 查看RabbitMQ集群状态
发现rabbitmq集群各节点状态正常。
# kubectl exec -it rabbitmq-cluster-1 -n rabbitmq-cluster -- rabbitmqctl cluster_status
Cluster status of node rabbit@rabbitmq-cluster-1 ...
[{nodes,[{disc,['rabbit@rabbitmq-cluster-0','rabbit@rabbitmq-cluster-1',
               'rabbit@rabbitmq-cluster-2']}]},
{running_nodes,['rabbit@rabbitmq-cluster-0','rabbit@rabbitmq-cluster-2',
                 'rabbit@rabbitmq-cluster-1']},
{cluster_name,<<"rabbit@rabbitmq-cluster-0.rabbitmq-cluster.rabbitmq-cluster.svc.cluster.local">>},
{partitions,[]},
{alarms,[{'rabbit@rabbitmq-cluster-0',[]},
         {'rabbit@rabbitmq-cluster-2',[]},
         {'rabbit@rabbitmq-cluster-1',[]}]}]
[root@k8s-master1 rabbitmq-cluster]#

5 客户端访问RabbitMQ集群地址
(1) 访问域名如下,端口为5672
# kubectl run -i --tty --image busybox:1.28.4 dns-test --restart=Never --rm /bin/sh
/ # nslookup rabbitmq-cluster.rabbitmq-cluster.svc.cluster.local
Server:   172.28.0.2
Address 1: 172.28.0.2 kube-dns.kube-system.svc.cluster.local

Name:     rabbitmq-cluster.rabbitmq-cluster.svc.cluster.local
Address 1: 172.27.36.88   rabbitmq-cluster-2.rabbitmq-cluster.rabbitmq-cluster.svc.cluster.local
Address 2: 172.27.169.155 rabbitmq-cluster-1.rabbitmq-cluster.rabbitmq-cluster.svc.cluster.local
Address 3: 172.27.36.87   rabbitmq-cluster-0.rabbitmq-cluster.rabbitmq-cluster.svc.cluster.local
/ #

(2) 连接方式
客户端可以连接RabbitMQ集群中的任意一个节点,如果一个节点故障,客户端自行重新连接到其他的可用节点,也就是说,RabbitMQ集群有"重连"机
制,但是这种集群连接方式对客户端不透明,不太建议这种连接方式。推荐方式,给客户端提供一个统一的透明的集群连接地址,在集群前面部署LVS或
Haproxy,通过四层负载均衡代理RabbitMQ的三个node节点的5672端口。

6 集群故障修复
[root@k8s-master1 rabbitmq-cluster]# kubectl delete -f rabbitmq-cluster.yml
[root@k8s_nfs ~]# rm -rf /ifs/kubernetes/*/*
[root@k8s-master1 rabbitmq-cluster]# kubectl apply -f rabbitmq-cluster.yml
posted @ 2022-02-18 14:05  云起时。  阅读(1149)  评论(0编辑  收藏  举报