RAPID INCIDENT TRIAGE & ACTION PLAN•Performance
01. Error Signature
Multus Secondary Interface Attachment Fix
02. Root Cause Vector

Multus CNI fails to attach a secondary network interface to a pod due to misconfigured NetworkAttachmentDefinition, missing IPAM data, or...

03. Rapid Prescription

Sort lock acquisition order deterministically, or configure explicit session timeouts.

Zero-Trust Client IDE/ Performance

Multus Secondary Interface Attachment Fix

Multus CNI fails to attach a secondary network interface to a pod due to misconfigured NetworkAttachmentDefinition, missing IPAM data, or RBAC gaps — killing workloads that depend on data-plane separation.

SYSTEM STATUS
CREDITS: 0 / 3
source.yaml(46L)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
apiVersion: v1
kind: Pod
metadata:
  name: legacy-payment-processor
  namespace: pci-secure-zone
  annotations:
    # TODO: This annotation is deprecated, but the new CNI config hasn't been rolled out yet.
    k8s.v1.cni.cncf.io/networks: '[{"name": "sriov-net", "interface": "net1"}, {"name": "old-vlan-net", "interface": "net2"}]'
    # VULNERABILITY: Multus expects a single JSON list, but the legacy script injects a malformed second entry.
    v1.multus-cni.io/default-network: 'my-registry.internal/legacy-api:sriov-net@eth1'
    # The old PCI scanner expects this exact format; do not remove.
    internal.annotation.legacy: 'enabled'
spec:
  containers:
  - name: app
    image: my-registry.internal/legacy-api:v2.1.3
    env:
    - name: AWS_ACCESS_KEY_ID
      value: "AKIAIOSFODNN7EXAMPLE"
    - name: AWS_SECRET_ACCESS_KEY
      value: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
    - name: STRIPE_API_KEY
      value: "sk_live_4eC39HqLyjWDarjtT1zdp7dc"
    # TODO: Move this to a secret, but the vault integration is broken.
    - name: DATABASE_URI
      value: "postgresql://user:SuperSecretPass123!@pci-db.internal:5432/transactions?sslmode=require"
    # The following RSA key is a dummy for the legacy SSH tunnel; rotation is overdue.
    - name: LEGACY_SSH_PRIVATE_KEY
      value: |
        -----BEGIN RSA PRIVATE KEY-----
        MIIEowIBAAKCAQEArX8eMH2m7lV8vT6NkL8zK7qjvKpP5nJtYwZqAa1fGgH7sT
        ... [truncated for brevity] ...
        N4K7v8k3qPqQwIDAQABAoIBAQCwV7pJcLkFzQpXKpQ2qYqYQqYqYQqYqYQqYq
        -----END RSA PRIVATE KEY-----
    # Workaround for the network readiness probe; sometimes fails on net2.
    command: ["/bin/sh"]
    args: ["-c", "while true; do sleep 30; done"]
  # The nodeSelector targets old hardware that might not have the SRIOV VF.
  nodeSelector:
    node-role.kubernetes.io/legacy: "true"
  # This toleration is a hack to bypass the taint; the SRIOV DP is not installed on these nodes.
  tolerations:
  - key: "node.kubernetes.io/unschedulable"
    operator: "Exists"
    effect: "NoSchedule"
AI Audit Console
> Waiting for pre-flight audit...
HybridRedactor Engine: Active
TECHNICAL WHITEPAPER & ARCHITECTURE SPEC•Updated 2026

Fixing Multus 'Failed to Create Network Attachment' for Secondary Interfaces in Kubernetes

Threat/Impact Level: HIGH | Downtime Risk: HIGH | Time to Fix: 15–30 mins


TL;DR

  • What broke: Multus CNI cannot attach a secondary interface to your pod. The pod enters ContainerCreating indefinitely or crashes. Network-dependent workloads (SR-IOV, DPDK, storage replication) are dead.
  • How to fix it: Validate the NetworkAttachmentDefinition IPAM config, confirm the master NIC exists on the node, verify the Multus pod annotation syntax, and check RBAC permissions for the net-attach-def resource.
  • Shortcut: Use our Client-Side Sandbox above to auto-refactor your failing NAD YAML or pod annotation without leaking your cluster config.

▼ 🔍 Root Cause Breakdown & Kernel Diagnostics [Click to Expand Deep Dive]

The Incident (What Does the Error Mean?)

You'll see this in kubectl describe pod <pod-name>:

Warning  FailedCreatePodSandBox  kubelet  Failed to create pod sandbox:
  rpc error: code = Unknown desc = failed to create pod network sandbox:
  [failed to create network attachment for pod "default/my-app-7d4f9b-xkp2q"
  in namespace "default": error adding container to network "sriov-net":
  failed to create network attachment: no IP addresses available in range set:
  192.168.1.0/24

Or alternatively:

failed to find network attachment definition "default/macvlan-conf"
failed to delegate add: failed to find plugin "macvlan" in path [/opt/cni/bin]
cannot find IPAM plugin "whereabouts" in /opt/cni/bin

Immediate consequence: The pod never reaches Running. Every restart loop burns node resources. If this is a DaemonSet, every node in the cluster may be affected simultaneously.


▼ 🔍 Detailed Impact & Blast Radius Analysis [Click to Expand Deep Dive]

The Attack Vector / Blast Radius

This is not a soft degradation. This is a hard pod scheduling failure.

Cascade path:

  1. Pod stuck in ContainerCreating → liveness/readiness never fires → Service endpoints never populate → upstream load balancer marks backend unhealthy.
  2. If the failing pod is a storage or CNF workload (Ceph OSD, vRAN DU, Whereabouts IPAM itself), the blast radius expands to data loss or full network plane outage.
  3. In SR-IOV environments, a bad resourceName in the NAD leaves Virtual Functions allocated but unbound — leaking VFs until node reboot.
  4. RBAC misconfiguration on net-attach-def means the Multus daemonset cannot read NADs in foreign namespaces — silently breaking cross-namespace network policies with no obvious error surface.

The non-obvious danger: Multus failures are often silent at the cluster level. Kubernetes marks the pod as ContainerCreating, not Error. Alerts tuned for CrashLoopBackOff miss this entirely. You find out from an application team, not your monitoring stack.


How to Fix It (The Solution)

Step 1 — Confirm the NAD exists in the correct namespace

kubectl get network-attachment-definitions -n <pod-namespace>

The NAD must be in the same namespace as the pod unless you've configured cluster-scoped NADs. This is the #1 mistake.

Step 2 — Validate the annotation syntax on the pod spec

# Pod metadata annotations
- annotations:
-   k8s.v1.cni.cncf.io/networks: macvlan-conf   # WRONG: bare string, no namespace
+ annotations:
+   k8s.v1.cni.cncf.io/networks: default/macvlan-conf  # CORRECT: namespace/name

Step 3 — Fix the NetworkAttachmentDefinition IPAM block

Most no IP addresses available errors are a misconfigured or missing IPAM range, or Whereabouts not installed.

apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: macvlan-conf
  namespace: default
spec:
  config: '{
    "cniVersion": "0.3.1",
    "type": "macvlan",
-   "master": "eth0",
+   "master": "ens3f0",
    "mode": "bridge",
    "ipam": {
-     "type": "host-local",
-     "subnet": "192.168.1.0/24"
+     "type": "whereabouts",
+     "range": "192.168.100.0/24",
+     "exclude": [
+       "192.168.100.0/32",
+       "192.168.100.255/32"
+     ]
    }
  }'

Why whereabouts over host-local: host-local is node-local only — it cannot deduplicate IPs across nodes. In any multi-node scenario, you will get IP collisions. Whereabouts uses etcd/Kubernetes API as a distributed lock.

Step 4 — Confirm the CNI plugin binary exists on the node

# SSH to the affected node
ls /opt/cni/bin/ | grep -E 'macvlan|sriov|whereabouts'

If the binary is missing, the fix is to redeploy the correct CNI plugin DaemonSet — not to patch the NAD.

Step 5 — Fix RBAC for Multus to read NADs

# ClusterRole for multus
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: multus
rules:
- apiGroups: ["k8s.cni.cncf.io"]
  resources: ["network-attachment-definitions"]
- verbs: ["get", "list", "watch"]
+ verbs: ["get", "list", "watch", "create", "update"]  # only if using auto-provisioning

For read-only Multus deployments, get/list/watch is sufficient and correct. If your Multus pods are running as a non-default service account, verify the ClusterRoleBinding maps to the actual service account in the kube-system namespace.

Enterprise Best Practice

  • Pin NAD configs to a dedicated namespace (network-infra) and use NetworkPolicy to restrict who can create/modify NADs. Treat NAD write access as equivalent to node network access.
  • Use Whereabouts with a dedicated etcd backend in high-churn environments (>500 pod/min). The default Kubernetes API store for Whereabouts IP allocations becomes a bottleneck under heavy pod scheduling.
  • Label nodes with available master interfaces and use nodeSelector or nodeAffinity on pods requiring specific secondary NICs. Scheduling a pod requiring ens3f0 onto a node that only has ens4f0 is a guaranteed attach failure.

