Deploying OpenFaaS using Docker Swarm

Updated on June 12, 2020
Deploying OpenFaaS using Docker Swarm header image

Introduction

OpenFaaS is an open-source Function-As-A-Service (FaaS) project which works with Docker Swarm. FaaS provides the ability to run a function by itself or with other functions in a workflow to process information. A function running as a service will be able to scale up or down depending on how much it's used. OpenFaaS will manage Docker containers and function scaling.

This tutorial demonstrates how to deploy a Python 3 function on Docker Swarm and OpenFaaS. The Vultr firewall will prevent extra services being exposed and the Vultr private network will allow Docker nodes to communicate.

1. Configure the Vultr Firewall

The Vultr firewall needs to allow incoming port 22 for SSH, and 8080 for OpenFaaS WebUI and functions. To deploy the firewall on Vultr:

  1. Go to your customer portal.
  2. Click the Firewall tab.
  3. Click blue + icon.
  4. Click Add Firewall Group.

Add a description for the firewall group. This tutorial will use openfaas_fw to to reference this group.

Add rules to the firewall by clicking the + sign under the Inbound IPv4 Rules section. Two rules will automatically be created: Accept traffic to SSH/port 22, and drop any other traffic.

Add a new rule: Accept TCP protocol on port 8080 for OpenFaaS. Check the Vultr Firewall FAQ to learn more.

2. Deploy One-Click Docker Instances

  1. Go to the Vultr dashboard and click "+" to deploy a new instance.

  2. Select the Cloud Compute option.

  3. Choose your desired server location.

  4. Select the Application tab under Server Type.

  5. Choose Docker, Ubuntu 18.04.

  6. Choose your desired server size.

  7. Be sure to click the checkbox for Enable Private Networking.

  8. (Optional) Select your SSH Key. See: How Do I generate SSH Keys

  9. Select the openfaas_fw Firewall group.

  10. Increase the number of VPS being deployed to two, because a manager and a worker node are needed for this guide.

  11. Input the desired hostnames. This guide uses ds1 and ds2.

  12. Click the Deploy button.

    • Host ds1 is the Docker swarm manager node.
    • Host ds2 is the worker node.

3. Configure Private Networking

Navigate to the Network tab in the customer portal. Click the Private Networks category. This page will provide the IP range for the private network. In this post, the 192.0.2.0/24 subnet will be used.

SSH into both ds1 and ds2 and use the Configuring Private Network guide to set the static IP addresses on interface ens7. Display the MAC address for the ens7 (private network) interface on both hosts.

# ip link show ens7

This MAC address will have to be used in the ens7 netplan configuration file. For this tutorial, ds1 (manager node) is assigned 192.0.2.1 and ds2 (worker node) is assigned 192.0.2.2. Replace these values with your private network information.

Disable the firewall on both of the hosts:

# ufw disable

Verify the private network is working by pinging from each host to the other host

4. Configure Docker Swarm

Sets up Docker swarm and make ds1 a manager node. On ds1, execute:

# docker swarm init --advertise-addr 192.0.2.1

When the command is executed, it will display a swarm join command, similar to this:

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-45m6nb1r1i2 ...

Paste that command in the ds2 terminal session to make ds2 a worker node.

root@ds2:~# docker swarm join --token SWMTKN-1-45m6nb1r1i2 ...
This node joined a swarm as a worker.

On host ds1, verify that the worker node appears in the swarm list.

root@ds1:~# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
zdwu416f6eua853dz873nqf2w *   ds1                 Ready               Active              Leader              19.03.9
pwyjws14064v1vs5c4pjzo39o     ds2                 Ready               Active                                  19.03.9

5. Install OpenFaaS

On ds1, the manager node, install OpenFaaS:

root@ds1:~# git clone https://github.com/openfaas/faas
root@ds1:~# cd faas
root@ds1:~# ./deploy_stack.sh

Look for a [Credentials] section in the output. Make note of the username, password, and the shell command displayed.

On ds1, the manager node, install the OpenFaaS command-line utility. The command-line utility provides the ability to build and deploy functions.

root@ds1:~# curl -sSL https://cli.openfaas.com | sudo sh

On ds1, the manager node, execute the shell command provided under the [Credentials] section previously. Below is a truncated example. This authenticates OpenFaaS on the manager node.

root@ds1:~# echo -n c90d...468b | faas-cli login --username=admin --password-stdin

6. Deploy a Function

This is a Python 3 function that returns the current time and your name. On ds1, the manager node, execute the following commands to deploy a function named whattimeisit.

root@ds1:~# cd ~/ && mkdir functions && cd functions
root@ds1:~/functions# faas-cli new whattimeisit --lang python3
root@ds1:~/functions# ls -l
total 12
drwxr-xr-x 21 root root 4096 Jun 10 19:44 template
drwx------  2 root root 4096 Jun 10 19:44 whattimeisit
-rw-------  1 root root  178 Jun 10 19:44 whattimeisit.yml
  • The template directory stores function templates for various different languages.
  • The whattimeisit directory will contain a Python 3 function template.
  • whattimeisit.yml contains OpenFaaS configuration for this function.

Edit whattimeisit/handler.py

root@ds1:~/functions# nano whattimeisit/handler.py

Replace the contents with the following code:

#import datetime library so it can be used to determine the current time
import datetime 
#req is the data provided as an input to the function
def handle(req): 
    #build a string to return
    retstring = "Hello %s, it's %s"%(req, datetime.datetime.now()) 
    return retstring

Save and exit the file. Execute the following to build and deploy the function:

root@ds1:~/functions# faas-cli build -f ./whattimeisit.yml
root@ds1:~/functions# faas-cli deploy -f ./whattimeisit.yml

Test the function, it should work from either node, to either node.

On ds1:

root@ds1:~# curl http://192.0.2.1:8080/function/whattimeisit -d "John"
Hello John, it's 2020-01-01 01:01:01

root@ds1:~# curl http://192.0.2.2:8080/function/whattimeisit -d "John"
Hello John, it's 2020-01-01 01:01:01

On ds2:

root@ds2:~# curl http://192.0.2.1:8080/function/whattimeisit -d "John"
Hello John, it's 2020-01-01 01:01:01

root@ds2:~# curl http://192.0.2.2:8080/function/whattimeisit -d "John"
Hello John, it's 2020-01-01 01:01:01

Resources

Find more information about OpenFaaS and Docker swarm mode.