documentation.suse.com / Documentación de SUSE Edge / Documentación del producto / Aprovisionamiento de red dirigida totalmente automatizado

42 Aprovisionamiento de red dirigida totalmente automatizado

42.1 Introducción

El aprovisionamiento de red dirigida es una función que permite automatizar el aprovisionamiento de clústeres descendentes. Esta función resulta útil cuando hay muchos clústeres descendentes que aprovisionar y se desea automatizar el proceso.

Un clúster de gestión (Capítulo 40, Configuración del clúster de gestión) automatiza el despliegue de los siguientes componentes:

  • SUSE Linux Micro RT como sistema operativo. Dependiendo del caso de uso, se pueden personalizar ajustes como las redes, el almacenamiento, los usuarios y los argumentos del kernel.

  • RKE2 como clúster de Kubernetes. El complemento de CNI predeterminado es Cilium. Dependiendo del caso práctico, se pueden usar determinados complementos de CNI, como Cilium+Multus.

  • SUSE Storage

  • SUSE Security

  • MetalLB se puede usar como equilibrador de carga para clústeres de varios nodos de alta disponibilidad.

Nota
Nota

Para obtener más información sobre SUSE Linux Micro, consulte el Capítulo 9, SUSE Linux Micro. Para obtener más información sobre RKE2, consulte el Capítulo 16, RKE2. Para obtener más información sobre SUSE Storage, consulte el Capítulo 17, SUSE Storage. Para obtener más información sobre SUSE Security, consulte el Capítulo 18, SUSE Security.

Las siguientes secciones describen los diferentes flujos de trabajo de aprovisionamiento de red dirigida y algunas características adicionales que se pueden añadir al proceso de aprovisionamiento:

Nota
Nota

Las siguientes secciones muestran cómo preparar los diferentes escenarios para el flujo de trabajo de aprovisionamiento de red dirigida utilizando SUSE Edge for Telco. Para ver ejemplos de las diferentes opciones de configuración para el despliegue (incluidos entornos aislados, redes con DHCP y sin DHCP, registros de contenedores privados, etc.), consulte el repositorio de SUSE Edge for Telco.

42.2 Preparación de la imagen del clúster descendente para entornos conectados

Edge Image Builder (Capítulo 11, Edge Image Builder) se utiliza para preparar una imagen base de SLEMicro modificada que se aprovisiona en los hosts del clúster descendente.

Gran parte de la configuración se puede realizar con Edge Image Builder, pero en esta guía cubrimos las configuraciones mínimas necesarias para configurar el clúster descendente.

42.2.1 Requisitos previos para entornos conectados

  • Se requiere un entorno de ejecución de contenedores como Podman o Rancher Desktop para ejecutar Edge Image Builder.

  • La imagen base se creará con las instrucciones del Capítulo 28, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi y el perfil Base-SelfInstall (o Base-RT-SelfInstall para el kernel en tiempo real). El proceso es el mismo para ambas arquitecturas (x86-64 y aarch64).

  • Para desplegar clústeres descendentes aarch64, antes del despliegue del clúster de gestión debe definir el parámetro deployArchitecture: arm64 en el archivo metal3.yaml, lo que se explica en la documentación del clúster de gestión (???). Esto es necesario para garantizar que se utiliza la arquitectura correcta para el clúster descendente.

Nota
Nota

Es necesario utilizar un host de creación con la misma arquitectura que las imágenes que se están creando. En otras palabras, para crear una imagen aarch64, es necesario utilizar un host de creación aarch64, y lo mismo ocurre para x86-64 (actualmente, no se admiten creaciones con arquitecturas cruzadas).

42.2.2 Configuración de la imagen para entornos conectados

Al ejecutar Edge Image Builder, se monta un directorio desde el host, por lo que es necesario crear una estructura de directorios para almacenar los archivos de configuración usados para definir la imagen de destino.

  • downstream-cluster-config.yaml es el archivo de definición de la imagen. Consulte el Capítulo 3, Clústeres independientes con Edge Image Builder para obtener más detalles.

  • La carpeta de imágenes base contendrá la imagen raw generada al seguir las instrucciones del Capítulo 28, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi con el perfil Base-SelfInstall (o Base-RT-SelfInstall para el kernel en tiempo real) y deberá copiarse/moverse a la carpeta base-images.

  • La carpeta network es opcional. Para obtener más información, consulte la Sección 42.2.2.6, “Guion adicional para la configuración avanzada de red”.

  • El directorio custom/scripts contiene guiones que se deben ejecutar en el primer arranque:

    1. El guion 01-fix-growfs.sh es necesario para cambiar el tamaño de la partición raíz del sistema operativo durante el despliegue.

    2. El guion 02-performance.sh es opcional y se puede usar para configurar el sistema con el fin de optimizar su rendimiento.

    3. El guion 03-sriov.sh es opcional y se puede usar para configurar el sistema para SR-IOV.

  • El directorio custom/files contiene los archivos performance-settings.sh y sriov-auto-filler.sh que se copiarán en la imagen durante el proceso de creación de la imagen.

├── downstream-cluster-config.yaml
├── base-images/
│   └ SL-Micro.x86_64-6.1-Base-GM.raw
├── network/
|   └ configure-network.sh
└── custom/
    └ scripts/
    |   └ 01-fix-growfs.sh
    |   └ 02-performance.sh
    |   └ 03-sriov.sh
    └ files/
        └ performance-settings.sh
        └ sriov-auto-filler.sh

42.2.2.1 Archivo de definición de la imagen del clúster descendente

El archivo downstream-cluster-config.yaml es el principal archivo de configuración para la imagen del clúster descendente. A continuación, se muestra un ejemplo mínimo de despliegue mediante Metal3:

apiVersion: 1.2
image:
  imageType: raw
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.1-Base-GM.raw
  outputImageName: eibimage-output-telco.raw
operatingSystem:
  kernelArgs:
    - ignition.platform.id=openstack
    - net.ifnames=1
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
      sshKeys:
      - $USERKEY1
  packages:
    packageList:
      - jq
    sccRegistrationCode: $SCC_REGISTRATION_CODE

Donde $SCC_REGISTRATION_CODE es el código de registro copiado del Centro de servicios al cliente de SUSE, y la lista de paquetes contiene jq, que es necesario.

$ROOT_PASSWORD es la contraseña cifrada del usuario root, que puede ser útil para pruebas y depuración. Se puede generar con el comando openssl passwd -6 PASSWORD.

En entornos de producción, se recomienda usar las claves SSH que se pueden añadir al bloque de usuarios sustituyendo $USERKEY1 por las claves SSH reales.

Nota
Nota

arch: x86_64 es la arquitectura de la imagen. Para la arquitectura arm64, utilice arch: aarch64.

net.ifnames=1 permite los nombres predecibles para las interfaces de red

Esto coincide con la configuración predeterminada para el chart de metal3, pero el ajuste debe coincidir con el valor de predictableNicNames configurado en el chart.

Tenga en cuenta también que ignition.platform.id=openstack es obligatorio. Sin este argumento, la configuración de SLEMicro mediante Ignition fallará en el flujo automatizado de Metal3.

42.2.2.2 Guion Growfs

Actualmente, se requiere un guion personalizado (custom/scripts/01-fix-growfs.sh) para ampliar el sistema de archivos y que coincida con el tamaño del disco en el primer arranque después del aprovisionamiento. El guion 01-fix-growfs.sh contiene la siguiente información:

#!/bin/bash
growfs() {
  mnt="$1"
  dev="$(findmnt --fstab --target ${mnt} --evaluate --real --output SOURCE --noheadings)"
  # /dev/sda3 -> /dev/sda, /dev/nvme0n1p3 -> /dev/nvme0n1
  parent_dev="/dev/$(lsblk --nodeps -rno PKNAME "${dev}")"
  # Last number in the device name: /dev/nvme0n1p42 -> 42
  partnum="$(echo "${dev}" | sed 's/^.*[^0-9]\([0-9]\+\)$/\1/')"
  ret=0
  growpart "$parent_dev" "$partnum" || ret=$?
  [ $ret -eq 0 ] || [ $ret -eq 1 ] || exit 1
  /usr/lib/systemd/systemd-growfs "$mnt"
}
growfs /

42.2.2.3 Guion performance

El siguiente guion opcional (custom/scripts/02-performance.sh) se puede usar para configurar el sistema a fin de optimizar su rendimiento:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/performance-settings

# copy the artifacts
cp performance-settings.sh /opt/performance-settings/

El contenido de custom/files/performance-settings. sh es un guion que se puede usar para configurar el sistema con el fin de optimizar su rendimiento, y se puede descargar desde el siguiente enlace.

42.2.2.4 Guion SR-IOV

El siguiente guion opcional (custom/scripts/03-sriov.sh) se puede usar para configurar el sistema para SR-IOV:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/sriov
# copy the artifacts
cp sriov-auto-filler.sh /opt/sriov/sriov-auto-filler.sh

El contenido de custom/files/ sriov-auto-filler.sh es un guion que se puede usar para configurar el sistema para SR-IOV, y se puede descargar desde el siguiente enlace.

Nota
Nota

Use el mismo método para añadir sus propios guiones personalizados que se ejecuten durante el proceso de aprovisionamiento. Para obtener más información, consulte el Capítulo 3, Clústeres independientes con Edge Image Builder.

42.2.2.5 Configuración adicional para cargas de trabajo de telecomunicaciones

Para habilitar funciones de telecomunicaciones como dpdk, sr-iov o FEC, es posible que se requieran paquetes adicionales, como se muestra en el siguiente ejemplo.

