Skip to the content.

在kubernetes中statefu方式安装rabbitmq集群

为何不用rabbitmq官方的RabbitMQ Cluster Operator? 因为官方的operator比较复杂,哪怕使用了bitnami的charts(helm), 比如需求是更改服务名称、更改mq的一个参数、每次重启pod存储目录不变。如果认为官方的更好用,下面文字可忽略

下面创建的rabbitmq集群,服务名为 rabbitmq-svc,namespace为 default,改为你自己所需要的service name,k8s集群中的rabbitmq,添加了rabbitmq_peer_discovery_k8s 插件,见 peer-discovery-k8s

statefulset需要使用动态pv,那么先创建pv,加入使用存储为glusterfs

三台gfs主机名称为:gfs1、gfs2、gfs3,在glusterfs主机创建volume

for i in {0..2};do gluster volume create mq-cluster${i} replica 3 transport tcp gfs1:/gfs/rabbitmq${i} gfs2:/gfs/rabbitmq${i} gfs3:/gfs/rabbitmq${i} force;done
for i in {0..2};do gluster volume start mq-cluster${i};done


不管用nas或者gfs,都需要创建pv,这里用gfs,接下来新建pv,

apiVersion: v1
kind: Endpoints
metadata:
  name: gfs-ep
  namespace: default
subsets:
- addresses:
  - ip: 192.168.3.100
  - ip: 192.168.3.101
  - ip: 192.168.3.102
  ports:
  - port: 10
    protocol: TCP
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-mq1
  namespace: default
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: "gfs-ep"
    path: "mq-cluster0"
    readOnly: false
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-mq2
  namespace: default
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: "gfs-ep"
    path: "mq-cluster1"
    readOnly: false
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-mq3
  namespace: default
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: "gfs-ep"
    path: "mq-cluster2"
    readOnly: false


设置RBAC

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: rabbitmq
  namespace: default
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rabbitmq
  namespace: default
