Cluster Operator 故障排除
使用此信息来排除 RabbitMQ Cluster Kubernetes Operator 的常见问题。
请注意,以下信息可能对 Kubernetes 上的 “自己动手” (DIY) 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 Operator 部署的底层 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 秒的范围。
Pod 处于 CrashLoopBackOff 状态
由于 Kubernetes 会重启失败的 Pod,如果 RabbitMQ 节点无法启动,则很可能会进入 CrashLoopBackOff 状态 - 它尝试启动,失败并再次重启。在这种情况下,如果需要访问 Pod 或其数据才能调试或修复问题,则可能会很困难。
调试这种情况的一种方法是创建一个新的 Pod,该 Pod 不是 StatefulSet 的一部分,但挂载了相同的持久卷。这是一个 Pod 定义示例,它挂载了 RabbitMQ 节点的持久卷
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 并删除它。
重新创建节点
在某些情况下,必须解除节点的授权(从集群中永久删除)并替换为新节点。然后,新节点将从其对等节点同步数据。
使用 Operator 替换节点的过程如下所示
以下步骤将完全删除 Pod(RabbitMQ 节点)及其磁盘。这意味着来自该节点的所有未复制数据都将丢失。请确保您了解后果。
在此示例中,我们假设要重新创建 server-2。如果要删除不同的节点,请调整命令。
kubectl rabbitmq pause-reconciliation RMQ_NAME
(或者如果您没有 kubectl-rabbitmq 插件/CLI,则添加标签) - 这意味着 Operator 不会 “修复”(覆盖)对底层对象的手动更改kubectl delete statefulset --cascade=orphan RMQ_NAME-server
- 删除 statefulset,使其不会 “修复” Pod(在我们删除 Pod 后重新创建丢失的 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
(或删除标签)- Operator 将重新创建 StatefulSet,StatefulSet 将重新创建丢失的 Pod;节点应加入集群- 将仲裁队列和流扩展到新节点
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 卡在 Terminating 状态
症状: “删除 RabbitmqCluster 实例后,某些 Pod 卡在 terminating 状态。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
Cluster Operator 启动失败
部署 RabbitMQ Cluster Operator 后,它在启动期间失败,并且其 Pod 被重启。
此类失败的常见原因有
- Operator 无法连接到 Kubernetes API。
解决此问题的潜在方案
- 检查 Operator 是否仍在崩溃。Pod 重启解决了许多临时问题,因此重启是一种症状,而不是问题。
- 检查 Operator 日志 (
kubectl -n rabbitmq-system logs -l app.kubernetes.io/name=rabbitmq-cluster-operator
) - 您可能会看到如下错误
获取 API Group-Resources 失败
Get https://ADDRESS:443/api: connect: connection refused
- 检查您的 Kubernetes 集群是否健康,特别是
kube-apiserver
组件 - 检查是否有任何安全网络策略可能会阻止 Operator 连接到 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 集群配置可能已过时。查看 Cluster Operator 日志有助于了解协调失败的原因。
要获取 Operator 日志
kubectl -n rabbitmq-system logs -l app.kubernetes.io/name=rabbitmq-cluster-operator