apiVersion: 1.2
image:
  imageType: raw
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.1-Base-GM.raw
  outputImageName: eibimage-output-telco.raw
operatingSystem:
  kernelArgs:
    - ignition.platform.id=openstack
    - net.ifnames=1
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
      sshKeys:
      - $user1Key1
  packages:
    packageList:
      - jq
      - dpdk
      - dpdk-tools
      - libdpdk-23
      - pf-bb-config
    sccRegistrationCode: $SCC_REGISTRATION_CODE

Donde $SCC_REGISTRATION_CODE es el código de registro copiado del Centro de servicios al cliente de SUSE, y la lista de paquetes contiene los paquetes mínimos que se utilizarán para los perfiles de telecomunicaciones.

Nota
Nota

arch: x86_64 es la arquitectura de la imagen. Para la arquitectura arm64, utilice arch: aarch64.

42.2.2.6 Guion adicional para la configuración avanzada de red

Si necesita configurar direcciones IP estáticas o escenarios de red más avanzados, como se describe en la Sección 42.6, “Configuración de red avanzada”, se requiere la siguiente configuración adicional.

En la carpeta network, cree el siguiente archivo configure-network.sh. Este archivo consume los datos de la unidad de configuración durante el primer arranque y configura la red del host utilizando la herramienta NM Configurator.

#!/bin/bash

set -eux

# Attempt to statically configure a NIC in the case where we find a network_data.json
# In a configuration drive

CONFIG_DRIVE=$(blkid --label config-2 || true)
if [ -z "${CONFIG_DRIVE}" ]; then
  echo "No config-2 device found, skipping network configuration"
  exit 0
fi

mount -o ro $CONFIG_DRIVE /mnt

NETWORK_DATA_FILE="/mnt/openstack/latest/network_data.json"

if [ ! -f "${NETWORK_DATA_FILE}" ]; then
  umount /mnt
  echo "No network_data.json found, skipping network configuration"
  exit 0
fi

DESIRED_HOSTNAME=$(cat /mnt/openstack/latest/meta_data.json | tr ',{}' '\n' | grep '\"metal3-name\"' | sed 's/.*\"metal3-name\": \"\(.*\)\"/\1/')
echo "${DESIRED_HOSTNAME}" > /etc/hostname

mkdir -p /tmp/nmc/{desired,generated}
cp ${NETWORK_DATA_FILE} /tmp/nmc/desired/_all.yaml
umount /mnt

./nmc generate --config-dir /tmp/nmc/desired --output-dir /tmp/nmc/generated
./nmc apply --config-dir /tmp/nmc/generated

42.2.3 Creación de la imagen

Cuando se haya preparado la estructura de directorios siguiendo las secciones anteriores, ejecute el siguiente comando para crear la imagen:

podman run --rm --privileged -it -v $PWD:/eib \
 registry.suse.com/edge/3.3/edge-image-builder:1.2.1 \
 build --definition-file downstream-cluster-config.yaml

Esto crea el archivo de imagen ISO de salida denominado eibimage-output-telco.raw, basado en la definición descrita anteriormente.

La imagen resultante debe estar disponible a través de un servidor Web, ya sea el contenedor del servidor de medios habilitado en los pasos descritos en la sección sobre el clúster de gestión (Nota) o algún otro servidor al que se pueda acceder localmente. En los ejemplos siguientes, nos referimos a este servidor como imagecache.local:8080.

42.3 Preparación de la imagen del clúster descendente para entornos aislados

Edge Image Builder (Capítulo 11, Edge Image Builder) se utiliza para preparar una imagen base de SLEMicro modificada que se aprovisiona en los hosts del clúster descendente.

Gran parte de la configuración se puede realizar con Edge Image Builder, pero en esta guía tratamos las configuraciones mínimas necesarias para configurar el clúster descendente en entornos aislados.

42.3.1 Requisitos previos para entornos aislados

  • Se requiere un entorno de ejecución de contenedores como Podman o Rancher Desktop para ejecutar Edge Image Builder.

  • La imagen base se creará con las instrucciones del Capítulo 28, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi y el perfil Base-SelfInstall (o Base-RT-SelfInstall para el kernel en tiempo real). El proceso es el mismo para ambas arquitecturas (x86-64 y aarch64).

  • Para desplegar clústeres descendentes aarch64, antes del despliegue del clúster de gestión debe definir el parámetro deployArchitecture: arm64 en el archivo metal3.yaml, lo que se explica en la documentación del clúster de gestión (???). Esto es necesario para garantizar que se utiliza la arquitectura correcta para el clúster descendente.

  • Si desea utilizar SR-IOV o cualquier otra carga de trabajo que requiera una imagen de contenedor, debe desplegar y configurar previamente un registro privado local (con o sin TLS y/o autenticación). Este registro se utilizará para almacenar las imágenes y las imágenes OCI del chart de Helm.

Nota
Nota

Es necesario utilizar un host de creación con la misma arquitectura que las imágenes que se están creando. En otras palabras, para crear una imagen aarch64, es necesario utilizar un host de creación aarch64, y lo mismo ocurre para x86-64 (actualmente, no se admiten creaciones con arquitecturas cruzadas).

42.3.2 Configuración de la imagen para entornos aislados

Al ejecutar Edge Image Builder, se monta un directorio desde el host, por lo que es necesario crear una estructura de directorios para almacenar los archivos de configuración usados para definir la imagen de destino.

  • downstream-cluster-airgap-config.yaml es el archivo de definición de la imagen. Para obtener más información, consulte el Capítulo 3, Clústeres independientes con Edge Image Builder.

  • La carpeta de imágenes base contendrá la imagen raw generada al seguir las instrucciones del Capítulo 28, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi con el perfil Base-SelfInstall (o Base-RT-SelfInstall para el kernel en tiempo real) y deberá copiarse/moverse a la carpeta base-images.

  • La carpeta network es opcional. Para obtener más información, consulte la Sección 42.2.2.6, “Guion adicional para la configuración avanzada de red”.

  • El directorio custom/scripts contiene guiones que se deben ejecutar en el primer arranque:

    1. El guion 01-fix-growfs.sh es necesario para cambiar el tamaño de la partición raíz del sistema operativo durante el despliegue.

    2. El guion 02-airgap.sh es necesario para copiar las imágenes en el lugar correcto durante el proceso de creación de imágenes para entornos aislados.

    3. El guion 03-performance.sh es opcional y se puede usar para configurar el sistema con el fin de optimizar su rendimiento.

    4. El guion 04-sriov.sh es opcional y se puede usar para configurar el sistema para SR-IOV.

  • El directorio custom/files contiene las imágenes rke2 y cni que se copiarán en la imagen durante el proceso de creación de la imagen. Además, se pueden incluir los archivos opcionales performance-settings.sh y sriov-auto-filler.sh.

├── downstream-cluster-airgap-config.yaml
├── base-images/
│   └ SL-Micro.x86_64-6.1-Base-GM.raw
├── network/
|   └ configure-network.sh
└── custom/
    └ files/
    |   └ install.sh
    |   └ rke2-images-cilium.linux-amd64.tar.zst
    |   └ rke2-images-core.linux-amd64.tar.zst
    |   └ rke2-images-multus.linux-amd64.tar.zst
    |   └ rke2-images.linux-amd64.tar.zst
    |   └ rke2.linux-amd64.tar.zst
    |   └ sha256sum-amd64.txt
    |   └ performance-settings.sh
    |   └ sriov-auto-filler.sh
    └ scripts/
        └ 01-fix-growfs.sh
        └ 02-airgap.sh
        └ 03-performance.sh
        └ 04-sriov.sh

42.3.2.1 Archivo de definición de la imagen del clúster descendente

El archivo downstream-cluster-airgap-config.yaml es el archivo de configuración principal para la imagen del clúster descendente y su contenido se ha descrito en la sección anterior (Sección 42.2.2.5, “Configuración adicional para cargas de trabajo de telecomunicaciones”).

42.3.2.2 Guion Growfs

Actualmente, se requiere un guion personalizado (custom/scripts/01-fix-growfs.sh) para ampliar el sistema de archivos y que coincida con el tamaño del disco en el primer arranque después del aprovisionamiento. El guion 01-fix-growfs.sh contiene la siguiente información:

#!/bin/bash
growfs() {
  mnt="$1"
  dev="$(findmnt --fstab --target ${mnt} --evaluate --real --output SOURCE --noheadings)"
  # /dev/sda3 -> /dev/sda, /dev/nvme0n1p3 -> /dev/nvme0n1
  parent_dev="/dev/$(lsblk --nodeps -rno PKNAME "${dev}")"
  # Last number in the device name: /dev/nvme0n1p42 -> 42
  partnum="$(echo "${dev}" | sed 's/^.*[^0-9]\([0-9]\+\)$/\1/')"
  ret=0
  growpart "$parent_dev" "$partnum" || ret=$?
  [ $ret -eq 0 ] || [ $ret -eq 1 ] || exit 1
  /usr/lib/systemd/systemd-growfs "$mnt"
}
growfs /

42.3.2.3 Guion air-gap

El siguiente guion (custom/scripts/02-airgap.sh) es necesario para copiar las imágenes en el lugar correcto durante el proceso de creación de la imagen:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/rke2-artifacts
mkdir -p /var/lib/rancher/rke2/agent/images

# copy the artifacts
cp install.sh /opt/
cp rke2-images*.tar.zst rke2.linux-amd64.tar.gz sha256sum-amd64.txt /opt/rke2-artifacts/

42.3.2.4 Guion performance