rules:
- apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get"]
- apiGroups: [""]
  resources: ["events"]
  verbs: ["create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rabbitmq
  namespace: default
subjects:
- kind: ServiceAccount
  name: rabbitmq
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: rabbitmq



设置rabbitmq的配置,configmap

apiVersion: v1
kind: ConfigMap
metadata:
  name: rabbitmq-config
  namespace: default
data:
  enabled_plugins: |
    [rabbitmq_peer_discovery_k8s, rabbitmq_management, rabbitmq_prometheus].
  rabbitmq.conf: |
    cluster_formation.peer_discovery_backend = k8s
    cluster_formation.k8s.host = kubernetes.default.svc.cluster.local
    cluster_formation.k8s.address_type = hostname
    cluster_formation.k8s.service_name = rabbitmq-svc
    cluster_formation.k8s.hostname_suffix = .rabbitmq-svc.default.svc.cluster.local
    queue_master_locator=min-masters
    cluster_formation.node_cleanup.interval = 30
    loopback_users.guest = false
    vm_memory_high_watermark.relative = 0.6

最后,创建rabbitmq的statefulset

kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: rabbitmq
  namespace: default
spec:
  serviceName: rabbitmq-svc
  replicas: 3
  selector:
    matchLabels:
      app: rabbitmq
  template:
    metadata:
      labels:
        app: rabbitmq
    spec:
      initContainers:
      - name: "rabbitmq-config"
        image: busybox:1.32.0
        volumeMounts:
        - name: rabbitmq-config
          mountPath: /tmp/rabbitmq
        - name: rabbitmq-config-rw
          mountPath: /etc/rabbitmq
        command:
        - sh
        - -c
        - cp /tmp/rabbitmq/rabbitmq.conf /etc/rabbitmq/rabbitmq.conf && echo '' >> /etc/rabbitmq/rabbitmq.conf;
          cp /tmp/rabbitmq/enabled_plugins /etc/rabbitmq/enabled_plugins
      volumes:
      - name: rabbitmq-config
        configMap:
          name: rabbitmq-config
          optional: false
          items:
          - key: enabled_plugins
            path: "enabled_plugins"
          - key: rabbitmq.conf
            path: "rabbitmq.conf"
      - name: rabbitmq-config-rw
        emptyDir: {}
      serviceAccount: rabbitmq
      containers:
      - name: rabbitmq      
        image: rabbitmq:3.8.5
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            cpu: 4
            memory: 2048Mi
          requests:
            cpu: 0.1
            memory: 128Mi
        ports:
            - name: epmd
              protocol: TCP
              containerPort: 4369
            - name: amqp
              protocol: TCP
              containerPort: 5672
            - name: http
              protocol: TCP
              containerPort: 15672
        readinessProbe:
          httpGet:
            path: /
            port: 15672
          initialDelaySeconds: 5
          periodSeconds: 15
          timeoutSeconds: 10
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: RABBITMQ_NODENAME
          value: rabbit@$(POD_NAME).rabbitmq-svc.$(POD_NAMESPACE).svc.cluster.local
        - name: RABBITMQ_USE_LONGNAME
          value: "true"
        - name: RABBITMQ_DEFAULT_VHOST
          value: 'rabbitmq_vhost'
        - name: RABBITMQ_DEFAULT_USER
          value: admin
        - name: RABBITMQ_DEFAULT_PASS
          value: rabbitmq
        - name: RABBITMQ_LOGS
          value: /var/lib/rabbitmq/rabbitmq/rabbitmq.log
        - name: RABBITMQ_SASL_LOGS
          value: /var/lib/rabbitmq/rabbitmq/rabbitmq-sasl.log
        - name: TZ
          value: 'Asia/Shanghai'
        - name: RABBITMQ_ERLANG_COOKIE
          value: RABBITMQ-SECRET-KEY
        volumeMounts:
          - name: rabbitmq-config-rw
            mountPath: "/etc/rabbitmq"
          - name: mq-data
            mountPath: /var/lib/rabbitmq
      imagePullSecrets:
        - name: harbor-bbotte
  volumeClaimTemplates:
  - metadata:
      name: mq-data
    spec:
      accessModes: [ "ReadWriteMany" ]
      resources:
        requests:
          storage: 10Gi



最后配置rabbitmq的service

kind: Service
apiVersion: v1
metadata:
  name: rabbitmq-svc
  namespace: default
spec:
  type: NodePort
  selector:
    app: rabbitmq
  ports:
  - port: 5672
    name: mq5672
    targetPort: 5672
    nodePort: 32701
  - port: 15672
    name: mqweb
    targetPort: 15672
    nodePort: 30572
  - port: 4369
    name: epmd
    targetPort: 4369
  - port: 25672
    name: mq25672
    targetPort: 25672

这时候,3个mq的pod已经创建,那么让这3个pod成为一个集群,进入rabbitmq-1

kubectl exec -it rabbitmq-1 bash
rabbitmqctl stop_app ;rabbitmqctl join_cluster --disc rabbit@rabbitmq-0.rabbitmq-svc.default.svc.cluster.local ;rabbitmqctl start_app

进入rabbitmq-2,并配置ha策略

kubectl exec -it rabbitmq-2 bash
root@rabbitmq-2:/# rabbitmqctl stop_app ;rabbitmqctl join_cluster --disc rabbit@rabbitmq-0.rabbitmq-svc.default.svc.cluster.local ;rabbitmqctl start_app

root@rabbitmq-2:/# rabbitmqctl --erlang-cookie ${RABBITMQ_ERLANG_COOKIE} set_policy --vhost rabbitmq_vhost mq-ha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

root@rabbitmq-2:/#  查看rabbitmq集群状态
root@rabbitmq-2:/# rabbitmqctl cluster_status|head -n 20
Cluster status of node rabbit@rabbitmq-2.uclass-rabbitmq-svc.default.svc.cluster.local ...
Basics

Cluster name: rabbit@rabbitmq-0.uclass-rabbitmq-svc.default.svc.cluster.local

Disk Nodes

rabbit@rabbitmq-0.uclass-rabbitmq-svc.default.svc.cluster.local
rabbit@rabbitmq-1.uclass-rabbitmq-svc.default.svc.cluster.local
rabbit@rabbitmq-2.uclass-rabbitmq-svc.default.svc.cluster.local

Running Nodes

rabbit@rabbitmq-0.uclass-rabbitmq-svc.default.svc.cluster.local
rabbit@rabbitmq-1.uclass-rabbitmq-svc.default.svc.cluster.local
rabbit@rabbitmq-2.uclass-rabbitmq-svc.default.svc.cluster.local

Versions

rabbit@rabbitmq-0.uclass-rabbitmq-svc.default.svc.cluster.local: RabbitMQ 3.8.5 on Erlang 23.0.3

last,删除rabbitmq集群:

kubectl delete -f rabbitmq-statefulset.yaml  还有 rbac,configmap的yaml
kubectl delete pvc/mq-data-rabbitmq-2
kubectl delete pvc/mq-data-rabbitmq-1
kubectl delete pvc/mq-data-rabbitmq-0
kubectl delete pv/pv-mq3
kubectl delete pv/pv-mq2
kubectl delete pv/pv-mq1

参考 diy-kubernetes-examples

2021年01月11日 于 linux工匠 发表