Distributed Fn: beyond “fn start”

Denis Makogon
4 min readFeb 5, 2019

--

A single instance of Fn

One of the most important goals of an open source project is to create a simple and solid user experience. For many projects, this means an easy path from “initial experience” (aka local, single server, etc.) to production deployment.

The Fn Project team works hard on both of these goals. The initial experience is two steps, first installing the CLI:

curl -LSs https://bit.ly/2B7x4zD | sh

Then starting the Fn server using the fn start command.

And that’s it. You now have the Fn server running locally and ready for some serverless magic! You can find the full documentation here.

Distributed Fn

A single instance of Fn server is easy to run, good for demos, presentations, developing functions, and learning the project. It was never meant to be a production deployment. That’s where a bit of configuration turns the same Fn server into a distributed deployment.

By referring to “configuration” I’m talking about a set of environment variables that Fn expects. Specifically, these are:

  • FN_NODE_TYPE — defines a set of API’s that are provided by the Fn node.
  • FN_PUBLIC_LB_URL — an API URL of the Fn runner LB node.
  • FN_RUNNER_API_URL — an API URL of the Fn API node.
  • FN_RUNNER_ADDRESSES — a comma-separated list of addresses of the Fn runner nodes.

These ENV vars are supposed to be assigned to Fn nodes depending on the node type defined with FN_NODE_TYPE.

Node types

All-in-one node. Fn node type defined by FN_NODE_TYPE=all, this is the type of deployment you get from fn start, such that the node plays the role of all 3 node types. The API’s available are apps, functions, and triggers both CRUD and Invoke API’s.

No additional configuration to this node is required.

API node. Fn node type defined by FN_NODE_TYPE=api, this is a type of Fn node that provides Apps/Functions/Triggers CRUD API only. Invoke API is not available. This node must be exposed to users.

Additional configuration required: FN_PUBLIC_LB_URL

Runner node. Fn node type defined by FN_NODE_TYPE=pure-runner , this is a type of Fn node that provides Invoke/Triggers API only. This type of node must not be directly exposed to users.

No additional configuration required.

Runner load balancer. Fn node type defined by FN_NODE_TYPE=lb , this is a type of Fn node that balances the workload among Fn runner nodes.

Additional configuration required: FN_RUNNER_ADDRESSES

With such deployment schema, users will have to work with 2 endpoints — API node endpoint (explicitly) and LB node (implicitly).

Two endpoints?

Yes, this aspect is different from a single instance of Fn server. As a user, you don’t know that you work with two endpoints when you play with a single instance of Fn server because they are identical.

When we are talking about a distributed Fn deployment, we have two types of services: one for performing CRUD operations on app/functions/triggers and another one for calling functions (both invoke and triggering API).

So, for the sake of solid and predictable UX, on the attempt to invoke a function:

fn invoke my-app my-fn

Fn API service will return an annotated invocation URL that will contain a reference to runner LB node:

The same thing happens to the triggering API:

Best ways to deploy Fn

In Kubernetes we trust

The hottest trend in hosting container-based workloads is using Kubernetes and since Fn itself is distributed as a Docker container, the preferred deployment model is to use Kubernetes. That is why we developed the Kuberentes Helm Chart for Fn.

If you prefer not to use Helm, you can still operate Fn on Kubernetes “manually”, e.g. using the Kubernetes Services for the runners (node type pure-runner ). No matter how many copies of Fn runners will be deployed, Kubernetes will take care of traffic routing for all of the Fn runners hosted behind K8s Service, for more information please read the K8S doc.

No Kubernetes — no problem

As you’ve noticed we rely on Kubernetes quite a bit to deploy Fn — mostly because it has become somewhat of a standard for deploying container-based applications. That said, K8S is not required, i.e. there are no strict requirements to run Fn only on top of the K8S. The purpose of this post is to describe the core principles of how Fn is supposed to be deployed and managed. And please, let us know if you have another target platform for deployment.

You may find the following links useful as a general follow-up on this post:

Finally, join the growing Fn Army on Slack!

--

--