Skip to content

RabbitMQ on Kubernetes 部署

在 Kubernetes 中部署 RabbitMQ 的完整指南:涵蓋 Cluster Operator、Helm (Bitnami)、TLS 設定、插件管理與自訂 Service 暴露方式。

概述

RabbitMQ 在 Kubernetes 上有兩種主流部署路徑:RabbitMQ Cluster OperatorBitnami Helm Chart。Cluster Operator 是官方推薦做法,以 RabbitmqCluster Custom Resource 描述叢集設定,具備良好的生命週期管理能力;Bitnami Helm Chart 則適用於 Azure Marketplace 環境,安裝快速但客製化彈性略低。

在 Kubernetes 上暴露 RabbitMQ 有多種方式演進。早期使用 NodePort 固定埠號,後來改為直接讓 Operator 管理的 Service Type 設為 LoadBalancer,最成熟的做法是:RabbitmqCluster 使用 ClusterIP,另外建立獨立的 LoadBalancer Service,這樣可以完全控制 IP 位址與埠號,不受 Operator 的 Service 管理邏輯限制。

核心內容

RabbitMQ Cluster Operator

Operator 安裝後,透過 RabbitmqCluster Custom Resource 宣告式定義叢集:

bash
kubectl apply -f https://github.com/rabbitmq/cluster-operator/releases/latest/download/cluster-operator.yml

RabbitmqCluster 資源支援的關鍵欄位:

  • spec.replicas:節點數量
  • spec.tls:TLS 設定(secretName、disableNonTLSListeners)
  • spec.service.type:Service 類型(ClusterIP / NodePort / LoadBalancer)
  • spec.persistence:持久化儲存設定
  • spec.rabbitmq.additionalConfig:以 rabbitmq.conf 格式的額外設定
  • spec.rabbitmq.additionalPlugins:啟用的插件清單
  • spec.resources:CPU/Memory 請求與限制
  • spec.override.service.spec.ports:自訂 Service 埠號(用於固定 NodePort)

TLS 設定

RabbitMQ 支援啟用 TLS 加密所有連線,並可強制關閉所有非 TLS 監聽器(disableNonTLSListeners: true)。憑證以 Kubernetes Secret 存放:

bash
kubectl create secret tls rabbitmq-tls-secret \
  --cert=server_certificate.pem \
  --key=server_key.pem \
  -n rabbitmq-system

開發環境可使用 tls-gen 快速產生無密碼憑證。啟用 TLS 後,MQTT 的非加密端口(1883)將自動失效,需使用加密的 MQTTS(8883)。

Service 暴露策略演進

階段做法適用場景
早期NodePort(固定埠號透過 override)本地 K8s 測試
中期Operator 管理的 LoadBalancer簡單 Azure 環境
推薦ClusterIP + 獨立 LoadBalancer Service生產環境(完全掌控 IP)

推薦做法的優勢:可以指定固定的 Azure Internal LB IP(service.beta.kubernetes.io/azure-load-balancer-ipv4),Operator 不會覆蓋這個獨立的 Service。

插件管理

透過 additionalPlugins 欄位啟用所需插件,例如 MQTT 支援與 Prometheus 監控:

yaml
rabbitmq:
  additionalPlugins:
    - rabbitmq_mqtt
    - rabbitmq_prometheus

插件 rabbitmq_prometheus 會開啟 /metrics 端點(Port 15691 for TLS),可被 Prometheus 直接抓取。

關鍵要點

  • Cluster Operator 是官方推薦做法,以 CR 管理 RabbitMQ 叢集生命週期
  • 生產環境建議:ClusterIP + 獨立 LoadBalancer Service,可固定 Azure Internal LB IP
  • TLS 需同時為 Management(15671)、AMQP(5671)、MQTT(8883)、Prometheus(15691)四個埠號啟用
  • disableNonTLSListeners: true 啟用後所有非加密連線(包括 MQTT 1883)將失效
  • consumer_timeout 建議設定避免長時間任務被強制斷線(預設值可能過短)

實際應用

RabbitMQ 在 AKS 上透過 Internal LoadBalancer 固定 IP(10.30.196.40)對內部服務暴露,搭配 TLS 加密確保傳輸安全。Python 應用程式使用 Pika 函式庫連線時,需載入 CA 憑證建立 TLS Context。監控方面,啟用 rabbitmq_prometheus 插件後配合 RabbitMQ Exporter 部署 將指標匯入 Prometheus

部署設定參考

以下為實際部署時使用的完整設定,供日後查詢與複製使用。

環境參數

