• 基于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

  • 相关阅读:
    51 Nod 1068 Bash游戏v3
    51 Nod Bash 游戏v2
    51 Nod 1073 约瑟夫环
    UVA 12063 Zeros and ones 一道需要好好体会的好题
    51 Nod 1161 Partial sums
    2018中国大学生程序设计竞赛
    UVA 11971 Polygon
    UVA 10900 So do you want to be a 2^n-aire?
    UVA 11346 Possibility
    python with as 的用法
  • 原文地址:https://www.cnblogs.com/ssgeek/p/14426487.html
Copyright © 2020-2023  润新知