The module lifecycle stagePreview

This guide is dedicated to creating user resources based on existing administrative resources that have been received from the cluster or network administrator.

User resources/Custom resources

Network

To create a network for a specific project, use the Network and NetworkClass resources provided to you by the administrator:

apiVersion: network.deckhouse.io/v1alpha1
kind: Network
metadata:
  name: my-network
  namespace: my-namespace
spec:
  networkClass: my-network-class # mandatory

After creating the Network resource you can check its status:

d8 k -n my-namespace get network my-network -o yaml
Example of the status of a Network resource
apiVersion: network.deckhouse.io/v1alpha1
kind: Network
metadata:
...
status:
  bridgeName: d8-br-600
  conditions:
  - lastTransitionTime: "2025-09-29T14:51:26Z"
    message: All node interface attachments are ready
    reason: AllNodeInterfaceAttachmentsAreReady
    status: "True"
    type: AllNodeAttachementsAreReady
  - lastTransitionTime: "2025-09-29T14:51:26Z"
    message: Network is operational
    reason: NetworkReady
    status: "True"
    type: Ready
  nodeAttachementsCount: 1
  observedGeneration: 1
  readyNodeAttachementsCount: 1
  vlanID: 600

Static identification of the VLAN ID number from the pool assigned by the cluster or network administrator is supported. If the value of the spec.vlan.id field is not specified in the resource specification, the VLAN ID will be assigned dynamically.

Connecting additional networks to pods

Additional networks are configured using a pod annotation.

Example of a pod manifest with two additional networks added (the cluster network my-cluster-network and the project network my-network):

The ifName field (optional) specifies the name of the TAP interface within the subnet. The mac field (optional) specifies the MAC address to be assigned to the TAP interface.

apiVersion: v1
kind: Pod
metadata:
  name: app-with-additional-networks
  namespace: my-namespace
  annotations:
    network.deckhouse.io/networks-spec: |
      [
        {
          "type": "Network",
          "name": "my-network",
          "ifName": "veth_mynet",
          "mac": "aa:bb:cc:dd:ee:ff"
        },
        {
          "type": "ClusterNetwork",
          "name": "my-cluster-network",
          "ifName": "veth_public"
        }
      ]
spec:
  containers:
    - name: app
    # other parameters...

IPAM for additional networks (IP allocation and assignment)

The sdn module implements the ability to use the IPAM mechanism to allocate IP addresses from pools and assign them to additional Pod interfaces.

Usage details:

  • IPAM is enabled at the network level (project network (Network) or cluster network (ClusterNetwork)) via the spec.ipam.ipAddressPoolRef parameter.
  • IP address assignment to the pod interface is described in the annotation network.deckhouse.io/networks-spec added to the pod through the following fields:
  • ipAddressNames — a list of IPAddress objects to be assigned to this interface (if not specified, the module can create IPAddress automatically).
    • skipIPAssignment — control of IPAddress reservation/tracking. If skipIPAssignment: true, IPAddress reservation/tracking is enabled, but the IP address is not assigned to the interface within the pod (advanced usage option).
  • Only IPv4 is supported.

If multiple additional networks with IPAM enabled are connected to a single pod, it is recommended to explicitly specify ipAddressNames for each interface (creating separate IPAddresses). Automatically created IPAddress is bound to the pod and may not be suitable for multiple IPAM networks at the same time.

The IPAM mechanism supports automatic assignment and manual assignment of static IP addresses to pods.

Automatic IP address assignment

If IPAM is enabled for an additional network (see Administrator’s Guide), simply connect the network to the pod using the pod annotation. If ipAddressNames is not specified in the interface description in the annotation, the module will automatically create an IPAddress object (type Auto) and assign the allocated IP address to the interface.

Example (an IP will be assigned to interface net1):