El siguiente guion opcional (custom/scripts/03-performance.sh) se puede usar para configurar el sistema con el fin de optimizar su rendimiento:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/performance-settings

# copy the artifacts
cp performance-settings.sh /opt/performance-settings/

El contenido de custom/files/performance-settings. sh es un guion que se puede usar para configurar el sistema con el fin de optimizar su rendimiento, y se puede descargar desde el siguiente enlace.

42.3.2.5 Guion SR-IOV

El siguiente guion opcional (custom/scripts/04-sriov.sh) se puede usar para configurar el sistema para SR-IOV:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/sriov
# copy the artifacts
cp sriov-auto-filler.sh /opt/sriov/sriov-auto-filler.sh

El contenido de custom/files/ sriov-auto-filler.sh es un guion que se puede usar para configurar el sistema para SR-IOV, y se puede descargar desde el siguiente enlace.

42.3.2.6 Archivos personalizados para entornos aislados

El directorio custom/files contiene las imágenes rke2 y cni que se copiarán en la imagen durante el proceso de creación de la imagen. Para generar fácilmente las imágenes, prepárelas localmente utilizando el siguiente guion y la lista de imágenes que encontrará aquí para generar los artefactos que deben incluirse en custom/files. Además, puede descargar el guion rke2-install más reciente desde aquí.

$ ./edge-save-rke2-images.sh -o custom/files -l ~/edge-release-rke2-images.txt

Después de descargar las imágenes, la estructura de directorios debería tener este aspecto:

└── custom/
    └ files/
        └ install.sh
        └ rke2-images-cilium.linux-amd64.tar.zst
        └ rke2-images-core.linux-amd64.tar.zst
        └ rke2-images-multus.linux-amd64.tar.zst
        └ rke2-images.linux-amd64.tar.zst
        └ rke2.linux-amd64.tar.zst
        └ sha256sum-amd64.txt

42.3.2.7 Carga previa del registro privado con las imágenes necesarias para situaciones de entornos aislados y SR-IOV (opcional)

Si desea utilizar SR-IOV en un entorno aislado o en cualquier otra imagen de carga de trabajo, debe cargar previamente su registro privado local con las imágenes siguiendo estos pasos:

  • Descargar, extraer y enviar las imágenes OCI del chart de Helm al registro privado

  • Descargar, extraer y enviar el resto de imágenes necesarias al registro privado

Los guiones siguientes se pueden usar para descargar, extraer y enviar las imágenes al registro privado. Mostraremos un ejemplo para precargar las imágenes de SR-IOV, pero también puede usar el mismo método para cargar previamente cualquier otra imagen personalizada:

  1. Realice la carga previa con imágenes OCI del chart de Helm para SR-IOV:

    1. Debe crear una lista con las imágenes OCI del chart de Helm necesarias:

      $ cat > edge-release-helm-oci-artifacts.txt <<EOF
      edge/sriov-network-operator-chart:303.0.2+up1.5.0
      edge/sriov-crd-chart:303.0.2+up1.5.0
      EOF
    2. Genere un archivo tarball local utilizando el siguiente guion y la lista creada anteriormente:

      $ ./edge-save-oci-artefacts.sh -al ./edge-release-helm-oci-artifacts.txt -s registry.suse.com
      Pulled: registry.suse.com/edge/charts/sriov-network-operator:303.0.2+up1.5.0
      Pulled: registry.suse.com/edge/charts/sriov-crd:303.0.2+up1.5.0
      a edge-release-oci-tgz-20240705
      a edge-release-oci-tgz-20240705/sriov-network-operator-chart-303.0.2+up1.5.0.tgz
      a edge-release-oci-tgz-20240705/sriov-crd-chart-303.0.2+up1.5.0.tgz
    3. Suba el archivo tarball a su registro privado (por ejemplo, myregistry:5000) usando el guion siguiente para cargar previamente su registro con las imágenes OCI del chart de Helm descargadas en el paso anterior:

      $ tar zxvf edge-release-oci-tgz-20240705.tgz
      $ ./edge-load-oci-artefacts.sh -ad edge-release-oci-tgz-20240705 -r myregistry:5000
  2. Realice la carga previa del resto de las imágenes necesarias para SR-IOV:

    1. En este caso, debemos incluir las imágenes de contenedor sr-iov para cargas de trabajo de telecomunicaciones (por ejemplo, como referencia, puede obtenerlas de los valores del chart de Helm).

      $ cat > edge-release-images.txt <<EOF
      rancher/hardened-sriov-network-operator:v1.3.0-build20240816
      rancher/hardened-sriov-network-config-daemon:v1.3.0-build20240816
      rancher/hardened-sriov-cni:v2.8.1-build20240820
      rancher/hardened-ib-sriov-cni:v1.1.1-build20240816
      rancher/hardened-sriov-network-device-plugin:v3.7.0-build20240816
      rancher/hardened-sriov-network-resources-injector:v1.6.0-build20240816
      rancher/hardened-sriov-network-webhook:v1.3.0-build20240816
      EOF
    2. Con el guion siguiente y la lista creada anteriormente, debe generar localmente el archivo tarball con las imágenes necesarias:

      $ ./edge-save-images.sh -l ./edge-release-images.txt -s registry.suse.com
      Image pull success: registry.suse.com/rancher/hardened-sriov-network-operator:v1.3.0-build20240816
      Image pull success: registry.suse.com/rancher/hardened-sriov-network-config-daemon:v1.3.0-build20240816
      Image pull success: registry.suse.com/rancher/hardened-sriov-cni:v2.8.1-build20240820
      Image pull success: registry.suse.com/rancher/hardened-ib-sriov-cni:v1.1.1-build20240816
      Image pull success: registry.suse.com/rancher/hardened-sriov-network-device-plugin:v3.7.0-build20240816
      Image pull success: registry.suse.com/rancher/hardened-sriov-network-resources-injector:v1.6.0-build20240816
      Image pull success: registry.suse.com/rancher/hardened-sriov-network-webhook:v1.3.0-build20240816
      Creating edge-images.tar.gz with 7 images
    3. Suba el archivo tarball a su registro privado (por ejemplo, myregistry:5000) usando el guion siguiente para precargar su registro privado con las imágenes descargadas en el paso anterior:

      $ tar zxvf edge-release-images-tgz-20240705.tgz
      $ ./edge-load-images.sh -ad edge-release-images-tgz-20240705 -r myregistry:5000

42.3.3 Creación de la imagen para entornos aislados

Cuando se haya preparado la estructura de directorios siguiendo las secciones anteriores, ejecute el siguiente comando para crear la imagen:

podman run --rm --privileged -it -v $PWD:/eib \
 registry.suse.com/edge/3.3/edge-image-builder:1.2.1 \
 build --definition-file downstream-cluster-airgap-config.yaml

Esto crea el archivo de imagen ISO de salida denominado eibimage-output-telco.raw, basado en la definición descrita anteriormente.

La imagen resultante debe estar disponible a través de un servidor Web, ya sea el contenedor del servidor de medios habilitado siguiendo los pasos de la sección sobre el clúster de gestión (Nota) o algún otro servidor al que se pueda acceder localmente. En los ejemplos siguientes, nos referimos a este servidor como imagecache.local:8080.

42.4 Aprovisionamiento de clústeres descendentes con aprovisionamiento de red dirigida (nodo único)

En esta sección se describe el flujo de trabajo usado para automatizar el aprovisionamiento de un clúster descendente de un solo nodo con el método de aprovisionamiento de red dirigida. Se trata de la forma más sencilla de automatizar el aprovisionamiento de un clúster descendente.

Requisitos

Flujo de trabajo

El diagrama siguiente muestra el flujo de trabajo usado para automatizar el aprovisionamiento de un clúster descendente de un solo nodo con el método de aprovisionamiento de red dirigida:

atip automatizado de un solo nodo 1

Hay dos pasos diferentes para automatizar el aprovisionamiento de un clúster descendente de un solo nodo con el método de aprovisionamiento de red dirigida:

  1. Inscribir el host bare metal para que esté disponible para el proceso de aprovisionamiento.

  2. Proporcionar el host bare metal para instalar y configurar el sistema operativo y el clúster de Kubernetes.

Inscripción del host bare metal

El primer paso es inscribir el nuevo host bare metal en el clúster de gestión para que esté disponible para su aprovisionamiento. Para ello, se debe crear el archivo bmh-example.yaml en el clúster de gestión, con el fin de especificar las credenciales de BMC que se van a utilizar y el objeto BaremetalHost que se va a inscribir:

apiVersion: v1
kind: Secret
metadata:
  name: example-demo-credentials
