OpenFaaS*

This tutorial shows how to set up OpenFaaS running on top of a Kubernetes* cluster on Clear Linux OS, obtain Clear Linux OS based OpenFaaS templates, and develop an example function.

Background

Functions as a Service (FaaS) is a framework for building serverless functions that are ephemeral, automatically scalable, and focused pieces of code running within containers to allow developers to focus on application code rather than infrastructure nuances.

Many cloud service providers have ready-to-use FaaS offerings which offer a high degree of convenience for developers and granular billing based on per-second usage.

If you want an on-premise or self-hosted serverless capability to avoid vendor lock-in or simply want more development, OpenFaaS is currently the most popular solution in the space based on the number of Github stars on the project.

Prerequisites

For simplicity, this tutorial assumes you have a Kubernetes single node cluster with only master node running Clear Linux OS.

  • For detailed instructions on how to install Clear Linux OS, see the getting started section.
  • For a detailed guide on how to set up Kubernetes, see the documentation on Kubernetes.

Note

Please note that in this example the master node was tainted to be able to be scheduled, which means containers are able to be deployed to the master node.

kubectl taint nodes --all node-role.kubernetes.io/master-

Deploy OpenFaaS

  1. Install the official command line tool for using OpenFaas, faas-cli, by installing the faas-cli bundle.

    sudo swupd bundle-add faas-cli
    
  2. Download the faas-netes, the OpenFaaS provider templates that enable Kubernetes for OpenFaaS.

    git clone https://github.com/openfaas/faas-netes.git
    
  3. Set variables for the OpenFaaS admin user and password.

    Warning

    For simplicity, this tutorial uses a basic authentication with an unecrypted username and password. For production environments, see the OpenFaaS documentation on Deploying OpenFaas in Production.

    export FAAS_USER=admin
    export FAAS_PASSWD=clearlinux
    
  4. Deploy the OpenFaaS stack on Kubernetes using kubectl.

    kubectl apply -f faas-netes/namespaces.yml
    
    kubectl -n openfaas create secret generic basic-auth \
    --from-literal=basic-auth-user=$FAAS_USER \
    --from-literal=basic-auth-password="$FAAS_PASSWD"
    
    kubectl apply -f faas-netes/yaml/
    

    Wait for the OpenFaaS pods and services to get ready. This involves downloading container images from the Internet and may take some time depending on your Internet connection. You can enter the commands below to have the terminal wait until services are ready to use.

    kubectl wait --for=condition=available --timeout=600s deployment/gateway -n openfaas
    kubectl wait --for=condition=available --timeout=600s deployment/faas-idler -n openfaas
    
  5. Login to the OpenFaaS instance. 31112 is the default port.

    • You can login over the command-line:

      export OPENFAAS_URL=http://127.0.0.1:31112
      echo -n $FAAS_PASSWD | faas-cli login --password-stdin
      
    • You can also login to the OpenFaaS web interface by navigating to http://${master_node_IP}:31112

    OpenFaaS web interface login page

    Figure 1: OpenFaaS web interface login page

OpenFaaS templates

OpenFaaS templates, though not necessary, abstract configurations for running functions in common programming languages. Templates allows developers to better focus on writing the code for their function.

OpenFaaS has dozens of templates in the official store. There are also Clear Linux OS-based templates available for download.

  1. You can list all the official templates in the store using faas-cli.

    faas-cli template store list
    
    NAME                     SOURCE             DESCRIPTION
    csharp                   openfaas           Classic C# template
    dockerfile               openfaas           Classic Dockerfile template
    go                       openfaas           Classic Golang template
    java8                    openfaas           Classic Java 8 template
    node                     openfaas           Classic NodeJS 8 template
    php7                     openfaas           Classic PHP 7 template
    python                   openfaas           Classic Python 2.7 template
    python3                  openfaas           Classic Python 3.6 template
    ...
    
  2. Create and enter a workspace.

    mkdir ~/faas-example
    cd ~/faas-example
    
  3. Download the Clear Linux OS-based OpenFaaS templates which are stored in the https://github.com/clearlinux/dockerfiles repository and copy them into your working directory.

    git clone https://github.com/clearlinux/dockerfiles.git
    cp -r dockerfiles/FaaS/OpenFaaS/template/ .
    
  4. After the Clear Linux OS based templates have been retrieved, they will show up in the same repository and available to use locally.

    faas-cli new --list
    
    Languages available as templates:
    - dockerfile-clearlinux
    - python3-clearlinux
    

OpenFaaS is ready to use at this point. See the OpenFaaS documentation to learn more about deploying functions.

Example: Develop a function

In this example, we’ll imagine a FaaS solution where: a user provides a URL to a pictures, which invokes a function to do image classification and outputs the result.

