# Multus CNI: multi-homed pods in Kubernetes, and when a meta-plugin is the wrong layer

> Multus CNI is a CNI meta-plugin that gives pods additional network interfaces by calling other CNI plugins. It solves a real gap in Kubernetes networking, but it sits in front of your default CNI rather than replacing it, and the thick plugin deployment changes the resource profile.

**k8snetworkplumbingwg/multus-cni** — A CNI meta-plugin for multi-homed pods in Kubernetes

- Repository: https://github.com/k8snetworkplumbingwg/multus-cni
- Stars: 2,957 · Forks: 679
- Language: Go
- License: Apache-2.0
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/k8snetworkplumbingwg-multus-cni

## What Multus actually solves, and who ends up needing it

Stock Kubernetes gives each pod one interface besides loopback. That is fine for a web service. It is not fine for a workload that has to sit on a storage VLAN, a management segment and a data plane at the same time. Multus exists for that second case. It is a CNI meta-plugin, meaning it is itself a CNI plugin whose job is to call other CNI plugins, so a pod can be multi-homed with interfaces such as eth0, net0 and net1.

The README is explicit that eth0 stays the cluster network used to reach the Kubernetes API server, kubelet and services, while net0 and net1 are additional attachments created through other plugins such as vlan, vxlan or ptp. That distinction matters more than it looks. Multus does not replace your pod network, and it cannot create one. It layers on top of whatever CNI you already run. The repository topics point at the audience: containerized VNFs, control plane and data plane separation, Kubernetes networking. If you are running telecom network functions, NFV workloads or anything that needs a dedicated interface per traffic class, you are the target user. If you are running ordinary microservices, you almost certainly are not.

## The meta-plugin mechanism and the NetworkAttachmentDefinition contract

Multus follows the Kubernetes Network Custom Resource Definition De-facto Standard from the Network Plumbing Working Group. Rather than inventing its own configuration format, it reads additional network configurations from that standard, which is why the same NetworkAttachmentDefinition objects work across CNI vendors. The meta-plugin receives the pod sandbox request, resolves the additional attachments named in the pod annotation, and delegates each one to the underlying CNI plugin that the attachment describes.

The data flow is therefore: kubelet invokes the CNI plugin chain, Multus runs as the plugin, Multus reads the pod's attachment list, Multus calls each referenced CNI binary in turn, and each of those plugins configures its own interface inside the pod netns. Multus itself does not know how to make a macvlan or an SR-IOV VF; it only knows how to sequence and pass through. That is the whole design, and it is why the project is small in concept and large in operational surface: every additional interface is really your other CNI plugin's problem, surfaced through Multus.

## Installing Multus CNI with kubectl and attaching a macvlan interface

The quickstart requires a default network CNI plugin to be installed first. The README states that each attachment Multus creates is in addition to that default interface, so this is a prerequisite, not a suggestion.

The project's recommended path is the thick plugin, applied as a daemonset. The README gives this exact command:

```bash
kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset-thick.yml
```

After this, the cluster is configured to use Multus, but no pod has an extra interface yet. You still need an attachment definition and a pod that references it. The repository ships examples under examples/, including macvlan-pod.yml and sriov-pod.yml, which are the two most common starting points. The general shape of the workflow is: create a NetworkAttachmentDefinition describing the secondary network, then annotate the pod so Multus knows to attach it. The README points to docs/how-to-use.md and docs/quickstart.md for the full procedure rather than reproducing it inline.

If you are in a resource-constrained environment, the README offers the thin plugin instead:

```bash
kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset.yml
```

Beyond the daemonsets, the README lists three other distribution routes: binaries from the release page, a Docker image from GitHub Container Registry, and building from source via docs/development.md. The Makefile exposes build and test targets that call hack/build-go.sh and hack/test-go.sh, the latter under sudo.

## Thick versus thin: the trade-off you have to pick before you start

Multus 4.0 introduced a client/server deployment called the thick plugin, and renamed the previous approach the thin plugin. The thick plugin is two binaries: multus-daemon, which runs as a local agent on every node, and multus-shim, the CNI plugin that talks to it. The README says the daemon supports additional features that the thin plugin did not have, and names metrics as the example. It also states the cost plainly: the thick plugin consumes more resources.

That is the decision in one sentence. You are trading node memory and a long-running process for features including metrics. The README recommends the thick plugin in most environments and reserves the thin plugin for resource-constrained nodes. I would push back slightly on how casually that recommendation reads, because a daemon on every node is a new failure domain. If multus-daemon is unhealthy, pod sandbox creation on that node is affected. The thin plugin has no such dependency. For a cluster where secondary interfaces are a nice-to-have, the thin plugin is the lower-risk default, and the README does not argue that case for you.

## Where Multus is the wrong tool

