Target pod leaks MAC address before migration handover with Bridge CNI
What happened: During a Live Migration of a Virtual Machine using Multus with Bridge CNI, the target node announces the VM's MAC address to the physical network prematurely, specifically, as soon as the target virt-launcher pod is created (during the Scheduling / PreparingTarget phases). Since the source VM is still active and transmitting data on the source node, the physical switch detects the same MAC address on two different ports, causing MAC Flapping.
What you expected to happen: The network interface on the target node should remain silent until the memory migration is finalized and the source VM is paused. The MAC address should only be visible on the target node during the final handover phase.
How to reproduce it (as minimally and precisely as possible): Steps to reproduce the behavior.
- Setup a 2-node Kubernetes cluster with KubeVirt and Multus CNI.
- Configure a NetworkAttachmentDefinition using the bridge CNI plugin connected to a physical bridge (L2).
- Start a Virtual Machine with a fixed MAC address (e.g., 4a:1b:58:c2:93:07) attached to the bridge network.
- On the target node, monitor the bridge forwarding database in real-time:
bridge monitor | while read line; do echo "[$(date '+%H:%M:%S.%3N')] $line"; done | grep -i <VM_MAC> - In another terminal, monitor the migration phases:
kubectl get vmim -w - Trigger a live migration:
virtctl migrate <VM_NAME>.
Additional context:
kubectl get vmim -A -w -o custom-columns="NAMESPACE:.metadata.namespace,NAME:.metadata.name,PHASE:.status.phase,SOURCE:.status.migrationState.sourceNode,TARGET:.status.migrationState.targetNode" | while read line; do echo "[$(date '+%H:%M:%S.%3N')] $line"; done
[13:57:43.571] default kubevirt-migrate-vm-58jf8 <none> <none> <none>
[13:57:43.591] default kubevirt-migrate-vm-58jf8 <none> <none> <none>
[13:57:43.601] default kubevirt-migrate-vm-58jf8 Pending <none> <none>
[13:57:43.659] default kubevirt-migrate-vm-58jf8 Scheduling <none> <none>
[13:57:51.117] default kubevirt-migrate-vm-58jf8 Scheduled <none> <none>
[13:57:51.159] default kubevirt-migrate-vm-58jf8 PreparingTarget <none> <none>
[13:57:51.277] default kubevirt-migrate-vm-58jf8 TargetReady <none> <none>
[13:57:51.318] default kubevirt-migrate-vm-58jf8 Running <none> <none>
[13:57:53.040] default kubevirt-migrate-vm-58jf8 Succeeded <none> <none>
[13:57:53.058] default kubevirt-migrate-vm-58jf8 Succeeded node2 node1
[13:57:53.094] default kubevirt-migrate-vm-58jf8 Succeeded node2 node1root@node1:/home/ubuntu# bridge monitor | while read line; do echo "[$(date '+%H:%M:%S.%3N')] $line"; done | grep -i "4a:1b:58:c2:93:07"
[13:57:45.323] 4a:1b:58:c2:93:07 dev veth64f5f47a master br0
[13:57:51.176] Deleted 4a:1b:58:c2:93:07 dev veth64f5f47a master br0
[13:57:52.842] 4a:1b:58:c2:93:07 dev veth64f5f47a master br0 root@node2:/home/ubuntu# bridge monitor | while read line; do echo "[$(date '+%H:%M:%S.%3N')] $line"; done | grep -i "4a:1b:58:c2:93:07"
[13:58:02.064] Deleted 4a:1b:58:c2:93:07 dev veth9a43fe13 master br0Environment:
- KubeVirt version (use
virtctl version): v1.7.0 - Kubernetes version (use
kubectl version): v1.34.5+rke2r1 - VM or VMI specifications: N/A
- Cloud provider or hardware configuration: N/A
- OS (e.g. from /etc/os-release): Ubuntu 24.04.3 LTS
- Kernel (e.g.
uname -a):Linux rancher1 6.8.0-101-generic #101-Ubuntu SMP PREEMPT_DYNAMIC Mon Feb 9 10:15:05 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux - Install tools: N/A
- Others: N/A
Source: kubevirt/kubevirt