Skip to content

Develop your Python functions with OpenFaaS and Okteto

Notifications You must be signed in to change notification settings

okteto/python-openfaas

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Develop you Python functions with OpenFaaS and Okteto

In this post we'll talk about how to build a python-based function with OpenFaaS and Okteto.

Prerequisites

  1. Create a free Okteto Cloud account
  2. Install the OpenFaaS cli
  3. Docker running on your local machine
  4. Download and configure your Okteto Cloud Kubernetes credentials

Steps

Deploy your Initial Function

Login to Okteto Cloud and deploy your own instance of OpenFaaS. Don't forget to update the password!

OpenFaaS in Okteto Cloud

Open a terminal, and export your github ID (e.g. rberrelleza)

export GITHUBID=rberrelleza

Login to the Okteto Container Registry with docker. Use your Okteto API token as the password.

docker login registry.cloud.okteto.net -u $GITHUBID
Password:
Login Succeeded

Once OpenFaaS is up and running, login to the gateway from your local computer.

faas-cli login --gateway https://openfaas-ingress-$GITHUBID.cloud.okteto.net --password 'Password123!'
Calling the OpenFaaS server to validate the credentials...
credentials saved for admin https://openfaas-ingress-rberrelleza.cloud.okteto.net

For this post, we are going to create a python function. We'll use faas-cli to create the basic skeleton, using the python3-debian template. This command will create a file called hello-python3.yml with all the details of your function.

faas-cli new --lang python3-debian --prefix registry.cloud.okteto.net/$GITHUBID --gateway https://openfaas-ingress-$GITHUBID.cloud.okteto.net hello-python3
...
...
Function created in folder: hello-python3
Stack file written: hello-python3.yml

Build and Deploy the first version of your function

faas-cli up -f hello-python3.yml
...
...
Deployed. 202 Accepted.
URL: https://openfaas-ingress-rberrelleza.cloud.okteto.net/function/hello-python3

The function is an echo function. You can try it out from the command line:

https://openfaas-ingress-$GITHUBID.cloud.okteto.net/function/hello-python3 -d "hello"
hello

Launch MongoDB

For the purpose of this demo, we are going to update our function to keep track of who attended our event. It needs to do the following:

  • Access MongoDB
  • On POST, take the body of the request and save in on mongodb
  • On GET, return the list of attendees.

You can deploy MongoDB with one click in Okteto Cloud, so we'll go with tat. Browse back to Okteto Cloud and deploy your MongoDB instance.

OpenFaaS in Okteto Cloud

The MongoDB instance deployed by Okteto creates a kubernetes secret with the password. OpenFaaS supports directly mounting Kubernetes secrets in any function. We We are going to use this feature so we don't have to hard code any passwords. Add a secrets key to your hello-python3.yml so it looks like this:

version: 1.0
provider:
  name: openfaas
  gateway: https://openfaas-ingress-rberrelleza.cloud.okteto.net
functions:
  hello-python3:
    lang: python3-debian
    handler: ./hello-python3
    image: registry.cloud.okteto.net/rberrelleza/hello-python3:latest
    secrets:
      - mongodb

And update the function:

faas-cli up -f hello-python3.yml
Deploying: hello-python3.

Deployed. 202 Accepted.
URL: https://openfaas-ingress-rberrelleza.cloud.okteto.net/function/hello-python3

Develop your function

Now is time to add our new code. Normally, you would write the code locally, repackage your function, push the container, wait for the update... Instead, we are going to do it the Okteto style, directly in the cluster. First, create hello-python3/okteto.yml and paste the content below.

name: hello-python3
workdir: /home/app
command: ["bash"]
mountPath: /home/app/function

This file will tell okteto to convert your hello-python3 function into a development environment. It will keep the same configuration, permissions, volumes, etc... but okteto will automatically synchronize your code automatically into /home/app/function.

Start your development environment by running okteto up in the hello-python3 folder:

cd hello-python3
okteto up
 ✓  Development environment activated
 ✓  Files synchronized
    Namespace: rberrelleza
    Name:      hello-python3

And start the function execution by running fwatchdog in your remote development environment:

app@hello-python3-846f46875f-h99tn:~$ fwatchdog
2020/04/25 07:14:33 Version: 0.18.1	SHA: b46be5a4d9d9d55da9c4b1e50d86346e0afccf2d
2020/04/25 07:14:33 Timeouts: read: 5s, write: 5s hard: 0s.
2020/04/25 07:14:33 Listening on port: 8080
2020/04/25 07:14:33 Writing lock-file to: /tmp/.lock
2020/04/25 07:14:33 Metrics listening on port: 8081

At this point, we have the same function we had before, but in a live development environment. Validate that everything works by calling the function again from your local terminal:

$ curl https://openfaas-ingress-$GITHUBID.cloud.okteto.net/function/hello-python3 -d "hello"
hello

Let's implement the first part of our new function. We'll change it so it returns and updates our list of attendees. Open handler.py in your local IDE, and update it to look like this:

import os, json

def handle(req):
    """handle a request to the function
    Args:
        req (str): request body
    """

    method = os.getenv("Http_Method")
    
    if method == "POST":
        return "ok"

    elif method == "GET":
        result = []
        return json.dumps(result)

    return "method not supported"

Save the file, go back to your local terminal, and call the function again:

