StatefulSet 与 RabbitMQ 仲裁队列 Hands-on

验证:未记录
适用版本
未记录
验证范围
尚未登记验证记录。
本文缩写(英文全称与中文含义)
缩写 英文全称/名称 中文含义
ACK Acknowledgement 消息或数据接收确认
ACME Automatic Certificate Management Environment 自动化证书管理协议
API Application Programming Interface 应用程序编程接口
AZ Availability Zone 可用区
CA Certificate Authority 证书颁发机构
CR Custom Resource Kubernetes 自定义资源对象
CSI Container Storage Interface 容器存储接口
DLQ Dead-Letter Queue 死信队列
DLX Dead-Letter Exchange RabbitMQ 死信交换机
ESO External Secrets Operator 将外部秘密系统中的值同步到 Kubernetes 的控制器
HSM Hardware Security Module 硬件安全模块
ID Identifier 标识符
PDB Pod Disruption Budget Pod 中断预算,约束自愿驱逐
PKI Public Key Infrastructure 公钥基础设施
PSA Pod Security Admission Kubernetes Pod 安全准入
PVC Persistent Volume Claim 持久卷申领
TLS Transport Layer Security 传输层安全协议
UI User Interface 用户界面

场景:三副本 RabbitMQ 支撑真实订单异步任务,使用 quorum queue、TLS 和独立持久卷。前置:实践约定、三台以上业务节点、CSI 的 WaitForFirstConsumer/Retain StorageClass、cert-manager 和企业 CA。不要用三个单实例数据库冒充复制集。

1. 安装固定版本 Operator#

export RABBIT_OPERATOR_VERSION='vREPLACE_VERSION'
curl -fsSL "https://github.com/rabbitmq/cluster-operator/releases/download/$RABBIT_OPERATOR_VERSION/cluster-operator.yml" -o rabbit-operator.yaml
# 审阅 CRD、RBAC、镜像,按供应商兼容表选择 RabbitMQ 版本。
kubectl apply --server-side -f rabbit-operator.yaml
kubectl -n rabbitmq-system rollout status deployment/rabbitmq-cluster-operator --timeout=5m
kubectl create namespace messaging --dry-run=client -o yaml | kubectl apply -f -

固定 Operator 与 broker 镜像 digest;验证镜像能按目标 PSA 策略运行,系统权限例外只给所需 namespace。生产网络放行 orders→5671、broker 间发现/复制、Operator→管理 API 和监控采集;管理入口不暴露公网,不能只放行 5671 把集群复制阻断。

2. 签发内部服务证书#

cert-manager 篇安装控制器,但其 ACME 示例没有创建企业 CA。此处单独接入 PKI 团队签发的专用中间 CA,不要把企业根 CA 私钥放进集群。前置材料为 0600 文件 intermediate.key 和完整中间证书链 intermediate-chain.crt,需有 CA 签发用途、有效期覆盖业务证书,并获准签发下列内部名称。若组织要求密钥不出 HSM/Vault,改用该 PKI 的 issuer 接口,不能导出私钥硬套本例。

本例使用仅 messaging namespace 可引用的 CA Issuer,保存 rabbit-issuer.yaml:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata: {name: enterprise-ca, namespace: messaging}
spec:
  ca:
    secretName: messaging-intermediate-ca
kubectl -n messaging create secret tls messaging-intermediate-ca --cert=/secure/pki/intermediate-chain.crt --key=/secure/pki/intermediate.key
kubectl apply -f rabbit-issuer.yaml
kubectl -n messaging wait --for=condition=Ready issuer/enterprise-ca --timeout=2m

限制此 Secret 的读取和可创建 Certificate 的身份,按 静态加密保护;为中间 CA 自身设置过期告警和轮换计划,CA Issuer 不替你自动轮换 CA。将根/中间信任链分发给客户端后,保存 rabbit-tls.yaml:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata: {name: orders-rabbit, namespace: messaging}
spec:
  secretName: orders-rabbit-tls
  duration: 2160h
  renewBefore: 720h
  privateKey: {rotationPolicy: Always}
  issuerRef: {name: enterprise-ca, kind: Issuer}
  dnsNames:
    - orders-rabbit.messaging.svc
    - orders-rabbit.messaging.svc.cluster.local
    - '*.orders-rabbit-nodes.messaging.svc.cluster.local'
kubectl apply -f rabbit-tls.yaml
kubectl -n messaging wait --for=condition=Ready certificate/orders-rabbit --timeout=5m

确认 Secret 的 tls.crt/tls.key 存在,CA 信任链单独分发给业务;不关闭 hostname 校验。

3. 建三成员集群#

保存 rabbit-cluster.yaml,替换 image 和 StorageClass:

apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata: {name: orders-rabbit, namespace: messaging}
spec:
  replicas: 3
  image: REPLACE_RABBITMQ_IMAGE_AT_DIGEST
  resources:
    requests: {cpu: '1', memory: 2Gi}
    limits: {cpu: '2', memory: 2Gi}
  persistence:
    storageClassName: REPLACE_RETAIN_STORAGECLASS
    storage: 50Gi
  tls:
    secretName: orders-rabbit-tls
    disableNonTLSListeners: true
  rabbitmq:
    additionalConfig: |
      default_queue_type = quorum
      disk_free_limit.absolute = 5GB
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchLabels: {app.kubernetes.io/name: orders-rabbit}
          topologyKey: kubernetes.io/hostname
