排查集群控制器
使用此信息排查 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.) - 修正
imagePullSecrets和storageClassName配置。请参阅 imagePullSecrets、持久化和更新 RabbitMQ 实例。 - 如果在更新上述配置后问题仍然存在,请按照检查实例状态中的过程查看 RabbitMQ 集群资源的狀態。
如果部署到资源受限的集群(例如,本地环境如 kind 或 minikube),您可能需要调整集群的 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。如果要删除不同的节点,请相应调整命令。
kubectl rabbitmq pause-reconciliation RMQ_NAME(如果您没有 kubectl-rabbitmq 插件/CLI,可以添加标签)- 这意味着控制器不会“修复”(覆盖)对底层对象的手动更改。kubectl delete statefulset --cascade=orphan RMQ_NAME-server- 删除 statefulset,这样它就不会“修复”(在我们删除它后重新创建丢失的 pod)。kubectl delete pod RMQ_NAME-server-2(您可以删除任何您想要的 pod)。kubectl delete pvc persistence-RMQ_NAME-server-2(如果persistentVolumeReclaimPolicy设置为Delete,这将删除 PV 和该节点上的所有数据)。kubectl delete pv PV_NAME(仅当persistentVolumeReclaimPolicy设置为Retain时才需要;这将删除 PV 和该节点上的所有数据)。rabbitmqctl forget_cluster_node rabbit@RMQ_NAME-server-2.RMQ_NAME-nodes.NAMESPACE(从任何运行的节点执行)- 从集群中移除已删除的节点。kubectl rabbitmq resume-reconciliation RMQ_NAME(或删除标签)- 控制器将重新创建 StatefulSet,StatefulSet 将重新创建丢失的 pod;该节点应加入集群。- 将队列和流扩展到新节点
rabbitmq-queues grow rabbit@RMQ_NAME-server-2.RMQ_NAME-nodes.NAMESPACE allrabbitmq-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