Introducing NATS support in Kubeless

murali-reddy
Bitnami Perspectives
4 min readApr 26, 2018

Kubeless is a Kubernetes-native serverless solution or Function-as-a-Service framework that lets you deploy small bits of code (functions) without building a container or writing a Kubernetes manifest and without worrying about the underlying infrastructure. You can use Kubeless to deploy your business logic and trigger it in response to events. Kubeless supports a variety of event triggers, which represent a binding between an event source and a set functions.

NATS is a CNCF incubation-level hosted project which is simple yet powerful open source messaging technology built from the ground up to be cloud native and implements Publish Subscribe, Request Reply, Queueing messaging models.

Kubeless recently added support for NATS as an event Trigger. This is a major development for kubeless, as it show cases a recent refactor aimed at supporting event sources in a very generic manner. Users can map a NATS queue topic to a Kubeless function using a NATS Trigger. Kubeless then sets up a subscription for that topic, and invokes the associated function for each message in the queue.

In this story we will quickly walk you through how a NATS trigger is setup and how associated functions get invoked when events are published in the NATS queue.

Deploy NATS CRD and CRD controller

Thanks to Kubernetes Custom Resource Definitions (CRD) and CRD controllers, Kubeless has an elegant approach to adding new event sources as Kubeless Triggers. Kubeless models Trigger/event source as a Kubernetes CRD object. Do not be fooled by the simplicity of this past statement, this shows the real power of Kubernetes extensions and the ability to extend it in a very elegant manner.

Corresponding to Trigger CRD object a CRD controller handles all the CRUD operations. Both CRD and CRD controller for a Trigger is bundled into a single manifest with necessary RBAC roles. Lets dig into how the manifest for the NATS Trigger looks like. You would typically start by applying one of the released manifests for NATS like below (see the GitHub release page).

~ » kubectl create -f https://github.com/kubeless/kubeless/releases/download/$RELEASE/nats-$RELEASE.yaml

Once the manifest is applied you will have a new CRD object named natstrigger in kubeless.io API group. Below is the straightforward CRD for the natstrigger.

To perform operations when new natstrigger objects are created or deleted, you need a controller. The deployment for the NATS trigger controller will be created with the definition shown below.

You shall see a NATS trigger controller running in the kubeless namespace

At this point we are all set to deploy a function and create a mapping between a NATS topic and a function, so the function gets triggered or invoked when a new event is published to a NATS queue topic.

Deploying Function

One of the neat things about Kubeless is Functions and Triggers has independent life-cycles, so you can create them independently (A corollary of this is that a function can be triggered by multiple event sources, HTTP, NATS, Kafka, the sky is the limit). Kubeless functions follow standard signature irrespective of language (note: we try to follow the CloudEvents specification). First argument gives the event metadata and payload. Lets deploy a simple Python function below which just prints the event payload.

You can deploy the Kubeless function with kubeless CLI as below.

$ kubeless function deploy order-handler \
--runtime python2.7 \
--handler order_hanlder.order_handler \
--from-file order_handler.py

Once a function is deployed you shall see the following Kubernetes resources created:

The user given function combined with Kubeless wrapper code that provides an HTTP endpoint is deployed as a Kubernetes pod. A ClusterIP service is created to expose the function deployment as a in-cluster service. Now that this function is ready to be invoked through an http endpoint lets see how the function gets invoked.

Deploying NATS trigger

The kubless CLI provides a convenient way to create a NATS trigger CRD object. The CLI command below basically creates a NATS trigger object that declaratively specifies to invoke one or more functions matching given label selectors when there is a message in the NATS queue topic order

kubeless trigger nats create order-handler \
--function-selector created-by=kubeless,function=order-handler \
--trigger-topic order

Lets see how the NATS trigger CRD object created by kubeless CLI looks like:

Once NATS trigger CRD object is created, NATS trigger controller watching the Kubernetes API server for new NATSTrigger objects kicks in and creates a an event consumer subscribing to the topic order in the NATS cluster. Please see quick start guide to learn how a NATS cluster is configured to be used by Kubeless.

Triggering the function

When there is a published event in the NATS topic queue, NATS server invokes NATS trigger controller as it is subscribed to the topic. NATS trigger controller invokes the matching functions by sending the event over the corresponding cluster-ip services.

Lets publish a message to NATS topic and see it in action. Kubeless CLI provides a convenient command to publish message to a NATS topic.

$ kubeless trigger nats publish \
--url nats://nats-server-ip:4222 \
--topic order --message "Hello World!"

Once message is published you shall see a log in the pod running the function like below.

$ kubectl logs order-handler-6df8c7c849-v8228
172.17.0.1 - - [25/Apr/2018:06:30:34 +0000] "GET /healthz HTTP/1.1" 200 2 "" "kube-probe/." 0/85
{'event-time': '2018-04-25 06:30:55.753467874 +0000 UTC', 'extensions': {'request': <LocalRequest: POST http://order-handler.default.svc.cluster.local:8080/>}, 'event-type': 'application/x-www-form-urlencoded', 'event-namespace': 'natstriggers.kubeless.io', 'data': 'Hello World', 'event-id': 'IOIPR9dor8B5y3E'}
172.17.0.7 - - [25/Apr/2018:06:30:55 +0000] "POST / HTTP/1.1" 200 11 "" "Go-http-client/1.1" 0/7013

Conclusion

In this story we have seen how Kubeless provides a way to trigger Kubeless function in response to events published in NATS topic queues. NATS integration in Kubeless provides exciting possibilities. A function can publish result to a different topic on NATS which in turn can result in invoking other Kubeless function essentially achieving function chaining. Also Kubeless provides n:m association between Kubeless functions and NATS triggers. i.e. a function can subscribe to multiple NATS topics, and a NATS topic has multiple functions associated with it. Overall we are excited about the possibilities NATS integration in Kubeless can provide for complex functions based micro-services architecture.

--

--