In this post I’ll share my experience with installing Cilium in Minikube on my Mac. It was not that hard but I faced an issue I had to troubleshoot. I’ll also show you how to create several Kubernetes clusters in Minikube in order to have one with Calico as CNI and another one with Cilium as CNI. This way I can switch from one to the other according to my needs.

Cilium is a Container Network Interface (CNI) based on eBPF (a recent linux kernel technology that offers better performance than the traditional iptables) which provides network connectivity between the pods as does Calico, Flannel, Weave,… In addition to CNI, Cilium provides also more advanced features in Networking, Observability and Security.

Calico Cluster in Minikube

Let’s start by creating our Calico cluster in Minikube with the following command:

enb@DBI-LT-ENB ~ % minikube start --nodes 2 --network-plugin=cni --cni=calico -p cluster-calico

With this command I’ll start a cluster with 2 nodes and use Calico as CNI. The name of this cluster is cluster-calico.

Cilium Cluster in Minikube

The installation instructions are provided on the Cilium website and include instructions for a cluster using Minikube:

By adapting those instructions we can now create another cluster in Minikube as follows:

enb@DBI-LT-ENB ~ % minikube start --nodes 3 --network-plugin=cni --cni=false -p cluster-cilium

This cluster is named cluster-cilium and will have 3 nodes and will be ready to use the cilium.

Then we can install Cilium CLI and Cilium as per the instructions.

The issue

Unfortunately, the Cilium installation didn’t complete as expected, below is the output of the cilium install command:

enb@DBI-LT-ENB ~ % cilium install
Using Cilium version 1.12.1
Auto-detected cluster name: cluster-cilium
Auto-detected datapath mode: tunnel
Auto-detected kube-proxy has been installed
helm template --namespace kube-system cilium cilium/cilium --version 1.12.1 --set,,encryption.nodeEncryption=false,kubeProxyReplacement=disabled,operator.replicas=1,,,tunnel=vxlan
Storing helm values file in kube-system/cilium-cli-helm-values Secret
Created CA in secret cilium-ca
Generating certificates for Hubble...
Creating Service accounts...
Creating Cluster roles...
Creating ConfigMap for Cilium version 1.12.1...
Creating Agent DaemonSet...
Creating Operator Deployment...
Waiting for Cilium to be installed and ready...
 /¯¯\__/¯¯\    Cilium:         1 errors, 3 warnings
 \__/¯¯\__/    Operator:       OK
 /¯¯\__/¯¯\    Hubble:         disabled
 \__/¯¯\__/    ClusterMesh:    disabled

Deployment        cilium-operator    Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet         cilium             Desired: 3, Unavailable: 3/3
Containers:       cilium             Pending: 3
                  cilium-operator    Running: 1
Cluster Pods:     0/1 managed by Cilium
Image versions    cilium    3
                  cilium-operator 1
Errors:           cilium             cilium          3 pods of DaemonSet cilium are not ready
Warnings:         cilium             cilium-ccmms    pod is pending
                  cilium             cilium-hlwvq    pod is pending
                  cilium             cilium-vpjbq    pod is pending
↩️ Rolling back installation...

Error: Unable to install Cilium: timeout while waiting for status to become successful: context deadline exceeded

We can see that the cilium pod stay in the pending state and so the installation fails. This is confirmed with the following command that gives more information:

enb@DBI-LT-ENB ~ % k get po -n kube-system
NAME                                     READY   STATUS                  RESTARTS      AGE
cilium-operator-6f5c6f768d-zpgjl         1/1     Running                 0             7m5s
cilium-pw7bm                             0/1     Init:ImagePullBackOff   0             7m5s
cilium-qnf4j                             0/1     Init:ImagePullBackOff   0             7m5s
cilium-wzz2t                             0/1     Init:ImagePullBackOff   0             7m5s

The Events section of one of those pod (using kubectl describe pod cilium-pw7bm -n kube-system) gives the output below:

  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  7m21s                  default-scheduler  Successfully assigned kube-system/cilium-pw7bm to cluster-cilium-m03
  Normal   Pulling    2m44s (x3 over 7m20s)  kubelet            Pulling image ""
  Warning  Failed     45s (x3 over 5m21s)    kubelet            Failed to pull image "": rpc error: code = Unknown desc = context deadline exceeded
  Warning  Failed     45s (x3 over 5m21s)    kubelet            Error: ErrImagePull
  Normal   BackOff    7s (x5 over 5m21s)     kubelet            Back-off pulling image ""
  Warning  Failed     7s (x5 over 5m21s)     kubelet            Error: ImagePullBackOff

The kubelet failed to pull the required image for this pod.

The solution

After some investigation I’ve found this post that seemed to be related to the issue above:

The issue is that there is a timeout before the image is completely pulled. The workaround is to pull the image manually with the command below:

enb@DBI-LT-ENB ~ % minikube ssh docker pull "" -p cluster-cilium

I deleted the 3 cilium pods and they came back with the image properly loaded and reached the Running state. I could then run cilium status in order to validate everything was in order:

enb@DBI-LT-ENB ~ % cilium status
 /¯¯\__/¯¯\    Cilium:         OK
 \__/¯¯\__/    Operator:       OK
 /¯¯\__/¯¯\    Hubble:         disabled
 \__/¯¯\__/    ClusterMesh:    disabled

DaemonSet         cilium             Desired: 3, Ready: 3/3, Available: 3/3
Deployment        cilium-operator    Desired: 1, Ready: 1/1, Available: 1/1
Containers:       cilium             Running: 3
                  cilium-operator    Running: 1
Cluster Pods:     1/1 managed by Cilium
Image versions    cilium    3
                  cilium-operator 1

According to the last comments of the post about this issue less than 2 weeks ago, it should be fixed when minikube is using a different container runtime as containerd but I haven’t tried it yet.

Last tips

I’ve started this post by using 2 clusters in minikube, one for calico and one for cilium. If you want to check minikube status or install some addons, you need to specify on which cluster you want to do it using the -p flag. Each cluster is called a profile in minikube and you can check them as follows:

enb@DBI-LT-ENB ~ % minikube profile list
|    Profile     | VM Driver | Runtime |      IP      | Port | Version | Status  | Nodes | Active |
| cluster-calico | docker    | docker  | | 8443 | v1.24.3 | Running |     2 |        |
| cluster-cilium | docker    | docker  | | 8443 | v1.24.3 | Running |     3 |        |

If you want to switch to your calico cluster, just enter the following command:

enb@DBI-LT-ENB ~ % minikube profile cluster-calico
minikube profile was successfully set to cluster-calico

And use minikube profile cluster-cilium in order to switch back to your cilium cluster.

That’s all folks, I hope this post will help you in your testing with minikube and cilium.