RabbitMQ 消息队列

RabbitMQ支持单机部署,也提供了”高可用”的集群部署方式,以提升性能和(或)可用性。

RabbitMQ支持两种形式的集群模式:

  • 普通模式: 默认的模式。消息队列的数据结构存在于每个节点上,但实际消息只存储于某一个节点上。这种模式的优点是性能较高。缺点是,一旦存储数据的节点挂掉,消息就暂时不可用了,需要节点启动后才能恢复。
  • 镜像模式: 在普通模式的基础上可配置需要镜像的队列。配置队列后,消息数据会自动同步到集群中的每个节点上。该模式的优点是可用性高,缺点是性能相对较低。

在本节,我们将首先配置普通模式的集群,然后配置镜像队列。

Kubernetes下配置RabbitMQ集群

与Memcached类似,RabbitMQ集群中的节点,是相互独立的,而不是可替代的,因此我们也使用StatefulSet。

然而,RabbitMQ比Memcached更为复杂,他需要磁盘存储,即在StatefulSet上的Volume。这种情况下,是无法直接创建Volume挂载点的,而是需要先手动创建Persistent Volume(简称PV),然后再通过Persistent Volume Claim(简称PVC)去关联创建可用的PV。上述过程可以参考Kubernetes的Persistent Volume文档

我们首先创建3个PV, pvs.yaml:

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: pv001
  5. spec:
  6. storageClassName: standard
  7. accessModes:
  8. - ReadWriteOnce
  9. capacity:
  10. storage: 20Gi
  11. hostPath:
  12. path: /data/pv001/
  13. ---
  14. apiVersion: v1
  15. kind: PersistentVolume
  16. metadata:
  17. name: pv002
  18. spec:
  19. storageClassName: standard
  20. accessModes:
  21. - ReadWriteOnce
  22. capacity:
  23. storage: 20Gi
  24. hostPath:
  25. path: /data/pv002/
  26. ---
  27. apiVersion: v1
  28. kind: PersistentVolume
  29. metadata:
  30. name: pv003
  31. spec:
  32. storageClassName: standard
  33. accessModes:
  34. - ReadWriteOnce
  35. capacity:
  36. storage: 20Gi
  37. hostPath:
  38. path: /data/pv003/

在这里,我们使用的是minikube做演示,因而直接创建基于路径的Volume,在实际生产中,你可能需要创建支持自动迁移的Volume,具体可以参考Storage Classes

我们应用一下:

  1. kubectl apply -f pvs.yaml
  2. persistentvolume "pv001" created
  3. persistentvolume "pv002" created
  4. persistentvolume "pv003" created

在创建RabbitMQ集群之前,我们先要针对rabnbitmq这个metadata修改rbac。rbac是Kubernetes的安全性访问限制,具体原因可以参考这个Issue

rabbitmq-rbac.yaml:

  1. ---
  2. apiVersion: v1
  3. kind: ServiceAccount
  4. metadata:
  5. name: rabbitmq
  6. ---
  7. kind: Role
  8. apiVersion: rbac.authorization.k8s.io/v1beta1
  9. metadata:
  10. name: rabbitmq
  11. rules:
  12. - apiGroups: [""]
  13. resources: ["endpoints"]
  14. verbs: ["get"]
  15. ---
  16. kind: RoleBinding
  17. apiVersion: rbac.authorization.k8s.io/v1beta1
  18. metadata:
  19. name: rabbitmq
  20. roleRef:
  21. apiGroup: rbac.authorization.k8s.io
  22. kind: Role
  23. name: rabbitmq
  24. subjects:
  25. - kind: ServiceAccount
  26. name: rabbitmq

上述修改了rabbitmq的ServiceSccount、Role、RoleBinding默认安全设置,简要来说是允许其访问get和endpoints这两个Kubernetes提供的API。

我们应用上述修改,修改成功:

  1. kubectl apply -f ./rabbitmq-rbac.yaml
  2. serviceaccount "rabbitmq" configured
  3. role.rbac.authorization.k8s.io "rabbitmq" configured
  4. rolebinding.rbac.authorization.k8s.io "rabbitmq" configured

