DHCP IPAM for Localnet Networks¶
Introduction¶
A Localnet network
attaches pods and VMs directly to a physical network in the provider's
infrastructure. For IP addressing on such a network, Localnet offers three
IPAM modes:
Enabled: OVN-Kubernetes allocates addresses from a statically configuredsubnetspool.Disabled: addressing is left entirely to the workload.DHCP: IP assignment is delegated to an external DHCP server managing the physical network, and OVN-Kubernetes learns the assigned addresses instead of allocating them itself.
This document covers the DHCP mode.
Lease handling depends on the workload type, selected automatically by OVN-Kubernetes:
- Pods use the standard DHCP CNI IPAM plugin on the node, which acquires the lease and maintains it (renewals for the pod's lifetime, and a release attempt on pod deletion).
- KubeVirt VMs (including VFIO passthrough) run a DHCP client inside the guest OS, which owns the lease. OVN-Kubernetes only discovers and reports the initial IP so that features relying on the pod IP keep working.
Enabling the Feature¶
DHCP IPAM mode does not have its own feature flag. It is available whenever
Localnet secondary networks are, i.e. with --enable-multi-network set. No
additional flag is required.
For the pod delegation path, the DHCP CNI IPAM plugin must be present on the node:
/opt/cni/bin/dhcpand a running/opt/cni/bin/dhcp daemonon every node that will host pods on aDHCPIPAM localnet network.ovnkube-nodemust have/opt/cni/binand/run/cnimounted in from the host, so it can exec thedhcpplugin binary and reach the daemon's RPC socket.
KubeVirt VMs do not need the DHCP CNI plugin installed as the one-shot discovery is performed by OVN-Kubernetes itself.
Supported Scope¶
This feature currently supports:
Localnettopology,Secondaryrole networks (the only roleLocalnetsupports).- IPv4 only.
- Regular pods, delegated to the DHCP CNI plugin daemon.
- KubeVirt VMs, including VFIO passthrough,
l2bridge, andmanagedTapbindings, via one-shot DHCP discovery. - Features that rely on the pod IP, such as MultiNetworkPolicy and NetworkQoS.
- KubeVirt VM cold migration (stopping a VM and starting it on another node).
This feature does not currently support:
Layer2topology.- KubeVirt VM live migration.
- IPv6 or dual-stack — the upstream DHCP CNI plugin and the one-shot VM discovery both speak DHCPv4 only.
- Combining
DHCPmode withsubnets—subnetsmust be omitted whenipam.modeisDHCP.
API Overview¶
Set spec.network.localnet.ipam.mode to DHCP on a Secondary role
Localnet CUDN:
apiVersion: k8s.ovn.org/v1
kind: ClusterUserDefinedNetwork
metadata:
name: localnet-dhcp-ipam
spec:
namespaceSelector:
matchLabels:
localnet: "true"
network:
topology: Localnet
localnet:
role: Secondary
physicalNetworkName: physnet
ipam:
mode: DHCP
The CUDN controller renders a NetworkAttachmentDefinition in every selected
namespace. With ipam.mode: DHCP, the generated NAD config carries an
explicit ipam section selecting DHCP addressing. The same NAD serves both
workload types: pods are delegated to the DHCP CNI plugin, while KubeVirt VMs
go through the one-shot discovery described above:
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: localnet-dhcp-ipam
namespace: test-localnet-dhcp-ipam
labels:
k8s.ovn.org/user-defined-network: ""
spec:
config: |
{
"cniVersion": "1.1.0",
"type": "ovn-k8s-cni-overlay",
"name": "cluster_udn_localnet-dhcp-ipam",
"netAttachDefName": "test-localnet-dhcp-ipam/localnet-dhcp-ipam",
"topology": "localnet",
"role": "secondary",
"physicalNetworkName": "physnet",
"ipam": { "type": "dhcp" }
}
Attach a pod or VM to the network the same way as any other secondary UDN, via
the k8s.v1.cni.cncf.io/networks annotation (or the KubeVirt equivalent for
VMs). No further per-pod configuration is required: ovnkube-node detects
ipam.type: "dhcp" in the NAD config automatically on CNI ADD.
Troubleshooting¶
Check the DHCP-learned IP recorded on the pod. The entry for the DHCP
network carries an additional ipam_mode: "dhcp" field marking the address as
externally assigned rather than allocated by OVN-Kubernetes:
kubectl get pod test-localnet-pod -n test-localnet-dhcp-ipam \
-o jsonpath='{.metadata.annotations.k8s\.ovn\.org/pod-networks}' | jq
{
"default": {
"ip_addresses": ["10.192.89.6/26"],
"mac_address": "0a:58:0a:c0:59:06",
"gateway_ips": ["10.192.89.1"],
"role": "primary"
},
"test-localnet-dhcp-ipam/localnet-dhcp-ipam": {
"ip_addresses": ["172.18.0.242/16"],
"mac_address": "7e:b3:9b:ea:06:bd",
"gateway_ips": ["172.18.0.5"],
"role": "secondary",
"ipam_mode": "dhcp"
}
}
The multus k8s.v1.cni.cncf.io/network-status annotation reports the same IP
along with the pod interface the network was attached on:
[
{
"name": "test-localnet-dhcp-ipam/localnet-dhcp-ipam",
"interface": "net1",
"ips": [
"172.18.0.242"
],
"mac": "7e:b3:9b:ea:06:bd",
"dns": {}
}
]
For regular pods, the DHCP-assigned IP is also configured directly on that interface by the OVN-Kubernetes CNI and can be confirmed from inside the pod:
kubectl exec test-localnet-pod -n test-localnet-dhcp-ipam -- ip -4 addr show net1
3: net1@if52142: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 7e:b3:9b:ea:06:bd brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.0.242/16 brd 172.18.255.255 scope global net1
valid_lft forever preferred_lft forever
For KubeVirt VMs the annotation is populated the same way, and the guest's own DHCP client configures the IP inside the VM.
Common problems:
- The pod is stuck in
ContainerCreatingand the CNI ADD fails for the network: check that thedhcp daemonis running on the node and that its socket (/run/cni/dhcp.sock) is mounted intoovnkube-node— for the pod path, ovnkube-node must be able to exec/opt/cni/bin/dhcpand reach the daemon. - CNI ADD times out waiting for a lease: verify a DHCP server is actually
reachable on the physical network mapped by
physicalNetworkName, e.g. run a DHCP client ortcpdumpport 67/68 on the mapped bridge on that node. - The pod comes up but the annotation entry is missing
ipam_mode: "dhcp": the NAD in the pod's namespace does not carryipam: {"type": "dhcp"}— confirm the CUDN hasipam.mode: DHCPand the NAD was re-rendered.
Known Limitations¶
- DHCP RELEASE with dnsmasq (pod path). The upstream DHCP CNI plugin
sends RELEASE packets from source IP
0.0.0.0instead of the client's assigned IP, whichdnsmasqdrops. The lease simply expires naturally on the server side instead of being released early. - Lease loss on DHCP daemon restart (pod path). The DHCP CNI daemon keeps leases in memory only; a daemon restart loses all active leases and no further renewals happen for pods relying on it. As a mitigation, configure the DHCP server with static MAC-to-IP reservations, and restart affected pods to trigger a fresh DORA that re-registers with the running daemon.