As the trend doesn’t show any signs of slowing, it is safe to say that Kubernetes (a.k.a k8s) is here to stay: more and more of our customers are running Kubernetes clusters on their Exoscale infrastructure, granting the flexibility of today’s gold standard of workload orchestration on top of rock-solid IaaS foundations.

For them and for everyone, we are happy to announce the first release of the Exoscale Kubernetes Cloud Controller Manager, paving the way for better integration of your Kubernetes clusters on the Exoscale platform.

Exoscale's Official Kubernetes Cloud Controller Manager

First-Class Integration of Your Kubernetes Clusters on Exoscale

A Kubernetes Cloud Controller Manager (CCM) is a software component, part of the control plane, in charge of interacting with the underlying cloud infrastructure. It features transparent bridging of k8s functionalities to corresponding provider-side ones, such as mapping a Kubernetes Service of type LoadBalancer to an Exoscale Network Load Balancer.

Use Case: Load Balancing a Static Website

To demonstrate the benefits of using the Exoscale CCM in your Kubernetes cluster running on Exoscale, let’s use a simple static website exposed outside the cluster via a k8s Service which will be available on the Internet through a Network Load Balancer. For the sake of brevity, we’ll assume that we have a Docker image (hello-corp/website) of it ready to run.

After installing the Cloud Controller in your cluster, we then proceed to deploy the website as a k8s Deployment:

$ cat <<EOF | kubectl apply --namespace=hello-corp -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: website
spec:
  selector:
    matchLabels:
      app: website
  replicas: 3
  template:
    metadata:
      labels:
        app: website
    spec:
      containers:
      - name: website
        image: hello-corp/website:latest
        ports:
        - containerPort: 80
EOF
deployment.apps/website created

We can ensure that our website deployment is effective by looking at the Pods running:

$ kubectl get pods --namespace hello-corp --selector app=website
NAME                       READY   STATUS    RESTARTS   AGE
website-5cfbcdbc65-csxk4   1/1     Running   0          18s
website-5cfbcdbc65-d2zvt   1/1     Running   0          18s
website-5cfbcdbc65-fkvd9   1/1     Running   0          18s

We can now proceed to the declaration of a k8s Service of type LoadBalancer, which will be delegated to the Exoscale CCM for it to handle the creation and management of a Network Load Balancer instance configured to forward the ingress traffic to the cluster Nodes that run our website deployment Pods:

$ cat <<EOF | kubectl apply --namespace hello-corp -f -
kind: Service
apiVersion: v1
metadata:
  name: website
  annotations:
    service.beta.kubernetes.io/exoscale-loadbalancer-zone: "de-muc-1"
spec:
  selector:
    app: website
  type: LoadBalancer
  ports:
  - port: 80
EOF
service/website created

After a short while, we can confirm the availability of our website through a Network Load Balancer instance:

$ kubectl get svc website --namespace hello-corp
NAME      TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
website   LoadBalancer   10.110.181.100   194.182.182.79   80:31476/TCP   37s

If we look at the Network Load Balancer resources in our Exoscale account, we can see the corresponding instance:

$ exo nlb list -z de-muc-1
┼──────────────────────────────────────┼──────────────────────────────────────────┼──────────┼────────────────┼
│                  ID                  │                   NAME                   │   ZONE   │   IP ADDRESS   │
┼──────────────────────────────────────┼──────────────────────────────────────────┼──────────┼────────────────┼
│ 7cdd1d43-9514-414b-937f-a9743754ab19 │ k8s-981eddc1-436c-4c0f-a0d2-b24455d1e48e │ de-muc-1 │ 194.182.182.79 │
┼──────────────────────────────────────┼──────────────────────────────────────────┼──────────┼────────────────┼

