faas-containerd - serverless without Kubernetes
A little over a year ago I started an experiment to see if I could build an OpenFaaS provider for containerd that would mean a computer could run OpenFaaS functions without the need for a cluster and Kubernetes.
Thanks to some help from @_AkihiroSuda_ 👨🏫 and networking expertise from @bboreham 👑, I now have a working @containerd provider for @OpenFaaS 🚀
— Alex Ellis (@alexellisuk) December 18, 2019
Trying it out on my Mac with multipass from @Canonical
It's early work, but super fast and lean vs. k8shttps://t.co/RPHVX2QnQH pic.twitter.com/fBkq1IkwqO
An update - Jan 2020
faas-containerd is now part of the faasd project, which brings the OpenFaaS experience and ecosystem to containerd.
Learn more about faasd, or continue reading for the original story.
Overview
Let's start with a quick glossary then get into the detail.
-
If you haven't heard of containerd yet, it's a CNCF project and was spun out of the main Docker project. It runs containers, has advanced features like snapshotting and is both fast and lightweight.
-
A simple, modular, and extensible serverless platform for containers, the primary target for production is Kubernetes. Driven three values: developers-first, operator-friendly, and community-centric.
-
A production grade container orchestrator, offered as a service by many cloud providers.
-
A light-weight version of Kubernetes which passes conformance tests.
-
My newest OpenFaaS provider which runs functions in containerd instead of with Kubernetes.
Since my initial attempt went on hold, k3s arrived and has dramatically reduced the memory footprint of Kubernetes and even enabled the single-node use-case even further. k3s does so many smart things like replacing etcd with sqlite and packaging all the code needed into a single binary, including a network driver.
k3s is positioned for the edge, but it does need 500MB of RAM to even run hello-world, that feels like way too much, that's where faas-containerd comes in.
OpenFaaS was originally built only for Docker Swarm and was tightly coupled to its API, so when requirements changed I extracted an interface called "faas-provider", which is now a Golang SDK and has been used by dozens of developers to build different providers for functions. Read more about The Power of Interfaces in OpenFaaS.
A provider implmements: CRUD on functions, secrets and logs. Functions are simply containers that serve traffic on port 8080. For bash, CLIs and other binaries, our "watchdog" can be used as a shim.
In this post I'll introduce you to faas-containerd, what it does, and how you can get involved. First of all, a bit more context.
List of OpenFaaS providers
Here's a summary from the OpenFaaS community.md file. Not all providers are "equal" in terms of features, and support so we've included some notes and grouping.
Official providers developed and supported by the OpenFaaS project
Project name and description | Author | Site | Status |
---|---|---|---|
faas-netes- Kubernetes provider | OpenFaaS | github.com | Supported |
faas-swarm - Docker Swarm provider | OpenFaaS | github.com | Supported |
openfaas-operator - Kubernetes Operator provider | OpenFaaS | github.com | Incubation |
Community providers actively being developed and/or supported by a third-party
Project name and description | Author | Site | Status |
---|---|---|---|
faas-nomad - Nomad provider | Andrew Cornies & Nic Jackson (Hashicorp) | github.com | Incubation |
faas-memory - In-memory provider | Ed Wilde / Alex Ellis | github.com | Inception |
faas-federation - federation provider to route between one or more providers | Ed Wilde / Alex Ellis | github.com | Inception |
faas-fargate - AWS Fargate provider | Edward Wilde | github.com | Incubation |
faas-lambda - AWS Lambda provider | Ed Wilde / Alex Ellis | sales@openfaas.com | Incubation |
faas-containerd - containerd provider for single node / edge | Alex Ellis | github.com | Inception |
Community providers no-longer being maintained
Project name and description | Author | Site | Status |
---|---|---|---|
faas-rancher - Rancher/Cattle provider | Ken Fukuyama | github.com | Inception |
faas-dcos - DCOS provider | Alberto Quario | github.com | Inception |
faas-hyper - Hyper.sh provider | Hyper | github.com | Inception |
faas-guardian - Guardian provider | Nigel Wright | github.com | Inception |
faas-ecs | Xicheng Chang (Huawei) | github.com | Inception |
faas-opendns | OpenDNS / Cisco / EC2 | medium.com | Inception |
What's the role of a provider?
The OpenFaaS gateway hosts a UI and adds some important middleware like metrics, scale from zero, and authz. The provider deals with function CRUD, logs, and secret management.
From the faas-provider sample:
timeout := 8 * time.Second
bootstrapHandlers := bootTypes.FaaSHandlers{
FunctionProxy: handlers.MakeProxy(),
DeleteHandler: handlers.MakeDeleteHandler(clientset),
DeployHandler: handlers.MakeDeployHandler(clientset),
FunctionReader: handlers.MakeFunctionReader(clientset),
ReplicaReader: handlers.MakeReplicaReader(clientset),
ReplicaUpdater: handlers.MakeReplicaUpdater(clientset),
InfoHandler: handlers.MakeInfoHandler(),
LogHandler: logs.NewLogHandlerFunc(requestor,timeout),
}
var port int
port = 8080
bootstrapConfig := bootTypes.FaaSConfig{
ReadTimeout: timeout,
WriteTimeout: timeout,
TCPPort: &port,
}
bootstrap.Serve(&bootstrapHandlers, &bootstrapConfig)
To create your own provider, just head over to faas-provider, vendor the project and create your own HTTP handlers.
The simplest example is the faas-memory provider that I worked on with Ed Wilde. It's useful for testing.
Introducing faas-containerd
The idea with faas-containerd is to create a provider that can run any OpenFaaS function or service using containerd, but faster and using less resources than Kubernetes or k3s.
From the repo:
Some users could benefit from a lightweight, single-node execution environment. Using containerd and bypassing Kubernetes or Docker should reduce the start-time for functions and allow for running in resource-constrained environments.
Pros:
- Fast cold-start
- containerd features available such as pause/snapshot
- Super lightweight
Cons:
- No clustering (yet)
- No inter-service communication (yet)
- Very experimental
I was excited to share a Tweet showing the provider working with faas-cli
and unmodified functions directly from the Function Store, a good test I think.
What are people saying?
There's already been some initial interest from my network.
Here's our first tester, tweeting a picture of his deployment of my ping function:
@alexellisuk one more time, just awesome, check i deploy in @CivoCloud and work nice, and i ask, in theory i can run this in k3s? pic.twitter.com/3z46mhyqWe
— Alejandro JNM. (@alejandrojnm) December 19, 2019
Other folks in the ecosystem are also interested by the possiblities this might bring:
Oooohhhhh! Me likey the sound of this! 🤤
— Michael Irwin (@mikesir87) December 18, 2019
Very cool project
— Jeff Hollan (@jeffhollan) December 18, 2019
Darren Shepherd, the creator of k3s also had some ideas about the project
This makes way more sense to me than FaaS on k8s. I'd even go as far as embed containerd in openfaas. Just make it a single executable.
— Darren Shepherd (@ibuildthecloud) December 19, 2019
Darren's done great work with k3s, and I'm sure there's a lot that can be learned from his approach.
Going further
faas-containerd has generated some initial interest and the proof of concept is working, so you can take it for a spin yourself on a Linux computer, or even a Raspberry Pi.
If you like this idea, or think it's cool, Star / Fork the project for later:
- alexellis/faas-containerd - the new provider
- alexellis/faasd - a Go controller to setup the provider, the Gateway UI, and Prometheus
Here's a diagram of what things might look like, if a "faasd" process was used to package and deploy everything needed:
My wishlist now is to:
- Add "faasd" a controller which starts faas-containerd, the OpenFaaS gateway, and Prometheus to give a fully-functional OpenFaaS setup
- Move from netns to using CNI, perhaps with containerd/go-cni
- Find a way to make the functions run as daemons, or long-running
- Benchmark scenarios like cold-start and raw performance vs a single-node k3s cluster
- Benchmark total memory usage vs single-node k3s
- Ship official builds on GitHub releases and Docker Hub
Stretch goals are:
- To explore inter-service communication - i.e. so that Prometheus can scrape the OpenFaaS gateway
- Service discovery/look-up by name from container to container
Contribute
I'm looking for contributors who can help me with code contributions. It turns out that low-level systems programming with containers is not well documented, but it can be learned through experimentation, which is what I've done here.
If you can help with features, improvements or testing, then please join OpenFaaS Slack.
Similar projects
I wanted to highlight a few similar projects for lightweight multi-node clustering. These are alternatives to Kubernetes, but you may not want to move prod there any time soon.
- boss - run containers like a boss from Michael Crosby - containerd maintainer at Docker
- stellar - a re-think of container orchestration using containerd by Evan Hazlett, Docker
Both projects have some simularities and Michael/Evan are contributing to each other's projects. Guys, if you're listening, thank you for containerd :-)
Tiny provider for a tiny devicxe
It even works on Raspberry Pi / armhf / ARM64 thanks to Golang's cross-compilation ability and the current state of dependent projects like OpenFaaS, Prometheus, NATS, and containerd itself. Given how light-weight this is, it may even open up the possibility of using the dozen of Raspberry Pi Zeros I have in my spare parts box.
Nice! faas-containerd for @openfaas cross-compiles and runs fine on @Raspberry_Pi 😱 #arm #devops #o6s #TeamServerless @containerd pic.twitter.com/5mY6b6zuIa
— Alex Ellis (@alexellisuk) December 18, 2019