Cilium
This page replaces the CNI of a node with Cilium. It shows what to put in the cloud-config, how to make sure that the install worked, and what changes if you also remove kube-proxy. Corium ships kube-router because k0s ships it. That one component does networking, network policy and service proxying. To replace it, you make two decisions.
This page applies to a node that you are about to boot, not to a cluster that already runs. Corium renders
cni: custominto/etc/k0s/k0s.yamlat bootstrap. To change it later, you must edit that file and restart k0s.
For a single node, start at Configure the node. For multiple nodes, read Multi-node clusters first. The CNI is a decision for the whole cluster, and you must declare the chart on the controller only.
Both decisions go in the cloud-config that the node already boots with. First,
k0s must install no CNI, so that two CNIs do not conflict on the same node.
Second, something must install Cilium. cni: custom does the first, and an
entry under addons: does the second. The node then gets to the correct state
without help, and you do not need a second provisioning step.
Configure the node
#cloud-config
corium:
role: single
network:
podCIDR: 10.244.0.0/16
cni: custom
addons:
- name: cilium
chart: cilium/cilium
version: 1.20.2
namespace: kube-system
repository:
name: cilium
url: https://helm.cilium.io/
values:
ipam:
mode: cluster-pool
operator:
clusterPoolIPv4PodCIDRList:
- 10.244.0.0/16This is a complete node.
examples/custom-cni.yaml
is the same document with an SSH key, ready to boot.
Before you boot anything, validate the document:
corium-agent validate node.yaml
node.yaml: valid (role single, cluster corium)What cni: custom and addons: do
cni: custom renders spec.network.provider: custom into /etc/k0s/k0s.yaml.
k0s then deploys no CNI. The node registers, comes up NotReady, and stays
NotReady until Cilium runs. This state is expected, and it is not a failed
boot. See
troubleshooting to tell the two apart.
addons: renders spec.extensions.helm. k0s turns this into Chart resources
that its own controller reconciles, with no Helm binary and no in-cluster
operator. The controller runs the install, not a pod. So the install works while
the cluster has no pod network yet, and this is why you can install a CNI this
way. The Cilium agent and operator both run on the host network, so they do not
need the network that they will provide.
corium-agent bootstrap --dry-run shows what the two fields produce, and it
does not change the machine. The output below shows only the parts that this
page is about:
# /etc/k0s/k0s.yaml
spec:
extensions:
helm:
charts:
- chartname: cilium/cilium
name: cilium
namespace: kube-system
values: |
ipam:
mode: cluster-pool
operator:
clusterPoolIPv4PodCIDRList:
- 10.244.0.0/16
version: 1.20.2
repositories:
- name: cilium
url: https://helm.cilium.io/
network:
podCIDR: 10.244.0.0/16
provider: custom
serviceCIDR: 10.96.0.0/12Corium passes the chart values through without changes. It does not compare
them with the rest of the configuration. You must make sure that
clusterPoolIPv4PodCIDRList agrees with network.podCIDR. If they disagree,
pods get addresses that the cluster does not route.
Nothing to configure for the immutable filesystem
On a read-only OS, two items usually need work. Corium already handles both:
/opt/cni/binis writable. The image points/optat/var/opt, because the CNI DaemonSet installs its binary there. Without this, the first error you see ismkdir /opt/cni: read-only file system. The chart defaults,/opt/cni/binand/etc/cni/net.d, are already where k0s looks. You do not need to setcni.binPathandcni.confPath.- The inotify limits are higher. On a stock host,
cilium connectivity testfails with too many open files. The image ships the higher values in/usr/lib/sysctl.d/.
Verify the install
k0s kubectl get charts -A # did the chart install
k0s kubectl -n kube-system get pods -l k8s-app=cilium # is the agent running
k0s kubectl get nodes # Ready, once it isA few minutes after boot, all three of these must be true:
get charts -Alistsk0s-addon-chart-ciliuminkube-system. If it is missing, k0s did not see the add-on. Make sure that theaddons:block is correct.- The Cilium agent pod is
Runningand1/1ready, one per node.Pendingmeans that nothing scheduled it.CrashLoopBackOffmeans that it started and failed, so read its logs. - The node is
Ready, approximately one minute after the agent reports healthy. Until then,NotReadyis expected, because nothing installed a network yet.
If you install the
Cilium CLI,
cilium status --wait gives more information.
Without kube-proxy
Cilium can do all of the service handling. This needs two changes, and both must be in the configuration that the node first boots with. To remove kube-proxy from a cluster that already runs it is a different task, and a more difficult one.
corium:
role: controller+worker
cluster:
endpoint: 10.0.0.10
network:
cni: custom
# kube-proxy has no corium: key. k0s.patch is applied verbatim to the
# rendered k0s.yaml, so every k0s setting stays reachable.
k0s:
patch:
spec:
network:
kubeProxy:
disabled: true
addons:
- name: cilium
chart: cilium/cilium
version: 1.20.2
namespace: kube-system
repository:
name: cilium
url: https://helm.cilium.io/
values:
kubeProxyReplacement: true
k8sServiceHost: 10.0.0.10
k8sServicePort: 6443Here, k8sServiceHost is required. Cilium must reach the API server to load its
own configuration. Usually it uses the in-cluster kubernetes Service, but that
Service is a ClusterIP, and nothing translates it yet. kube-proxy is gone, and
Cilium is its replacement. Give Cilium an address that works without a cluster
network: the address of a controller, or the HA virtual IP.
Multi-node clusters
The CNI is a decision for the whole cluster, and the control plane makes it:
- Declare the chart on the controller only. If a worker declares
addons:, validation rejects it withaddons: only a controller installs add-ons, but role is "worker". The worker does not ignore it without a message. - Put
network:on the controller too. Corium writes the k0s cluster configuration on controllers only, so it never renders thecni:value of a worker. - Workers need nothing. A worker that joins later is
NotReadyuntil the DaemonSet starts on it, thenReady. There is no step for each node.
Troubleshooting
The node is NotReady and there are no Cilium pods. The chart did not install.
k0s kubectl get charts -A shows what k0s thinks it did, and
journalctl -u k0scontroller | grep -i helm tells you why it did not. The usual
cause is a version that does not exist. The second cause is a node with no route
to helm.cilium.io, because k0s fetches the repository at install time.
Cilium crash-loops with Unable to contact k8s api-server. With
kubeProxyReplacement: true, the cause is a missing or wrong k8sServiceHost.
The agent tries to reach the API server through a Service IP that nothing
translates.
Pods get addresses that the cluster does not route.
clusterPoolIPv4PodCIDRList and network.podCIDR disagree. Nothing makes sure
that they agree, so you must do it.
Everything works, but you expected kube-router. cni: custom stays after
bootstrap. Corium renders it into /etc/k0s/k0s.yaml at bootstrap. To change it
later, edit that file and restart k0s. A reboot does not change it.
Other CNIs
Only the values on this page are specific to Cilium. You install any CNI that
comes as a chart with cni: custom and an add-on. Look for the same two
failures: a chart that does not install, and a pod CIDR that disagrees. Calico
is the exception. It has its own value, cni: calico, and k0s installs it for
you.
The
configuration reference describes every field on
this page.
Feature support lists what else
k0s.patch can reach.