Skip to content

Workloads

OpenFaaS can host multiple types of workloads from functions to microservices, but FaaS Functions have the best support.

Common properties

All workloads must:

  • serve HTTP traffic on TCP port 8080
  • assume ephemeral storage
  • be stateless

And integrate with a health-check mechanism with Kubernetes:

  • or enable httpProbe in the helm chart and implement /_/health as a HTTP endpoint
  • create a lock file in /tmp/.lock - removing this file signals service degradation

Note: You can specify a custom HTTP Path for the health-check using the com.openfaas.health.http.path annotation

If running in read-only mode, then you can write files to the /tmp/ mount only. These files may be accessible upon subsequent requests but it is not guaranteed. For instance - if you have two replicas of a function then both may have different contents in their /tmp/ mount. When running without read-only mode you can write files to the user's home directory subject to the same rules.

Functions

To build a function simply use the OpenFaaS CLI to scaffold a new function using one of the official templates or one of your own templates. All FaaS Functions make use of the OpenFaaS classic watchdog or the next-gen of-watchdog.

faas-cli template pull
faas-cli new --list

Or build your own templates Git repository and then pass that as an argument to faas-cli template pull

faas-cli template pull https://github.com/my-org/templates
faas-cli new --list

Custom binaries can also be used as a function. Just use the dockerfile language template and replace the fprocess variable with the command you want to run per request. If you would like to pipe arguments to a CLI utility you can prefix the command with xargs.

Running an existing Docker image on OpenFaaS

Let's take a Node.js app which listens on traffic using port 3000, and assume that we can't make any changes to it.

You can view its Dockerfile and code at: alexellis/expressjs-k8s and the image is published to the Docker Hub at: alexellis2/service:0.3.6

Start by creating a new folder:

mkdir -p node-service/

Write a custom Dockerfile ./node-service/Dockerfile:

# Import the OpenFaaS of-watchdog
FROM openfaas/of-watchdog:0.7.2 as watchdog

# Add a FROM line from your existing image
FROM alexellis2/service:0.3.6

# Let's say that the image listens on port 3000 and 
# that we can't change that easily
ENV http_port 3000

# Install the watchdog from the base image
COPY --from=watchdog /fwatchdog /usr/bin/

# Now set the watchdog as the start-up process
# Along with the HTTP mode, and an upstream URL to 
# where your HTTP server will be running from the original
# image.
ENV mode="http"
ENV upstream_url="http://127.0.0.1:3000"

# Set fprocess to the value you have in your base image
ENV fprocess="node index.js"
CMD ["fwatchdog"]

Now create a stack.yml at the root directory ./stack.yml:

provider:
  name: openfaas
functions:
  node-service:
    handler: ./node-service
    image: docker.io/alexellis2/node-service-watchdog:0.1.0
    lang: dockerfile

Now run faas-cli up

Your code will now listen on port 8080 and fulfil the serverless definition including automatic health-checks and a graceful shutdown.

You can then access the service at: http://127.0.0.1:8080/function/node-service

Custom service account

OpenFaaS Pro feature

This feature is part of the OpenFaaS Pro distribution.

When using Kubernetes, OpenFaaS Pro functions can assume a ServiceAccount in the namespace in which they are deployed.

For example if a workload needed to read logs from the Kubernetes API using a ServiceAccount named function-logs-sa, you could bind it in this way:

stack.yml

functions:
  system-logs:
     annotations:
       com.openfaas.serviceaccount: function-logs-sa

Here is an example Role that can list pods and work with Pod logs within the openfaas-fn namespace:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: function-logs-role
  namespace: openfaas-fn
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: function-logs-role-binding
  namespace: openfaas-fn
subjects:
- kind: ServiceAccount
  name: function-logs-sa
  namespace: openfaas-fn
roleRef:
  kind: Role
  name: function-logs-role
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: function-logs-sa
  namespace: openfaas-fn
  labels:
    app: openfaas

For a full code example and additional use cases, read: Learn how to access the Kubernetes API from a Function

Custom TerminationGracePeriod for long running functions

OpenFaaS Pro feature

This feature is part of the OpenFaaS Pro distribution.

You can configure your functions to drain any requests in flight when scaling down. This prevents errors and makes sure all work is processed, before Kubernetes finally removes any Pods.

To set a custom TerminationGracePeriod for a function, configure a write_timeout environment variable.

functions:
  email-batch:
     environment:
       write_timeout: "1m"

When scaling down the function after scaling up, or scaling to zero, Kubernetes will wait for 1m before removing the function. If there is no work to be done, it could exit sooner because the OpenFaaS watchdog does a safe shutdown.

Read more here: Improving long-running jobs for OpenFaaS users

Stateless microservices

A stateless microservice can be built using the dockerfile language type and the OpenFaaS CLI - or by building a custom Docker image which serves traffic on port 8080 and deploying that via the RESTful API, CLI or UI.

An example of a stateless microservice may be an Express.js application using Node.js, a Sinatra app with Ruby or an ASP.NET 2.0 Core website.

Use of the OpenFaaS next-gen of-watchdog is optional, but recommended for stateless microservices to provide a consistent experience for timeouts, logging and configuration.

On Kubernetes is possible to run any container image as an OpenFaaS function as long as your application exposes port 8080 and has a HTTP health check endpoint.

Custom HTTP health checks

OpenFaaS Pro feature

This feature is part of the OpenFaaS Pro distribution.

The timeoutSeconds, initialDelaySeconds and periodSeconds for liveness and readiness probes can be set globally for the installation: OpenFaaS chart reference.

Annotations can be used to configure probes on a per function basis. Any overrides set in annotations will take precedence over the global configuration.

You can specify the HTTP path of your health check and the initial check delay duration with the following annotations:

  • com.openfaas.health.http.path
  • com.openfaas.health.http.initialDelay
  • com.openfaas.health.http.periodSeconds

Readiness probes use the same HTTP path as the health check by default. The path, initial check delay and failure threshold can be set with these annotations:

  • com.openfaas.ready.http.path
  • com.openfaas.ready.http.initialDelay
  • com.openfaas.ready.http.periodSeconds
  • com.openfaas.ready.http.failureThreshold

For example, you may have a function that takes 30s to initialise, but then only needs to be checked every 5s after that.

functions:
  kubesec:
    image: docker.io/stefanprodan/kubesec:v2.1
    skip_build: true
    annotations:
      com.openfaas.ready.http.path: "/_/ready"
      com.openfaas.ready.http.initialDelay: "30s"
      com.openfaas.ready.http.periodSeconds: 5s

Note: The initial delay value must be a valid Go duration e.g. 80s or 3m.