跳至主内容

仲裁状态监控

简介

RabbitmqCluster 状态中的 quorumStatus 字段提供了对 RabbitMQ 集群仲裁健康状况的近实时可见性。该字段可帮助运维人员了解执行维护操作(例如缩减节点数量、进行滚动升级或为配置更改执行滚动重启)是否安全。

为什么仲裁状态很重要

RabbitMQ 仲裁队列 (quorum queues)流 (streams) 以及 Khepri 元数据存储均使用 Raft 一致性算法在多个节点间复制数据。当某个节点持有关键的仲裁队列副本时,将其关闭可能会导致仲裁丢失,从而使队列不可用,直到该节点恢复。quorumStatus 字段会指示哪些节点(如果有)处于“仲裁关键 (quorum critical)”状态,这些节点不应被关闭。

提示

本指南包含关于最佳实践故障排查的章节。

工作原理

集群操作员会自动监控 RabbitMQ 集群的仲裁状态

  1. 在每次协调循环 (Reconciliation Loop) 中:操作员会定期检查所有 RabbitMQ 节点的仲裁状态
  2. 直接连接到每个 Pod:使用其稳定的 DNS 名称:<pod-name>.<cluster-name>-nodes.<namespace>.svc
  3. RabbitMQ 管理 API:使用每个节点上的 /api/health/checks/node-is-quorum-critical HTTP API 端点
  4. 并发检查:为了提高效率,所有节点均并行执行检查
  5. 状态更新:使用聚合结果更新 quorumStatus 字段

连接方式

操作员使用 StatefulSet 的稳定 DNS 名称连接到每个 Pod。对于证书包含 Pod DNS 名称作为主体备用名称 (SANs) 的 TLS 部署,这一点尤为重要。

<pod-name>.<headless-service>.<namespace>.svc

例如,对于命名空间 default 中名为 my-rabbit 的集群

  • Pod 0: my-rabbit-server-0.my-rabbit-nodes.default.svc
  • Pod 1: my-rabbit-server-1.my-rabbit-nodes.default.svc
  • Pod 2: my-rabbit-server-2.my-rabbit-nodes.default.svc

这种方法确保了 TLS 对等方验证能够正常工作,而无需用户在证书中包含基于 Pod IP 的 DNS 条目 (*.pod)。

状态值

quorumStatus 字段可以包含以下值

"ok"

所有节点均健康,且没有节点处于仲裁关键状态。执行维护操作是安全的。

status:
quorumStatus: "ok"

"ok (N unavailable)"

没有节点处于仲裁关键状态,但在健康检查期间无法访问某些节点。如果 Pod 正在重启或遇到网络问题,可能会发生这种情况。

status:
quorumStatus: "ok (1 unavailable)"

解读:虽然没有检测到仲裁关键节点,但在继续维护之前,运维人员应调查部分节点不可用的原因。

"quorum-critical: pod-name"

一个或多个 Pod 处于仲裁关键状态,不应关闭。状态中包含处于关键状态的 Pod 名称。

status:
quorumStatus: "quorum-critical: my-cluster-server-0"
危险

请勿删除或重启被列为仲裁关键的 Pod,因为这可能导致队列不可用或数据丢失。

"quorum-critical: pod-name1, pod-name2 (N unavailable)"

多个 Pod 处于仲裁关键状态,且无法访问部分节点。这在滚动重启期间是预料之中的。请调查滚动重启完成后状态是否持续存在。

status:
quorumStatus: "quorum-critical: my-cluster-server-0, my-cluster-server-2 (1 unavailable)"
警告

这表明集群状态可能不稳定。请避免任何破坏性操作,并调查不可用的节点。

"unavailable"

所有节点均无法访问或 StatefulSet 未就绪。这种情况通常发生在集群初始创建期间或整个集群关闭时。

status:
quorumStatus: "unavailable"

解读:集群未运行。请等待 Pod 就绪后再评估仲裁状态。

如何检查仲裁状态

查看当前状态

# View quorum status for a specific cluster
kubectl get rabbitmqcluster my-cluster -o jsonpath='{.status.quorumStatus}'

实时监控状态

# Monitor quorum status changes
kubectl get rabbitmqcluster my-cluster -w -o jsonpath='{.metadata.name}{"\t"}{.status.quorumStatus}{"\n"}'

查看完整集群状态

# See all status fields including quorum status
kubectl describe rabbitmqcluster my-cluster

获取 YAML 格式的状态

# View complete status object
kubectl get rabbitmqcluster my-cluster -o yaml | grep -A 1 quorumStatus

用例

quorumStatus 字段在以下场景中特别有用

维护窗口期间

在执行滚动更新或节点维护时监控仲裁状态,以了解集群稳定性。

监控集群健康状况

将仲裁状态检查集成到您的监控和告警系统中,以便在潜在的可用性问题影响应用程序之前将其发现。

排查数据可用性问题

如果应用程序报告队列不可用,请检查仲裁状态以识别哪些节点是关键的,以及是否有任何节点不可用。

限制

关键限制:直接修改 RabbitMQ

重要