kubectl apply --dry-run=server -f rabbit-cluster.yaml
kubectl apply -f rabbit-cluster.yaml
kubectl -n messaging get rabbitmqcluster,sts,pods,pvc,svc,pdb
kubectl -n messaging rollout status statefulset/orders-rabbit-server --timeout=15m
kubectl -n messaging exec orders-rabbit-server-0 -- rabbitmqctl cluster_status

确认 Operator 实际生成的 labels 与反亲和匹配,三个成员分散且每个有独立 PVC;跨 AZ 还需 zone 分散和相应磁盘拓扑。检查是否已有匹配 PDB;本路径按官方独立创建方式设置至少两成员可用,不重复创建重叠 PDB。保存 rabbit-pdb.yaml:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: {name: orders-rabbit, namespace: messaging}
spec:
  minAvailable: 2
  selector:
    matchLabels: {app.kubernetes.io/name: orders-rabbit}
kubectl apply -f rabbit-pdb.yaml
kubectl -n messaging get pdb orders-rabbit

StatefulSet 提供稳定 ordinal、网络名与卷声明,不提供 RabbitMQ 仲裁/消息复制。这些由 broker 协议完成。OrderedReady、partition、PVC retention 等字段由 Operator 管理,不直接修改生成的 StatefulSet。

4. 真实业务接入与数据验证#

创建订单专用 vhost 和非管理员用户,密码通过终端提示输入,不放命令行历史;采用企业随机生成的密码并存入密钥系统。只在首次创建时执行:

kubectl -n messaging exec orders-rabbit-server-0 -- rabbitmqctl add_vhost orders
kubectl -n messaging exec -it orders-rabbit-server-0 -- rabbitmqctl add_user orders-app
kubectl -n messaging exec orders-rabbit-server-0 -- rabbitmqctl set_permissions -p orders orders-app '^orders[.].*' '^orders[.].*' '^orders[.].*'
kubectl -n messaging exec orders-rabbit-server-0 -- rabbitmqctl list_permissions -p orders

业务队列/exchange 名必须以 orders. 开头,用户不授予 administrator tag。默认管理用户留给受控运维,不能作为应用长期身份。业务使用 orders-rabbit.messaging.svc.cluster.local:5671 和 vhost orders,声明 durable quorum queue,启用 publisher confirms、手工 ACK、幂等消费和 DLQ。凭据经 ESO 注入应用;CA 挂载为只读文件并启用证书校验。

kubectl -n messaging exec orders-rabbit-server-0 -- rabbitmqctl list_vhosts
kubectl -n messaging exec orders-rabbit-server-0 -- rabbitmqctl list_queues -p orders name type messages_ready messages_unacknowledged

用预生产 API 发一批带唯一业务 ID 的真实订单,记录确认发布数、成功消费数、DLQ 和去重数;队列必须显示 quorum。完成这一步后再故障演练,不能以 UI 能打开代替消息可靠性验收。

业务先创建 durable 的 orders.dlx、orders.dlq 并完成 routing-key 绑定。若要求死信转移也不静默丢失,为来源队列 orders.tasks 设置以下策略;普通 DLX 默认行为不能等同至少一次交付:

kubectl -n messaging exec orders-rabbit-server-0 -- rabbitmqctl set_policy -p orders --apply-to quorum_queues orders-reliable-dlx '^orders[.]tasks$' '{"dead-letter-exchange":"orders.dlx","dead-letter-routing-key":"orders.failed","dead-letter-strategy":"at-least-once","overflow":"reject-publish","max-length":100000}'

容量阈值需压测;死信目标不可用时来源可能积压并拒绝发布,生产者必须处理 nack/重试。验证 DLQ 恢复后消息能转移且重复投递被幂等处理。

5. 单节点故障与恢复#

  1. 持续发布/消费,确认无内存/磁盘告警且三成员健康。
  2. 找出 server-0 所在节点,按 节点维护排空该节点;只维护一台。
  3. 检查剩余两成员 quorum、publisher confirms 的失败/重试、业务幂等;目标是无已确认消息静默丢失。
  4. 恢复节点,等待副本追平、三成员健康后才继续第二台;失败不 force detach 正在写入的旧卷。
  5. 按 备份篇配合 RabbitMQ 原生恢复约束做异集群恢复。导出 definitions 只备份拓扑/权限,不备份消息;在线磁盘快照也不自动保证多节点一致性。

扩容和 broker 跨版本升级按兼容矩阵处理队列成员;所选 Operator 可能不支持普通缩容,不能直接减少 replicas。增加节点也不代表既有 quorum queue 自动完成成员再平衡。清理前排空队列、保存数据和定义、确认 PVC Retain;不得用删 CR 作为修复步骤。

参考:Operator 配置、quorum queue、StatefulSet。

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