OpenFaas NATS Event Connector

NATS As eVENT tRIGGER

In the previous two articles, we discussed NATS messaging, its message streaming progeny JetStream, and how we can use it to communicate between services. We will finish our discussion of NATS with this mercifully shorter article in which we will use NATS messages to trigger OpenFaaS functions using the OpenFaaS NATS Connector.

OpenFAAS Event Connector Pattern

The most common way to trigger an OpenFaaS function is via HTTP/webhooks. However, OpenFaas provides an Event-connector pattern to allow third-party development of custom code to invoke functions.

OpenFaas Event-Connector Pattern

Currently, OpenFaaS has support for several additional integrations, including Cron, MQTT, AWS SQS, and of course, NATS. When no existing integration is available, OpenFaaS provides the Connector SDK to simplify creating custom integrations.

NATS Connector

In this article, we are exclusively interested in the NATS Connector. Unsurprisingly, this connector allows us to trigger OpenFaaS functions when a NATS message is published to a given topic.

Setting up the Environment

We will be using the OpenFaaS instance we deployed in the article Microservices, Functions-as-a-service, and Kubernetes. This instance is deployed to a local MicroK8S Kubernetes node. It is strongly recommended that you deploy OpenFaaS according to that article, as this article's instructions are predicated on it.

With OpenFaaS deployed to our MicroK8S node, we will use the faas-cli tool to deploy two test functions: receive-message and publish-message, which are provided by the NATS connector. The receive-message function is triggered when a message arrives at the designated NATS topic. The publish-message will publish a message to the designated NATS topic when it is triggered.

We must, of course, also deploy the NATS-connector. We accomplish this by deploying it to the same Kubernetes openfaas namespace where we originally deployed our OpenFaaS instance.

Verify our OpenFaas Instance

Before we get started, let's verify that OpenFaaS is running on our MicroK8S instance by getting its gateway address. :
microk8s kubectl get svc -n openfaas gateway-external -o wide

The output should appear similar to:

Terminal
    gateway-external   NodePort   10.152.183.45   <none>        8080:31112/TCP   46h   app=gateway

  

From this output, we can see that our gateway address is 10.152.183.45:8080.

Let's also retrieve our OpenFaaS password. We can do that with the following command::

PASSWORD=$(microk8s kubectl -n openfaas get secret basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode) && \ echo "OpenFaaS admin password: $PASSWORD"

Your output should be similar to:

OpenFaaS admin password: atDHpyHle9tN

With our gateway address and password, we can now log in to OpenFaaS.

Log in to OPenFaas

Let's start by setting the OPENFAAS_URL to our gateway address with the following command:

export OPENFAAS_URL=< gateway address>

Now we will log in to OpenFaaS using the faas-cli and the password we retrieved (If you don't have the faas-cli installed, please refer to the instructions in the article Microservices, Functions-as-a-service, and Kubernetes). Login with the following command:

faas-cli login -g $OPENFAAS_URL -u admin --password < password>

Your output should appear similar to:

WARNING! Using --password is insecure, consider using: cat ~/faas_pass.txt | faas-cli login -u user --password-stdin Calling the OpenFaaS server to validate the credentials... WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates. credentials saved for admin http://10.152.183.45:8080

We can ignore the password WARNING for now.

We can obtain a listing of all our deployed functions with the following command:

faas-cli list

If you have a fresh install with no functions deployed, your output should appear similar to:

Function Invocations Replicas

The listing should be empty.

Deployment

Our first step is to deploy the receive-message function. This function will be triggered by the NATS connector when a NATS message arrives. Here we see the function's handler (written in GO):


  loading...

The handler receives the message body and echoes its contents to the function's log.

We can deploy the receive-message function with the following command:

faas-cli deploy --name receive-message --image openfaas/receive-message:latest --fprocess='./handler' --annotation topic="nats-test"

The output should be similar to:

Terminal
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.

Deployed. 202 Accepted.
URL: http://10.152.183.45:8080/function/receive-message

If we request the function listing again, you should see:

Terminal
Function                        Invocations     Replicas
receive-message                 0               1    

Now we need to deploy the NATS connector to MicroK8S. We will do this using the following deployment YAML:


  loading...

We can apply this with the following command:

microk8s kubectl apply -f https://raw.githubusercontent.com/openfaas/nats-connector/master/yaml/kubernetes/connector-dep.yaml

If everything went correctly, your output should be similar to:

deployment.apps/nats-connector created

We can verify it deployed correctly by retrieving the list of deployments in the openfaas namespace. We can do this with the following command:

microk8s kubectl get deployments -n openfaas

The output should include the nats-connector:

Terminal
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
nats                1/1     1            1           1h
basic-auth-plugin   1/1     1            1           1h
queue-worker        1/1     1            1           1h
prometheus          1/1     1            1           1h
gateway             1/1     1            1           1h
alertmanager        1/1     1            1           1h
nats-connector      1/1     1            1           1m22s


With the NATS-Connector deployed, let's deploy the publish-message function. Let's take a look at this function (also written in GO):


  loading...

Here we see the function connects to NATS and publishes its request body to the nats-test subject.

We can deploy the function with the following command:

faas-cli deploy --name publish-message --image openfaas/publish-message:latest --fprocess='./handler' --env nats_url=nats://nats.openfaas:4222

The output should appear similar to:

WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates. Deployed. 202 Accepted. URL: http://10.152.183.45:8080/function/publish-message

Let's verify both functions have been deployed by listing our functions:

faas-cli list

If we request the function listing again, you should see:

Terminal
Function                        Invocations     Replicas
receive-message                 0               1    
publish-message                 0               1  

With the NATS-Connector and two test functions deployed, we are now ready to test our setup.

Testing The NATS connector

We will test out the NATS connector by invoking the publish-message function from the faas-cli:

faas-cli invoke publish-message <<< "nats connector message test"

This command will call the publish-message with the string "nats connector message test". Once the function handler completes, the message will be published to the NATS topic. Once published, the NATS Connector will receive the message and trigger the receive-function message.

We can't directly see the function triggered, but we can view the logs of the receive-message function with the faas-cli. To view the log, we invoke the following command:

faas-cli logs receive-message

Your log output should look similar to the following.

Terminal
2021-08-10T16:22:07Z 2021/08/10 16:22:07 received "nats connector message test"

Here we see that our receive-message function was triggered with the message string that the publish-message function published.

Configuring the NATS Connector

In this article, we have used the NATS Connector default configuration. However, you will likely want to configure it to suit the needs of your application. To change the configuration, update the appropriate container environment variables in the connector-dep.yaml deployment file and re-apply it with kubectl.

Variable Description Default
topics Delimited list of topics nats-test,
broker_host The host, but not the port for NATS nats
async-invocation Queue the invocation with the built-in OpenFaaS queue-worker and return immediately false
gateway_url The URL for the OpenFaaS gateway http://gateway:8080
upstream_timeout Timeout to wait for synchronous invocations 60s
rebuild_interval Interval at which to rebuild the map of topics <> functions 5s
topic_delimiter Used to separate items in topics variable ,

Summary

In this article, we have demonstrate how to deploy the NATS-Connector in a MicroK8S instance and use NATS messages to trigger OpenFaaS functions. With this approach, we have expanded NATS'sutility beyond inter-service messaging to now include OpenFaaS functions.

Summary


Coming up

In the next article, we will consider the problem of where to store state in stateless microservices.