Your First OpenFaaS Function on RaspberryPi

Serverless with Functions as a Service!

This post is deprecated, look at The Official OpenFaas Github Repo

Detailed Tour through OpenFaaS:

Go on tour with Alex Ellis, where he takes you through a tour on OpenFaaS and how to setup the framework, and more information on the project:

This is also a great resource OpenFaaS TestDrive

Developing a Random Name and Surname Generator Function:

Using the faas-cli is one amazing cli client, to build, push and deploy your functions, but I wanted to post on how to write a minimal function for Python on the ARM Architecture:

Setting up the OpenFaaS Framework:

I am using my RaspberryPi Swarm Cluster, so I will be using the ARMHF compose file to deploy my stack:

$ git clone https://github.com/openfaas/faas
$ cd faas
$ git checkout 0.6.5
$ ./deploy_stack.armhf.sh

After the deployment is done, you will find the following when listing your services:

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                                   PORTS  
4jcqosqvsnp3        func_wordcount      replicated          1/1                 functions/alpine:latest-armhf  
4wvoqci6sm44        func_nodeinfo       replicated          2/2                 functions/nodeinfo:latest-armhf  
j7l8pbs1cbux        func_gateway        replicated          1/1                 functions/gateway-armhf:0.6.0           *:8080->8080/tcp  
k7wdp7rx4q8j        func_markdown       replicated          1/1                 functions/markdownrender:latest-armhf  
k8zjdgfu9hvq        func_prometheus     replicated          1/1                 alexellis2/prometheus-armhf:1.5.2       *:9090->9090/tcp  
uk4k207ttay4        func_alertmanager   replicated          1/1                 alexellis2/alertmanager-armhf:0.5.1     *:9093->9093/tcp  
ymneye82ktpc        func_echoit         replicated          1/1                 functions/alpine:latest-armhf  

When you head over to http://docker-swarm-address:8080/ui/ you will be able to access the awesome FaaS Gateway Web Interface, where you will be able to execute and add functions.

Port: 9090 is for Prometheus and Port: 9093 is for the AlertManager.

Lets Build a Python Function:

Like mentioning before the faas-cli makes it really convenient to build / deploy your functions, but we will go through them section at a time. All the content is from Alex's Github Repo: OpenFaaS

Create the Working Directory:

$ mkdir openfaas-myfunctions
$ cd openfaas-myfunctions

Create the Dockerfile:

$ cat Dockerfile
FROM armhf/python:2.7-alpine  
RUN apk --no-cache add curl \  
    && curl -sSL https://github.com/openfaas/faas/releases/download/0.6.1/fwatchdog-armhf > /usr/bin/fwatchdog \
    && chmod +x /usr/bin/fwatchdog \
    && apk del curl --no-cache

WORKDIR /root/

COPY index.py .  
# we wont be installing external packages, so leaving out the following:
# COPY requirements.txt .
# RUN pip install -r requirements.txt

COPY function function  
RUN touch ./function/__init__.py  
WORKDIR /root/function/

# we wont be installing external packages, so leaving out the following:
#COPY function/requirements.txt  .
#RUN pip install -r requirements.txt

WORKDIR /root/  
ENV fprocess="python index.py"  
HEALTHCHECK --interval=1s CMD [ -e /tmp/.lock ] || exit 1  
CMD ["fwatchdog"]  

The fwatchdog process provides a interface between the internet and your serverless function. The fwatchdog process is written in Golang and the best of all, its really small in size, but yet powerful!

From the docs:

Every function needs to embed this binary and use it as its ENTRYPOINT or CMD, in effect it is the init process for your container. Once your process is forked the watchdog passses in the HTTP request via stdin and reads a HTTP response via stdout. This means your process does not need to know anything about the web or HTTP.

The main function that will be set to the fprocess environment variable for fwatchdog:

$ cat index.py
# Copyright (c) Alex Ellis 2017. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.

import sys  
from function import handler

def get_stdin():  
    buf = ""
    for line in sys.stdin:
        buf = buf + line
    return buf

if(__name__ == "__main__"):  
    st = get_stdin()
    handler.handle(st)

Our handler function, where we will develop a small function that uses the random library to randomly select a value from an index number using random.choice, and then using a if statement to add some logic between name and surname.

So when we do a POST request, and our body states name, we will then print a name from our names list, that we defined. And so for surnames as well:

$ cat function/handler.py
import random

names = ["ruan", "stefan", "james", "peter", "frank", "george"]  
surnames = ["franklin", "james", "john", "peters", "bester", "adams"]

def handle(st):  
    if st == 'name':
        print(random.choice(names))
    elif st == 'surname':
        print(random.choice(surnames))
    else:
        print(st + ' is not supported')

So we should have this directory structure:

$ tree
.
├── Dockerfile
├── function
│   └── handler.py
└── index.py

1 directory, 3 files  

Now to build and push our image to Docker Hub:

$ docker build -t rbekker87/functions:names-amrhf .
$ docker push rbekker87/functions:names-amrhf

You can use the FaaS Web UI to Deploy your Function, but I will use the REST API to deploy my function:

$ curl http://docker-swarm-address:8080/system/functions -d '{"service": "random", "image": "rbekker87/functions:names-amrhf", "envProcess": "python index.py", "network": "func_functions"}'

Testing out our Serverless Function:

To get a name, pass the name as the data of our POST request:

$ curl -XPOST http://docker-swarm-address:8080/function/random/ -d "name"
peter  

The same, with a surname:

$ curl -XPOST http://docker-swarm-address:8080/function/random/ -d "surname"
bester  

Next, I would like to use Consul as a Key/Value Pair to PUT and GET data from teh K/V store using OpenFaaS.

Have a look at what the community is doing with OpenFaaS, its becoming (well its already) popular!!