項目
Namespacerabbitmq-system
StorageClassmanaged-csi(AKS)/ azurefile-csi
PVC 大小10Gi
預設帳號admin
預設密碼Bed200@Passw0rd
consumer_timeout21600000(ms,6 小時)
Azure Internal LB IP10.30.196.40
CPU 請求/限制2 / 3
Memory 請求/限制4Gi / 6Gi

完整 RabbitmqCluster YAML(推薦配置)

yaml
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
  name: rabbitmqcluster
  namespace: rabbitmq-system
spec:
  replicas: 1
  tls:
    secretName: rabbitmq-tls-secret
    disableNonTLSListeners: true
  service:
    type: ClusterIP
  persistence:
    storageClassName: managed-csi
    storage: 10Gi
  rabbitmq:
    additionalConfig: |
      default_user = admin
      default_pass = Bed200@Passw0rd
      consumer_timeout = 21600000
    additionalPlugins:
      - rabbitmq_mqtt
      - rabbitmq_prometheus
  resources:
    requests:
      cpu: 2
      memory: 4Gi
    limits:
      cpu: 3
      memory: 6Gi

獨立 LoadBalancer Service

yaml
apiVersion: v1
kind: Service
metadata:
  name: rabbitmq-loadbalancer
  namespace: rabbitmq-system
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"
    service.beta.kubernetes.io/azure-load-balancer-ipv4: 10.30.196.40
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: rabbitmqcluster
  ports:
    - name: management-tls
      protocol: TCP
      port: 15671
      targetPort: 15671
    - name: amqps
      protocol: TCP
      port: 5671
      targetPort: 5671
    - name: mqtts
      protocol: TCP
      port: 8883
      targetPort: 8883
    - name: prometheus-tls
      protocol: TCP
      port: 15691
      targetPort: 15691

NodePort 配置(本地 K8s)

yaml
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
  name: rabbitmqcluster
  namespace: rabbitmq-system
spec:
  replicas: 1
  tls:
    secretName: rabbitmq-tls-secret
    disableNonTLSListeners: true
  service:
    type: NodePort
  override:
    service:
      spec:
        ports:
          - name: management-tls
            protocol: TCP
            port: 15671
            targetPort: 15671
            nodePort: 32071
          - name: amqps
            protocol: TCP
            port: 5671
            targetPort: 5671
            nodePort: 32072
          - name: mqtts
            protocol: TCP
            port: 8883
            targetPort: 8883
            nodePort: 32073
          - name: prometheus-tls
            protocol: TCP
            port: 15691
            targetPort: 15691
            nodePort: 32074
  persistence:
    storageClassName: managed-csi
    storage: 10Gi
  rabbitmq:
    additionalConfig: |
      default_user = admin
      default_pass = Bed200@Passw0rd
      consumer_timeout = 21600000
    additionalPlugins:
      - rabbitmq_mqtt
      - rabbitmq_prometheus
  resources:
    requests:
      cpu: 2
      memory: 4Gi
    limits:
      cpu: 3
      memory: 6Gi
服務名稱PortNodePort
management-tls1567132071
amqps567132072
mqtts888332073
prometheus-tls1569132074

Helm 安裝(Bitnami AKS)

bash
helm repo add bitnami-azure https://marketplace.azurecr.io/helm/v1/repo

helm install --namespace rabbitmq-system rabbitmq-cluster \
  --set auth.username=admin,auth.password=password,auth.erlangCookie=a2FrZWlsZWVAV0lXWU5OTzU0MDAxOTg5LXdzbA,service.type=LoadBalancer \
  bitnami-azure/rabbitmq

TLS 憑證建立

bash
# 使用 tls-gen 產生開發用憑證
cd [path to tls-gen repository]/basic
make
# 憑證輸出於 ./result 目錄

# 建立 Kubernetes Secret
kubectl create secret tls rabbitmq-tls-secret \
  --cert=server_certificate.pem \
  --key=server_key.pem \
  -n rabbitmq-system

Python (Pika) TLS 連線範例

python
import pika
import ssl

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations('ssl/ca_certificate.pem')
ssl_options = pika.SSLOptions(context)
credentials = pika.PlainCredentials('admin', 'Bed200@Passw0rd')
conn_params = pika.ConnectionParameters(
    host="10.30.202.46",
    credentials=credentials,
    ssl_options=ssl_options
)

with pika.BlockingConnection(conn_params) as conn:
    ch = conn.channel()
    ch.queue_declare("foobar")
    ch.basic_publish("", "foobar", "THIS IS SSL")

Docker 環境變數設定

bash
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="-rabbit consumer_timeout 31622400000"

相關概念

來源