The module lifecycle stage: Preview

The module has requirements for installation

A RabbitMQ instance is described by a Rabbit object in your namespace. The module deploys one RabbitMQ server for each Rabbit object and creates a Service and a Secret with credentials for connecting to it.

Quick start

To deploy a RabbitMQ instance with the default class, follow these steps:

  1. Create a namespace for the instance or choose an existing one, for example rabbit.

  2. Save the following manifest to the rabbit-sample.yaml file:

    apiVersion: managed-services.deckhouse.io/v1alpha1
    kind: Rabbit
    metadata:
      name: rabbit-sample
    spec:
      rabbitClassName: default
      configuration:
        maxMessageSize: 16Mi
      instance:
        memory:
          size: 512Mi
        cpu:
          cores: 1
          coreFraction: "50%"
        persistentVolumeClaim:
          size: 1Gi
  3. Apply the manifest:

    d8 k -n rabbit apply -f rabbit-sample.yaml
  4. Wait until the instance is ready:

    d8 k -n rabbit wait rabbit/rabbit-sample --for=condition=LastValidConfigurationApplied --timeout=10m
  5. Connect your application to the d8ms-rmq-rabbit-sample Service on port 5672 with the credentials from the d8ms-rmq-rabbit-sample-user-secret Secret. The details are in Connecting to RabbitMQ.

Choosing a class

The class sets the allowed instance sizes, the RabbitMQ settings you can change and the nodes where RabbitMQ runs. Specify the class name in the spec.rabbitClassName parameter. If the parameter is not set, the default class is used.

To list the available classes, run the following command:

d8 k get rabbitclasses

To see the limits of a class, run the following command:

d8 k get rabbitclass <CLASS_NAME> -o yaml

The limits are described in the sizingPolicies, validations and overridableConfiguration parameters of the class. If the class does not exist, the module accepts the Rabbit object with a warning, but does not deploy RabbitMQ until the class is created.

Setting CPU and memory

The resources of the RabbitMQ pod are set in the spec.instance section:

spec:
  instance:
    cpu:
      cores: 2
      coreFraction: "50%"
    memory:
      size: 2Gi

The module sets the pod resources as follows:

Resource Limit Request
CPU cores cores multiplied by coreFraction
Memory memory.size memory.size

The class checks the values when you create or change the object:

  • cores must fall within the cores range of one of the class sizing policies. The first matching policy is used for the other checks.
  • memory.size must fall within the memory range of that policy and be a multiple of its step.
  • coreFraction must be one of the coreFractions values of that policy, written in the same form, for example "50%".
  • The values must satisfy every CEL rule in the validations parameter of the class.

The module passes memory.size to RabbitMQ as the amount of available memory and sets the memory watermark, at which RabbitMQ blocks publishers, to 60% of this value.

Configuring storage

RabbitMQ stores messages and metadata on a persistent volume described in the spec.instance.persistentVolumeClaim section:

spec:
  instance:
    persistentVolumeClaim:
      size: 10Gi
      storageClassName: <STORAGE_CLASS_NAME>

Replace <STORAGE_CLASS_NAME> with the name of a StorageClass in the cluster. If storageClassName is not set, the default StorageClass of the cluster is used.

Storage follows these rules:

  • The storage class is fixed when the volume is created. A later change of storageClassName is not applied.
  • The volume size can only be increased. The StorageClass must allow volume expansion. A smaller value is ignored.
  • Without the persistentVolumeClaim section, the module creates no volume, and the data is lost when the pod restarts.

The volume belongs to the Rabbit object. When you delete the Rabbit object, the volume and all RabbitMQ data are deleted too.

Changing RabbitMQ settings

The RabbitMQ settings are set in the spec.configuration section:

spec:
  configuration:
    maxMessageSize: 16Mi

The maxMessageSize parameter sets the largest allowed message size. RabbitMQ rejects larger messages. You can set it only if the class lists it in the overridableConfiguration parameter; the default class allows it. Other RabbitMQ settings are set by the administrator in the class.

Enabling TLS

With TLS, RabbitMQ accepts only encrypted AMQPS connections on port 5671, and port 5672 is closed. TLS is set in the spec.tls section; without this section, TLS is disabled.

The server certificate must contain the following DNS names, where <NAME> is the Rabbit object name and <NAMESPACE> is its namespace:

  • d8ms-rmq-<NAME>;
  • d8ms-rmq-<NAME>.<NAMESPACE>;
  • d8ms-rmq-<NAME>.<NAMESPACE>.svc;
  • d8ms-rmq-<NAME>.<NAMESPACE>.svc.<CLUSTER_DOMAIN>, where <CLUSTER_DOMAIN> is the cluster domain, cluster.local by default.

Clients can connect without a client certificate. If a client presents a certificate, RabbitMQ verifies it against the CA certificate from ca.crt.

Certificate from cert-manager

