How to Deploy Multus CNI with Calico and Flannel for Multi‑Network Pods in Kubernetes
This guide explains the background of Multus CNI, details its architecture and CNI type classification, and provides step‑by‑step commands to deploy Multus alongside Calico and Flannel, configure network interfaces, modify Calico IP detection, and verify multi‑network pod connectivity in a Kubernetes cluster.
Background and Need for Multus CNI
In a default Kubernetes pod only two network interfaces exist: loopback and eth0. When an application must expose APIs externally while also handling internal data synchronization, a single NIC cannot meet production‑grade performance, leading to latency and bottlenecks. Multi‑network solutions, especially Multus CNI, are widely adopted because they follow the CNI spec, are stable, and integrate well with other CNI plugins.
What Is Multus CNI?
Multus CNI is an open‑source plugin that implements the CNI specification to enable multiple network interfaces for a pod. It does not provide network configuration itself; instead it delegates to other CNI plugins (e.g., Calico, Flannel) to configure each interface. When Multus is installed, pods can have additional interfaces beyond eth0.
CNI Types Overview
Main : creates container interfaces such as bridge, ipvlan, macvlan, ptp.
IPAM : manages IP address allocation (host‑local, dhcp, calico‑ipam, static, whereabouts).
Meta : extends third‑party plugins (tuning, bandwidth, portmap, etc.). Multus belongs to the Meta class.
Deploying Multus CNI
git clone https://github.com/k8snetworkplumbingwg/multus-cni.git && cd multus-cni/deployments # Deploy the DaemonSet</code><code>kubectl apply -f multus-daemonset-thick.yml # Verify deployment</code><code>kubectl get ds -n kube-system | grep multus</code><code>kubectl get po -n kube-system -o wide | grep multusMultus runs as a DaemonSet on each node, creates the multus‑daemon process, places the multus‑shim binary in /opt/cni/bin, and generates 00-multus.conf with capabilities for bandwidth and port mappings.
{
"capabilities": {"bandwidth": true, "portMappings": true},
"cniVersion": "0.3.1",
"logLevel": "verbose",
"logToStderr": true,
"name": "multus-cni-network",
"clusterNetwork": "/host/etc/cni/net.d/10-calico.conflist",
"type": "multus-shim"
}Environment Information
The cluster uses Calico as the primary CNI (attached to eth0) and Flannel as an attachment network (attached to eth1).
Host eth0 eth1
node1 192.168.5.79 192.168.10.11
node2 192.168.5.126 192.168.10.12
node3 192.168.5.27 192.168.10.13Routing tables show eth0 as the default route on each node.
Deploying Flannel (Attachment Network)
wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.ymlModify the Flannel DaemonSet to bind to eth1 and use a VXLAN backend to avoid conflicts with Calico.
containers:
- name: kube-flannel
image: docker.io/flannel/flannel:v0.22.3
args:
- --iface=eth1
net-conf.json: |
{
"Network": "10.233.0.0/16",
"Backend": {"Type": "vxlan"}
} kubectl apply -f kube-flannel.ymlVerify Flannel pods are running and check the generated flannel.1 bridge on each node.
ip a | grep flannel.1Adjusting Calico to Use eth0
Calico originally uses can‑reach=$(NODEIP), which selects the IP of eth0. To ensure consistency, set the environment variable IP_AUTODETECTION_METHOD=interface=eth0 either via kubectl set env or by editing the DaemonSet.
kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD=interface=eth0After the change, the Calico pods restart and the variable can be verified inside a pod.
kubectl exec -it calico-node-xxxx -n kube-system -- env | grep IP_AUTODETECTION_METHODTesting Multi‑Network Pods
Create a pod that requests the Flannel attachment network via the annotation k8s.v1.cni.cncf.io/networks: flannel.
apiVersion: v1
kind: Pod
metadata:
name: nginx
annotations:
k8s.v1.cni.cncf.io/networks: flannel
spec:
containers:
- name: nginx
image: docker.io/library/nginx:latest kubectl apply -f pod.yamlInspect the pod’s network namespace to see two interfaces: eth0 (Calico) and net1 (Flannel).
nsenter -t $(crictl ps | grep nginx | awk '{print $1}') -n ip aRouting tables show the default route via eth0 and a specific route for the Flannel subnet via net1. Ping tests confirm that the Flannel IP is reachable from the host and from other nodes, while the Calico IP is reachable only through the default route.
ping 10.233.66.2 # Flannel IP – reachable
ping 172.16.28.2 # Calico IP – reachable via eth0Note that NetworkPolicy rules apply only to the primary interface ( eth0) because Flannel does not support NetworkPolicy.
Key Takeaways
Multus CNI enables pods to have multiple network interfaces by delegating to other CNI plugins.
Combining Calico (for primary networking) with Flannel (as an attachment network) provides separate data and control planes.
Proper IP‑autodetection configuration for Calico ensures the intended NIC is used.
Testing confirms that pods can communicate over both networks, but NetworkPolicy only affects the primary Calico interface.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