如果直接通过 RabbitMQ(CLI 工具、HTTP API)修改队列成员身份或仲裁队列配置,而绕过了 Kubernetes Operator,则 quorumStatus 字段可能无法准确反映实际风险。

例如:

  • 使用 rabbitmq-queues growrabbitmq-queues shrink 添加或删除队列成员(副本)
  • 使用 RabbitMQ 管理界面修改队列设置
  • 使用直接与 RabbitMQ API 交互的外部工具或脚本

如果仲裁队列成员身份是在 Kubernetes 之外修改的,操作员的状态可能会变得陈旧或不准确,直到 RabbitMQ 的内部状态同步为止。请尽可能始终使用 Kubernetes 原生方法进行集群管理。

其他限制

非实时:状态仅在协调循环(通常每隔几分钟)期间更新。实际仲裁状态可能会在更新之间发生变化。

需要管理 API 访问权限:所有 Pod 必须具有可访问的管理 API 端点。如果由于网络策略、防火墙规则或身份验证问题导致管理 API 不可用,节点将被报告为“不可用”。

需要 TLS 配置:如果 DisableNonTLSListeners 设置为 true,则必须配置在 SAN 中包含 Pod DNS 的 TLS。TLS 连接(对等方验证)问题将导致节点被报告为“不可用”。

例如,对于名为 my-rabbitRabbitmqCluster

DNS:my-rabbit-server-0.my-rabbit-nodes.default.svc
DNS:my-rabbit-server-1.my-rabbit-nodes.default.svc
DNS:my-rabbit-server-2.my-rabbit-nodes.default.svc

不能阻止 Pod 删除quorumStatus 字段仅供参考。控制器不会基于此状态阻止 Pod 删除。对不安全关闭的保护是由 StatefulSet 的 preStop 钩子提供的。

与 StatefulSet PreStop 钩子的集成

了解 quorumStatus 字段与集群删除保护之间的关系非常重要

  • 状态报告:控制器报告仲裁状态,但不阻止 Pod 操作
  • PreStop 钩子保护:StatefulSet 包含一个 preStop 钩子,当节点处于仲裁关键状态时,该钩子会阻止 Pod 关闭
  • 操作员决策quorumStatus 字段有助于运维人员和自动化工具在启动维护操作前做出明智决策

PreStop 钩子会调用相同的 RabbitMQ 健康检查端点,如果节点处于仲裁关键状态,则会阻止 Pod 终止,即使操作员继续执行删除操作,也能提供安全保障。

最佳实践

  1. 扩展前检查:在缩减集群规模前务必检查 quorumStatus
  2. 持续监控:将仲裁状态集成到您的监控仪表板中
  3. 合理配置规模:为仲裁队列至少保留 3 个节点(奇数
  4. 避免手动更改:优先使用 Kubernetes 原生方法,而非直接修改 RabbitMQ
  5. 在暂存环境测试:先在非生产环境中验证您的扩展和维护流程

故障排除

状态显示为“不可用”

可能的原因:

  • Pod 未就绪(仍在启动中)
  • 控制器与 Pod 之间的网络连接问题
  • 管理 API 不可访问
  • TLS 配置问题(如果启用了 TLS)
  • 身份验证凭据不正确

解决步骤:

  1. 检查 Pod 就绪状态:kubectl get pods -l app.kubernetes.io/name=<cluster-name>
  2. 验证网络策略是否允许控制器到 Pod 的通信
  3. 检查管理 API 可访问性:kubectl port-forward <pod-name> 15672:15672
  4. 查看控制器日志以获取特定错误:kubectl logs -n <operator-namespace> <controller-pod>

状态未更新

可能的原因:

  • 协调循环未运行
  • 控制器不健康
  • 集群资源未被监控

解决步骤:

  1. 检查控制器日志是否存在错误
  2. 验证控制器是否正在运行:kubectl get pods -n <operator-namespace>
  3. 检查 observedGeneration 字段是否与集群的 generation 匹配
  4. 通过添加注解手动触发协调:kubectl annotate rabbitmqcluster my-cluster reconcile=$(date +%s)

意外出现“仲裁关键”状态

可能的原因:

  • 仲裁队列副本分布不均
  • 集群规模对于已配置的队列复制因子来说太小
  • 最近的节点故障尚未进行重新平衡

解决步骤:

  1. 在 RabbitMQ 管理 UI 中检查仲裁队列分布
  2. 验证集群规模是否满足要求(建议仲裁队列至少 3 个节点)
  3. 审查队列策略和复制设置
  4. 考虑重新平衡队列主节点:必要时使用 RabbitMQ 的重新平衡命令

所有节点显示为仲裁关键

可能的原因:

  • 每个节点都托管着关键的仲裁队列副本
  • 集群容量不足以承载仲裁队列的数量

解决步骤:

  1. 扩展集群以添加更多节点
  2. 审查并调整仲裁队列复制因子
  3. 更均匀地在各节点间分布队列
  4. 考虑是否所有队列都需要是仲裁队列

参考资料

© . This site is unofficial and not affiliated with VMware.