We will use the OpenVINO Deep Learning Deployment Toolkit (DLDT) to do the image inference. As inference development is not the focus of this example, we will just use the built-in sample “classification_sample_async” for this function.

We’ll use the python3-clearlinux template as a base and customize it by:

  • Adding additional Clear Linux OS bundles (bundles.txt)
  • Adding additional required python packages (requirements.txt)
  • Adding a script to download and convert dldt models (helper_script.sh)
  • Finally, we’ll develop the python function to be run (handler.py)

More ways to customize the Clear Linux OS based OpenFaaS templates can be found in the README on GitHub.

  1. Enter the previously created working directory.

    cd ~/faas-example
    
  2. Create a new function skeleton

    faas-cli new --lang python3-clearlinux classification-sample --prefix="<your docker name>"
    

    This will create the directory structure below:

    tree .
     ├── classification-sample
     │   ├── bundles.txt
     │   ├── handler.py
     │   ├── helper_script.sh
     │   ├── __init__.py
     │   └── requirements.txt
     ├── classification-sample.yml
    
  3. Add the required Clear Linux OS bundles to the bundles.txt file.

    echo "computer-vision-openvino" >> classification-sample/bundles.txt
    
  4. Add the required python packages to the requirements.txt file.

    echo "glob3" >> classification-sample/requirements.txt
    echo "urllib3" >> classification-sample/requirements.txt
    echo "networkx==2.3" >> classification-sample/requirements.txt
    
  5. OpenCV has a model downloader and other automation tools to help downloading models and converting them into different formats. Customize the OpenFaaS template to use the model-downloader in the helper_script.sh file. The helper_script.sh file script gets executed during the build process.

    helper_script.sh
    cat classification-sample/helper_script.sh
    #!/bin/bash
    
    # Download and convert models
    export MODEL_DIR="/models"
    export MO_PATH="/usr/share/openvino/model-optimizer/mo.py"
    export MODEL_NAME="resnet-50-int8-tf-0001"
    
    # Download and convert models
    model-downloader --name $MODEL_NAME -o $MODEL_DIR
    model-converter --name $MODEL_NAME -d $MODEL_DIR -o $MODEL_DIR --mo $MO_PATH
    
  6. With the requirements added to the template. Write a python in the handler.py file. This function will parse the input picture URL, find the model path, and call “classification_sample_async” to do image classification.

    handler.py
    #!/usr/bin/python3
    
    import os
    import glob
    import urllib.request
    from urllib.parse import urlparse
    from os.path import splitext
    
    ALLOWED_IMAGE_TYPE = [".bmp", ".BMP"]
    
    def get_ext(url):
        parsed = urlparse(url)
        _, ext = splitext(parsed.path)
        return ext
    
    def get_image_from_url(url):
        """get image and save to local path"""
    
        ext = get_ext(url)
    
        local_file_path = "/tmp/image" + ext
        urllib.request.urlretrieve(url, local_file_path)
        return local_file_path
    
    def find_model_path():
        """ return model xml path """
    
        model_dir = os.getenv('MODEL_DIR', '/models')
        model_name = os.getenv('MODEL_NAME', 'resnet-50-int8-tf-0001') + ".xml"
        precision = os.getenv('MODEL_PRECISION', 'FP32')
    
        pattern = model_dir + '/**/' + precision + '/' + model_name
        paths = glob.glob(pattern, recursive=True)
    
        if not len(paths):
            print("No " + model_name + " found")
            return None
    
        return paths[0]
    
    def do_classification(image, model_path):
        """ Use dldt sample classification_sample_async """
    
        cmd = "classification_sample_async -i " + image + " -m " + model_path
        return os.system(cmd)
    
    def handle(req):
        """handle a request to the function
        Args:
            req (str): request body
        """
        if not len(req):
            print("Request body is missing.")
            return
    
        model_path = find_model_path()
        if model_path is None:
            return
    
        if get_ext(req) not in ALLOWED_IMAGE_TYPE:
            print("Only " + ALLOWED_IMAGE_TYPE + " images are allowed.")
            return
    
        file_path = get_image_from_url(req)
        do_classification(file_path, model_path)
    
  7. Build and deploy the function to the OpenFaaS instance.

    faas-cli build --build-arg http_proxy=$http_proxy --build-arg https_proxy=$https_proxy -f classification-sample.yml
    faas-cli deploy --env=http_proxy=$http_proxy --env=https_proxy=$https_proxy -f classification-sample.yml
    
  8. Finally, test the function by going to the OpenFaaS web interface at http://${master_node_IP}:31112 and Invoking the classification-sample function with a URL to any BMP image. The result should show the what the image has been identified as and probability.

    OpenFaaS web interface invoke function

    Figure 2: OpenFaaS web interface invoke function

    OpenFaaS web interface function output

    Figure 3: OpenFaaS web interface invoke function