Skip to content
Akrobateo is a simple Kubernetes operator to expose in-cluster LoadBalancer services as node hostPorts using DaemonSets.
Branch: master
Clone or download
Type Name Latest commit message Commit time
Failed to load latest commit information.
cmd/manager do single arch builds only in pipeline (#14) May 10, 2019
deploy fix multiarch build and image versions Apr 17, 2019
lb-image log if ip_forward is disabled (#23) May 20, 2019
pkg service lb -> akrobateo (#27) May 24, 2019
test-service Handle updates on the services to trigger DS changes (#6) Mar 11, 2019
version Multiarch images (#10) Apr 11, 2019
.dockerignore Rename to akrobateo (#8) Mar 22, 2019
.drone.yml do single arch builds only in pipeline (#14) May 10, 2019
.gitignore 🌅 Mar 8, 2019
Gopkg.lock 🌅 Mar 8, 2019
Gopkg.toml 🌅 Mar 8, 2019
LICENSE Create LICENSE (#12) May 7, 2019 tweak readme intro (#15) May 13, 2019 do single arch builds only in pipeline (#14) May 10, 2019 fix tag usage in multiarch script (#17) May 13, 2019


Akrobateo is a universal load balancer service implementation for Kubernetes. Akrobateo can work in any environment which makes it suitable for many use cases. And it's super light-weight too. It is implemented as an operator that reacts when it sees type: LoadBalancer services in the cluster.

Akrobateo exposes in-cluster LoadBalancer services as node hostPorts using DaemonSets. The operator naturally also syncs the addresses for the services. This essentially makes the LoadBalancer type services behave pretty much like NodePort services. The drawback with NodePort services is that we're not able to use additional components such as ExternalDNS and others.

The node-port proxy Pods utilize iptables to do the actual traffic forwarding.


This operator draws heavy inspiration from K3S servicelb controller:

As K3S controller is fully and tightly integrated into K3S, with good reasons, we thought we'd separate the concept into generic operator usable in any Kubernetes cluster.

Why DaemonSets?

Running the "proxies" as DaemonSets makes the proxy not to be a single-point-of-failure. So once you've exposed the service you can safely e.g. push the services external addresses into your DNS. This does have the drawback that a given port can be exposed only in one service throughout the cluster.


Use the included script. There's naturally also a Dockerfile for putting everything into an image.

Build automation takes care of building all the release artifacts. So just create a tag for the release and everything will be build. The current build also produces multiarch images for both the operator and the LB image itself.

Running locally

Either use operator-sdk to run it like so:

operator-sdk up local

Or use the locally built binary:

WATCH_NAMESPACE="default" ./output/akrobateo_darwin_amd64

LB_IMAGE env variable can be set to define a custom LB image to be used.


To deploy to live cluster, use manifests in deploy directory. It sets up the operator in kube-system namespace with proper service-account and RBAC to allow access to only needed resources.


Some ideas how to make things more configurable and/or future-proof

DaemonSet vs. Deployment

The original Klippy controller creates Deployments. Maybe user could put some annotation on the service whether he/she wants a deployment or a daemonset created. Operator SDK SHOULD be able to handle the different kinds of objects as long as there's proper owner references set.

Node selection

There should be some way for the user to select which nodes should act as LBs. So something like a node selector is needed on the services as annotation. That probably also means we'd need to support also tolerations.

You can’t perform that action at this time.