Stateful Serverless stack with OpenFaaS & Minio

Would it be for trained AI models or simple files, sometimes you want serverless functions to be able to store data for reuse.

This post presents the deployment of a Stateful Serverless stack. Serverless functions will be deployed with OpenFaas. Static data will be stored on Minio.

Prerequisites

Make sure Docker and faas-cli are installed on your server.

$ command -v docker && echo "Docker is installed." || echo "Docker is not installed."
/usr/bin/docker
Docker is installed.
$ command -v faas && echo "faas-cli is installed." || echo "faas-cli is not installed."
/usr/local/bin/faas
faas-cli is installed.

Run Minio database

By default, OpenFaaS functions are part of func_functions network. Minio database needs to be part of the same network in order to be accessible from OpenFaaS deployments. The --name option specifies the name and hostname of the service.

$ docker service create --name minio \
                        -p 9000:9000 \
                        --network=func_functions \
                        --env MINIO_ACCESS_KEY=minio \
                        --env MINIO_SECRET_KEY=minio123 \
                        minio/minio server /data

OpenFaaS functions can now access the database at minio:9000.

Serverless function

Create

Let us create a simple function which creates a Minio bucket.

$ faas new --lang python3-debian make-bucket

The function uses Minio Python library. Add it to the dependencies.

$ printf "minio\n" >> make-bucket/requirements.txt

Write the handler in make-bucket/handler.py.

import os, json

from minio import Minio

def handle(req):
    client = Minio('minio:9000', access_key=os.environ['MINIO_ACCESS_KEY'], secret_key=os.environ['MINIO_SECRET_KEY'], secure=False)

    err = None
    try:
        client.make_bucket('abucket')
    except Exception as e:
        err = e.message

    resp = { 'success': False, 'error': err } if err else { 'success': True }
    
    print(json.dumps(resp))

Define Minio creds in make-bucket.yml.

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

functions:
  make-bucket:
    lang: python3-debian
    handler: ./make-bucket
    image: make-bucket
    environment:
      MINIO_ACCESS_KEY: minio     # here
      MINIO_SECRET_KEY: minio123  # and here

Deploy

$ faas build -f make-bucket.yml && faas deploy -f make-bucket.yml

Test

Call it once.

$ curl localhost:8080/function/make-bucket
{"success": true}

The bucket is successfully created.

Call it twice.

$ curl localhost:8080/function/make-bucket
{"success": false, "error": "Your previous request to create the named bucket succeeded and you already own it."}

The bucket already exists.