在创建了pv,修改了rbac后,可以创建rabbitmq集群了,我们来看一下描述文件,rabbitmq-service.yaml:

  1. kind: Service
  2. apiVersion: v1
  3. metadata:
  4. name: rabbitmq
  5. labels:
  6. app: rabbitmq
  7. spec:
  8. type: NodePort
  9. ports:
  10. - name: http
  11. protocol: TCP
  12. port: 15672
  13. targetPort: 15672
  14. nodePort: 31672
  15. selector:
  16. app: rabbitmq
  17. ---
  18. apiVersion: apps/v1
  19. kind: StatefulSet
  20. metadata:
  21. name: rabbitmq
  22. spec:
  23. selector:
  24. matchLabels:
  25. app: rabbitmq
  26. serviceName: rabbitmq
  27. replicas: 3
  28. template:
  29. metadata:
  30. labels:
  31. app: rabbitmq
  32. spec:
  33. serviceAccountName: rabbitmq
  34. terminationGracePeriodSeconds: 10
  35. containers:
  36. - name: rabbitmq-autocluster
  37. image: pivotalrabbitmq/rabbitmq-autocluster
  38. ports:
  39. - name: http
  40. protocol: TCP
  41. containerPort: 15672
  42. - name: amqp
  43. protocol: TCP
  44. containerPort: 5672
  45. livenessProbe:
  46. exec:
  47. command: ["rabbitmqctl", "status"]
  48. initialDelaySeconds: 30
  49. timeoutSeconds: 5
  50. readinessProbe:
  51. exec:
  52. command: ["rabbitmqctl", "status"]
  53. initialDelaySeconds: 10
  54. timeoutSeconds: 5
  55. volumeMounts:
  56. - mountPath: /var/lib/rabbitmq/mnesia
  57. name: rabbitmq-pvc
  58. env:
  59. - name: MY_POD_IP
  60. valueFrom:
  61. fieldRef:
  62. fieldPath: status.podIP
  63. - name: RABBITMQ_USE_LONGNAME
  64. value: "true"
  65. - name: RABBITMQ_NODENAME
  66. value: "rabbit@$(MY_POD_IP)"
  67. - name: AUTOCLUSTER_TYPE
  68. value: "k8s"
  69. - name: AUTOCLUSTER_DELAY
  70. value: "10"
  71. - name: K8S_ADDRESS_TYPE
  72. value: "ip"
  73. - name: AUTOCLUSTER_CLEANUP
  74. value: "true"
  75. - name: CLEANUP_WARN_ONLY
  76. value: "false"
  77. volumeClaimTemplates:
  78. - metadata:
  79. name: rabbitmq-pvc
  80. spec:
  81. storageClassName: standard
  82. accessModes:
  83. - ReadWriteOnce
  84. resources:
  85. requests:
  86. storage: 20Gi

解释一下上面的描述文件:

  • 创建了Headless Service用于暴露管理界面的Web端口31672。这里主要是为了演示,在实际应用中,这个可能是没必要的。
  • 创建了rabbitmq的StatefulSet,含有3个节点,其中每个节点通过livenessProbe和readinessProbe检查可用性。
  • 使用volumeClaimTemplates自动生成volumeClaim,这里的template即模板,会自动给StatefulSet中的每一个节点创建一个Volume Claim,命名为rabbitmq-pvc-0/1/2

下面我们来应用下上面的描述:

  1. kubectl apply -f ./rabbitmq-service.yaml
  2. service "rabbitmq" created
  3. statefulset.apps "rabbitmq" created

稍过一会后,我们来看一下Web服务器的管理界面,http://192.168.99.100,用户名密码都是guest:

查看RabbitMQ集群

登录成功后,如上图所示。不难发现,已经成功启动了3个节点,并组成了集群,至此,我们的RabbitMQ基本集群配置成功。

配置镜像集群

下面,我们来配置镜像策略,在Web管理工具上点击”Admin” -> “Policies” -> “Add / update a policy”,如下填写:

  • Name: ha_mirror_queue
  • Pattern: ^
  • Apply to: All exchange and queues
  • Defination:
    • ha-mode: all

添加好后点击”Add”

配置好后,我们尝试创建一个Queue,在Web管理工具点击”Queues” -> “Add queue”,name写test,其他保持默认,最后点击”Add queue”。

添加完成后,可以发现队列有一个”+2”的标志,如下图所示。这个+2意思是队列有额外的2个备份(主1+镜2一共3个节点),镜像配置成功。

查看RabbitMQ镜像队列

至此,我们已经完成了RabbitMQ的集群配置、镜像队列配置。

关于Rabbit MQ的高可用、集群的更相信信息,可以查看官方文档:RabbitMQ 集群