In the CertManager mode, the module requests the certificate from cert-manager and puts the DNS names listed above into it. This mode requires the cert-manager module: enable it if it is disabled. Specify either a ClusterIssuer or an Issuer from the namespace of the Rabbit object:

spec:
  tls:
    mode: CertManager
    certManager:
      clusterIssuerName: <CLUSTER_ISSUER_NAME>

To use an Issuer, replace clusterIssuerName with issuerName. The issuer must put the CA certificate into the ca.crt key of the certificate Secret. The module starts RabbitMQ after cert-manager has issued the certificate.

Your own certificate

In the CustomCertificate mode, RabbitMQ uses certificates from Secrets in the namespace of the Rabbit object:

spec:
  tls:
    mode: CustomCertificate
    customCertificate:
      serverTLSSecret: <TLS_SECRET_NAME>
      serverCASecret: <CA_SECRET_NAME>

Replace the placeholders:

  • <TLS_SECRET_NAME>: Secret of the kubernetes.io/tls type with the server certificate in tls.crt and its key in tls.key.
  • <CA_SECRET_NAME>: Secret with the CA certificate in the ca.crt key.

Certificate state

The status.certificate.server section of the Rabbit object shows the state of the server certificate:

  • ttl: number of days until the certificate expires;
  • failed: true if the certificate cannot be read.

Connecting to RabbitMQ

The module creates the following objects for connecting to the instance, where <NAME> is the Rabbit object name:

  • Service d8ms-rmq-<NAME> with port 5672, or port 5671 with TLS;
  • Secret d8ms-rmq-<NAME>-user-secret with the username and password keys.

The user from the Secret has full permissions on the / virtual host. The password is generated when the Rabbit object is created and does not change.

To get the password, run the following command:

d8 k -n <NAMESPACE> get secret d8ms-rmq-<NAME>-user-secret -o jsonpath='{.data.password}' | base64 -d

An application in the cluster connects with the following URI:

amqp://<USERNAME>:<PASSWORD>@d8ms-rmq-<NAME>.<NAMESPACE>.svc:5672/

With TLS, use the amqps scheme and port 5671. The password can contain the !@#$%^&* characters: URL-encode it in the URI.

Checking the status

The state of the instance is shown in the status.conditions list of the Rabbit object. To see the conditions, run the following command:

d8 k -n <NAMESPACE> get rabbit <NAME> -o jsonpath='{range .status.conditions[*]}{.type}{"\t"}{.status}{"\t"}{.reason}{"\t"}{.message}{"\n"}{end}'

The instance is ready when all conditions are True:

Condition Meaning when True Reasons when False
ConfigurationValid The current object specification passed the class checks RulesValidationFailed, ValidationFailed
ScaledToLastValidConfiguration The RabbitMQ pod is ready and runs the last valid configuration ScaleError, NotScaled
Available RabbitMQ accepts connections NotServing
LastValidConfigurationApplied The last valid configuration is applied, and RabbitMQ is available. This is the summary condition Syncing while changes are applied, or <OBJECT>ReconciliationFailed if the module cannot create a Kubernetes object

Each False condition has a reason and a message that describe the problem.

If a change of the object does not pass the checks, RabbitMQ keeps running with the last valid configuration. This configuration is shown in the status.lastValidConfiguration section.

Troubleshooting

This section lists typical errors, their causes and fixes.

Object is rejected with a sizing error

The module rejects a Rabbit object whose resources do not match the class. The error message contains one of the following texts:

Message Cause Fix
cpu does not fit any of Sizing Policies of the chosen Class cores is outside the ranges of all sizing policies Choose cores within a range from sizingPolicies of the class
memory setting does not fit selected ... Class in range memory.size is outside the range of the matching policy Choose memory.size within the range; the limits are shown in bytes
memory setting does not fit Step memory.size is not a multiple of step Round memory.size to a multiple of step
core fraction does not match array in selected ... Class coreFraction is not in coreFractions Use one of the coreFractions values in the same form, for example "50%"

Object is rejected because of a setting

The message restricted to override by administrator means that the class does not allow the setting you changed in spec.configuration. Remove the setting or choose a class that lists it in overridableConfiguration.

The message Message: <TEXT> means that the object does not satisfy a CEL rule of the class. <TEXT> is the message of the rule. Change the object so that it satisfies the rule.

Pod cannot be scheduled

The ScaledToLastValidConfiguration condition with the ScaleError reason means that the RabbitMQ pod cannot be placed on any node. The pod placement is set in the class by the administrator. Check the pod events and contact the administrator:

d8 k -n <NAMESPACE> describe pod d8ms-rmq-<NAME>-0

Object has no conditions

If a new Rabbit object has no conditions, the class it references probably does not exist. When such an object is created, the module shows the warning RabbitClass <CLASS_NAME> was not found yet, skipping validation. Check the spec.rabbitClassName value, or ask the administrator to create the class.