type: Opaque
data:
  username: ${BMC_USERNAME}
  password: ${BMC_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: example-demo
  labels:
    cluster-role: control-plane
spec:
  online: true
  bootMACAddress: ${BMC_MAC}
  rootDeviceHints:
    deviceName: /dev/nvme0n1
  bmc:
    address: ${BMC_ADDRESS}
    disableCertificateVerification: true
    credentialsName: example-demo-credentials

Donde:

  • ${BMC_USERNAME}: es el nombre de usuario del BMC del nuevo host bare metal.

  • ${BMC_PASSWORD}: es la contraseña para el BMC del nuevo host bare metal.

  • ${BMC_MAC}: es la dirección MAC del nuevo host bare metal que se va a utilizar.

  • ${BMC_ADDRESS}: es la URL del host bare metal de BMC (por ejemplo, redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/). Para obtener más información sobre las opciones disponibles en función de su proveedor de hardware, consulte el siguiente enlace.

Nota
Nota

Si no se ha especificado ninguna configuración de red para el host, ya sea en el momento de la creación de la imagen o en la definición BareMetalHost, se utilizará un mecanismo de configuración automática (DHCP, DHCPv6 o SLAAC). Para obtener más detalles o configuraciones complejas, consulte la Sección 42.6, “Configuración de red avanzada”.

Una vez creado el archivo, se debe ejecutar el siguiente comando en el clúster de gestión para comenzar a inscribir el nuevo host bare metal en el clúster de gestión:

$ kubectl apply -f bmh-example.yaml

El nuevo objeto host bare metal se inscribirá y cambiará su estado de "registering" (en registro) a "inspecting" (en inspección) y "available" (disponible). Los cambios se pueden comprobar con el siguiente comando:

$ kubectl get bmh
Nota
Nota

El objeto BaremetalHost permanece en estado registering (en registro) hasta que se validan las credenciales de BMC. Una vez validadas las credenciales, el objeto BaremetalHost cambia su estado a inspecting (en inspección), y este paso puede tardar algún tiempo dependiendo del hardware (hasta 20 minutos). Durante la fase de inspección, se recupera la información del hardware y se actualiza el objeto de Kubernetes. Compruebe la información con el siguiente comando: kubectl get bmh -o yaml.

Paso de aprovisionamiento

Una vez que el host bare metal está inscrito y disponible, el paso siguiente es aprovisionar el host bare metal para instalar y configurar el sistema operativo y el clúster de Kubernetes. Para ello, se debe crear el archivo capi-provisioning-example.yaml en el clúster de gestión con la siguiente información (el archivo capi-provisioning-example.yaml se puede generar uniendo los bloques siguientes).

Nota
Nota

Solo los valores entre $\{…​\} deben sustituirse por los valores reales.

El siguiente bloque es la definición del clúster, donde se puede configurar la red utilizando los bloques pods y services. Además, contiene las referencias al plano de control y a los objetos de infraestructura (utilizando el proveedor de Metal3) que se van a utilizar.

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: single-node-cluster
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
    services:
      cidrBlocks:
        - 10.96.0.0/12
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: RKE2ControlPlane
    name: single-node-cluster
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3Cluster
    name: single-node-cluster

Para un despliegue con pods y servicios de doble pila, se puede utilizar la siguiente definición en su lugar:

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: single-node-cluster
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
        - fd00:bad:cafe::/48
    services:
      cidrBlocks:
        - 10.96.0.0/12
        - fd00:bad:bad:cafe::/112
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: RKE2ControlPlane
    name: single-node-cluster
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3Cluster
    name: single-node-cluster
Importante
Importante

Los despliegues de IPv6 y doble pila se encuentran en fase de tecnología en fase preliminar y no son compatibles oficialmente.

El objeto Metal3Cluster especifica el punto final del plano de control (en sustitución de ${DOWNSTREAM_CONTROL_PLANE_IP}) que se va a configurar y el objeto noCloudProvider, ya que se utiliza un nodo bare metal.

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
  name: single-node-cluster
  namespace: default
spec:
  controlPlaneEndpoint:
    host: ${DOWNSTREAM_CONTROL_PLANE_IP}
    port: 6443
  noCloudProvider: true

El objeto RKE2ControlPlane especifica la configuración de plano de control que se va a utilizar y el objeto Metal3MachineTemplate especifica la imagen de plano de control que se va a utilizar. Además, contiene la información sobre el número de réplicas que se utilizarán (en este caso, una) y el complemento de CNI que se usará (en este caso, Cilium). El bloque agentConfig contiene el formato de Ignition que se va a usar y el objeto additionalUserData que se va a usar para configurar el nodo RKE2 con información como un servicio systemd denominado rke2-preinstall.service para sustituir automáticamente BAREMETALHOST_UUID y node-name durante el proceso de aprovisionamiento utilizando la información de Ironic. Para habilitar Multus con Cilium, se crea un archivo en el directorio de manifiestos del servidor rke2 llamado rke2-cilium-config.yaml con la configuración que se va a usar. El último bloque de información contiene la versión de Kubernetes que se va a usar. ${RKE2_VERSION} es la versión de RKE2 que se va a usar en sustitución de este valor (por ejemplo, v1.32.4+rke2r1).

apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  serverConfig:
    cni: cilium
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
            - name: rke2-preinstall.service
              enabled: true
              contents: |
                [Unit]
                Description=rke2-preinstall
                Wants=network-online.target
                Before=rke2-install.service
                ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                [Service]
                Type=oneshot
                User=root
                ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                ExecStartPost=/bin/sh -c "umount /mnt"
                [Install]
                WantedBy=multi-user.target
        storage:
          files:
            # https://docs.rke2.io/networking/multus_sriov#using-multus-with-cilium
            - path: /var/lib/rancher/rke2/server/manifests/rke2-cilium-config.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChartConfig
                  metadata:
                    name: rke2-cilium
                    namespace: kube-system
                  spec:
                    valuesContent: |-
                      cni:
                        exclusive: false
              mode: 0644
              user:
                name: root
              group:
                name: root
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

El objeto Metal3MachineTemplate especifica la información siguiente:

  • La plantilla de datos (dataTemplate) que se usará como referencia para la plantilla.

  • El selector de host (hostSelector) que se usará que coincida con la etiqueta creada durante el proceso de inscripción.

  • La imagen (image) que se usará como referencia para la imagen generada mediante EIB en la sección anterior (Sección 42.2, “Preparación de la imagen del clúster descendente para entornos conectados”), y la suma de comprobación (checksum) y el tipo de suma (checksumType) que se usarán para validar la imagen.

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: single-node-cluster-controlplane
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: single-node-cluster-controlplane-template
      hostSelector:
        matchLabels:
          cluster-role: control-plane
      image:
        checksum: http://imagecache.local:8080/eibimage-output-telco.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/eibimage-output-telco.raw

El objeto Metal3DataTemplate especifica los metadatos (metaData) para el clúster descendente.

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: single-node-cluster-controlplane-template
  namespace: default
spec:
  clusterName: single-node-cluster
  metaData:
    objectNames:
      - key: name
        object: machine
      - key: local-hostname
        object: machine
      - key: local_hostname
        object: machine

Una vez creado el archivo uniendo los bloques anteriores, se debe ejecutar el comando siguiente en el clúster de gestión para iniciar el aprovisionamiento del nuevo host bare metal:

$ kubectl apply -f capi-provisioning-example.yaml

42.5 Aprovisionamiento de clústeres descendentes con aprovisionamiento de red dirigida (varios nodos)

En esta sección se describe el flujo de trabajo usado para automatizar el aprovisionamiento de un clúster descendente de varios nodos con el método de aprovisionamiento de red dirigida y MetalLB como equilibrador de carga. Esta es la forma más sencilla de automatizar el aprovisionamiento de un clúster descendente. El siguiente diagrama muestra el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente de varios nodos con el método de aprovisionamiento de red dirigida y MetalLB.

Requisitos

Flujo de trabajo

El diagrama siguiente muestra el flujo de trabajo usado para automatizar el aprovisionamiento de un clúster descendente de varios nodos con el método de aprovisionamiento de red dirigida:

atip automatizado de varios nodos 1
  1. Inscriba los tres hosts bare metal para que estén disponibles para el proceso de aprovisionamiento.

  2. Aprovisione los tres hosts bare metal para instalar y configurar el sistema operativo y el clúster de Kubernetes con MetalLB.

Inscripción de los hosts bare metal

El primer paso es inscribir los tres hosts bare metal en el clúster de gestión para que estén disponibles para su aprovisionamiento. Para ello, se deben crear los archivos bmh-example-node1.yaml, bmh-example-node2.yaml y bmh-example-node3.yaml en el clúster de gestión para especificar las credenciales de BMC que se van a utilizar y el objeto BaremetalHost que se va a inscribir en el clúster de gestión.

Nota
Nota
  • Solo los valores entre $\{…​\} deben sustituirse por los valores reales.

  • Le guiaremos por el proceso para un solo host. Los mismos pasos se aplican a los otros dos nodos.

apiVersion: v1
kind: Secret
metadata:
  name: node1-example-credentials
type: Opaque
data:
  username: ${BMC_NODE1_USERNAME}
  password: ${BMC_NODE1_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: node1-example
  labels:
    cluster-role: control-plane
spec:
  online: true
  bootMACAddress: ${BMC_NODE1_MAC}
  bmc:
    address: ${BMC_NODE1_ADDRESS}
    disableCertificateVerification: true
    credentialsName: node1-example-credentials

Donde:

  • ${BMC_NODE1_USERNAME}: es el nombre de usuario para el BMC del primer host bare metal.

  • ${BMC_NODE1_PASSWORD}: es la contraseña para el BMC del primer host bare metal.

  • ${BMC_NODE1_MAC}: es la dirección MAC del primer host bare metal que se utilizará.

  • ${BMC_NODE1_ADDRESS}: es la URL del primer host BMC bare metal (por ejemplo, redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/). Para obtener más información sobre las opciones disponibles en función de su proveedor de hardware, consulte el siguiente enlace.

Nota
Nota
  • Si no se ha especificado ninguna configuración de red para el host, ya sea en el momento de la creación de la imagen o en la definición BareMetalHost, se utilizará un mecanismo de configuración automática (DHCP, DHCPv6 o SLAAC). Para obtener más detalles o configuraciones complejas, consulte la Sección 42.6, “Configuración de red avanzada”.

  • Aún no se admiten clústeres de varios nodos con doble pila o solo IPv6.

Una vez creado el archivo, se debe ejecutar el comando siguiente en el clúster de gestión para comenzar a inscribir los hosts bare metal en el clúster de gestión:

$ kubectl apply -f bmh-example-node1.yaml
$ kubectl apply -f bmh-example-node2.yaml
$ kubectl apply -f bmh-example-node3.yaml

Los nuevos objetos host bare metal se inscriben y cambian su estado de "registering" (en registro) a "inspecting" (en inspección) y "available" (disponible). Los cambios se pueden comprobar con el siguiente comando:

$ kubectl get bmh -o wide
Nota
Nota

El objeto BaremetalHost permanece en estado registering (en registro) hasta que se validan las credenciales de BMC. Una vez validadas las credenciales, el objeto BaremetalHost cambia su estado a inspecting (en inspección), y este paso puede tardar algún tiempo dependiendo del hardware (hasta 20 minutos). Durante la fase de inspección, se recupera la información del hardware y se actualiza el objeto de Kubernetes. Compruebe la información con el siguiente comando: kubectl get bmh -o yaml.

Paso de aprovisionamiento

Una vez que los tres hosts bare metal se han inscrito y están disponibles, el siguiente paso es aprovisionar los hosts bare metal para instalar y configurar el sistema operativo y el clúster de Kubernetes, creando un equilibrador de carga para gestionarlos. Para ello, se debe crear el archivo capi-provisioning-example.yaml en el clúster de gestión con la siguiente información (el archivo capi-provisioning-example.yaml se puede generar uniendo los siguientes bloques).

Nota
Nota
  • Solo los valores entre $\{…​\} deben sustituirse por los valores reales.

  • La dirección IP virtual es una dirección IP reservada que no se asigna a ningún nodo y se utiliza para configurar el equilibrador de carga.

A continuación, se muestra la definición del clúster, donde la red del clúster se puede configurar utilizando los bloques pods y services. Además, contiene las referencias al plano de control y a los objetos de infraestructura (utilizando el proveedor de Metal3) que se van a utilizar.

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: multinode-cluster
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
    services:
      cidrBlocks:
        - 10.96.0.0/12
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: RKE2ControlPlane
    name: multinode-cluster
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3Cluster
    name: multinode-cluster

El objeto Metal3Cluster especifica el punto final de plano de control que usa la dirección IP virtual ya reservada (en sustitución de ${DOWNSTREAM_VIP_ADDRESS}) que se va a configurar y noCloudProvider porque se utilizan los tres nodos bare metal.

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
  name: multinode-cluster
  namespace: default
spec:
  controlPlaneEndpoint:
    host: ${EDGE_VIP_ADDRESS}
    port: 6443
  noCloudProvider: true

El objeto RKE2ControlPlane especifica la configuración de plano de control que se va a utilizar, y el objeto Metal3MachineTemplate especifica la imagen de plano de control que se va a utilizar.

  • El número de réplicas que se utilizarán (en este caso, tres).

  • El modo de anuncios que utilizará el equilibrador de carga (en address se usa la implementación L2), así como la dirección que se va a usar (sustituyendo ${EDGE_VIP_ADDRESS} por la dirección IP virtual).

  • El serverConfig con el complemento de CNI que se va a usar (en este caso, Cilium) y el tlsSan que se va a usar para configurar la dirección IP virtual.

  • El bloque agentConfig contiene el formato de Ignition que se va a usar y el bloque additionalUserData que se va a usar para configurar el nodo RKE2 con información como:

    • El servicio systemd denominado rke2-preinstall.service que sustituye automáticamente a BAREMETALHOST_UUID y node-name durante el proceso de aprovisionamiento con la información de Ironic.

    • El bloque storage que contiene los charts de Helm que se van a usar para instalar MetalLB y endpoint-copier-operator.

    • El archivo de recurso personalizado de metalLB con el IPaddressPool y el L2Advertisement que se van a usar (sustituyendo ${EDGE_VIP_ADDRESS} por la dirección IP virtual).

    • El archivo endpoint-svc.yaml que se va a usar para configurar el servicio kubernetes-vip que utilizará MetalLB para gestionar la dirección IP virtual.

  • El último bloque de información contiene la versión de Kubernetes que se va a usar. ${RKE2_VERSION} es la versión de RKE2 que se va a usar en sustitución de este valor (por ejemplo, v1.32.4+rke2r1).

apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
  name: multinode-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: multinode-cluster-controlplane
  replicas: 3
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  registrationMethod: "control-plane-endpoint"
  registrationAddress: ${EDGE_VIP_ADDRESS}
  serverConfig:
    cni: cilium
    tlsSan:
      - ${EDGE_VIP_ADDRESS}
      - https://${EDGE_VIP_ADDRESS}.sslip.io
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
            - name: rke2-preinstall.service
              enabled: true
              contents: |
                [Unit]
                Description=rke2-preinstall
                Wants=network-online.target
                Before=rke2-install.service
                ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                [Service]
                Type=oneshot
                User=root
                ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                ExecStartPost=/bin/sh -c "umount /mnt"
                [Install]
                WantedBy=multi-user.target
        storage:
          files:
            # https://docs.rke2.io/networking/multus_sriov#using-multus-with-cilium
            - path: /var/lib/rancher/rke2/server/manifests/rke2-cilium-config.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChartConfig
                  metadata:
                    name: rke2-cilium
                    namespace: kube-system
                  spec:
                    valuesContent: |-
                      cni:
                        exclusive: false
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /var/lib/rancher/rke2/server/manifests/endpoint-copier-operator.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: endpoint-copier-operator
                    namespace: kube-system
                  spec:
                    chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
                    targetNamespace: endpoint-copier-operator
                    version: 303.0.0+up0.2.1
                    createNamespace: true
            - path: /var/lib/rancher/rke2/server/manifests/metallb.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: metallb
                    namespace: kube-system
                  spec:
                    chart: oci://registry.suse.com/edge/charts/metallb
                    targetNamespace: metallb-system
                    version: 303.0.0+up0.14.9
                    createNamespace: true

            - path: /var/lib/rancher/rke2/server/manifests/metallb-cr.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: metallb.io/v1beta1
                  kind: IPAddressPool
                  metadata:
                    name: kubernetes-vip-ip-pool
                    namespace: metallb-system
                  spec:
                    addresses:
                      - ${EDGE_VIP_ADDRESS}/32
                    serviceAllocation:
                      priority: 100
                      namespaces:
                        - default
                      serviceSelectors:
                        - matchExpressions:
                          - {key: "serviceType", operator: In, values: [kubernetes-vip]}
                  ---
                  apiVersion: metallb.io/v1beta1
                  kind: L2Advertisement
                  metadata:
                    name: ip-pool-l2-adv
                    namespace: metallb-system
                  spec:
                    ipAddressPools:
                      - kubernetes-vip-ip-pool
            - path: /var/lib/rancher/rke2/server/manifests/endpoint-svc.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: v1
                  kind: Service
                  metadata:
                    name: kubernetes-vip
                    namespace: default
                    labels:
                      serviceType: kubernetes-vip
                  spec:
                    ports:
                    - name: rke2-api
                      port: 9345
                      protocol: TCP
                      targetPort: 9345
                    - name: k8s-api
                      port: 6443
                      protocol: TCP
                      targetPort: 6443
                    type: LoadBalancer
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "Node-multinode-cluster"

El objeto Metal3MachineTemplate especifica la información siguiente:

  • La plantilla de datos (dataTemplate) que se usará como referencia para la plantilla.

  • El selector de host (hostSelector) que se usará que coincida con la etiqueta creada durante el proceso de inscripción.

  • La imagen (image) que se va a usar como referencia para la imagen generada con EIB en la sección anterior (Sección 42.2, “Preparación de la imagen del clúster descendente para entornos conectados”), y la suma de comprobación (checksum) y el tipo de suma (checksumType) que se van a usar para validar la imagen.

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: multinode-cluster-controlplane
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: multinode-cluster-controlplane-template
      hostSelector:
        matchLabels:
          cluster-role: control-plane
      image:
        checksum: http://imagecache.local:8080/eibimage-output-telco.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/eibimage-output-telco.raw

El objeto Metal3DataTemplate especifica los metadatos (metaData) para el clúster descendente.

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: multinode-cluster-controlplane-template
  namespace: default
spec:
  clusterName: multinode-cluster
  metaData:
    objectNames:
      - key: name
        object: machine
      - key: local-hostname
        object: machine
      - key: local_hostname
        object: machine

Una vez creado el archivo uniendo los bloques anteriores, se debe ejecutar el comando siguiente en el clúster de gestión para iniciar el aprovisionamiento de los tres nuevos hosts bare metal:

$ kubectl apply -f capi-provisioning-example.yaml

42.6 Configuración de red avanzada

El flujo de trabajo de aprovisionamiento de red dirigida permite configuraciones de red específicas en clústeres descendentes, como direcciones IP estáticas, vinculación, VLAN, IPv6, etc.

Las secciones siguientes describen los pasos adicionales necesarios para habilitar el aprovisionamiento de clústeres descendentes con el método de configuración de red avanzada.

Requisitos

Configuración

Antes de continuar, consulte en las secciones siguientes los pasos necesarios para inscribir y aprovisionar los hosts:

Cualquier configuración de red avanzada debe aplicarse en el momento de la inscripción mediante la definición de host BareMetalHost y un secreto asociado que contenga un bloque networkData con formato nmstate. El siguiente archivo de ejemplo define un secreto que contiene el bloque networkData necesario que solicita una IP estática y una VLAN para el host del clúster descendente:

apiVersion: v1
kind: Secret
metadata:
  name: controlplane-0-networkdata
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: ${CONTROLPLANE_INTERFACE}
      type: ethernet
      state: up
      mtu: 1500
      identifier: mac-address
      mac-address: "${CONTROLPLANE_MAC}"
      ipv4:
        address:
        - ip:  "${CONTROLPLANE_IP}"
          prefix-length: "${CONTROLPLANE_PREFIX}"
        enabled: true
        dhcp: false
    - name: floating
      type: vlan
      state: up
      vlan:
        base-iface: ${CONTROLPLANE_INTERFACE}
        id: ${VLAN_ID}
    dns-resolver:
      config:
        server:
        - "${DNS_SERVER}"
    routes:
      config:
      - destination: 0.0.0.0/0
        next-hop-address: "${CONTROLPLANE_GATEWAY}"
        next-hop-interface: ${CONTROLPLANE_INTERFACE}

Como puede ver, el ejemplo muestra la configuración para habilitar la interfaz con direcciones IP estáticas, así como la configuración para habilitar la VLAN utilizando la interfaz base, una vez que las siguientes variables se sustituyan por los valores reales de su infraestructura:

  • ${CONTROLPLANE1_INTERFACE}: es la interfaz de plano de control que se usará para el clúster periférico (por ejemplo, eth0). Si se incluye identificador: dirección MAC, el nombre se comprueba automáticamente por su dirección MAC, por lo que se puede utilizar cualquier nombre de interfaz.

  • ${CONTROLPLANE1_IP}: es la dirección IP que se usará como punto final para el clúster periférico (debe coincidir con el punto final kubeapi-server).

  • ${CONTROLPLANE1_PREFIX}: es el CIDR que se usará para el clúster periférico (por ejemplo, 24 si desea /24 o 255.255.255.0).

  • ${CONTROLPLANE1_GATEWAY}: es el gateway que se usará para el clúster periférico (por ejemplo, 192.168.100.1).

  • ${CONTROLPLANE1_MAC}: es la dirección MAC que se usará para la interfaz de plano de control (por ejemplo, 00:0c:29:3e:3e:3e).

  • ${DNS_SERVER}: es el servidor DNS que se usará para el clúster periférico (por ejemplo, 192.168.100.2).

  • ${VLAN_ID}: es el ID de VLAN que se usará para el clúster periférico (por ejemplo, 100).

Se puede usar cualquier otra definición compatible con nmstate para configurar la red del clúster descendente y adaptarla a los requisitos específicos. Por ejemplo, es posible especificar una configuración estática de doble pila:

apiVersion: v1
kind: Secret
metadata:
  name: controlplane-0-networkdata
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: ${CONTROLPLANE_INTERFACE}
      type: ethernet
      state: up
      mac-address: ${CONTROLPLANE_MAC}
      ipv4:
        enabled: true
        dhcp: false
        address:
        - ip: ${CONTROLPLANE_IP_V4}
          prefix-length: ${CONTROLPLANE_PREFIX_V4}
      ipv6:
        enabled: true
        dhcp: false
        autoconf: false
        address:
        - ip: ${CONTROLPLANE_IP_V6}
          prefix-length: ${CONTROLPLANE_PREFIX_V6}
    routes:
      config:
      - destination: 0.0.0.0/0
        next-hop-address: ${CONTROLPLANE_GATEWAY_V4}
        next-hop-interface: ${CONTROLPLANE_INTERFACE}
      - destination: ::/0
        next-hop-address: ${CONTROLPLANE_GATEWAY_V6}
        next-hop-interface: ${CONTROLPLANE_INTERFACE}
    dns-resolver:
      config:
        server:
        - ${DNS_SERVER_V4}
        - ${DNS_SERVER_V6}

En el ejemplo anterior, sustituya las variables siguientes por los valores reales de su infraestructura:

  • ${CONTROLPLANE_IP_V4}: la dirección IPv4 que se asignará al host

  • ${CONTROLPLANE_PREFIX_V4}: el prefijo IPv4 de la red a la que pertenece la IP del host

  • ${CONTROLPLANE_IP_V6}: la dirección IPv6 que se asignará al host

  • ${CONTROLPLANE_PREFIX_V6}: el prefijo IPv6 de la red a la que pertenece la IP del host

  • ${CONTROLPLANE_GATEWAY_V4}: la dirección IPv4 del gateway para el tráfico que coincide con la ruta predeterminada

  • ${CONTROLPLANE_GATEWAY_V6}: la dirección IPv6 del gateway para el tráfico que coincide con la ruta predeterminada

  • ${CONTROLPLANE_INTERFACE}: el nombre de la interfaz a la que se asignarán las direcciones y que se usará para el tráfico de salida que coincida con la ruta predeterminada, tanto para IPv4 como para IPv6

  • ${DNS_SERVER_V4} y/o ${DNS_SERVER_V6}: las direcciones IP de los servidores DNS que se van a usar, que pueden especificarse como entradas únicas o múltiples. Se admiten direcciones IPv4 y/o IPv6

Importante
Importante

Los despliegues de IPv6 y doble pila se encuentran en fase de tecnología en fase preliminar y no son compatibles oficialmente.

Nota
Nota

En el repositorio de ejemplos de SUSE Edge for Telco encontrará ejemplos más complejos, incluidas configuraciones solo de IPv6 y de doble pila.

Por último, independientemente de los detalles de la configuración de red, asegúrese de que se haga referencia al secreto añadiendo preprovisioningNetworkDataName al objeto BaremetalHost para inscribir correctamente el host en el clúster de gestión.

apiVersion: v1
kind: Secret
metadata:
  name: example-demo-credentials
type: Opaque
data:
  username: ${BMC_USERNAME}
  password: ${BMC_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: example-demo
  labels:
    cluster-role: control-plane
spec:
  online: true
  bootMACAddress: ${BMC_MAC}
  rootDeviceHints:
    deviceName: /dev/nvme0n1
  bmc:
    address: ${BMC_ADDRESS}
    disableCertificateVerification: true
    credentialsName: example-demo-credentials
  preprovisioningNetworkDataName: controlplane-0-networkdata
Nota
Nota
  • Si necesita desplegar un clúster de varios nodos, debe realizar el mismo proceso para cada nodo.

  • Actualmente, Metal3DataTemplate, networkData y Metal3 IPAM no se admiten; solo se admite plenamente la configuración mediante secretos estáticos.

42.7 Funciones para telecomunicaciones (DPDK, SR-IOV, aislamiento de CPU, páginas enormes, NUMA, etc.)

El flujo de trabajo de aprovisionamiento de red dirigida permite automatizar las funciones de telecomunicaciones que se usarán en los clústeres descendentes para ejecutar cargas de trabajo de telecomunicaciones en esos servidores.

Requisitos

Configuración

Use las dos secciones siguientes como base para inscribir y aprovisionar los hosts:

Las funciones de telecomunicaciones que se tratan en esta sección son las siguientes:

  • DPDK y creación de funciones virtuales

  • Asignación de SR-IOV y funciones virtuales que usarán las cargas de trabajo

  • Aislamiento de CPU y optimización del rendimiento

  • Configuración de páginas enormes

  • Optimización de los parámetros del kernel

Nota
Nota

Para obtener más información sobre las funciones de telecomunicaciones, consulte el Capítulo 41, Configuración de funciones de telecomunicaciones.

Todos los cambios necesarios para habilitar las funciones de telecomunicaciones indicados arriba se encuentran en el bloque RKE2ControlPlane del archivo de aprovisionamiento capi-provisioning-example.yaml. El resto de la información contenida en el archivo capi-provisioning-example.yaml es la misma que se proporciona en la sección sobre aprovisionamiento (Sección 42.4, “Aprovisionamiento de clústeres descendentes con aprovisionamiento de red dirigida (nodo único)”).

Para que el proceso quede claro, los cambios necesarios en ese bloque (RKE2ControlPlane) para habilitar las funciones de telecomunicaciones son los siguientes:

  • Los comandos preRKE2Commands que se usarán para ejecutar los comandos antes del proceso de instalación de RKE2. En este caso, use el comando modprobe para habilitar los módulos del kernel vfio-pci y SR-IOV.

  • El archivo de Ignition /var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml se usará para definir las interfaces, los controladores y el número de funciones virtuales que se crearán y expondrán a las cargas de trabajo.

    • Los valores del mapa de configuración sriov-custom-auto-config son los únicos que deben sustituirse por valores reales.

      • ${RESOURCE_NAME1}: el nombre del recurso que se va a usar para la primera interfaz de función física PF (por ejemplo, sriov-resource-du1). Se añade al prefijo rancher.io para usarse como etiqueta que utilizarán las cargas de trabajo (por ejemplo, rancher.io/sriov-resource-du1).

      • ${SRIOV-NIC-NAME1}: el nombre de la primera interfaz de función física PF que se usará (por ejemplo, eth0).

      • ${PF_NAME1}: el nombre de la primera función física PF que se usará. Con esto, puede generar filtros más complejos (por ejemplo, eth0#2-5).

      • ${DRIVER_NAME1}: el nombre del controlador que se usará para la primera interfaz de función virtual VF (por ejemplo, vfio-pci).

      • ${NUM_VFS1}: el número de funciones virtuales que se crearán para la primera interfaz de función física PF (por ejemplo, 8).

  • El archivo /var/sriov-auto-filler.sh que se usará como traductor entre el mapa de configuración general sriov-custom-auto-config y el archivo sriovnetworknodepolicy, que contiene la información de hardware de bajo nivel. Este guion se ha creado para evitar al usuario la complejidad que supone que tenga que conocer de antemano la información de hardware. No es necesario realizar cambios en este archivo, pero debe estar presente si necesitamos habilitar sr-iov y crear funciones virtuales.

  • Los argumentos del kernel que se usarán para habilitar las siguientes funciones:

Parámetro

Valor

Descripción

isolcpus

domain,nohz,managed_irq,1-30,33-62

Aísla los núcleos 1-30 y 33-62.

skew_tick

1

Permite al kernel distribuir las interrupciones del temporizador entre las CPU aisladas.

nohz

on

Permite al kernel ejecutar la marca del temporizador en una sola CPU cuando el sistema está inactivo.

nohz_full

1-30,33-62

El parámetro de arranque del kernel es la interfaz principal actual para configurar dynticks completos junto con el aislamiento de la CPU.

rcu_nocbs

1-30,33-62

Permite al kernel ejecutar las retrollamadas de RCU en una sola CPU cuando el sistema está inactivo.

irqaffinity

0,31,32,63

Permite al kernel ejecutar las interrupciones en una sola CPU cuando el sistema está inactivo.

idle

poll

Minimiza la latencia al salir del estado inactivo.

iommu

pt

Permite usar vfio para las interfaces dpdk.

intel_iommu

on

Habilita el uso de vfio para funciones virtuales.

hugepagesz

1G

Permite establecer el tamaño de las páginas enormes en 1 GB.

hugepages

40

El número de páginas enormes definidas anteriormente.

default_hugepagesz

1G

Valor predeterminado para habilitar las páginas enormes.

nowatchdog

 

Inhabilita el watchdog.

nmi_watchdog

0

Inhabilita el watchdog de NMI.

  • Los siguientes servicios systemd se utilizan para habilitar lo siguiente:

    • rke2-preinstall.service para sustituir automáticamente BAREMETALHOST_UUID y node-name durante el proceso de aprovisionamiento utilizando la información de Ironic.

    • cpu-partitioning.service para habilitar los núcleos de aislamiento de la CPU (por ejemplo, 1-30,33-62).

    • performance-settings.service para habilitar la optimización del rendimiento de la CPU.

    • sriov-custom-auto-vfs.service para instalar el chart de Helm sriov. Espere hasta que se creen los recursos personalizados y ejecute /var/sriov-auto-filler.sh para reemplazar los valores en el mapa de configuración sriov-custom-auto-config y crear el sriovnetworknodepolicy que utilizarán las cargas de trabajo.

  • ${RKE2_VERSION} es la versión de RKE2 que se usará en sustitución de este valor (por ejemplo, v1.32.4+rke2r1).

Con todos estos cambios mencionados, el bloque RKE2ControlPlane del archivo capi-provisioning-example.yaml tendrá el siguiente aspecto:

apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  serverConfig:
    cni: calico
    cniMultusEnable: true
  preRKE2Commands:
    - modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        storage:
          files:
            - path: /var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: v1
                  kind: ConfigMap
                  metadata:
                    name: sriov-custom-auto-config
                    namespace: kube-system
                  data:
                    config.json: |
                      [
                         {
                           "resourceName": "${RESOURCE_NAME1}",
                           "interface": "${SRIOV-NIC-NAME1}",
                           "pfname": "${PF_NAME1}",
                           "driver": "${DRIVER_NAME1}",
                           "numVFsToCreate": ${NUM_VFS1}
                         },
                         {
                           "resourceName": "${RESOURCE_NAME2}",
                           "interface": "${SRIOV-NIC-NAME2}",
                           "pfname": "${PF_NAME2}",
                           "driver": "${DRIVER_NAME2}",
                           "numVFsToCreate": ${NUM_VFS2}
                         }
                      ]
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /var/lib/rancher/rke2/server/manifests/sriov-crd.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: sriov-crd
                    namespace: kube-system
                  spec:
                    chart: oci://registry.suse.com/edge/charts/sriov-crd
                    targetNamespace: sriov-network-operator
                    version: 303.0.2+up1.5.0
                    createNamespace: true
            - path: /var/lib/rancher/rke2/server/manifests/sriov-network-operator.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: sriov-network-operator
                    namespace: kube-system
                  spec:
                    chart: oci://registry.suse.com/edge/charts/sriov-network-operator
                    targetNamespace: sriov-network-operator
                    version: 303.0.2+up1.5.0
                    createNamespace: true
        kernel_arguments:
          should_exist:
            - intel_iommu=on
            - iommu=pt
            - idle=poll
            - mce=off
            - hugepagesz=1G hugepages=40
            - hugepagesz=2M hugepages=0
            - default_hugepagesz=1G
            - irqaffinity=${NON-ISOLATED_CPU_CORES}
            - isolcpus=domain,nohz,managed_irq,${ISOLATED_CPU_CORES}
            - nohz_full=${ISOLATED_CPU_CORES}
            - rcu_nocbs=${ISOLATED_CPU_CORES}
            - rcu_nocb_poll
            - nosoftlockup
            - nowatchdog
            - nohz=on
            - nmi_watchdog=0
            - skew_tick=1
            - quiet
        systemd:
          units:
            - name: rke2-preinstall.service
              enabled: true
              contents: |
                [Unit]
                Description=rke2-preinstall
                Wants=network-online.target
                Before=rke2-install.service
                ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                [Service]
                Type=oneshot
                User=root
                ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                ExecStartPost=/bin/sh -c "umount /mnt"
                [Install]
                WantedBy=multi-user.target
            - name: cpu-partitioning.service
              enabled: true
              contents: |
                [Unit]
                Description=cpu-partitioning
                Wants=network-online.target
                After=network.target network-online.target
                [Service]
                Type=oneshot
                User=root
                ExecStart=/bin/sh -c "echo isolated_cores=${ISOLATED_CPU_CORES} > /etc/tuned/cpu-partitioning-variables.conf"
                ExecStartPost=/bin/sh -c "tuned-adm profile cpu-partitioning"
                ExecStartPost=/bin/sh -c "systemctl enable tuned.service"
                [Install]
                WantedBy=multi-user.target
            - name: performance-settings.service
              enabled: true
              contents: |
                [Unit]
                Description=performance-settings
                Wants=network-online.target
                After=network.target network-online.target cpu-partitioning.service
                [Service]
                Type=oneshot
                User=root
                ExecStart=/bin/sh -c "/opt/performance-settings/performance-settings.sh"
                [Install]
                WantedBy=multi-user.target
            - name: sriov-custom-auto-vfs.service
              enabled: true
              contents: |
                [Unit]
                Description=SRIOV Custom Auto VF Creation
                Wants=network-online.target  rke2-server.target
                After=network.target network-online.target rke2-server.target
                [Service]
                User=root
                Type=forking
                TimeoutStartSec=900
                ExecStart=/bin/sh -c "while ! /var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml wait --for condition=ready nodes --all ; do sleep 2 ; done"
                ExecStartPost=/bin/sh -c "while [ $(/var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml get sriovnetworknodestates.sriovnetwork.openshift.io --ignore-not-found --no-headers -A | wc -l) -eq 0 ]; do sleep 1; done"
                ExecStartPost=/bin/sh -c "/opt/sriov/sriov-auto-filler.sh"
                RemainAfterExit=yes
                KillMode=process
                [Install]
                WantedBy=multi-user.target
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

Una vez creado el archivo uniendo los bloques anteriores, se debe ejecutar el siguiente comando en el clúster de gestión para iniciar el aprovisionamiento del nuevo clúster descendente utilizando las funciones de telecomunicaciones:

$ kubectl apply -f capi-provisioning-example.yaml

42.8 Registro privado

Es posible configurar un registro privado como duplicado de las imágenes usadas por las cargas de trabajo.

Para ello, creamos el secreto que contiene la información sobre el registro privado que usará el clúster descendente.

apiVersion: v1
kind: Secret
metadata:
  name: private-registry-cert
  namespace: default
data:
  tls.crt: ${TLS_CERTIFICATE}
  tls.key: ${TLS_KEY}
  ca.crt: ${CA_CERTIFICATE}
type: kubernetes.io/tls
---
apiVersion: v1
kind: Secret
metadata:
  name: private-registry-auth
  namespace: default
data:
  username: ${REGISTRY_USERNAME}
  password: ${REGISTRY_PASSWORD}

Los archivos tls.crt, tls.key y ca.crt son los certificados que se usarán para autenticar el registro privado. username y password son las credenciales que se usarán para autenticar el registro privado.

Nota
Nota

Los campos tls.crt, tls.key, ca.crt, username y password deben cifrarse en formato base64 antes de utilizarse en el secreto.

Con todos estos cambios mencionados, el bloque RKE2ControlPlane del archivo capi-provisioning-example.yaml tendrá el siguiente aspecto:

apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  privateRegistriesConfig:
    mirrors:
      "registry.example.com":
        endpoint:
          - "https://registry.example.com:5000"
    configs:
      "registry.example.com":
        authSecret:
          apiVersion: v1
          kind: Secret
          namespace: default
          name: private-registry-auth
        tls:
          tlsConfigSecret:
            apiVersion: v1
            kind: Secret
            namespace: default
            name: private-registry-cert
  serverConfig:
    cni: calico
    cniMultusEnable: true
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
            - name: rke2-preinstall.service
              enabled: true
              contents: |
                [Unit]
                Description=rke2-preinstall
                Wants=network-online.target
                Before=rke2-install.service
                ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                [Service]
                Type=oneshot
                User=root
                ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                ExecStartPost=/bin/sh -c "umount /mnt"
                [Install]
                WantedBy=multi-user.target
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

Donde registry.example.com es el nombre de ejemplo del registro privado que usará el clúster descendente, y debe sustituirse por los valores reales.

42.9 Aprovisionamiento de clústeres descendentes en entornos aislados

El flujo de trabajo de aprovisionamiento de red dirigida permite automatizar el aprovisionamiento de clústeres descendentes en entornos aislados.

42.9.1 Requisitos para entornos aislados

  1. La imagen raw generada con EIB debe incluir las imágenes de contenedor específicas (OCI de chart de Helm e imágenes de contenedor) necesarias para ejecutar el clúster descendente en un entorno aislado. Para obtener más información, consulte la Sección 42.3, “Preparación de la imagen del clúster descendente para entornos aislados”.

  2. En caso de usar SR-IOV o cualquier otra carga de trabajo personalizada, las imágenes necesarias para ejecutar las cargas de trabajo deben cargarse previamente en su registro privado siguiendo las instrucciones de la Sección 42.3.2.7, “Carga previa del registro privado con las imágenes necesarias para situaciones de entornos aislados y SR-IOV (opcional)”.

42.9.2 Inscripción de los hosts bare metal en entornos aislados

El proceso para inscribir los hosts bare metal en el clúster de gestión es el mismo que se describe en la Sección 42.4, “Aprovisionamiento de clústeres descendentes con aprovisionamiento de red dirigida (nodo único)”.

42.9.3 Aprovisionamiento del clúster descendente en entornos aislados

Hay algunos cambios importantes que se deben realizar para aprovisionar el clúster descendente en entornos aislados:

  1. El bloque RKE2ControlPlane del archivo capi-provisioning-example.yaml debe incluir la directiva spec.agentConfig.airGapped: true.

  2. La configuración del registro privado debe incluirse en el bloque RKE2ControlPlane del archivo capi-provisioning-airgap-example.yaml, después de la sección del registro privado (Sección 42.8, “Registro privado”).

  3. Si usa SR-IOV o cualquier otra configuración AdditionalUserData (guion de Combustion) que requiera la instalación del chart de Helm, debe modificar el contenido para que haga referencia al registro privado en lugar de utilizar el registro público.

El siguiente ejemplo muestra la configuración SR-IOV del bloque AdditionalUserData del archivo capi-provisioning-airgap-example.yaml con las modificaciones necesarias para hacer referencia al registro privado.

  • Referencias de secretos del registro privado

  • Definición del chart de Helm que usa el registro privado en lugar de las imágenes OCI públicas

# secret to include the private registry certificates
apiVersion: v1
kind: Secret
metadata:
  name: private-registry-cert
  namespace: default
data:
  tls.crt: ${TLS_BASE64_CERT}
  tls.key: ${TLS_BASE64_KEY}
  ca.crt: ${CA_BASE64_CERT}
type: kubernetes.io/tls
---
# secret to include the private registry auth credentials
apiVersion: v1
kind: Secret
metadata:
  name: private-registry-auth
  namespace: default
data:
  username: ${REGISTRY_USERNAME}
  password: ${REGISTRY_PASSWORD}
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  privateRegistriesConfig:       # Private registry configuration to add your own mirror and credentials
    mirrors:
      docker.io:
        endpoint:
          - "https://$(PRIVATE_REGISTRY_URL)"
    configs:
      "192.168.100.22:5000":
        authSecret:
          apiVersion: v1
          kind: Secret
          namespace: default
          name: private-registry-auth
        tls:
          tlsConfigSecret:
            apiVersion: v1
            kind: Secret
            namespace: default
            name: private-registry-cert
          insecureSkipVerify: false
  serverConfig:
    cni: calico
    cniMultusEnable: true
  preRKE2Commands:
    - modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  agentConfig:
    airGapped: true       # Airgap true to enable airgap mode
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        storage:
          files:
            - path: /var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: v1
                  kind: ConfigMap
                  metadata:
                    name: sriov-custom-auto-config
                    namespace: sriov-network-operator
                  data:
                    config.json: |
                      [
                         {
                           "resourceName": "${RESOURCE_NAME1}",
                           "interface": "${SRIOV-NIC-NAME1}",
                           "pfname": "${PF_NAME1}",
                           "driver": "${DRIVER_NAME1}",
                           "numVFsToCreate": ${NUM_VFS1}
                         },
                         {
                           "resourceName": "${RESOURCE_NAME2}",
                           "interface": "${SRIOV-NIC-NAME2}",
                           "pfname": "${PF_NAME2}",
                           "driver": "${DRIVER_NAME2}",
                           "numVFsToCreate": ${NUM_VFS2}
                         }
                      ]
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /var/lib/rancher/rke2/server/manifests/sriov.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: v1
                  data:
                    .dockerconfigjson: ${REGISTRY_AUTH_DOCKERCONFIGJSON}
                  kind: Secret
                  metadata:
                    name: privregauth
                    namespace: kube-system
                  type: kubernetes.io/dockerconfigjson
                  ---
                  apiVersion: v1
                  kind: ConfigMap
                  metadata:
                    namespace: kube-system
                    name: example-repo-ca
                  data:
                    ca.crt: |-
                      -----BEGIN CERTIFICATE-----
                      ${CA_BASE64_CERT}
                      -----END CERTIFICATE-----
                  ---
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: sriov-crd
                    namespace: kube-system
                  spec:
                    chart: oci://${PRIVATE_REGISTRY_URL}/sriov-crd
                    dockerRegistrySecret:
                      name: privregauth
                    repoCAConfigMap:
                      name: example-repo-ca
                    createNamespace: true
                    set:
                      global.clusterCIDR: 192.168.0.0/18
                      global.clusterCIDRv4: 192.168.0.0/18
                      global.clusterDNS: 10.96.0.10
                      global.clusterDomain: cluster.local
                      global.rke2DataDir: /var/lib/rancher/rke2
                      global.serviceCIDR: 10.96.0.0/12
                    targetNamespace: sriov-network-operator
                    version: 303.0.2+up1.5.0
                  ---
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: sriov-network-operator
                    namespace: kube-system
                  spec:
                    chart: oci://${PRIVATE_REGISTRY_URL}/sriov-network-operator
                    dockerRegistrySecret:
                      name: privregauth
                    repoCAConfigMap:
                      name: example-repo-ca
                    createNamespace: true
                    set:
                      global.clusterCIDR: 192.168.0.0/18
                      global.clusterCIDRv4: 192.168.0.0/18
                      global.clusterDNS: 10.96.0.10
                      global.clusterDomain: cluster.local
                      global.rke2DataDir: /var/lib/rancher/rke2
                      global.serviceCIDR: 10.96.0.0/12
                    targetNamespace: sriov-network-operator
                    version: 303.0.2+up1.5.0
              mode: 0644
              user:
                name: root
              group:
                name: root
        kernel_arguments:
          should_exist:
            - intel_iommu=on
            - iommu=pt
            - idle=poll
            - mce=off
            - hugepagesz=1G hugepages=40
            - hugepagesz=2M hugepages=0
            - default_hugepagesz=1G
            - irqaffinity=${NON-ISOLATED_CPU_CORES}
            - isolcpus=domain,nohz,managed_irq,${ISOLATED_CPU_CORES}
            - nohz_full=${ISOLATED_CPU_CORES}
            - rcu_nocbs=${ISOLATED_CPU_CORES}
            - rcu_nocb_poll
            - nosoftlockup
            - nowatchdog
            - nohz=on
            - nmi_watchdog=0
            - skew_tick=1
            - quiet
        systemd:
          units:
            - name: rke2-preinstall.service
              enabled: true
              contents: |
                [Unit]
                Description=rke2-preinstall
                Wants=network-online.target
                Before=rke2-install.service
                ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                [Service]
                Type=oneshot
                User=root
                ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                ExecStartPost=/bin/sh -c "umount /mnt"
                [Install]
                WantedBy=multi-user.target
            - name: cpu-partitioning.service
              enabled: true
              contents: |
                [Unit]
                Description=cpu-partitioning
                Wants=network-online.target
                After=network.target network-online.target
                [Service]
                Type=oneshot
                User=root
                ExecStart=/bin/sh -c "echo isolated_cores=${ISOLATED_CPU_CORES} > /etc/tuned/cpu-partitioning-variables.conf"
                ExecStartPost=/bin/sh -c "tuned-adm profile cpu-partitioning"
                ExecStartPost=/bin/sh -c "systemctl enable tuned.service"
                [Install]
                WantedBy=multi-user.target
            - name: performance-settings.service
              enabled: true
              contents: |
                [Unit]
                Description=performance-settings
                Wants=network-online.target
                After=network.target network-online.target cpu-partitioning.service
                [Service]
                Type=oneshot
                User=root
                ExecStart=/bin/sh -c "/opt/performance-settings/performance-settings.sh"
                [Install]
                WantedBy=multi-user.target
            - name: sriov-custom-auto-vfs.service
              enabled: true
              contents: |
                [Unit]
                Description=SRIOV Custom Auto VF Creation
                Wants=network-online.target  rke2-server.target
                After=network.target network-online.target rke2-server.target
                [Service]
                User=root
                Type=forking
                TimeoutStartSec=1800
                ExecStart=/bin/sh -c "while ! /var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml wait --for condition=ready nodes --timeout=30m --all ; do sleep 10 ; done"
                ExecStartPost=/bin/sh -c "/opt/sriov/sriov-auto-filler.sh"
                RemainAfterExit=yes
                KillMode=process
                [Install]
                WantedBy=multi-user.target
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"
Documentation survey