Note
The CCM is natively integrated in [Exoscale Scalable Kubernetes Service][kubernetes] to provides the benefits outlined below seamlessly.
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.
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!