The most common misreading is that Multus is a pod network. It is not. It does not provide IPAM, it does not route between pods, and it does not create the eth0 interface that every pod needs. If your problem is pod-to-pod connectivity, Multus will not solve it, and installing it adds a daemonset plus a CRD for nothing.

The second boundary is overlap with your primary CNI. Several CNIs now offer their own multi-network or secondary-interface support, and if yours does, running Multus on top means two systems managing the same interfaces. The README does not discuss this overlap at all, which is a real gap for anyone evaluating the project against a CNI that already handles the case.

The third is operational. Every additional interface depends on the CNI plugin named in its attachment definition being present and working on the node. Multus sequences those calls; it does not validate that the referenced plugin exists or that its configuration is sane. A typo in an attachment definition surfaces as a pod sandbox creation failure, and the README does not document rollback for a failed attachment. That is a debugging path you should expect to walk through kubelet logs rather than Multus documentation.

## Multus CNI versus Cilium and Calico

The comparison people search for is Multus against Cilium or Calico, and the framing is usually wrong. Cilium and Calico are full CNI implementations: they own pod IP addressing, routing, network policy and the default interface. Multus owns none of that. It is a meta-plugin that calls other CNI plugins, so in practice Multus runs alongside Cilium or Calico rather than instead of one.

The real difference in approach is where the network logic lives. Cilium and Calico implement their own dataplane and policy engine, and their secondary-network support is an extension of that engine. Multus delegates entirely. A secondary interface under Multus is configured by whichever plugin the attachment definition names, which could be macvlan, SR-IOV, bridge or a vendor plugin. That delegation is the strength: Multus is not tied to one vendor's dataplane, and the NetworkAttachmentDefinition standard is shared across the ecosystem. It is also the weakness: Multus cannot enforce policy on those interfaces, cannot give you visibility into them, and cannot paper over a broken underlying plugin. Choose Multus when the secondary network belongs to a different technology than your pod network. Choose your CNI's native multi-network feature when it does not.

## Maintenance, licensing and upgrade cost

The last push to the default branch was on 2026-09-16, and the most recent release is v4.3.1 from 2026-09-08, following v4.3.0 in June 2026 and v4.2.4 in February 2026. That cadence suggests a project still being maintained, and the repository is not archived.

The project is licensed Apache-2.0, which is permissive and includes an explicit patent grant. That is a favourable position for commercial adoption, but the licence covers the Multus code only. The CNI plugins you reference in your attachment definitions, and the CNI runtime you deploy, carry their own licences, and you are responsible for checking those separately. Nothing here is legal advice.

The upgrade cost is mostly in the CRD and the daemonset. Because Multus follows the NetworkAttachmentDefinition standard rather than its own format, attachment definitions are not versioned with Multus itself, which reduces churn. The deployment manifests are, so a version bump means reapplying a daemonset and restarting the daemon on every node. go.mod pins Go 1.26.0 and Kubernetes client libraries at v0.36.2, so if you build from source rather than consuming the published image, plan for a toolchain that keeps up with those.

## Conclusion

Adopt Multus when pods genuinely need a second or third interface on a network your default CNI does not own: SR-IOV VFs, macvlan segments, VLAN or VXLAN attachments. Do not adopt it to fix pod-to-pod connectivity, because every attachment it creates is in addition to the default interface, and it cannot create that default itself. Before rolling it out, verify which deployment you are applying (multus-daemonset-thick.yml or multus-daemonset.yml), confirm a default network CNI plugin is already installed, and check whether your CNI's own multi-network support covers the case, since Multus adds a daemon and a NetworkAttachmentDefinition CRD you then have to operate.

## FAQ

### Is Multus a CNI plugin?

Yes, but specifically a meta-plugin: a CNI plugin that calls multiple other CNI plugins. It does not implement pod networking itself, and it requires a default network CNI plugin to already be installed.

### What is Multus CNI?

Multus CNI is a container network interface plugin for Kubernetes that enables attaching multiple network interfaces to pods, creating multi-homed pods with interfaces such as eth0, net0 and net1.

### How to install Multus CNI?

Install a default network CNI plugin first, then apply the thick plugin daemonset with kubectl apply -f https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset-thick.yml. A thin plugin manifest is also provided for resource-constrained environments.

### Is Multus CNI an alternative to Cilium?

No. Cilium is a full CNI implementation that owns pod addressing and policy, while Multus is a meta-plugin that delegates each additional interface to another CNI plugin. In practice Multus runs alongside a CNI such as Cilium rather than replacing it.

## Sources

- [Issues](https://github.com/k8snetworkplumbingwg/multus-cni/issues)
- [k8snetworkplumbingwg/multus-cni on GitHub](https://github.com/k8snetworkplumbingwg/multus-cni)
- [License: Apache-2.0](https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/LICENSE)
- [README](https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/README.md)
- [Releases](https://github.com/k8snetworkplumbingwg/multus-cni/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/k8snetworkplumbingwg-multus-cni
