Akrobateo: A General Purpose Load Balancer for K8s
Want a handy, lightweight load balancer for your Kubernetes deployments? Let's see Kontena's Akrobateo in action.
Join the DZone community and get the full member experience.Join For Free
A lot of solutions rely on the fact that Kubernetes has
LoadBalancer type services. And why not, it's a fantastic way to indirectly get a load balancing solution in place in front of the applications. And of course, there are other nice building blocks that rely on the existence of these load balancers such as external-dns and others. Unfortunately, not all environments are such that there is something to be configured as a load balancer for a service. The environment could be on-premise and/or have the network set up in a way that MetalLB cannot be used. Or you might be running just a small test setup locally and do not wish to build any heavy solutions for it.
To help with these kinds of cases, Kontena has unveiled its newest open source component to the land of Kubernetes. Say hello to Akrobateo, a universal load balancer service implementation. 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 draws heavy inspiration from K3S servicelb controller: https://github.com/rancher/k3s/blob/master/pkg/servicelb/controller.go. As K3S controller is fully and tightly integrated into K3S, for good reason, so we separated the concept into a generic operator usable in any Kubernetes cluster.
To deploy Akrobateo, just use the pre-made deployment manifests to deploy the operator. It'll set up the operator itself and all the needed RBAC rules for it to operate properly.
Let's dig in how Akrobateo works by setting up an example service. As a typical case, you have a
Deployment for which you need to create a load balancer in front. For our example deployment, we'll use a typical
echoserver based example:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: echoserver spec: replicas: 1 template: metadata: labels: app: echoserver spec: containers: - image: gcr.io/google_containers/echoserver:1.0 imagePullPolicy: Always name: echoserver ports: - containerPort: 8080
Then, to create the needed
Service in front of it, we'll use a simple
LoadBalancer type service:
apiVersion: v1 kind: Service metadata: name: echoserver spec: type: LoadBalancer ports: - name: echo port: 8080 targetPort: 8080 protocol: TCP selector: app: echoserver
There's nothing atypical in this — make sure you use proper selector labels to match the pods in the service and also remember to configure the service port(s) properly to match what the application is listening on.
Once Akrobateo sees a service like this, it'll start its operations.
Step one of Akrobateo in action is an automatic creation of a
DaemonSet to deploy an actual load balancer for the service on each node. The pods in the
DaemonSet will do the actual load balancing using the trusted workhorse of the entire internet, iptables. The neat "trick" here is that even as the service is of type
LoadBalancer, it will still get the cluster IP assigned for service. So the actual balancer pod will "route" the traffic from a host port to the services cluster IP on a specific port. Simple, eh?
The second part of Akrobateo in action is the fact that once the balancer pods become active, Akrobateo will sync the node's addresses as the external addresses in the service details. So you should see something like this:
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echoserver LoadBalancer 220.127.116.11 18.104.22.168,22.214.171.124,126.96.36.199,188.8.131.52,184.108.40.206 8080:31278/TCP 34m kubernetes ClusterIP 220.127.116.11 <none> 443/TCP 5d3h
Naturally, hitting any of the reported LB addresses on the configured port should get you directed into the application:
$ curl 18.104.22.168:8080 CLIENT VALUES: client_address=('172.31.5.104', 58861) (172.31.5.104) command=GET path=/ real path=/ query= request_version=HTTP/1.1 SERVER VALUES: server_version=BaseHTTP/0.6 sys_version=Python/3.5.0 protocol_version=HTTP/1.0 HEADERS RECEIVED: Accept=*/* Host=22.214.171.124:9090 User-Agent=curl/7.57.0
The third part of Akrobateo in action is when you actually go and delete the given service. Akrobateo will automatically react and remove the created daemonset. No traces are left behind.
Please give Akrobateo a test run if you have a suitable use case in your hands. Remember that this is the first public release so there might be still some rough edges. And as always, we'd be delighted to hear what you think of it and if you've hit into any troubles. So create issues, give stars and open PR's on the GitHub repo.
Published at DZone with permission of Jussi Nummelin, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.