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-cakubectl -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/hostnamekubectl 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-rabbitStatefulSet 提供稳定 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. 单节点故障与恢复#
- 持续发布/消费,确认无内存/磁盘告警且三成员健康。
- 找出 server-0 所在节点,按 节点维护排空该节点;只维护一台。
- 检查剩余两成员 quorum、publisher confirms 的失败/重试、业务幂等;目标是无已确认消息静默丢失。
- 恢复节点,等待副本追平、三成员健康后才继续第二台;失败不 force detach 正在写入的旧卷。
- 按 备份篇配合 RabbitMQ 原生恢复约束做异集群恢复。导出 definitions 只备份拓扑/权限,不备份消息;在线磁盘快照也不自动保证多节点一致性。
扩容和 broker 跨版本升级按兼容矩阵处理队列成员;所选 Operator 可能不支持普通缩容,不能直接减少 replicas。增加节点也不代表既有 quorum queue 自动完成成员再平衡。清理前排空队列、保存数据和定义、确认 PVC Retain;不得用删 CR 作为修复步骤。