【问题标题】:Rabbit mq - Error while waiting for Mnesia tablesRabbit mq - 等待 Mnesia 表时出错
【发布时间】:2020-06-09 22:08:46
【问题描述】:

我在 kubernetes 集群上使用 helm chart 安装了 rabbitmq。 rabbitmq pod 不断重启。在检查 pod 日志时,我收到以下错误

2020-02-26 04:42:31.582 [warning] <0.314.0> Error while waiting for Mnesia tables: {timeout_waiting_for_tables,[rabbit_durable_queue]}
2020-02-26 04:42:31.582 [info] <0.314.0> Waiting for Mnesia tables for 30000 ms, 6 retries left

当我尝试执行 kubectl describe pod 时出现此错误

Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
Volumes:
  data:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  data-rabbitmq-0
    ReadOnly:   false
  config-volume:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      rabbitmq-config
    Optional:  false
  healthchecks:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      rabbitmq-healthchecks
    Optional:  false
  rabbitmq-token-w74kb:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  rabbitmq-token-w74kb
    Optional:    false
QoS Class:       Burstable
Node-Selectors:  beta.kubernetes.io/arch=amd64
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason     Age                      From                                               Message
  ----     ------     ----                     ----                                               -------
  Warning  Unhealthy  3m27s (x878 over 7h21m)  kubelet, gke-analytics-default-pool-918f5943-w0t0  Readiness probe failed: Timeout: 70 seconds ...
Checking health of node rabbit@rabbitmq-0.rabbitmq-headless.default.svc.cluster.local ...
Status of node rabbit@rabbitmq-0.rabbitmq-headless.default.svc.cluster.local ...
Error:
{:aborted, {:no_exists, [:rabbit_vhost, [{{:vhost, :"$1", :_, :_}, [], [:"$1"]}]]}}
Error:
{:aborted, {:no_exists, [:rabbit_vhost, [{{:vhost, :"$1", :_, :_}, [], [:"$1"]}]]}}

我已在 Kubernetes 集群上的 Google Cloud 上配置了上述内容。我不确定它是在什么特定情况下开始失败的。我不得不重新启动 pod,从那以后它一直失败。

这里有什么问题?

【问题讨论】:

  • 您是否尝试过描述正在运行的 pod?您能否提供有关您的设置的更多信息?是云配置的吗?它是在特定条件下失败还是在helm install 之后失败?
  • 这是我得到的错误。我已经用错误详细信息Error: {:aborted, {:no_exists, [:rabbit_vhost, [{{:vhost, :"$1", :_, :_}, [], [:"$1"]}]]}} Error: {:aborted, {:no_exists, [:rabbit_vhost, [{{:vhost, :"$1", :_, :_}, [], [:"$1"]}]]}} 更新了问题
  • 您到底使用了哪个舵图?
  • 好的,让我用最新的舵图测试一下,然后再试一次
  • 这是我使用的舵图。 github.com/helm/charts/tree/master/stable/rabbitmq。这些是我使用的值 - github.com/helm/charts/blob/master/stable/rabbitmq/… 这部分单独在 values-production.yaml # extraPlugins: "rabbitmq_auth_backend_ldap

标签: kubernetes rabbitmq google-kubernetes-engine kubernetes-helm rabbitmq-exchange


【解决方案1】:

就我而言,解决方案很简单

Step1:缩小有状态集,它不会删除 PVC。

kubectl scale statefulsets rabbitmq-1-rabbitmq --namespace teps-rabbitmq --replicas=1

第二步:访问 RabbitMQ Pod。

kubectl exec -it rabbitmq-1-rabbitmq-0 -n Rabbit

Step3:重置集群

rabbitmqctl stop_app
rabbitmqctl force_boot

Step4:重新调整有状态集

  kubectl scale statefulsets rabbitmq-1-rabbitmq --namespace teps-rabbitmq --replicas=4

