KubeVirt VM Network Connectivity#
KubeVirt surfaces VM network connectivity through four interrelated mechanisms: IP address population in VMI.Status.Interfaces, TCP port-forwarding, SSH/console tunneling via virt-handler, and the Network Binding Plugin DownwardAPI for exposing pod metadata to sidecars.
VMI Network Status (IP Population)#
vmi.Status.Interfaces is the canonical list of per-interface data (IP, MAC, queue count, link state). It is populated by NetStat.UpdateStatus() in pkg/network/setup/netstat.go, which merges four data sources in priority order:
- Domain spec — MAC address, queue count, link state from the libvirt domain XML
- Pod interface cache — IPv4/IPv6 addresses written during network setup by
discover() - Guest Agent — guest-OS-reported IPs and interface names via QEMU guest agent; overrides cache data only when the existing entry is empty or the guest reports no IPs
- Multus status — secondary interface names from Multus pod annotations
The primary (pod-network) interface is always placed at index 0 in the list . When using masquerade binding, guest-reported IPv6 link-local addresses are filtered out because they are unreachable from the pod network .
How IPs enter the cache#
During NetPod.Setup(), the discover() function reads the pod's current network state via nmstate and writes PodIfaceCacheData{PodIP, PodIPs} to disk for each supported binding: bridge, masquerade, passthrough (PasstBinding), and binding-plugin interfaces (when the pod interface exists). SR-IOV interfaces are skipped. IP ordering (IPv4-first vs. IPv6-first) follows the cluster primary stack by inspecting the MY_POD_IP environment variable .
Port-Forwarding and TCP Tunneling#
Entry point#
PortForwardRequestHandler in pkg/virt-api/rest/portforward.go is the subresource handler registered on both VMI and VM objects. It creates a WebsocketStreamer with:
validateVMIForPortForward— rejects paused VMsnetDial{request}as the connection dialer
Dialer implementations#
pkg/virt-api/rest/dialers.go defines two dialer types sharing a common dialer interface:
| Dialer | Usage | Mechanism |
|---|---|---|
netDial | Port-forward (direct TCP to VM) | Reads vmi.Status.Interfaces[0].IP, dials net.Dial(protocol, ip:port) directly |
handlerDial | VNC, serial console, SSH (via virt-handler) | Resolves virt-handler URL for the VMI's node, opens a WebSocket |
netDial handles IPv6 by wrapping the address in brackets . If vmi.Status.Interfaces is empty, the dial fails with a BadRequest .
handlerDial requires the VMI to be in Running or Scheduled phase and connects to the virt-handler on the VMI's node via TLS .
Network Binding Plugin DownwardAPI#
InterfaceBindingPlugin struct#
Plugins are registered in the KubeVirt CR under spec.configuration.network.binding. The struct includes:
SidecarImage— container run as a sidecar in the virt-launcher podNetworkAttachmentDefinition— Multus NAD referenceDomainAttachmentType—tapormanagedTap(since v1.4)DownwardAPI— which pod data to project into the sidecarMigration— migration method (link-refresh)ComputeResourceOverhead— extra resources added to the compute container
Current DownwardAPI values#
The NetworkBindingDownwardAPIType type currently has one defined constant:
DeviceInfo = "device-info"— projects Multus device-info annotation data into the sidecar. Used today for SR-IOV wiring.
Proposed pod-info extension (in-progress)#
Issue #18025 proposes a second value, pod-info, which would mount a Kubernetes DownwardAPI volume containing metadata.labels and metadata.annotations from the virt-launcher pod. The volume would be projected only into the requesting sidecar — no service-account token or RBAC needed.
The primary motivating use case is SR-IOV + UDN: a sidecar needs final pod annotations (OVN/Multus network status, subnets, routes) to generate guest cloud-init network configuration before KubeVirt creates the cloud-init ISO. A structured follow-up VEP is being tracked in issue #18155 as part of the VEP-190 plugin work.
Key Files Reference#
| File | Role |
|---|---|
pkg/network/setup/netstat.go | IP status aggregation; NetStat.UpdateStatus() |
pkg/network/setup/netpod/discover.go | Pod IP discovery and cache writes during network setup |
pkg/network/setup/netpod/netpod.go | Network binding configuration (bridge, masquerade, managedTap, passthrough) |
pkg/virt-api/rest/portforward.go | Port-forward subresource handler |
pkg/virt-api/rest/dialers.go | netDial (direct TCP) and handlerDial (virt-handler WebSocket) |
staging/src/kubevirt.io/api/core/v1/types.go | InterfaceBindingPlugin, NetworkBindingDownwardAPIType, DeviceInfo |