• 基于k8s手动部署rabbitmq集群


    1、RabbitMQ介绍

    RabbitMQ是实现了高级消息队列协议AMQP的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。AMQPAdvanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言灯条件的限制

    AMQP具有如下的特性:

    • 可靠性Reliablity:使用了一些机制来保证可靠性,比如持久化、传输确认、发布确认
    • 灵活的路由Flexible Routing:在消息进入队列之前,通过Exchange来路由消息。对于典型的路由功能,Rabbit已经提供了一些内置的Exchange来实现。针对更复杂的路由功能,可以将多个Exchange绑定在一起,也通过插件机制实现自己的Exchange
    • 消息集群Clustering:多个RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker
    • 高可用Highly Avaliable Queues:队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用
    • 多种协议Multi-protocol:支持多种消息队列协议,如STOMPMQTT
    • 多种语言客户端Many Clients:几乎支持所有常用语言,比如Java.NETRuby
    • 管理界面Management UI:提供了易用的用户界面,使得用户可以监控和管理消息Broker的许多方面
    • 跟踪机制Tracing:如果消息异常,RabbitMQ提供了消息的跟踪机制,使用者可以找出发生了什么
    • 插件机制Plugin System:提供了许多插件,来从多方面进行扩展,也可以编辑自己的插件

    2、RabbitMQ的持久化和镜像队列

    RabbitMQ持久化分为ExchangeQueueMessage

    • ExchangeQueue持久化:指持久化ExchangeQueue元数据,持久化的是自身,服务宕机ExchangeQueue自身就没有了
    • Message持久化:顾名思义就是把每一条消息体持久化,服务宕机,消息不丢失

    RabbitMQ的队列Queue镜像,指master node在接受到请求后,会同步到其他节点上,以此来保证高可用。在confirm模式下,具体过程如下

    clientpublisher发送消息 –> master node接到消息 –> master node将消息持久化到磁盘 –> 将消息异步发送给其他节点 –> master将ack返回给client publisher
    

    3、RabbitMQ集群在k8s中的部署

    RabbitMQ以集群的方式部署在k8s中,前提是RabbitMQ的每个节点都能像传统方式一样进行相互的服务发现。因此RabbitMQk8s集群中通过rabbitmq_peer_discovery_k8s plugink8s apiserver进行交互,获取各个服务的URL,且RabbitMQk8s集群中必须用statefulsetheadless service进行匹配

    需要注意的是rabbitmq_peer_discovery_k8sRabbitMQ官方基于第三方开源项目rabbitmq-autocluster开发,对3.7.X及以上版本提供的Kubernetes下的对等发现插件,可实现rabbitmq集群在k8s中的自动化部署,因此低于3.7.X版本请使用rabbitmq-autocluster

    3.1 环境介绍

    本文部署的版本是3.8.3

    默认部署在default命名空间下,

    持久化存储为storageclass动态存储,底层为nfs提供

    镜像地址rabbitmq:3.8.3-management

    以下yaml参考自官方示例https://github.com/rabbitmq/diy-kubernetes-examples

    3.2 创建configmap

    01-rabbitmq-configmap.yaml

    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: rabbitmq-cluster-config
      namespace: default
      labels:
        addonmanager.kubernetes.io/mode: Reconcile
    data:
        enabled_plugins: |
          [rabbitmq_management,rabbitmq_peer_discovery_k8s].
        rabbitmq.conf: |
          default_user = admin
          default_pass = 123!@#
          ## Cluster formation. See https://www.rabbitmq.com/cluster-formation.html to learn more.
          cluster_formation.peer_discovery_backend = rabbit_peer_discovery_k8s
          cluster_formation.k8s.host = kubernetes.default.svc.cluster.local
          ## Should RabbitMQ node name be computed from the pod's hostname or IP address?
          ## IP addresses are not stable, so using [stable] hostnames is recommended when possible.
          ## Set to "hostname" to use pod hostnames.
          ## When this value is changed, so should the variable used to set the RABBITMQ_NODENAME
          ## environment variable.
          cluster_formation.k8s.address_type = hostname
          ## How often should node cleanup checks run?
          cluster_formation.node_cleanup.interval = 30
          ## Set to false if automatic removal of unknown/absent nodes
          ## is desired. This can be dangerous, see
          ##  * https://www.rabbitmq.com/cluster-formation.html#node-health-checks-and-cleanup
          ##  * https://groups.google.com/forum/#!msg/rabbitmq-users/wuOfzEywHXo/k8z_HWIkBgAJ
          cluster_formation.node_cleanup.only_log_warning = true
          cluster_partition_handling = autoheal
          ## See https://www.rabbitmq.com/ha.html#master-migration-data-locality
          queue_master_locator=min-masters
          ## See https://www.rabbitmq.com/access-control.html#loopback-users
          loopback_users.guest = false
          cluster_formation.randomized_startup_delay_range.min = 0
          cluster_formation.randomized_startup_delay_range.max = 2
          # default is rabbitmq-cluster's namespace
          # hostname_suffix
          cluster_formation.k8s.hostname_suffix = .rabbitmq-cluster.default.svc.cluster.local
          # memory
          vm_memory_high_watermark.absolute = 1GB
          # disk
          disk_free_limit.absolute = 2GB
    

    部分参数说明:

    • enabled_plugins:声明开启的插件名
    • default_pass/default_pass:声明用户名和密码(虽然有部分文章记录可以通过环境变量的方式声明,但是经测试,针对此版本如果指定了configmaprabbitmq的配置文件,声明的环境变量是没有用的,都需要在配置文件中指定)
    • cluster_formation.k8s.address_type:从k8s返回的Pod容器列表中计算对等节点列表,这里只能使用主机名,官方示例中是ip,但是默认情况下在k8spodip都是不固定的,因此可能导致节点的配置和数据丢失,后面的yaml中会通过引用元数据的方式固定pod的主机名。

    更多参数请参考官方文档,这里就不赘述了

    3.3 创建service

    02-rabbitmq-service.yaml

    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: rabbitmq-cluster
      name: rabbitmq-cluster
      namespace: default
    spec:
      clusterIP: None
      ports:
      - name: rmqport
        port: 5672
        targetPort: 5672
      selector:
        app: rabbitmq-cluster
    
    ---
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: rabbitmq-cluster
      name: rabbitmq-cluster-manage
      namespace: default
    spec:
      ports:
      - name: http
        port: 15672
        protocol: TCP
        targetPort: 15672
      selector:
        app: rabbitmq-cluster
      type: NodePort
    
    

    上面定义了两个Service,一个是rabbitmq的服务端口,一个是管理界面的端口,用户外部访问,这里通过NodePort方式进行暴露

    3.4 创建rbac授权

    前面的介绍中提到了RabbitMQ通过插件与k8s apiserver交互获得集群中节点相关信息,因此需要对其进行RBAC授权

    03-rabbitmq-rbac.yaml

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

    3.5 创建statefulset

    RabbitMQk8s中作为一个有状态应用进行部署,因此控制器类型为StatefulSetyaml中还定义了pvc相关内容

    04-rabbitmq-cluster-sts.yaml

    kind: StatefulSet
    apiVersion: apps/v1
    metadata:
      labels:
        app: rabbitmq-cluster
      name: rabbitmq-cluster
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: rabbitmq-cluster
      serviceName: rabbitmq-cluster
      template:
        metadata:
          labels:
            app: rabbitmq-cluster
        spec:
          containers:
          - args:
            - -c
            - cp -v /etc/rabbitmq/rabbitmq.conf ${RABBITMQ_CONFIG_FILE}; exec docker-entrypoint.sh
              rabbitmq-server
            command:
            - sh
            env:
            - name: TZ
              value: 'Asia/Shanghai'
            - name: RABBITMQ_ERLANG_COOKIE
              value: 'SWvCP0Hrqv43NG7GybHC95ntCJKoW8UyNFWnBEWG8TY='
            - name: K8S_SERVICE_NAME
              value: rabbitmq-cluster
            - name: POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: RABBITMQ_USE_LONGNAME
              value: "true"
            - name: RABBITMQ_NODENAME
              value: rabbit@$(POD_NAME).$(K8S_SERVICE_NAME).$(POD_NAMESPACE).svc.cluster.local
            - name: RABBITMQ_CONFIG_FILE
              value: /var/lib/rabbitmq/rabbitmq.conf
            image: rabbitmq:3.8.3-management
            imagePullPolicy: IfNotPresent
            livenessProbe:
              exec:
                command:
                - rabbitmq-diagnostics
                - status
              # See https://www.rabbitmq.com/monitoring.html for monitoring frequency recommendations.
              initialDelaySeconds: 60
              periodSeconds: 60
              timeoutSeconds: 15
            name: rabbitmq
            ports:
            - containerPort: 15672
              name: http
              protocol: TCP
            - containerPort: 5672
              name: amqp
              protocol: TCP
            readinessProbe:
              exec:
                command:
                - rabbitmq-diagnostics
                - status
              initialDelaySeconds: 20
              periodSeconds: 60
              timeoutSeconds: 10
            volumeMounts:
            - mountPath: /etc/rabbitmq
              name: config-volume
              readOnly: false
            - mountPath: /var/lib/rabbitmq
              name: rabbitmq-storage
              readOnly: false
            - name: timezone
              mountPath: /etc/localtime
              readOnly: true
          serviceAccountName: rabbitmq-cluster
          terminationGracePeriodSeconds: 30
          volumes:
          - name: config-volume
            configMap:
              items:
              - key: rabbitmq.conf
                path: rabbitmq.conf
              - key: enabled_plugins
                path: enabled_plugins
              name: rabbitmq-cluster-config
          - name: timezone
            hostPath:
              path: /usr/share/zoneinfo/Asia/Shanghai
      volumeClaimTemplates:
      - metadata:
          name: rabbitmq-storage
        spec:
          accessModes:
          - ReadWriteMany
          storageClassName: "managed-nfs-storage"
          resources:
            requests:
              storage: 2Gi
    

    3.6 部署检查

    ➜  rabbitmq-cluster pwd
    /Users/ssgeek/Documents/k8s-manifests/rabbitmq-cluster
    ➜  rabbitmq-cluster ls
    01-rabbitmq-configmap.yaml   02-rabbitmq-service.yaml     03-rabbitmq-rbac.yaml        04-rabbitmq-cluster-sts.yaml
    ➜  rabbitmq-cluster kubectl apply -f .
    configmap/rabbitmq-cluster-config created
    service/rabbitmq-cluster created
    service/rabbitmq-cluster-manage created
    serviceaccount/rabbitmq-cluster created
    role.rbac.authorization.k8s.io/rabbitmq-cluster created
    rolebinding.rbac.authorization.k8s.io/rabbitmq-cluster created
    statefulset.apps/rabbitmq-cluster created
    

    等待一段时间,查看创建的相关资源

    ➜  rabbitmq-cluster kubectl get po,sts -l app=rabbitmq-cluster
    NAME                     READY   STATUS    RESTARTS   AGE
    pod/rabbitmq-cluster-0   1/1     Running   0          3m22s
    pod/rabbitmq-cluster-1   1/1     Running   0          2m18s
    pod/rabbitmq-cluster-2   1/1     Running   0          2m23s
    
    NAME                                READY   AGE
    statefulset.apps/rabbitmq-cluster   3/3     3m25s
    

    查看日志,从日志的最后部分观察集群建立的状态

    ➜  rabbitmq-cluster kubectl logs -f rabbitmq-cluster-0
    '/etc/rabbitmq/rabbitmq.conf' -> '/var/lib/rabbitmq/rabbitmq.conf'
    2021-02-17 03:30:39.445 [info] <0.9.0> Feature flags: list of feature flags found:
    2021-02-17 03:30:39.445 [info] <0.9.0> Feature flags:   [ ] drop_unroutable_metric
    2021-02-17 03:30:39.445 [info] <0.9.0> Feature flags:   [ ] empty_basic_get_metric
    2021-02-17 03:30:39.445 [info] <0.9.0> Feature flags:   [ ] implicit_default_bindings
    2021-02-17 03:30:39.445 [info] <0.9.0> Feature flags:   [ ] quorum_queue
    2021-02-17 03:30:39.445 [info] <0.9.0> Feature flags:   [ ] virtual_host_metadata
    2021-02-17 03:30:39.445 [info] <0.9.0> Feature flags: feature flag states written to disk: yes
    2021-02-17 03:30:39.544 [info] <0.269.0> ra: meta data store initialised. 0 record(s) recovered
    2021-02-17 03:30:39.547 [info] <0.274.0> WAL: recovering []
    2021-02-17 03:31:10.676 [info] <0.313.0> 
     Starting RabbitMQ 3.8.3 on Erlang 22.3.4.1
     Copyright (c) 2007-2020 Pivotal Software, Inc.
     Licensed under the MPL 1.1. Website: https://rabbitmq.com
    
      ##  ##      RabbitMQ 3.8.3
      ##  ##
      ##########  Copyright (c) 2007-2020 Pivotal Software, Inc.
      ######  ##
      ##########  Licensed under the MPL 1.1. Website: https://rabbitmq.com
    
      Doc guides: https://rabbitmq.com/documentation.html
      Support:    https://rabbitmq.com/contact.html
      Tutorials:  https://rabbitmq.com/getstarted.html
      Monitoring: https://rabbitmq.com/monitoring.html
    
      Logs: <stdout>
    
      Config file(s): /var/lib/rabbitmq/rabbitmq.conf
    
      Starting broker...2021-02-17 03:31:10.678 [info] <0.313.0> 
     node           : rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local
     home dir       : /var/lib/rabbitmq
     config file(s) : /var/lib/rabbitmq/rabbitmq.conf
     cookie hash    : H+IQL2spD4MDV4jPi7mMAg==
     log(s)         : <stdout>
     database dir   : /var/lib/rabbitmq/mnesia/rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local
    2021-02-17 03:31:10.695 [info] <0.313.0> Running boot step pre_boot defined by app rabbit
    
    ...省略中间内容
    
    2021-02-17 03:31:13.273 [info] <0.824.0> Statistics database started.
    2021-02-17 03:31:13.273 [info] <0.823.0> Starting worker pool 'management_worker_pool' with 3 processes in it
    2021-02-17 03:31:13.467 [info] <0.9.0> Server startup complete; 5 plugins started.
     * rabbitmq_peer_discovery_k8s
     * rabbitmq_management
     * rabbitmq_web_dispatch
     * rabbitmq_management_agent
     * rabbitmq_peer_discovery_common
     completed with 5 plugins.
    2021-02-17 03:32:30.060 [info] <0.566.0> node 'rabbit@rabbitmq-cluster-1.rabbitmq-cluster.default.svc.cluster.local' up
    2021-02-17 03:32:31.264 [info] <0.566.0> rabbit on node 'rabbit@rabbitmq-cluster-1.rabbitmq-cluster.default.svc.cluster.local' up
    2021-02-17 03:33:31.280 [info] <0.566.0> node 'rabbit@rabbitmq-cluster-2.rabbitmq-cluster.default.svc.cluster.local' up
    2021-02-17 03:33:32.627 [info] <0.566.0> rabbit on node 'rabbit@rabbitmq-cluster-2.rabbitmq-cluster.default.svc.cluster.local' up
    

    进入到pod中通过客户端查看集群状态

    ➜  rabbitmq-cluster kubectl exec -it rabbitmq-cluster-0 bash
    root@rabbitmq-cluster-0:/# rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local ...
    Basics
    
    Cluster name: rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local
    
    Disk Nodes
    
    rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local
    rabbit@rabbitmq-cluster-1.rabbitmq-cluster.default.svc.cluster.local
    rabbit@rabbitmq-cluster-2.rabbitmq-cluster.default.svc.cluster.local
    
    Running Nodes
    
    rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local
    rabbit@rabbitmq-cluster-1.rabbitmq-cluster.default.svc.cluster.local
    rabbit@rabbitmq-cluster-2.rabbitmq-cluster.default.svc.cluster.local
    
    Versions
    
    rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local: RabbitMQ 3.8.3 on Erlang 22.3.4.1
    rabbit@rabbitmq-cluster-1.rabbitmq-cluster.default.svc.cluster.local: RabbitMQ 3.8.3 on Erlang 22.3.4.1
    rabbit@rabbitmq-cluster-2.rabbitmq-cluster.default.svc.cluster.local: RabbitMQ 3.8.3 on Erlang 22.3.4.1
    
    Alarms
    
    (none)
    
    Network Partitions
    
    (none)
    
    Listeners
    
    Node: rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
    Node: rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
    Node: rabbit@rabbitmq-cluster-0.rabbitmq-cluster.default.svc.cluster.local, interface: [::], port: 15672, protocol: http, purpose: HTTP API
    Node: rabbit@rabbitmq-cluster-1.rabbitmq-cluster.default.svc.cluster.local, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
    Node: rabbit@rabbitmq-cluster-1.rabbitmq-cluster.default.svc.cluster.local, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
    Node: rabbit@rabbitmq-cluster-1.rabbitmq-cluster.default.svc.cluster.local, interface: [::], port: 15672, protocol: http, purpose: HTTP API
    Node: rabbit@rabbitmq-cluster-2.rabbitmq-cluster.default.svc.cluster.local, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
    Node: rabbit@rabbitmq-cluster-2.rabbitmq-cluster.default.svc.cluster.local, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
    Node: rabbit@rabbitmq-cluster-2.rabbitmq-cluster.default.svc.cluster.local, interface: [::], port: 15672, protocol: http, purpose: HTTP API
    
    Feature flags
    
    Flag: drop_unroutable_metric, state: enabled
    Flag: empty_basic_get_metric, state: enabled
    Flag: implicit_default_bindings, state: enabled
    Flag: quorum_queue, state: enabled
    Flag: virtual_host_metadata, state: enabled
    

    通过NodePort访问管理界面

    kubectl get svc -l app=rabbitmq-cluster
    NAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)           AGE
    rabbitmq-cluster          ClusterIP   None           <none>        5672/TCP          8m47s
    rabbitmq-cluster-manage   NodePort    10.1.239.191   <none>        15672:30888/TCP   8m47s
    

    到这里,在k8s中手动部署一个RabbitMQ集群就完成啦~

    参考:
    https://www.rabbitmq.com/cluster-formation.html
    https://github.com/rabbitmq/diy-kubernetes-examples

  • 相关阅读:
    okHttp源码解析------待续
    AS: Unsupported method: AndroidProject.getPluginGeneration().
    vue项目根据不同环境调用不同请求地址
    文字跑马灯(无缝衔接) CSS+JS完美实现
    data 和 computed 的区别
    ES6解构赋值
    flex布局
    token验证
    vue组件传值
    vue钩子函数
  • 原文地址:https://www.cnblogs.com/ssgeek/p/14426487.html
Copyright © 2020-2023  润新知