Implementing Message Queues with NATS on Kubernetes

Brandon Kang
5 min readSep 5, 2023

--

What is NATs and how to use it on Kubernetes cluster environment?

NATS(https://nats.io/) is a connective technology built for the ever increasingly hyper-connected world. It is a single technology that enables applications to securely communicate across any combination of cloud vendors, on-premise, edge, web and mobile, and devices. NATS consists of a family of open source products that are tightly integrated but can be deployed easily and independently.

NATS was created by Derek Collison, in response to the market need for a simple, secure, and connective technology. NATS is currently deployed in some of the largest cloud platforms, including: VMware, CloudFoundry, Baidu, Siemens, and GE. NATS is 100% free to use under the Apache-2.0 Open Source License.

This article is about installing and operating NATS on Kubernetes. The easiest installation method, by all means, is to use Helm.

First, the PC used for installation should be connected to the Kubernetes cluster. You can achieve this by either copying the Kubernetes context to the `~/.kube/config` file or by using the `EXPORT KUBECONFIG` command as needed.

At first, Add NATS to your helm chart:

% helm repo add nats https://nats-io.github.io/k8s/helm/charts/
"nats" has been added to your repositories

Update the helm repository:

% helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "nats" chart repository
...Successfully got an update from the "openfaas" chart repository
Update Complete. ⎈Happy Helming!⎈

Check if NATS has been added to the repository:

% helm repo list
NAME URL
nats https://nats-io.github.io/k8s/helm/charts/

By using the default installation options, a single NATS server will be deployed as a StatefulSet with one Replica Deployment. Install the chart with the default options, using the name “my-nats” in this example:

% helm install my-nats nats/nats
NAME: my-nats
LAST DEPLOYED: Sun Sep 3 03:16:07 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1

Check the StatefulSet, Deployment, and Pods:

% kubectl get statefulset
NAME READY AGE
my-nats 1/1 22h

% kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
my-nats-box 1/1 1 1 22h

% kubectl get pods | grep nats
my-nats-0 2/2 Running 0 22h
my-nats-box-547fd47df-76fm9 1/1 Running 0 22h

To understand NATS server communication, check the Services. It uses the ClusterIP method:

% kubectl get service | grep nats
my-nats ClusterIP 10.128.78.134 <none> 4222/TCP 22h
my-nats-headless ClusterIP None <none> 4222/TCP,8222/TCP 22h

Now, let’s run the my-nats deployment for NATS server operation. Run both subscription and publishing in separate terminals.

<Publisher>

% kubectl exec -it deployment/my-nats-box -- nats pub my-subject "Hello?"
16:27:23 Published 6 bytes to "my-subject"

<Subscriber>
% kubectl exec -it deployment/my-nats-box -- nats sub my-subject
16:26:55 Subscribing on my-subject
[#1] Received on "my-subject"
Hello?
<Basic Pub/Sub messaging model>

Subscriber messages will reach all subscribers, even if there are multiple.

<1:N Pub/Sub messaging>

Now, let’s set up a Wild Card subject. This allows communication to all subscribers with matching subjects.

When a Subscriber’s subscribed subject is “greet.*,” it will receive messages with “greet.joe” and “greet.smith” subjects.

<wildcard styled subjects>

Next, let’s test Request-Reply messaging. Request-Reply is a unique messaging type in NATS where you send a request and receive a response. It can be represented as follows:

<image is from nats.io>

First, create a Reply client listener that subscribes to the “help.please” subject and automatically joins the “NATS-RPLY-22” group:

% kubectl exec -it deployment/my-nats-box -- nats reply help.please 'OK, I CAN HELP!'
16:36:36 Listening on "help.please" in group "NATS-RPLY-22"

Now, create a Request client. Sending a request with the same subject results in a response from the Reply client, including the response message and round-trip time (RTT):

% kubectl exec -it deployment/my-nats-box -- nats request help.please 'I need help!'
16:37:46 Sending request on "help.please"
16:37:46 Received with rtt 980.984µs
OK, I CAN HELP!
<Request-Reply messaging pattern>

Next, let’s test Queueing messaging, which is a form of messaging where only one subscriber receives the message.

According to the NATS official website, when using a globally deployed NATS cluster, it is possible to configure message routing to go to nearby subscribers using the “get-affinity” method. Additionally, if there are no listeners available, it is also possible to configure it to use clusters in different regions.

In this example, three subscribers are created, each with its own response containing A, B, or C for differentiation:

nats reply foo "service instance A Reply# {{Count}}"
nats reply foo "service instance B Reply# {{Count}}"
nats reply foo "service instance C Reply# {{Count}}"

All three subscribers join the “NATS-RPLY-22” group.

<Queueing messaging pattern>

Now, send a Request:

% kubectl exec -it deployment/my-nats-box -- nats request foo "Simple request"

The response will be from one of the three subscribers.

<randomly assigned subscribers>

You can continue to send requests, and they will be distributed randomly among subscribers, incrementing the Count variable:

% kubectl exec -it deployment/my-nats-box -- nats request foo "Another request"
16:52:44 Sending request on "foo"
16:52:44 Received with rtt 989.014µs
service instance A Reply# 4

That’s it! You’ve learned how to use NATS messaging service in a Kubernetes cluster environment.

--

--

Brandon Kang

This blog is for personal study purposes, not for the company I work for. I LOVE Cloud, DevOps and Open Source.