apiVersion: v1
kind: Pod
metadata:
  name: app-with-ipam
  namespace: my-namespace
  annotations:
    network.deckhouse.io/networks-spec: |
      [
        {
          "type": "Network",
          "name": "my-network",
          "ifName": "net1"
        }
      ]
spec:
  containers:
    - name: app
      image: nginx
Manual (explicit) creation of IPAddress with type Auto

You can also manually create an IPAddress object with spec.type: Auto (without specifying the static.ip parameter). In this case, the controller will allocate a free address from the pool, and you can bind it to a specific pod interface via ipAddressNames

Example:

  1. Create an IPAddress object:

    apiVersion: network.deckhouse.io/v1alpha1
    kind: IPAddress
    metadata:
      name: app-net1-auto
      namespace: my-namespace
    spec:
      networkRef:
        kind: Network          # or ClusterNetwork
        name: my-network
      type: Auto
  2. Assign an IP address from the pool to the interface:

    apiVersion: v1
    kind: Pod
    metadata:
      name: app-with-manual-auto-ip
      namespace: my-namespace
      annotations:
        network.deckhouse.io/networks-spec: |
          [
            {
              "type": "Network",
              "name": "my-network",
              "ifName": "net1",
              "ipAddressNames": ["app-net1-auto"]
            }
          ]
    spec:
      containers:
        - name: app
          image: nginx

Manually assigning a static IP address to an additional pod interface

To assign a specific static IP address to an additional pod interface, follow these steps:

  1. Create an IPAddress in the pod namespace and specify which network it is intended for and which IP address is required:

    apiVersion: network.deckhouse.io/v1alpha1
    kind: IPAddress
    metadata:
      name: app-net1-static
      namespace: my-namespace
    spec:
      networkRef:
        kind: Network
        name: my-network
      type: Static
      static:
        ip: 192.168.10.50
  2. Connect the network to the pod and specify the created IPAddress in ipAddressNames:

    apiVersion: v1
    kind: Pod
    metadata:
      name: app-with-static-ip
      namespace: my-namespace
      annotations:
        network.deckhouse.io/networks-spec: |
          [
            {
              "type": "Network",
              "name": "my-network",
              "ifName": "net1",
              "ipAddressNames": ["app-net1-static"]
            }
          ]
    spec:
      containers:
        - name: app
          image: nginx

How to verify that the IP was assigned

To verify that an IP address is assigned to the interface, follow these steps:

  1. Check the allocated address and phase at IPAddress (the phase should be Allocated):

    d8 k -n my-namespace get ipaddress app-net1-static -o yaml

    Output example:

    NAME               TYPE   KIND      NAME    ADDRESS        NETWORK           PHASE       AGE
    ipaddress-auto-1   Auto   Network   mynet   192.168.12.1   192.168.12.0/24   Allocated   4d1h
    ipaddress-auto-2   Auto   Network   mynet   192.168.12.2   192.168.12.0/24   Allocated   4d1h
    
  2. Check the pod annotation network.deckhouse.io/networks-status (including ipAddressConfigs and routes):

    d8 k -n my-namespace get pod app-with-static-ip -o jsonpath='{.metadata.annotations.network\.deckhouse\.io/networks-status}   ' | jq

    Output example:

    [
      {
        "type": "Network",
        "name": "mynet",
        "ifName": "aabbcc",
        "mac": "ae:1c:68:7a:00:8f",
        "vlanID": 0,
        "ipAddressConfigs": [
          {
            "name": "ipaddress-auto-1",
            "address": "192.168.12.1",
            "network": "192.168.12.0/24"
          }
        ],
        "conditions": [
          {
            "type": "Configured",
            "status": "True",
            "lastTransitionTime": "2026-02-26T10:06:49Z",
            "reason": "InterfaceConfiguredSuccessfully",
            "message": ""
          },
          {
            "type": "Negotiated",
            "status": "True",
            "lastTransitionTime": "2026-02-26T10:06:49Z",
            "reason": "Up",
            "message": ""
          }
        ]
      }
    ]

