Integrating CCM (Cloud Controller Manager) with k3s basically means that your k3s cluster will be able to talk to cloud provider API in order to request and configure things like LoadBalancers (for ingress), apply appropriate labels for nodes, etc. The process differs between cloud providers (and it depends if cloud provider provides CCM in the first place). In this article, we will be installing k3s on DigitalOcean (let me know in the comments if you would like to see an article for different clouds).

The whole process isn’t very complicated but you need to follow the steps carefully. So, first, the master node. We need to pass the following parameters when installing k3s master node:

— disable-cloud-controller

— no-deploy servicelb

— kubelet-arg=”cloud-provider=external”

— kubelet-arg=”provider-id=digitalocean://[master_node_id]”

So, what do they mean? First, as the name suggests disables default k3s cloud controller. We need to do that otherwise k3s will use it’s own builtin “dummy” cloud controller. Second — we ask k3s to not deploy servicelb because it would mess up IP addresses (servicelb would overwrite Ingress IPs with nodes IPs — we want to have DigitalOcean LoadBalancer IPs for service type LoadBalancer instead). Third — that’s a requirement for pretty much any CCM. We simply need to instruct kubelet that we will be using external cloud-provider. Last one — that’s a requirement from DO CCM — if you’ll check DO CCM GitHub repo you’ll see that they simply ask you do pass this parameter to kubelet. [master_node_id] is the droplet id which you can find either in DO Dashboard or by making GET call from the droplet itself to:

So in order to install k3s server prepared for CCM we need to do it this way:



--disable-cloud-controller \

--no-deploy servicelb \

--kubelet-arg=”cloud-provider=external” \

--kubelet-arg=”provider-id=digitalocean://$master_id” curl -sfL https://get.k3s.io | sh -s — server \--disable-cloud-controller \--no-deploy servicelb \--kubelet-arg=”cloud-provider=external” \--kubelet-arg=”provider-id=digitalocean://$master_id”

That’s the first part — the preparation. Now after k3s server starts we need to install the CCM itself. In order to do that, first clone the git repository:

Next, we need to create k8s secret containing DigitalOcean API token. To do that you can either use secret generator from the repo (just follow the instructions) or use this one-liner:

kubectl -n kube-system create secret generic digitalocean --from-literal=access-token=[YOUR_DO_API_TOKEN]

If the secret is saved then simply apply the yaml manifest from the repository:

kubectl apply -f releases/v0.1.21.yml

That’s it! Now, whenever you spin up service with type: LoadBalancer the DigitalOcean LoadBalancer will be created and configured to route the traffic to it. Also — since k3s comes by default with Traefik — the DO LB will be automatically created for it as well.

One more thing. So far we created only k3s master node, for any worker nodes you only need to install k3s with following parameters:

curl -sfL https://get.k3s.io | K3S_TOKEN=${token} sh -s - agent \

--server https://${master_node_ip}:6443 \

--kubelet-arg="cloud-provider=external" \

--kubelet-arg="provider-id=digitalocean://$worker_id"

And that’s it. All the nodes will have proper labels set (public/private ip, DO zone, etc) and routing via DO LB will happen seamlessly too.