🇬🇧 First contact with OpenFaaS

What is OpenFaaS?

OpenFaaS is a FaaS server, this is the introduction of the documentation website:

"OpenFaaS (Functions as a Service) is a framework for building serverless functions with Docker and Kubernetes which has first class support for metrics. Any process can be packaged as a function enabling you to consume a range of web events without repetitive boiler-plate coding."

You have to know that OpenFaaS is easy to set up and easy to use. OpenFaaS is polyglot, so it's a good way to learn new languages.

Today, I want to explain how to install OpenFaaS in a virtual machine, using your own Docker registry. And then, we'll see how to write our first function (and even a little bit more). Enjoy your reading 🙂

Install OpenFaaS

There are several ways to install OpenFaaS:

there is an article explaining how to setup OpenFaaS on MiniKube: https://medium.com/devopslinks/getting-started-with-openfaas-on-minikube-634502c7acdf

For my installation, I decided to install the Docker Swarm version of OpenFaaS in a VM and to use a private Docker registry (which I use in another VM). So you need Vagrant and VirtualBox. I did that because I want to be sure to have a reproducible setup everywhere.

So I created a vagrant file, that you can find in this repository https://gitlab.com/openfaas-experiments/openfaas-installation. And the Vagrantfile is here: https://gitlab.com/openfaas-experiments/openfaas-installation/blob/master/Vagrantfile

Some important things to know about this VagrantFile

You can change the IP and name of the virtual machines in the Vagrantfile:

REGISTRY_NAME = "my-registry"
REGISTRY_IP = "172.16.245.160"
REGISTRY_DOMAIN = "registry.test"
REGISTRY_PORT = 5000
REGISTRY = "registry.test:#{REGISTRY_PORT}"

OPENFAAS_NAME = "my-openfaas"
OPENFAAS_IP = "172.16.245.201"

And in the OpenFaaS VM, I add the registry as an unsecure registry in /etc/docker/daemon.json

# Add unsecure registry
echo "" >> /etc/docker/daemon.json
echo '{' >> /etc/docker/daemon.json
echo '  "insecure-registries" : ["#{REGISTRY}"]' >> /etc/docker/daemon.json
echo '}' >> /etc/docker/daemon.json
echo "" >> /etc/docker/daemon.json

OpenFaaS and Docker registry install

You only need to fork this repository: https://gitlab.com/openfaas-experiments/openfaas-installation, and simply run vagrant up at the root of the directory. And wait a little.

During the setup of OpenFaaS, if you watch the logs, you'll get the credentials of the OpenFaaS server. Something like that:

[Credentials]
 username: admin
 password: d3d24b12dcd369ef6707bc810c110b74b70cdfdd4e83f8b021c3d5e19d4ca86c

You need to update your /etc/hosts file with this data:

172.16.245.160 registry.test
172.16.245.201 openfaas.test

Now you can try to access to http://openfaas.test:8080 (and you need your credentials)

CLI Installation

The documentation about the CLI installation is here: https://github.com/openfaas/faas-cli#get-started-install-the-cli or here: https://docs.openfaas.com/cli/install/. In my case, I'm using OSX, so I just need to ype this:

brew install faas-cli

and brew upgrade faas-cli if you want to update (and you are on OSX)

⚠️ :information: On your laptop side (or desktop), you need to install Docker and in the Daemon panel of the Docker preferences, you need to add registry.test:5000 as an insecure registry to be able to use it (then click on Apply & Restart).

ğŸŽ‰ It's time to write our first OpenFaaS function.

First function

So, you have setup Docker, OpenFass CLI on your laptop, and you have 2 VMs runninf (a private Docker registry and an OpenFaaS server)

We are going to create a JavaScript OpenFaaS function, but you have to know that OpenFaaS is polyglot.

mkdir hello-word-project
cd hello-word-project
faas-cli new hello-world --lang node

The OpenFaaS CLI create a full project for you:

.
├── hello-word-project
    ├── hello-world
    │   ├── handler.js
    │   └── package.json
    ├── hello-world.yml
    └── template

The template directory contains function templates for different languages. You can indeed use several functions with a different language in the same project. But today, we'll only use a single JavaScript function.