$ exo nlb show -z de-muc-1 k8s-981eddc1-436c-4c0f-a0d2-b24455d1e48e
┼───────────────────────┼────────────────────────────────────────────────────────────────────────────────┼
│ NETWORK LOAD BALANCER │                                                                                │
┼───────────────────────┼────────────────────────────────────────────────────────────────────────────────┼
│ ID                    │ 7cdd1d43-9514-414b-937f-a9743754ab19                                           │
│ Name                  │ k8s-981eddc1-436c-4c0f-a0d2-b24455d1e48e                                       │
│ Zone                  │ de-muc-1                                                                       │
│ IP Address            │ 194.182.182.79                                                                 │
│ Description           │                                                                                │
│ Services              │ 0c24cb2e-801f-4c30-9b02-dcc5fd79d580 | 981eddc1-436c-4c0f-a0d2-b24455d1e48e-80 │
│ State                 │ running                                                                        │
┼───────────────────────┼────────────────────────────────────────────────────────────────────────────────┼

Additionally, a NLB service has been defined to forward traffic towards our Kubernetes Service:

$ exo nlb svc show -z de-muc-1 k8s-981eddc1-436c-4c0f-a0d2-b24455d1e48e 981eddc1-436c-4c0f-a0d2-b24455d1e48e-80
┼──────────────────────┼─────────────────────────────────────────┼
│     NLB SERVICE      │                                         │
┼──────────────────────┼─────────────────────────────────────────┼
│ ID                   │ 0c24cb2e-801f-4c30-9b02-dcc5fd79d580    │
│ Name                 │ 981eddc1-436c-4c0f-a0d2-b24455d1e48e-80 │
│ Description          │                                         │
│ Instance Pool ID     │ 3a202310-0bbe-6045-52ea-82506d3b9594    │
│ Protocol             │ tcp                                     │
│ Port                 │ 80                                      │
│ Target Port          │ 31476                                   │
│ Strategy             │ round-robin                             │
│ Healthcheck Mode     │ tcp                                     │
│ Healthcheck Port     │ 31476                                   │
│ Healthcheck Interval │ 10s                                     │
│ Healthcheck Timeout  │ 5s                                      │
│ Healthcheck Retries  │ 1                                       │
│ Healthcheck Status   │ 194.182.181.144 | success               │
│                      │ 194.182.180.94 | success                │
│ State                │ running                                 │
┼──────────────────────┼─────────────────────────────────────────┼

If we query the Kubernetes cluster API to retrieve the external IP addresses of the Nodes, we can confirm that they match the NLB service’s target IP addresses:

$ kubectl get nodes --selector '!node-role.kubernetes.io/master' \
    -o jsonpath='{.items[*].status.addresses[?(@.type=="ExternalIP")].address}'
194.182.181.144 194.182.180.94

Finally, we can reach our website through the Load Balancer IP address:

$ curl http://194.182.182.79
Welcome to Hello Corp

To illustrate the load balancing across our Pods, we’ve added a custom HTTP header X-Served-By to our website responses to report information about the server that has handled the request:

$ for i in {1..10} ; do curl -iI http://194.182.182.79 | grep "^X-Served-By:" ; done
X-Served-By: 192.168.132.85:80@website-5cfbcdbc65-fkvd9
X-Served-By: 192.168.132.86:80@website-5cfbcdbc65-csxk4
X-Served-By: 192.168.132.86:80@website-5cfbcdbc65-csxk4
X-Served-By: 192.168.132.86:80@website-5cfbcdbc65-csxk4
X-Served-By: 192.168.132.85:80@website-5cfbcdbc65-fkvd9
X-Served-By: 192.168.132.86:80@website-5cfbcdbc65-csxk4
X-Served-By: 192.168.132.86:80@website-5cfbcdbc65-csxk4
X-Served-By: 192.168.194.129:80@website-5cfbcdbc65-d2zvt
X-Served-By: 192.168.132.86:80@website-5cfbcdbc65-csxk4
X-Served-By: 192.168.194.129:80@website-5cfbcdbc65-d2zvt

A Small Step Towards More Kubernetes Announcements

The Exoscale CCM has been designed to be easy to use with minimal configuration, however it is highly configurable through Kubernetes manifests annotations.

The introduction of the Exoscale Cloud Controller Manager will further increase the viability of our platform to deploy Kubernetes workloads onto, and we’re committed to support this technology with more upcoming announcements. Stay tuned!