NNCP Static IP Assignment on Worker Nodes
Use NodeNetworkConfigurationPolicy to assign static IPv4 and IPv6 addresses to worker node interfaces with nodeSelector targeting.
π‘ Quick Answer: Create a
NodeNetworkConfigurationPolicywithnodeSelectortargeting worker nodes and define static IPv4/IPv6 addresses underdesiredState.interfaces. The nmstate operator applies the configuration and reports status viaNodeNetworkConfigurationEnactment.
The Problem
Worker nodes in production Kubernetes clusters often need static IP addresses on secondary interfaces for:
- Storage networks β iSCSI, NFS, Ceph requiring predictable IPs
- GPU/RDMA networks β InfiniBand or RoCE interfaces for AI workloads
- Management networks β Out-of-band monitoring and administration
- Tenant isolation β Dedicated network segments per team or application
Manually configuring NetworkManager on each node doesnβt scale, isnβt declarative, and doesnβt survive node replacements. NNCP solves this by managing node networking through the Kubernetes API.
The Solution
Step 1: Verify nmstate Operator is Running
# OpenShift
oc get pods -n openshift-nmstate
# Kubernetes
kubectl get pods -n nmstateStep 2: Check Available Interfaces
View the current network state of your worker nodes:
# List all node network states
oc get nodenetworkstate
# View a specific node's interfaces
oc get nns worker-0 -o yaml | grep -A5 'name: ens'Step 3: Create NNCP for Static IPv4
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: worker-storage-ip
spec:
nodeSelector:
node-role.kubernetes.io/worker: ""
desiredState:
interfaces:
- name: ens224
type: ethernet
state: up
ipv4:
enabled: true
dhcp: false
address:
- ip: 192.168.100.{{ nodeIndex }}
prefix-length: 24
ipv6:
enabled: falseβ οΈ Note: NNCP applies the same config to all matching nodes. For per-node IPs, use separate NNCPs with specific
nodeSelectorlabels.
Step 4: Per-Node Static IPs
For unique IPs per worker, label nodes and create targeted policies:
# Label each worker with its storage IP
oc label node worker-0 network.storage-ip=192.168.100.10
oc label node worker-1 network.storage-ip=192.168.100.11
oc label node worker-2 network.storage-ip=192.168.100.12apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: worker-0-storage-ip
spec:
nodeSelector:
kubernetes.io/hostname: worker-0
desiredState:
interfaces:
- name: ens224
type: ethernet
state: up
ipv4:
enabled: true
dhcp: false
address:
- ip: 192.168.100.10
prefix-length: 24
ipv6:
enabled: false
---
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: worker-1-storage-ip
spec:
nodeSelector:
kubernetes.io/hostname: worker-1
desiredState:
interfaces:
- name: ens224
type: ethernet
state: up
ipv4:
enabled: true
dhcp: false
address:
- ip: 192.168.100.11
prefix-length: 24
ipv6:
enabled: falseStep 5: Dual-Stack IPv4 and IPv6
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: worker-dualstack
spec:
nodeSelector:
node-role.kubernetes.io/worker: ""
desiredState:
interfaces:
- name: ens224
type: ethernet
state: up
ipv4:
enabled: true
dhcp: false
address:
- ip: 192.168.100.10
prefix-length: 24
ipv6:
enabled: true
dhcp: false
autoconf: false
address:
- ip: fd00:storage::10
prefix-length: 64Step 6: Verify the Configuration
# Check NNCP status
oc get nncp worker-storage-ip
# Check per-node enactment
oc get nnce
# Verify the interface on a specific node
oc debug node/worker-0 -- chroot /host ip addr show ens224flowchart TD
A[NodeNetworkConfigurationPolicy] --> B[nmstate operator]
B --> C{nodeSelector matches?}
C -->|Yes| D[Apply to matching workers]
C -->|No| E[Skip node]
D --> F[NetworkManager configures interface]
F --> G[NodeNetworkConfigurationEnactment]
G --> H{Success?}
H -->|Yes| I[Available status]
H -->|No| J[Rollback to previous config]Common Issues
NNCP stuck in Progressing
# Check enactment status for each node
oc get nnce -o wide
# View detailed failure reason
oc get nnce worker-0.worker-storage-ip -o jsonpath='{.status.conditions}'
# Common cause: wrong interface name
oc get nns worker-0 -o yaml | grep -B2 -A10 'type: ethernet'Interface name varies across nodes
# Check each node's interface names
for node in worker-0 worker-1 worker-2; do
echo "=== $node ==="
oc get nns $node -o jsonpath='{.status.currentState.interfaces[*].name}'
echo
done
# Use consistent naming with udev rules or match by MAC addressStatic IP conflicts with DHCP
# Ensure DHCP is explicitly disabled
ipv4:
enabled: true
dhcp: false # Must be false for static IPs
auto-dns: false # Prevent DHCP DNS override
auto-routes: false
auto-gateway: falseBest Practices
- Use
nodeSelectorwith role labels to target only worker nodes β never accidentally configure control plane networking - Create per-node NNCPs for unique IPs β a single NNCP applies identical config to all matching nodes
- Verify interface names across all workers before applying β names like
ens224vsenp3s0vary by hardware - Disable DHCP explicitly when using static IPs β set
dhcp: false,auto-dns: false,auto-routes: false - Test on one node first β use
kubernetes.io/hostnameselector before rolling out to all workers - Monitor enactments β always check
oc get nnceafter applying an NNCP
Key Takeaways
NodeNetworkConfigurationPolicyprovides declarative, API-driven network configuration for node interfaces- Use
nodeSelectorto target workers βnode-role.kubernetes.io/worker: ""for all workers orkubernetes.io/hostnamefor specific nodes - For per-node unique IPs, create separate NNCPs with hostname selectors
- The nmstate operator handles applying, validating, and auto-rolling back failed configurations
- Always verify with
oc get nnceto confirm successful application on each node

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