$ curl https://openfaas-ingress-$GITHUBID.cloud.okteto.net/function/hello-python3
[]

As soon as you change the code okteto synchronizes it to your remote development environment. And as soon as it's updated there, OpenFaaS hot reloads your code, giving you instant feedback on your code changes. So fast.

One of my favorite things about building applications with Okteto is the fact that my remote development environment looks just like production. This means that I have access to the same features, APIs and access patterns that my app is going to use in production. In this case, we can to take advantage of Kubernetes and OpenFaaS' secrets from the very beginning.

When you add a secret in OpenFaaS, it will be mounted inside the /var/secrets/openfaas folder in your function. Our development environment inherits all the configuration, so we can use the same mechanism to get the password. Let's update the code to get the password from that directory and create the mongoDB URI.

import os, json

def get_uri():
    with open('/var/openfaas/secrets/mongodb-password', 'r') as file:
        password = file.read().replace('\n', '')
    return "mongodb://root:{password:s}@mongodb".format(password=password)


def handle(req):
    """handle a request to the function
    Args:
        req (str): request body
    """

    uri = get_uri()
    method = os.getenv("Http_Method")
    if method == "POST":
        return "ok"

    elif method == "GET":
        result = []
        return json.dumps(result)

    return "method not supported"

Finally, let's implement our read / write logic. To keep things simple, we'll assume that the body of the request contains the github ID of the attendee:

import os, json
from pymongo import MongoClient

def get_uri():
    with open('/var/openfaas/secrets/mongodb-password', 'r') as file:
        password = file.read().replace('\n', '')
    return "mongodb://root:{password:s}@mongodb".format(password=password)


def handle(req):
    """handle a request to the function
    Args:
        req (str): request body
    """

    uri = get_uri()
    client = MongoClient(uri)
    db = client['attendees']
    method = os.getenv("Http_Method")
    if method == "POST":
      a = {"githubid": req.strip()}
      db.attendees.insert_one(a)
      return "ok"

    elif method == "GET":
      result = []
      for a in db.attendees.find():
             result.append({"githubid": a[u'githubid']})
      return json.dumps(result)

    return "method not supported"

Since we are adding a non-standard dependency (pymongo), we'll have to install it into the dev environment. Open requirements.txt in your local IDE, and add pymongo. Then, go to your remote development environment, stop fwatchdog and pip install the new dependencies.

app@hello-python3-846f46875f-h99tn:~$ pip install -r function/requirements.txt
...
Collecting pymongo
  Using cached pymongo-3.10.1-cp38-cp38-manylinux2014_x86_64.whl (480 kB)
Installing collected packages: pymongo
Successfully installed pymongo-3.10.1

And start fwatchdog:

app@hello-python3-846f46875f-h99tn:~$ fwatchdog
2020/04/25 07:40:33 Version: 0.18.1	SHA: b46be5a4d9d9d55da9c4b1e50d86346e0afccf2d
2020/04/25 07:40:33 Timeouts: read: 5s, write: 5s hard: 0s.
2020/04/25 07:40:33 Listening on port: 8080
2020/04/25 07:40:33 Writing lock-file to: /tmp/.lock
2020/04/25 07:40:33 Metrics listening on port: 8081

No we are ready for the final test. First, let's do a POST call to register a new attendee.

$ curl -XPOST https://openfaas-ingress-$GITHUBID.cloud.okteto.net/function/hello-python3 -d "ramiro"
ok

Call it a couple of times with different names. Once you are done, do a GET to get the final list of attendees.

$ curl https://openfaas-ingress-$GITHUBID.cloud.okteto.net/function/hello-python3
[{"githubid": "ramiro"}, {"githubid": "cindy"}, {"githubid": "cindy"}, {"githubid": "sangam"}]

Ship your Changes

Now that we are done developing, let's make our changes permanent. First, let's shutdown our remote development environment with the okteto down command:

app@hello-python3-846f46875f-h99tn:~$ exit
$ okteto down
 ✓  Development environment deactivated
 i  Run 'okteto push' to deploy your code changes to the cluster

okteto down will restore your function to the state before we started developing.

Finally, run faas-cli up one more time to build and deploy the final version of your function.

$ cd ..
$ faas-cli up -f hello-python3.yml
Deploying: hello-python3.

Deployed. 202 Accepted.
URL: https://openfaas-ingress-rberrelleza.cloud.okteto.net/function/hello-python3

Check that everything worked by calling the function to get the list of attendees:

$ curl https://openfaas-ingress-$GITHUBID.cloud.okteto.net/function/hello-python3
[{"githubid": "ramiro"}, {"githubid": "cindy"}, {"githubid": "cindy"}, {"githubid": "sangam"}]

Conclusion

In this post we showed you how easy it is to develop OpenFaaS functions with Okteto and Okteto Cloud

First, we used Okteto Cloud to deploy dev instances of OpenFaaS and MongoDb with a single click, creating a realistic production-like environment for us to develop our function.

Then we used okteto to deploy a remote development environment for our function, with the same configuration we would use in production. There, we took advantage of okteto's file synchronization and hot reloading features to get instant feedback as we updated our function.

Okteto Cloud is the best platform for building Cloud Native applications. Get started for free at https://okteto.com.

Releases

No releases published

Packages

No packages published

Languages