Introduction

Civo provides an automatic load balancing function for all of your Kubernetes clusters. This guide will walk you through the process of creating a Load Balancer service for an application that is running on a cluster on Civo. We will be creating a cluster, adding an Ingress Controller and a simple application, creating a Load Balancer Service, and seeing the result.

Until the launch of the updated Load Balancer function, the Civo Kubernetes service would default to starting up an Ingress Controller that allowed traffic routing to pods on your cluster. You can still opt to start this kind of Ingress Controller by choosing to install the Traefik (NodePort) application from the Marketplace. If you do not specify this NodePort-type Ingress Controller, you will have to set up a Load Balancer-type Ingress Controller. In other words, Civo Kubernetes clusters require you to specify the type of Ingress Controller you want to have running on your cluster.

Load Balancer technology

By creating a Load Balancer, you can manage traffic routing from outside your cluster into the apps running in it. On Civo, these Load Balancers are assigned a public IP address and are separate to your cluster's internal workings. In other words, Civo Load Balancers are our implementation of the Kubernetes External Load Balancer. While these Load Balancers are external to your cluster, they are created and managed as part of your cluster's service definitions, and not from the Civo dashboard. In terms of Kubernetes, a Civo Load Balancer is a Service object with rules much like other Service type objects in Kubernetes, with the key difference that its state is handled by the Cloud Controller Manager that speaks to the Civo API.

Prerequisites

This guide will assume that you have an active Civo account where you can create a Kubernetes cluster. If you have not yet signed up, you can do so here.

In addition, you will need:

Launching a Kubernetes cluster

Let's begin by creating our Kubernetes cluster. This can be done through the Civo dashboard interface on the web, or in one command using the Civo CLI:

$ civo k8s create --wait
The cluster blue-breeze (9574007b-7c52-453d-a483-a9594a312e73) has been created in 1 min 44 sec

In this instance we've just gone with the default values for node count and size and with the generated cluster name.

Next, save our KUBECONFIG file so that we can get to deploying our load balancer.

On the CLI, you can run civo k8s config your_cluster_name --save --merge to have it save the new cluster's configuration alongside any existing KUBECONFIG files you may have. There should then be instructions on how to switch to your new cluster context to be able to run commands against it:

Access your cluster with:
kubectl config use-context blue-breeze
kubectl get node

Once we've switched our context to the new cluster, we're ready to start deploying!

Deploying the sample application

In order for us to test the load balancer functionality, we will need an app to deploy. This guide uses a simple app that returns some information about the request, appropriately called echo. In order to get it to run on our cluster we'll need to prepare a Deployment and a Service for it. Here is an example:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
        - image: dmajrekar/nginx-echo:latest
          name: echo

---
apiVersion: v1
kind: Service
metadata:
  name: echo
  labels:
    app: echo
spec:
  ports:
    - name: "echo"
      port: 5000
      targetPort: 8443
  selector:
    app: echo

Save the above file into a file called deployment.yaml in your working directory. Then, apply it to your cluster:

kubectl apply -f deployment.yaml

You should see the Kubernetes objects be created:

deployment.apps/echo created
service/echo created

We now have an app that is ready to respond to our requests, but no routing to it yet. It's time to deploy our load balancer.

Setting up a Load Balancer

As mentioned above, a Civo Kubernetes Load Balancer is created as a service within your cluster. When that service object is created, the Civo API recognises the request and assigns the Load Balancer a public IP address, as well as begins charging the account for its usage.

Let's start by defining a route into our app that we deployed earlier. Here is a very bare-bones load balancer definition file:

apiVersion: v1
kind: Service
metadata:
  name: civo-lb-service
spec:
  type: LoadBalancer
  selector:
    app: echo
  ports:
  - protocol: TCP
    port: 5000
    targetPort: 8443
    name: echo

You can see that the object is of kind: Service and type: LoadBalancer. Any object with these qualities applied to your cluster will be picked up by the Cloud Controller Manager and trigger the creation of an external load balancer.

If you save the file above as loadbalancer.yaml and run kubectl apply -f loadbalancer.yaml you should see the following:

$ kubectl apply -f loadbalancer.yaml
service/civo-lb-service created

The load balancer should show on your cluster's dashboard page in your account too:

Load Balancer showing its name, algorithm, public IP, private IP within the cluster, state and firewall in this screenshot from the cluster's information page

As mentioned, this is a bare-bones Load Balancer. We will be looking at some configuration options in a moment, but let's test the routing first.

Once the Civo Load Balancer is deployed by creating the Service object, it will begin routing requests sent to the IP address assigned. In this demonstration case, making a HTTP request to 74.220.23.6 on port 5000 will respond with a rotation of the echo deployment on the cluster. The app is one that responds with details of the request and server, so we can extract just the name of the responding host. This shows that the requests are routed to both replica pods I have defined for my app:

$ while sleep 1; do curl -k --silent https://74.220.23.6:5000 | grep -w Hostname; done
Hostname: echo-588764ddd9-jlgx6
Hostname: echo-588764ddd9-xdpjq
Hostname: echo-588764ddd9-jlgx6
Hostname: echo-588764ddd9-xdpjq
Hostname: echo-588764ddd9-jlgx6
Hostname: echo-588764ddd9-xdpjq
Hostname: echo-588764ddd9-jlgx6

If you want to see what the echo app returns in full, you can run curl -k https://your-load-balancer-ip-address:5000 - there's quite a lot of information there.

Configuring Load Balancer options

You may have noticed that the algorithm for the load balancer was round_robin. There is an option to adjust this to least_connections which can be helpful if you have multiple pods and more replicas than the two we defined in our deployment example.

You can see the whole list of available configuration options in the Load Balancer documentation but just as an example we are going to change the algorithm.

For this, we will need to edit our Load Balancer specification. Let's open up our loadbalancer.yaml and add in the annotation nested under metadata:

annotations:
    kubernetes.civo.com/loadbalancer-algorithm: least_connections

So the file becomes

apiVersion: v1
kind: Service
metadata:
  name: civo-lb-service
  annotations:
    kubernetes.civo.com/loadbalancer-algorithm: least_connections
spec:
  type: LoadBalancer
  selector:
    app: echo
  ports:
  - protocol: TCP
    port: 5000
    targetPort: 8443
    name: echo

Now, when we apply the manifest definition to our cluster with kubectl apply -f loadbalancer.yaml we should see a notification that the service has been reconfigured. On the web dashboard for your cluster, you should be able to see the algorithm reflected immediately as well.

This way you can adjust the load balancer specification to match your particular use case, including when already running. The new configuration will be picked up and applied the moment you let the cluster know about it.

Cleaning up

We can delete the load balancer, and this will immediately stop routing traffic to your app. If, for any reason, you decide to delete the load balancer, this is worth keeping in mind.

For the purposes of this guide, we will first delete the Load Balancer, and then the cluster.

To remove the load balancer, you can run a kubectl delete command to it:

$ kubectl delete -f loadbalancer.yaml
service "civo-lb-service" deleted

Alternatively, you can always delete the service by name, by using kubectl delete svc civo-lb-service. Both achieve the same goal.

You can then use the Civo CLI to delete your cluster:

$ civo k8s delete try-123
Warning: Are you sure you want to delete the blue-breeze Kubernetes cluster (y/N) ? y
The Kubernetes cluster (blue-breeze) has been deleted