跳至主内容

排查集群控制器

使用此信息排查 RabbitMQ 集群 Kubernetes 控制器的常见问题。

注意:以下信息可能对“自己动手”(DIY)的 Kubernetes 上的 RabbitMQ 部署有所帮助,但这类环境并非其主要关注点。

常见场景和错误

某些错误有专门的章节

RabbitMQ 集群部署失败

创建 RabbitMQ 实例后,几分钟内实例不可用,并且 RabbitMQ Pod 未运行。

此失败的常见原因包括:

  • 集群中的 CPU 或内存不足
  • imagePullSecrets 配置不正确。这会阻止从 Docker 注册表中拉取镜像。
  • storageClassName 配置不正确。

解决此问题的潜在方法

  • 运行 kubectl describe pod POD-NAME 查看是否有任何警告(例如,0/1 nodes are available: 1 Insufficient memory.
  • 修正 imagePullSecretsstorageClassName 配置。请参阅 imagePullSecrets持久化更新 RabbitMQ 实例
  • 如果在更新上述配置后问题仍然存在,请按照检查实例状态中的过程查看 RabbitMQ 集群资源的狀態。

如果部署到资源受限的集群(例如,本地环境如 kindminikube),您可能需要调整集群的 CPU 和/或内存限制。查看 resource-limits 示例了解如何操作。

Pod 未创建

例如,出现错误

pods POD-NAME is forbidden: unable to validate against any pod security policy: []

作为 Kubernetes 控制器部署的底层 ReplicaSet 的事件,或者 RabbitmqCluster 的底层 StatefulSet 的事件。

如果 Kubernetes 集群启用了 Pod 安全策略准入控制,但您尚未创建必要的 PodSecurityPolicy 和相应的基于角色的访问控制 (RBAC) 资源,则会出现此情况。

潜在的解决方案是按照Pod 安全策略中的过程创建 PodSecurityPolicy 和 RBAC 资源。

Pod 在启动时重启

RabbitMQ 容器可能在 Pod 启动时失败并记录类似消息

epmd error for host rabbitmq-server-1.rabbitmq-nodes.mynamespace: nxdomain (non-existing domain)

Error during startup: {error,no_epmd_port}

Pod 会重启,最终会变为 Ready 状态。

由于 RabbitMQ 节点 在启动时解析自身和对等节点的名称,CoreDNS 缓存超时可能需要从默认的 30 秒降低到 5-10 秒的范围。

CrashLoopBackOff 状态的 Pod

由于 Kubernetes 会重启失败的 Pod,如果 RabbitMQ 节点无法启动,它很可能会进入 CrashLoopBackOff 状态 - 它会尝试启动、失败然后被重新启动。在这种情况下,如果需要访问 Pod 或其数据,调试或修复问题可能会很困难。

调试这种情况的一种方法是创建一个新的 Pod,它不属于 StatefulSet,但挂载了相同的持久卷。以下是挂载 RabbitMQ 节点持久卷的 Pod 定义示例

apiVersion: v1
kind: Pod
metadata:
name: debug-rabbitmq
spec:
volumes:
- name: persistence
persistentVolumeClaim:
claimName: persistence-RMQ_NAME-server-2
containers:
- name: debug-rabbitmq
image: ... # you can use any image here, but for some tasks you should use the same image you use in the statefulset
command: ["/bin/sleep", "36000"]
volumeMounts:
- mountPath: /var/lib/rabbitmq/mnesia/
name: persistence

完成后,退出 Pod 并将其删除。

重新创建节点

在某些情况下,必须退役(永久从集群中移除)一个节点,并用一个新节点替换它。新节点将从其对等节点同步数据。

使用控制器替换节点的流程如下:

危险

以下过程将完全删除一个 Pod(RabbitMQ 节点)及其磁盘。这意味着该节点上所有非复制的数据都将丢失。请务必了解后果。

在此示例中,我们假设要重新创建 server-2。如果要删除不同的节点,请相应调整命令。

  1. kubectl rabbitmq pause-reconciliation RMQ_NAME(如果您没有 kubectl-rabbitmq 插件/CLI,可以添加标签)- 这意味着控制器不会“修复”(覆盖)对底层对象的手动更改。
  2. kubectl delete statefulset --cascade=orphan RMQ_NAME-server - 删除 statefulset,这样它就不会“修复”(在我们删除它后重新创建丢失的 pod)。
  3. kubectl delete pod RMQ_NAME-server-2(您可以删除任何您想要的 pod)。
  4. kubectl delete pvc persistence-RMQ_NAME-server-2(如果 persistentVolumeReclaimPolicy 设置为 Delete,这将删除 PV 和该节点上的所有数据)。
  5. kubectl delete pv PV_NAME(仅当 persistentVolumeReclaimPolicy 设置为 Retain 时才需要;这将删除 PV 和该节点上的所有数据)。
  6. rabbitmqctl forget_cluster_node rabbit@RMQ_NAME-server-2.RMQ_NAME-nodes.NAMESPACE(从任何运行的节点执行)- 从集群中移除已删除的节点。
  7. kubectl rabbitmq resume-reconciliation RMQ_NAME(或删除标签)- 控制器将重新创建 StatefulSet,StatefulSet 将重新创建丢失的 pod;该节点应加入集群。
  8. 将队列和流扩展到新节点
    • rabbitmq-queues grow rabbit@RMQ_NAME-server-2.RMQ_NAME-nodes.NAMESPACE all
    • rabbitmq-streams add_replica STREAM_NAME rabbit@RMQ_NAME-server-2.RMQ_NAME-nodes.NAMESPACE

Pod 卡在终止状态

症状:“删除 RabbitmqCluster 实例后,某些 Pod 卡在终止状态。RabbitMQ 仍在受影响的 Pod 中运行。”

原因:“最可能的原因是 RabbitMQ 中存在遗留的仲裁队列。”

解决此问题的潜在方法

  • 确保队列中没有消息,或者删除这些消息是可以接受的。
  • 通过运行以下命令强制删除队列:
kubectl delete pod --force --grace-period=0 POD-NAME

此示例使用 Pod 名称

kubectl delete pod --force rabbit-rollout-restart-server-1
# warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
# pod 'rabbit-rollout-restart-server-1' force deleted

要查看实例的状态,请运行:

kubectl -n NAMESPACE get all

其中 NAMESPACE 是实例的 Kubernetes 命名空间。

例如:

kubectl -n rmq-instance-1 get all
# NAME READY STATUS RESTARTS AGE
# pod/example-server-0 1/1 Running 0 2m27s
<br/>
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# service/example-nodes ClusterIP None None 4369/TCP 2m27s
# service/example ClusterIP 10.111.202.183 None 5672/TCP,15672/TCP,15692/TCP 2m28s
<br/>
# NAME READY AGE
# statefulset.apps/example-server 1/1 2m28s

集群控制器启动失败

部署 RabbitMQ Cluster Operator 后,它在启动过程中失败,并且其 Pod 被重启。

此失败的常见原因包括:

  • 控制器无法连接到 Kubernetes API。

解决此问题的潜在方法

  • 检查控制器是否仍在崩溃。Pod 重启可以解决许多临时性问题,因此重启本身是一种症状,而非问题。
  • 检查控制器日志(kubectl -n rabbitmq-system logs -l app.kubernetes.io/name=rabbitmq-cluster-operator
  • 您可能会看到类似这样的错误:
    • 无法获取 API 组资源
    • Get https://ADDRESS:443/api: connect: connection refused
  • 检查您的 Kubernetes 集群是否健康,特别是 kube-apiserver 组件。
  • 检查是否有任何安全网络策略阻止控制器访问 Kubernetes API 服务器。

RabbitMQ 集群状态条件

RabbitMQ 实例具有 status.conditions,用于描述 RabbitMQ 集群的当前状态。要获取状态,请运行:

kubectl describe rmq RMQ_NAME

示例状态条件可能如下所示:

Name:         test-rabbit
Namespace: rabbitmq-system
API Version: rabbitmq.com/v1beta1
Kind: RabbitmqCluster
...
Status:
Binding:
Name: sample-default-user
Conditions:
Last Transition Time: 2023-07-07T11:57:10Z
Reason: AllPodsAreReady
Status: True
Type: AllReplicasReady # true when all RabbitMQ pods are 'ready'
Last Transition Time: 2023-07-07T11:57:10Z
Reason: AtLeastOneEndpointAvailable
Status: True
Type: ClusterAvailable # true when at least one RabbitMQ pod is 'ready'
Last Transition Time: 2023-07-07T11:55:58Z
Reason: NoWarnings
Status: True
Type: NoWarnings
Last Transition Time: 2023-07-07T11:57:11Z
Message: Finish reconciling
Reason: Success
Status: True
Type: ReconcileSuccess
...

如果状态条件 ReconcileSuccess 为 false,则表示上一次协调已出错,RabbitMQ 集群配置可能已过时。查看集群控制器日志有助于了解协调失败的原因。

要获取控制器日志:

kubectl -n rabbitmq-system logs -l app.kubernetes.io/name=rabbitmq-cluster-operator
© . This site is unofficial and not affiliated with VMware.