Documentation survey

Static Network with nm-configurator

warning

Declarative Networking is in technology preview state with limited support. As such it is not recommended for production environments.

The nm-configurator per node configuration can be used to statically assign IP addresses to individual machines, based on the NIC’s MAC addresses.

This solution does not require a remote IPAM provider, but requires the user to maintain mapping between known MAC addresses and IP Addresses.

In this example, we are going to customize an Elemental image, and include a yip config that will apply the static network config early at boot.

The following configuration covers 2 nodes with a very basic network setup.

99_static_network_config.yaml
name: Static nm-configurator config
stages:
  initramfs:
  - directories:
      - path: /tmp/nmc/static/desired-states
        permissions: 448
        owner: 0
        group: 0
      - path: /tmp/nmc/static/network-config
        permissions: 448
        owner: 0
        group: 0
    files:
      - path: /tmp/nmc/static/desired-states/node1.yaml
        permissions: 384
        owner: 0
        group: 0
        content: |
          dns-resolver:
            config:
              server:
              - 192.168.122.1
              search: []
          routes:
            config:
            - destination: 0.0.0.0/0
              next-hop-interface: eth0
              next-hop-address: 192.168.122.1
              metric: 150
              table-id: 254
          interfaces:
          - name: eth0
            type: ethernet
            state: up
            mac-address: 52:54:00:45:14:c5
            ipv4:
              address:
              - ip: 192.168.122.150
                prefix-length: 24
              enabled: true
            ipv6:
              enabled: false
        encoding: ""
        ownerstring: ""
      - path: /tmp/nmc/static/desired-states/node2.yaml
        permissions: 384
        owner: 0
        group: 0
        content: |
          dns-resolver:
            config:
              server:
              - 192.168.122.1
              search: []
          routes:
            config:
            - destination: 0.0.0.0/0
              next-hop-interface: eth0
              next-hop-address: 192.168.122.1
              metric: 150
              table-id: 254
          interfaces:
          - name: eth0
            type: ethernet
            state: up
            mac-address: 52:54:00:3a:ae:3b
            ipv4:
              address:
              - ip: 192.168.122.151
                prefix-length: 24
              enabled: true
            ipv6:
              enabled: false
        encoding: ""
        ownerstring: ""
    commands:
    - nmc generate --config-dir /tmp/nmc/static/desired-states --output-dir /tmp/nmc/static/network-config
    - nmc apply --config-dir /tmp/nmc/static/network-config

Include the static network configuration in a custom OS image

We can extend an Elemental image to include the static network configuration in /system/oem. Any Elemental powered OS, where the Elemental Toolkit is running, will evaluate any config in this directory when executing any stage. Additionally we are going to customize the image to install the required nmc binary.

# The version of Elemental to modify
FROM registry.suse.com/suse/sl-micro/6.0/baremetal-os-container:latest

# Install the static network config
COPY 99_static_network_config.yaml /system/oem/99_static_network_config.yaml

# Install nmc
RUN curl -LO https://github.com/suse-edge/nm-configurator/releases/download/v0.3.1/nmc-linux-x86_64 && \
    install -o root -g root -m 0755 nmc-linux-x86_64 /usr/sbin/nmc

# IMPORTANT: /etc/os-release is used for versioning/upgrade.
ARG IMAGE_REPO=norepo
ARG IMAGE_TAG=latest
RUN \
    sed -i -e "s|^IMAGE_REPO=.*|IMAGE_REPO=\"${IMAGE_REPO}\"|g" /etc/os-release && \
    sed -i -e "s|^IMAGE_TAG=.*|IMAGE_TAG=\"${IMAGE_TAG}\"|g" /etc/os-release && \
    sed -i -e "s|^IMAGE=.*|IMAGE=\"${IMAGE_REPO}:${IMAGE_TAG}\"|g" /etc/os-release

# IMPORTANT: it is good practice to recreate the initrd and re-apply `elemental-init`
RUN elemental init --force elemental-rootfs,grub-config,dracut-config,cloud-config-essentials,elemental-setup

The OS container can now be built and pushed to your registry:

docker build --build-arg IMAGE_REPO=myrepo/static-network-os \
             --build-arg IMAGE_TAG=v1.1.1 \
             -t myrepo/static-network-os:v1.1.1 .
docker push myrepo/static-network-os:v1.1.1

Note that since the static network config is included in the image, this requires you to build and maintain different images with different configurations, most likely one per nodepool or one per cluster for example. Custom OS images need to be maintained to create the initial ISO bootable image (via a SeedImage), but also when upgrading the machines. The desired static network config must be present on the OS images used with the ManagedOSImage, otherwise the config will be missing when booting from the upgraded system.

The custom OS image can also be used as it is to build a bootable raw disk image:

apiVersion: elemental.cattle.io/v1beta1
kind: SeedImage
metadata:
  name: my-raw-image
  namespace: fleet-default
spec:
  type: raw
  baseImage: myrepo/static-network-os:v1.1.1
  registrationRef:
    apiVersion: elemental.cattle.io/v1beta1
    kind: MachineRegistration
    name: my-registration
    namespace: fleet-default

Create a bootable ISO

You can now build an ISO container from this OS container image. For more information on how to customize Elemental images, please refer to the documentation.

FROM myrepo/static-network-os:v1.1.1 AS os
FROM myrepo/static-network-os:v1.1.1 AS builder

WORKDIR /iso
COPY --from=os / rootfs

# work around buildah issue: https://github.com/containers/buildah/issues/4242
RUN rm -f rootfs/etc/resolv.conf

RUN elemental build-iso \
        dir:rootfs \
        --bootloader-in-rootfs \
        --squash-no-compression \
        -o /output -n "elemental"

FROM busybox
COPY --from=builder /output /elemental-iso

ENTRYPOINT ["busybox", "sh", "-c"]
docker build -t myrepo/static-network-iso:v1.1.1 .
docker push myrepo/static-network-iso:v1.1.1

Once the ISO container is published on your registry, you can refer to it in the SeedImage like any other Elemental distributed ISO image.

apiVersion: elemental.cattle.io/v1beta1
kind: SeedImage
metadata:
  name: my-iso
  namespace: fleet-default
spec:
  type: iso
  baseImage: myrepo/static-network-iso:v1.1.1
  registrationRef:
    apiVersion: elemental.cattle.io/v1beta1
    kind: MachineRegistration
    name: my-registration
    namespace: fleet-default

Note that the static network config will now be evaluated when the installation media boots, then it will be installed on the system as part of the base image.