Analytics Vidhya
Published in

Analytics Vidhya

Serverless with OpenFaas, Kubernetes, and Python

Serverless with OpenFaas

What is Serverless?

FaaS OpenFaas

Docker and Kubernetes

OpenFaas

  1. Setting up Kubernetes and OpenFaas
  2. Dockerizing Flask Application
  3. Creating a Custom Function
  4. Deploying the Function
  5. Testing the Function

Prerequisites

  • Kubernetes cluster: We will need a running Kubernetes cluster. In case Kubernetes Cluster is not available then follow the instructions to Set Up a Kubernetes Cluster.
  • Docker Hub Account: An account at Docker Hub for storing Docker images that we will create during this tutorial. Refer to the Docker Hub page for details about creating a new account.
  • kubectl: Refer to Install and Set Up kubectl page for details about installing kubectl.

1. Setting up Kubernetes and OpenFaas

1.1 Install arkade

# For MacOS / Linux: 
curl -SLsf https://dl.get-arkade.dev/ | sudo sh
# For Windows (using Git Bash)
curl -SLsf https://dl.get-arkade.dev/ | sh

1.2 Install OpenFaas

arkade install openfaas --basic-auth-password password123 --set=faasIdler.dryRun=false
kubectl get deploy --namespace openfaas
OpenFaas-Deployment
kubectl rollout status -n openfaas deploy/gateway
deployment "gateway" successfully rolled out
kubectl port-forward -n openfaas svc/gateway 8080:8080

1.3 Install faas-cli

# MacOS and Linux users# If you run the script as a normal non-root user then the script
# will download the faas-cli binary to the current folder
$ curl -sL https://cli.openfaas.com | sudo sh
# Windows users with (Git Bash)
$ curl -sL https://cli.openfaas.com | sh
faas-cli login --username admin --password password123

2. Dockerizing Flask Application

2.1 Prepare the Application

git clone https://github.com/sumanentc/python-sample-flask-application.git

2.2 Create a Dockerfile

FROM python:3.7-slim-buster

WORKDIR /home/app

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .

CMD python app.py
  • FROM specifies the base container image over which the new image for our application container will be built. Here, we have taken the base image as python:3.7-slim-buster, which is an official Python image in slim variant.
  • WORKDIR indicates the default directory where the application will be installed. I have set it to /home/app. Any commands that are run after this would be executed from inside this folder.
  • COPY simply copies the files specified on the local machine to the container filesystem. I have copied requirements.txt to /home/app.
  • This is followed by RUN, which executes the command provided. Here, we used pip command to install all the dependencies from requirements.txt.
  • Then, we simply copied all the files from our current local folder, which is essentially our application root folder, to /home/app.
  • Finally, we used CMD to run the application by running python app.py.
if __name__ == '__main__':
db.init_app(app)
ma.init_app(app)
app.run(port=5000, debug=True,host='0.0.0.0')

2.2 Create Docker Container Image

$ docker build -t sumand/python-sample-flask .
$ docker images
docker-image

2.3 Push the Image to Docker Hub

$ docker push sumand/python-sample-flask:latest

3. Creating a Custom Function

export OPENFAAS_PREFIX=sumand
faas-cli new --lang dockerfile sample-flask-service
  • sample-flask-service.yml
  • sample-flask-service/Dockerfile
function-files

3.1 Update sample-flask-service.yml

sample-flask-service.yml
  • Lines 1 to 4 contain information about OpenFaas and Gateway. We don’t have to change anything as we are using local OpenFass, else we need to update the gateway URL.
  • Line 6 contains the name of the function, which we created earlier.
  • Line 7 specifies the template, which we used while creating the function.
  • Line 8 specifies the folder (not the file) where our function code is to be found.
  • Line 9 specifies the Docker image name of the function, which will be built with its appropriate prefix.
  • Environment Variables: Lines 10 to 14 contain the environment values, which we have overridden according to our requirement.
    Setting the environment variable RAW_BODY to true is required to set the context.body to the original request body rather than the default behavior of parsing it as JSON.
    Also, we have updated the timeout values, as when these values are set too low they can cause the function to exit prematurely.
  • Autoscaling: Lines 15 to 18 are required to enable autoscaling. By default, OpenFaas will maintain at least one replica of our function so that it is warm and ready to serve traffic at any time with minimal latency. Since we need our function to be serverless we need to set com.openfaas.scale.zero:true along with faasIdler.dryRun=false, which we did earlier in step 1.2.

3.2 Update Dockerfile

DockerFile
  • Line 1 specifies the of-watchdog:0.8.0 as a base image. The of-watchdog implements an HTTP server listening on port 8080, and acts as a reverse proxy for running functions and microservices. It can be used to forward the request to our application.
  • Line 2 specifies the image of our sample flask application, which we created in step 2.
  • From lines 6–7 we are installing watchdog from the base image.
  • From lines 9–19 we are setting up non root user along with access rights.
  • From lines 21-27 we are setting watchdog as a startup process and upsteam_url as our flask application URL.

4. Deploying the Function

faas-cli up -f sample-flask-service.yml
  • creates a local container image of the function
  • pushes the image to the remote registry, which in our case is the docker hub
  • using the OpenFaas REST API, creates a deployment inside Kubernetes Cluster and a new Pod to serve the traffic

5. Testing the Function

kubectl -n openfaas run --image=stefanprodan/faas-grafana:4.6.3 \
--port=3000 grafana
kubectl port-forward deployment/grafana 3000:3000 -n openfaas
OpenFaas Grafana Dashboard
curl http://127.0.0.1:8080/function/sample-flask-service/api/items
Testing one of the API exposed by our Flask application
Grafana Dashboard Showing Autoscaling
kubectl logs -n openfaas deploy/gateway -c gateway -f
Gateway Logs for replica count
Scaling down to 0
Flask API Swagger

Conclusion

References & Useful Readings

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store