Kubernetes, Give Me a Queue

September 22, 2021 Yaron Parasol

A few months ago, we introduced a new messaging topology operator. As we noted in our announcement post, this new Operator—we use the upper-cased “Operator” to denote Kubernetes Operators vs. platform or service human operators—takes the concept of VMware Tanzu RabbitMQ infrastructure-as-code another step forward by allowing platform or service operators and developers to quickly create users, permissions, queues, and exchanges, as well as queue policies and parameters. It wraps RabbitMQ APIs in Kubernetes APIs so that users can create and modify complex messaging topologies simply by modifying YAML.

Before we developed the messaging topology Operator, the main way to manage messaging topologies was either directly through the RabbitMQ API or via the administrative GUI. In this post, we’ll double-click on this new Operator to show how the Kubernetes wrapper for the RabbitMQ API simplifies DevOps workflows.

Extending Kubernetes with custom resources

So how do you wrap a workload API with Kubernetes API, and why would you want to? Because as developers, your needs evolve over time. New use cases emerge, and existing ones change. The Kubernetes API is designed to be extended with new types of objects not included in base Kubernetes. The Kubernetes operator pattern gives developers the ability to create new custom resources and manage them via the Kubernetes API. 

We used the operator pattern to create our Tanzu RabbitMQ cluster operator. Here we’ll use the operator pattern to create a custom resource definition for each type of RabbitMQ resource (e.g., exchanges, queues, and their attributes) to create complex messaging topologies right from the Kubernetes API.    

And what will you get from all this? Easier adoption of RabbitMQ best practices, faster development, and simpler operations, with the potential for workflows that more closely resemble infrastructure as code. You’ll also be able to gain better consistency in deployments, with less manual intervention and human error.

Here are more reasons to add this API.

Support for Knative

Knative is a serverless framework native to Kubernetes as a runtime. Serverless architecture needs events (messages) to invoke functions, and at times, to communicate function output to other functions and services. With the automation provided by the messaging topology operator, Knative can provide messaging to both serverless functions and backing services.  

Faster development

Tanzu RabbitMQ has a complex API, with several types of queues and exchanges. There are also a variety of queue policies and parameters to select. Such complexity can become a pitfall for new users. The declarative Kubernetes API exposes all these options as YAML. Wrapping the RabbitMQ API with an Operator is the first step to enabling faster development. The Operator comes with examples that reflect the best practices and the right values for a range of parameters. 

GitOps for better business continuity

According to GitLab, “GitOps is used to automate the process of provisioning infrastructure. Similar to how teams use application source code, operations teams that adopt GitOps use configuration files stored as code (infrastructure as code).” When it comes to software development and testing, the ability to quickly identify which changes were made that may have resulted in bugs, and the ability to return to previous working versions, are both critically important.

More and more IT organizations realize that GitOps-style deployment is exactly the right way to go with infrastructure and configurations. As infrastructure and platforms become software-defined in the form of APIs, treating infrastructure as code prevails. GitOps means defining a desired state for your infrastructure through Git commits, and then automatically reconciling discrepancies between the declared state in the Git repository and the runtime environment. Having your messaging topologies in declarative YAML files in Git makes it easy for SRE and DevOps to replicate environments and to both understand and solve problems for greater business continuity.

Watch a demo of GitOps with RabbitMQ Messaging Topology Operator.

A quick “Hello, world!” example

In this example, we will use a RabbitMQ cluster we have created using the RabbitMQ Cluster Kubernetes Operator. If you have not used this operator before, refer to this quick-start guide.

Now, let’s install the messaging topology operator and start creating our first messaging topology.

First, install cert-manager version 1.2.0+ on your cluster. For example, for version 1.3.1, run:

kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml

Then, to install the Operator, run the following command:

kubectl apply -f https://github.com/rabbitmq/messaging-topology-operator/releases/latest/download/messaging-topology-operator-with-certmanager.yaml

Now you need to decide which queue type you want to use. Here’s a simple decision tree:

Can you afford to lose messages if a cluster node crashes? If the answer is no, you need a replicated queue. Use the quorum queue example.

Ask yourself: Do I need messages in memory only? If yes, you will have super fast messages, but you will be limited by RAM size, so your overall throughput per node will be limited.

If SSD speed is good enough (it should be for most use cases), use the lazy queues, which write messages directly to disk and have lower memory consumption than the default queue settings.

Now let’s create an exchange for your queue: 


apiVersion: rabbitmq.com/v1beta1
kind: Exchange
metadata:
   name: direct
spec:
   name: direct-exchange # name of the exchange
   vhost: "/test-vhost" # default to '/' if not provided
   type: direct
   autoDelete: false
   durable: true
   rabbitmqClusterReference:
      name: test

 

Next, we need to bind the queue to the exchange:


apiVersion: rabbitmq.com/v1beta1
kind: Binding
metadata:
  name: binding
spec:
  vhost: "/test-vhost" # default to '/' if not provided
  source: test # an existing exchange
  destination: test # an existing queue or exchange
  destinationType: queue # can be 'queue' or 'exchange'
  rabbitmqClusterReference:
    name: test # rabbitmqCluster must exist in the same namespace as this resource

That’s it! You now have a messaging topology with the default user and password, which you can use to connect your publisher and consumer and run the “Hello, world!” example.

Simplify your messaging workflows in Kubernetes!

To get started with your own projects, review the documentation for this new messaging topology Operator and download the code. We’ve also provided examples that you can follow and a tutorial if you’d like more guidance!

Previous
Modern SRE Practices for Incident Management
Modern SRE Practices for Incident Management

I sat down with Feargus O’Gorman, a member of the VMware Tanzu SRE team, to learn how he supports VMware Ta...

Next
Application Resiliency for Cloud Native Microservices with VMware Tanzu Service Mesh
Application Resiliency for Cloud Native Microservices with VMware Tanzu Service Mesh

In this post, we’re going to demonstrate how you can set up a service-level objective in Tanzu Service Mesh.