Your first serverless Python function with OpenFaaS

Let's write a Python function with OpenFaaS that executes hello-world and then move onto something more. We'll start by deploying OpenFaaS on our machine and then we'll install the CLI and write the handler for our function.

OpenFaaS is democratising serverless functions - through Docker containers.

Pre-requisites:

You can read my Introduction to Functions as a Service here.

Step 1 - Install OpenFaaS

If you already have FaaS and the CLI configured, skip to step 3.

If you head over to Github you will find full instructions on how to launch FaaS on Docker Swarm or Kubernetes. For this post we'll use with Swarm, but the instructions are effectively the same once FaaS is deployed.

$ git clone https://github.com/alexellis/faas

Initialize Swarm mode on your Docker daemon.

$ docker swarm init

If you have more than one Ethernet adapter, Swarm may ask you to select one via the --advertise-addr parameter.

You now have a single-node Docker cluster. That's all we need - so now we can deploy the FaaS stack and sample functions:

$ cd faas
$ ./deploy_stack.sh

The default stack contains sample functions, you can play with them via the UI at http://localhost:8080.

You can try out the functions in the UI, for instance The function named func_hubstats will tell you how many Docker Hub images a user has. I typed in my user account and found out I have almost 200 already!

Step 2 - Install the CLI

The CLI is a convenient way to interact with your functions. You can use it to build and/or deploy functions to your cluster.

On a Mac if you're using brew then you can type in:

$ brew install faas-cli

On Linux (or Mac without brew available) type in:

$ curl -sSL https://cli.openfaas.com | sudo sh

If you're using Windows, then you're not out of luck, you can actually find the Windows executable on the FaaS releases page.

Step 3 - Write your function

Create a new folder for your work:

$ mkdir -p ~/functions/hello-python
$ cd ~/functions

Now create hello-python/handler.py:

def handle(req):  
    print("Hello! You said: " + req)

handler.py

All your functions should be specified in a YAML file like this - it tells the CLI what to build and deploy onto your OpenFaaS cluster.

Create file in the root of the functions folder called stack.yml:

provider:  
  name: faas
  gateway: http://localhost:8080

functions:  
  hello-python:
    lang: python
    handler: ./hello-python/
    image: faas-hello-python

stack.yml

Here we can specify a remote gateway if we need to, what the programming language is and where our handler is located within the filesystem.

Even though Docker is used behind the scenes, you don't have to write your own Dockerfile unless you want to - you just need to specify an image name.

So let's build the function.

$ faas-cli -action build -f ./stack.yml
...

Successfully tagged faas-hello-python:latest  
Image: faas-hello-python built.  

You'll now see output from the Docker Engine as it builds your function into an image in your local Docker library. You'll see the image appear on docker images

For example you could run:

$ docker images | grep faas-hello-python
faas-hello-python        latest       e0344b26305f     one minute ago  

If you are using a remote server or a multi-node cluster then you can push your function's image to a registry or the Docker Hub. You'll also need to image the image: name to include your Hub account such as image: alexellis2/faas-hello-python.

Here's how to upload the function to a remote registry (if needed):

$ faas-cli -action push -f ./stack.yml

Let's deploy the function:

$ faas-cli -action deploy -f ./stack.yml
Deploying: hello-python.  
No existing service to remove  
Deployed.  
200 OK  
URL: http://localhost:8080/function/hello-python  

And it's ready to be tested! Either open up the UI or use curl to call it:

$ curl localhost:8080/function/hello-python -d "it's Alex here"
Hello! You said: its Alex here  

Step 4 - Import 3rd party dependencies

So what if you need some dependencies to add behaviour beyond the standard Python libraries? Well you can use pip by providing a requirements.txt file along with your function handler.

Let's include the popular requests module which we can use to interact with webpages.

Create hello-python/requirements.txt

requests  

requirements.txt

Now we can update our Python code. Let's make it so it can accept JSON request of a URL and a string we want to test for:

We'll trigger it using a JSON request, which will take this format:

{
 "url": "https://blog.alexellis.io/rss/",
 "term": "docker"
}

Now update the hello-python/handler.py file:

import requests  
import json

def handle(req):  
    result = {"found": False}
    json_req = json.loads(req)
    r = requests.get(json_req["url"])
    if json_req["term"] in r.text:
        result = {"found": True}

    print json.dumps(result)

handler.py

Then just rebuild, (re-push if needed) and re-deploy.

$ faas-cli -action build -f ./stack.yml
$ faas-cli -action deploy -f ./stack.yml

*This time you'll see pip installing your function's modules such as requests.

Finally test it out!

$ curl localhost:8080/function/hello-python --data-binary '{
 "url": "https://blog.alexellis.io/rss/",
 "term": "docker"
}'

Here's the result:

{"found": true}

Let's try another site:

$ curl localhost:8080/function/hello-python --data-binary '{
 "url": "https://www.kubernetes.io/",
 "term": "docker"
}'
{"found": False}

You can also access the function just as easily via the UI.

Logging and troubleshooting

  • Docker Swarm

You can check the services deployed through the command:

$ docker service ls

Check a specific function like this:

docker service ps <function_name_here>  

Find the logs for a function like this:

docker service ps <function_name_here>  
  • Metrics

Prometheus is also baked into the FaaS stack, which means you can checkout the various metrics on how your functions are being used as well as how long they're taking to run. You can view the Prometheus UI at http://localhost:9090

  • Troubleshooting

If you run into any errors such as Can't reach service check the following:

  • If it's a multi-node cluster, you have to push your images to the Docker Hub or similar registry before deploying
  • If you're still getting the error docker service logs --no-trunc=true hello-python will give a bit more info.
  • If the above didn't help then Docker Swarm has a known issue around re-creating Swarm services, you can work around it by running the deploy command a second time.

Step 5 - Going further

Please show support and Star the project on Github

Now that you've built your first function, why not checkout some of the examples built by the OpenFaaS community? You can share your first serverless OpenFaaS function with us on Twitter or Github.

Want to know more about the OpenFaaS Serverless framework for containers?

You can read my Introduction to Functions as a Service here.

Setup FaaS with free credits

Learn Docker If you want to learn more about Docker for DevOps and developers, checkout my Docker series.

Alex Ellis

Read more posts by this author.

United Kingdom http://alexellis.io/

Subscribe to alex ellis' blog

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!