💡 Tired of pasting proprietary infrastructure configs into public LLMs? Generic AI interfaces log your company's ARNs, connection strings, and private keys. StackEngine enforces client-side zero-trust boundaries—the sandbox above executes 100% locally in your browser. Drop your broken manifest above to redact secrets locally and synthesize deterministic patch drafts with your own API key.

(For CI/CD pipeline automation, install via npm i -g stackengine).


▼ 🔍 Continuous Pipeline Governance & CI/CD Guardrails [Click to Expand Deep Dive]

Prevention in CI/CD

1. OPA/Gatekeeper policy — enforce NAD namespace match:

package multus.nadnamespace

violation[{"msg": msg}] {
  input.review.object.kind == "Pod"
  annotation := input.review.object.metadata.annotations["k8s.v1.cni.cncf.io/networks"]
  not contains(annotation, "/")
  msg := sprintf("Multus network annotation must be namespace-qualified: got '%v'", [annotation])
}

2. Checkov custom check — validate NAD has IPAM type set:

checkov -f nad.yaml --check CKV_K8S_MULTUS_IPAM

Write a custom Checkov check that parses the embedded JSON in spec.config and fails if ipam.type is absent or set to host-local in a multi-node cluster context.

3. Pre-deployment node readiness gate:

Add a Job to your Helm chart or ArgoCD sync wave that runs before your workload:

#!/bin/bash
# Verify master interface and CNI binary exist before workload deploy
for node in $(kubectl get nodes -o jsonpath='{.items[*].metadata.name}'); do
  kubectl debug node/$node -it --image=busybox -- \
    sh -c "ls /host/opt/cni/bin/whereabouts && ip link show ens3f0" 2>&1
done

4. Whereabouts IP exhaustion alert:

# Prometheus alerting rule
- alert: WhereaboutsIPPoolExhausted
  expr: |
    (whereabouts_ip_allocations_total / whereabouts_ip_pool_size) > 0.85
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "Whereabouts IP pool >85% utilized — pod attach failures imminent"

Catch exhaustion before it becomes an outage. At 100% pool utilization, every new pod in that range fails with the exact error at the top of this guide.

Official Grounding & Normative Specifications

The technical diagnostics, error recovery protocols, and prevention patterns in this specification are grounded in official vendor documentation and standards:

Diagnostic & Architectural FAQ

Q1.Why does my pod stay in ContainerCreating with a Multus secondary interface error even though the NetworkAttachmentDefinition exists?
The root cause is a namespace mismatch. Multus requires the NAD to be in the same namespace as the pod, and the pod annotation must use the fully-qualified 'namespace/nad-name' format. Using a bare NAD name causes Multus to silently search in the wrong namespace, leading to a 'failed to create network attachment' error. This is a fundamental namespace isolation failure in your Kubernetes configuration.
Q2.What is the difference between using host-local and whereabouts IPAM in a Multus NetworkAttachmentDefinition?
host-local allocates IPs from a local file on each node with no cross-node coordination, causing IP collisions in multi-node clusters when pods on different nodes receive the same address, leading to silent network conflicts and potential data leakage. Whereabouts uses the Kubernetes API or etcd for distributed locking to ensure unique IP allocation cluster-wide. Manually configuring this is error-prone and introduces security vulnerabilities due to misconfigured IPAM policies. Drop the broken manifest into the StackEngine Local Sandbox above to automatically compile a zero-trust fix that enforces correct IPAM selection and prevents collision risks.
Q3.How do I confirm which CNI plugin binaries are available on a Kubernetes node for Multus secondary interfaces?
To verify CNI plugin binaries, SSH to the node and run 'ls /opt/cni/bin/' or use 'kubectl debug node/<node-name> -it --image=busybox -- ls /host/opt/cni/bin/'. Missing binaries like macvlan or whereabouts require redeploying the CNI plugin DaemonSet; patching the NAD config won't resolve this. Doing this manually across large mono-repos or at scale is a compliance nightmare, as inconsistent binary versions create security gaps and audit failures. Deploy the StackEngine CI/CD Automator (Team Edition) for on-prem, automated pull request generation with Maker-Checker review that enforces binary consistency and compliance across all environments.