Connecting physical network interfaces to pods (DPDK workloads)

To use physical network interfaces (PF/VF) directly in pods for DPDK applications, you need to:

  1. Ensure your namespace has been labeled by the administrator to allow UnderlayNetwork usage (see Admin Guide)
  2. Create a pod with an annotation requesting the UnderlayNetwork device

Creating a pod with UnderlayNetwork device

Create a pod that requests a device from an UnderlayNetwork. The pod annotation should specify:

  • type: "UnderlayNetwork": Indicates this is a physical device request
  • name: "underlay-network-name": The name of the UnderlayNetwork resource created by the administrator
  • bindingMode: The binding mode for the device (VFIO-PCI, DPDK, or NetDev).

Example pod configuration for DPDK mode (universal mode that automatically selects the appropriate driver for the network adapter vendor):

apiVersion: v1
kind: Pod
metadata:
  name: dpdk-app
  namespace: mydpdk
  annotations:
    network.deckhouse.io/networks-spec: |
      [
        {
          "type": "UnderlayNetwork",
          "name": "dpdk-shared-network",
          "bindingMode": "DPDK"
        }
      ]
spec:
  containers:
  - name: dpdk-container
    image: dpdk-app:latest
    securityContext:
      privileged: false
      capabilities:
        add:
        - NET_ADMIN
        - NET_RAW
        - IPC_LOCK
    volumeMounts:
    - mountPath: /hugepages
      name: hugepage
    resources:
      limits:
        hugepages-2Mi: 4Gi
        memory: 4Gi
        cpu: 4
      requests:
        cpu: 4
        memory: 4Gi
    command: ["/bin/sh", "-c", "sleep infinity"]
  volumes:
  - name: hugepage
    emptyDir:
      medium: HugePages

For DPDK applications, it is important to:

  • Configure capabilities (NET_ADMIN, NET_RAW, IPC_LOCK) to run in non-privileged mode instead of using privileged: true
  • Mount hugepages volumes, as DPDK requires hugepages for efficient memory management.

For VF devices in Shared mode, you can optionally specify a vlanID in the annotation to configure VLAN tagging on the VF:

network.deckhouse.io/networks-spec: |
  [
    {
      "type": "UnderlayNetwork",
      "name": "dpdk-shared-network",
      "bindingMode": "VFIO-PCI",
      "vlanID": 100
    }
  ]

After creating the pod, verify that the device was allocated by checking the network.deckhouse.io/networks-status annotation:

d8 k -n mydpdk get pod dpdk-app -o jsonpath='{.metadata.annotations.network\.deckhouse\.io/networks-status}' | jq

You can also check the ResourceClaim that was automatically created:

d8 k -n mydpdk get resourceclaim
Example pod status with allocated UnderlayNetwork device
apiVersion: v1
kind: Pod
metadata:
  name: dpdk-app
  namespace: mydpdk
  annotations:
    network.deckhouse.io/networks-spec: |
      [
        {
          "type": "UnderlayNetwork",
          "name": "dpdk-shared-network",
          "bindingMode": "DPDK"
        }
      ]
    network.deckhouse.io/networks-status: |
      [
        {
          "type": "UnderlayNetwork",
          "name": "dpdk-shared-network",
          "bindingMode": "DPDK",
          "netDevInterfaces": [
            {
              "name": "ens1f0",
              "mac": "00:1b:21:bb:aa:cc"
            }
          ],
          "conditions": [
            {
              "type": "Configured",
              "status": "True",
              "reason": "InterfaceConfiguredSuccessfully",
              "message": "",
              "lastTransitionTime": "2025-01-15T10:35:00Z"
            },
            {
              "type": "Negotiated",
              "status": "True",
              "reason": "Up",
              "message": "",
              "lastTransitionTime": "2025-01-15T10:35:00Z"
            }
          ]
        }
      ]
status:
  phase: Running
  ...