【讨论】:

    【解决方案2】:

    TLDR

    helm upgrade rabbitmq --set clustering.forceBoot=true

    问题

    出现问题的原因如下:

    • 由于某种原因,所有 RMQ pod 同时终止(可能是因为您将 StatefulSet 副本显式设置为 0,或其他原因)
    • 其中一个是最后一个停止的(可能只是在其他几个之后一点点)。它将这个条件(“我现在是独立的”)存储在它的文件系统中,在 k8s 中是 PersistentVolume(Claim)。假设这个 pod 是 rabbitmq-1。
    • 当您重新启动 StatefulSet 时,pod rabbitmq-0 始终是第一个启动的(请参阅 here)。
    • 在启动过程中,pod rabbitmq-0 首先检查它是否应该独立运行。但就它在自己的文件系统上看到的而言,它是集群的一部分。所以它检查它的对等点,但没有找到。这个results in a startup failure by default
    • rabbitmq-0 因此永远不会准备好。
    • rabbitmq-1 永远不会启动,因为这就是 StatefulSet 的部署方式——一个接一个。如果它要启动,它将成功启动,因为它看到它也可以独立运行。

    所以说到底,RabbitMQ 和 StatefulSets 的工作方式有点不匹配。 RMQ 说:“如果一切都失败了,只需启动一切,同时,一个就能启动,一旦这个启动,其他人就可以重新加入集群。” k8s StatefulSets 说:“一次启动所有东西是不可能的,我们将从 0 开始”。

    解决方案

    为了解决这个问题,rabbitmqctl 有一个force_boot 命令,它基本上告诉实例在找不到任何对等点时独立启动。如何在 Kubernetes 中使用它取决于您使用的 Helm 图表和容器。在使用Bitnami Docker imageBitnami Chart 中,有一个值clustering.forceBoot = true,它转换为容器中的环境变量RABBITMQ_FORCE_BOOT = yes,然后容器将为您发出上述命令。

    但是看看这个问题,你也可以看到为什么删除 PVC 会起作用 (other answer)。 pod 将完全“忘记”它们上次是 RMQ 集群的一部分,并愉快地开始。不过,我更喜欢上述解决方案,因为不会丢失任何数据。

    【讨论】:

    • 另外,Bitnami github 上有一个关于恢复的部分,其中提到了 forceBoot 和另一个选项(使用 Parallel podManagementPolicy)github.com/bitnami/charts/tree/master/bitnami/…
    • (1.) 仅供参考,当您有 3 台机器运行 rabbitmq 并配置为集群时,会发生相同的问题“等待 Mnesia 表时出错”。所以这不仅仅是一个 kubernetes,掌舵问题。 (2.) 不幸的是,对于 rabbitmq,clustering.forceBoot 没有配置文件设置。所以我必须清除 /var/lib/rabbitmq/mnesia 才能启动服务器。他们现在都陷入了引导循环......“inconsistent_database”。 (3.) 在我的情况下,如果您使用 server1、2、3 停止您的兔子集群,那么您必须以 LIFO 顺序开始,即 3、2、1。这使您可以毫无问题地开始。
    • 这应该被标记为答案。谢谢 Ulli,您为我节省了数小时的故障排除时间!
    • 我还必须添加podManagementPolicy=Parallel。即使使用forceBoot 选项rabbitmq-0 也没有启动
    【解决方案3】:

    测试这个部署:

    kind: Service
    apiVersion: v1
    metadata:
      namespace: rabbitmq-namespace
      name: rabbitmq
      labels:
        app: rabbitmq
        type: LoadBalancer  
    spec:
      type: NodePort
      ports:
       - name: http
         protocol: TCP
         port: 15672
         targetPort: 15672
         nodePort: 31672
       - name: amqp
         protocol: TCP
         port: 5672
         targetPort: 5672
         nodePort: 30672
       - name: stomp
         protocol: TCP
         port: 61613
         targetPort: 61613
      selector:
        app: rabbitmq
    ---
    kind: Service 
    apiVersion: v1
    metadata:
      namespace: rabbitmq-namespace
      name: rabbitmq-lb
      labels:
        app: rabbitmq
    spec:
      # Headless service to give the StatefulSet a DNS which is known in the cluster (hostname-#.app.namespace.svc.cluster.local, )
      # in our case - rabbitmq-#.rabbitmq.rabbitmq-namespace.svc.cluster.local  
      clusterIP: None
      ports:
       - name: http
         protocol: TCP
         port: 15672
         targetPort: 15672
       - name: amqp
         protocol: TCP
         port: 5672
         targetPort: 5672
       - name: stomp
         port: 61613
      selector:
        app: rabbitmq
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: rabbitmq-config
      namespace: rabbitmq-namespace
    data:
      enabled_plugins: |
          [rabbitmq_management,rabbitmq_peer_discovery_k8s,rabbitmq_stomp].
    
      rabbitmq.conf: |
          ## Cluster formation. See http://www.rabbitmq.com/cluster-formation.html to learn more.
          cluster_formation.peer_discovery_backend  = rabbit_peer_discovery_k8s
          cluster_formation.k8s.host = kubernetes.default.svc.cluster.local
          ## Should RabbitMQ node name be computed from the pod's hostname or IP address?
          ## IP addresses are not stable, so using [stable] hostnames is recommended when possible.
          ## Set to "hostname" to use pod hostnames.
          ## When this value is changed, so should the variable used to set the RABBITMQ_NODENAME
          ## environment variable.
          cluster_formation.k8s.address_type = hostname   
          ## Important - this is the suffix of the hostname, as each node gets "rabbitmq-#", we need to tell what's the suffix
          ## it will give each new node that enters the way to contact the other peer node and join the cluster (if using hostname)
          cluster_formation.k8s.hostname_suffix = .rabbitmq.rabbitmq-namespace.svc.cluster.local
          ## How often should node cleanup checks run?
          cluster_formation.node_cleanup.interval = 30
          ## Set to false if automatic removal of unknown/absent nodes
          ## is desired. This can be dangerous, see
          ##  * http://www.rabbitmq.com/cluster-formation.html#node-health-checks-and-cleanup
          ##  * https://groups.google.com/forum/#!msg/rabbitmq-users/wuOfzEywHXo/k8z_HWIkBgAJ
          cluster_formation.node_cleanup.only_log_warning = true
          cluster_partition_handling = autoheal
          ## See http://www.rabbitmq.com/ha.html#master-migration-data-locality
          queue_master_locator=min-masters
          ## See http://www.rabbitmq.com/access-control.html#loopback-users
          loopback_users.guest = false
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: rabbitmq
      namespace: rabbitmq-namespace
    spec:
      serviceName: rabbitmq
      replicas: 3
      selector:
        matchLabels:
          name: rabbitmq
      template:
        metadata:
          labels:
            app: rabbitmq
            name: rabbitmq
            state: rabbitmq
          annotations:
            pod.alpha.kubernetes.io/initialized: "true"
        spec:
          serviceAccountName: rabbitmq
          terminationGracePeriodSeconds: 10
          containers:        
          - name: rabbitmq-k8s
            image: rabbitmq:3.8.3
            volumeMounts:
              - name: config-volume
                mountPath: /etc/rabbitmq
              - name: data
                mountPath: /var/lib/rabbitmq/mnesia
            ports:
              - name: http
                protocol: TCP
                containerPort: 15672
              - name: amqp
                protocol: TCP
                containerPort: 5672
            livenessProbe:
              exec:
                command: ["rabbitmqctl", "status"]
              initialDelaySeconds: 60
              periodSeconds: 60
              timeoutSeconds: 10
            resources:
                requests:
                  memory: "0"
                  cpu: "0"
                limits:
                  memory: "2048Mi"
                  cpu: "1000m"
            readinessProbe:
              exec:
                command: ["rabbitmqctl", "status"]
              initialDelaySeconds: 20
              periodSeconds: 60
              timeoutSeconds: 10
            imagePullPolicy: Always
            env:
              - name: MY_POD_IP
                valueFrom:
                  fieldRef:
                    fieldPath: status.podIP
              - name: NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
              - name: HOSTNAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
              - name: RABBITMQ_USE_LONGNAME
                value: "true"
              # See a note on cluster_formation.k8s.address_type in the config file section
              - name: RABBITMQ_NODENAME
                value: "rabbit@$(HOSTNAME).rabbitmq.$(NAMESPACE).svc.cluster.local"
              - name: K8S_SERVICE_NAME
                value: "rabbitmq"
              - name: RABBITMQ_ERLANG_COOKIE
                value: "mycookie"      
          volumes:
            - name: config-volume
              configMap:
                name: rabbitmq-config
                items:
                - key: rabbitmq.conf
                  path: rabbitmq.conf
                - key: enabled_plugins
                  path: enabled_plugins
      volumeClaimTemplates:
      - metadata:
          name: data
        spec:
          accessModes:
            - "ReadWriteOnce"
          storageClassName: "default"
          resources:
            requests:
              storage: 3Gi
    
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: rabbitmq 
      namespace: rabbitmq-namespace 
    ---
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      name: endpoint-reader
      namespace: rabbitmq-namespace 
    rules:
    - apiGroups: [""]
      resources: ["endpoints"]
      verbs: ["get"]
    ---
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      name: endpoint-reader
      namespace: rabbitmq-namespace
    subjects:
    - kind: ServiceAccount
      name: rabbitmq
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: endpoint-reader
    

    【讨论】:

    • 说实话,这并没有什么帮助。为什么有人想尝试一下,以及一堆与他/她无关的配置?
    • @HarisOsmanagić 您可以根据您的使用情况编辑配置图。
    • 不,我不能,因为里面太多了。每个人都会很高兴看到解决问题的确切参数,而不必尝试另一个配置映射。
    【解决方案4】:

    我也遇到了类似的错误,如下所示。

    2020-06-05 03:45:37.153 [info] 等待 Mnesia 表 30000 毫秒,还剩 9 次重试 2020-06-05 03:46:07.154 [警告] 等待 Mnesia 表时出错: {timeout_waiting_for_tables,[rabbit_user,rabbit_user_permission,rabbit_topic_permission,rabbit_vhost,rabbit_durable_route,rabbit_durable_exchange,rabbit_runtime_parameters,rabbit_durable_queue]} 2020-06-05 03:46:07.154 [info] 等待 Mnesia 表 30000 毫秒,还剩 8 次重试

    在我的例子中,RabbitMQ 集群的从节点(服务器)宕机了。一旦我启动了从节点,主节点就启动了,没有错误。

    【讨论】:

    【解决方案5】:

    刚刚删除了现有的持久卷声明并重新安装了rabbitmq,它开始工作了。

    因此,每次在 kubernetes 集群上安装 rabbitmq 之后,如果我将 pod 缩小到 0 并且稍后扩大 pod 时,我都会遇到同样的错误。我还尝试在不卸载 rabbitmq helm 图表的情况下删除 Persistent Volume Claim,但仍然出现相同的错误。

    所以看来每次我将集群缩小到0,都需要卸载rabbitmq helm chart,删除对应的Persistent Volume Claims,每次都安装rabbitmq helm chart才能正常工作。

    【讨论】:

    • 请注意,删除持久卷声明可能会破坏您的数据。不会在生产中这样做。
    • 我同意通常删除持久卷会使您丢失数据。但特别是对于 rabbitmq 开发人员(以及我认识的许多其他 rabbitmq 用户),我们不需要也不想要或使用任何 rabbitmq 持久性功能。我的同事告诉我,他将掌舵 persistance 设置为 false 并且没有任何用于 rabbitmq 的 pvc。这也是我要尝试的。
    • 您删除 pod 和 pvc 的解决方案对我有用。我认为 rabbitmq 没有正常关闭,导致 mnesia 文件损坏,因此通过删除 pvc 和 pod,我得到了一个带有空 pvc 的新 pod,因此 rabbitmq 的掌舵图终于能够成功地重新上线。
    • 运行 rabbitmq helm chart 并将持久性设置为 false 肯定更好:1. 更简单的配置 2. 从 kubernetes 请求的资源更少 3. 更好的上下移动鲁棒性 4. 更可靠(否需要我编写一个自定义脚本来检查不良状态,然后删除 pod/pvc)
    猜你喜欢
    • 2014-05-31
    • 2023-04-01
    • 1970-01-01
    • 2023-03-25
    • 2016-11-01
    • 2018-07-30
    • 1970-01-01
    • 2018-08-08
    • 1970-01-01
    相关资源
    最近更新 更多