The hello-world.yml contains all the needed information to deploy the function:

provider:
  name: faas
  gateway: http://127.0.0.1:8080
functions:
  hello-world:
    lang: node
    handler: ./hello-world
    image: hello-world:latest

We are going to update this file with the information of our Docker registry and OpenFaaS server:

provider:
  name: faas
  gateway: http://openfaas.test:8080
functions:
  hello-world:
    lang: node
    handler: ./hello-world
    image: registry.test:5000/hello-world:latest

And as you can see, the main source code in handler.js is pretty simple:

"use strict"

module.exports = (context, callback) => {
  callback(undefined, {status: "done"});
}

Build, then push the function to the registry

faas-cli build -f hello-world.yml 
faas-cli push -f hello-world.yml 

Check it: if you type curl http://registry.test:5000/v2/_catalog you'll get this: {"repositories":["hello-world"]}

Deploy the function

In order to be able to deploy the function, we need to explain to the CLI where is the OpenFaaS server and what are the credentials:

export OPENFAAS_URL=http://openfaas.test:8080
echo -n d3d24b12dcd369ef6707bc810c110b74b70cdfdd4e83f8b021c3d5e19d4ca86c | faas-cli login --username=admin --password-stdin

See https://gitlab.com/openfaas-experiments/openfaas-installation to know how to get the credentials.

Then, you can deploy your :sparkes: function:

faas-cli deploy -f hello-world.yml

It's done ğŸŽ‰ and you can already test it: curl http://openfaas.test:8080/function/hello-world and you'll get {"status":"done"}

  • 👋 you can also test your function directly with the ui of the OpenFaaS server http://openfaas.test:8080/ui/
  • or even in using this: echo | faas-cli invoke hello-world

Some Tips

Environment variables

You can create environmant variables for your function(s). For example, update the hello-world.yml file like that:

provider:
  name: faas
  gateway: http://openfaas.test:8080
functions:
  hello-world:
    lang: node
    environment:
      TOKEN: "ILOVEPANDA"
      MESSAGE: "👋 Hello world 🌍"
    handler: ./hello-world
    image: registry.test:5000/hello-world:latest

and update handler.js:

"use strict"

module.exports = (context, callback) => {
  callback(undefined, {
      token: process.env['TOKEN']
    , message: process.env['MESSAGE']
  })
}

Then, deploy simply your updates with this command faas-cli up -f hello-world.yml. That's all 😀.

Type echo | faas-cli invoke hello-world and you'll get

{"token":"ILOVEPANDA","message":"👋 Hello world 🌍"}

Post data

You need to use contextarguments to get "posted" data. Update handler.js again:

"use strict"

module.exports = (context, callback) => {
  callback(undefined, {
      token: process.env['TOKEN']
    , message: process.env['MESSAGE']
    , data: context.length>0 ? JSON.parse(context) : {}
  })
}

Deploy: faas-cli up -f hello-world.yml and now, try this:

curl -H "Content-Type: application/json" -X POST -d '{"who":"Bob Morane"}' http://openfaas.test:8080/function/hello-world

And you should get:

{"token":"ILOVEPANDA","message":"👋 Hello world 🌍","data":{"who":"Bob Morane"}}

Path

If you want to get your http path (the called url) you can use the Http_Path variable:

Update handler.js again:

"use strict"

module.exports = (context, callback) => {
  callback(undefined, {
      token: process.env['TOKEN']
    , message: process.env['MESSAGE']
    , data: data: context.length>0 ? JSON.parse(context) : {}
    , path: process.env['Http_Path']
  })
}

Deploy: faas-cli up -f hello-world.yml and now, try this:

curl http://openfaas.test:8080/function/hello-world/ping/pong

You'll get:

{"token":"ILOVEPANDA","message":"👋 Hello world 🌍","data":{},"path":"/ping/pong"}

That's all folks for today. Next time will see how to use the GitLab Runners to deploy functions on OpenFaaS.

You can find the source code of the function: https://gitlab.com/openfaas-experiments/openfaas-first-steps

Have a good week-end 👋

Last Articles

Last Updated: 10/20/2018, 8:03:54 AM