documentation.suse.com / Documentación de SUSE Edge / Guías de inicio rápido / Despliegues automatizados de BMC con Metal3

1 Despliegues automatizados de BMC con Metal3

Metal3 es un projecto de la CNCF que proporciona capacidades de gestión de infraestructura bare metal para Kubernetes.

Metal3 ofrece recursos nativos de Kubernetes para gestionar el ciclo de vida de los servidores bare metal que admiten la gestión a través de protocolos fuera de banda, como Redfish.

También cuenta con un soporte maduro para Cluster API (CAPI) que permite la gestión de recursos de infraestructura a través de múltiples proveedores de infraestructura mediante API ampliamente adoptadas y neutrales con respecto a los proveedores.

1.1 Por qué usar este método

Este método es útil para situaciones en las que el hardware de destino admite la gestión fuera de banda y se desea un flujo de gestión de la infraestructura totalmente automatizado.

Se configura un clúster de gestión para proporcionar API declarativas que permitan la gestión del inventario y el estado de los servidores bare metal del clúster descendente, incluida la inspección, limpieza y aprovisionamiento/desaprovisionamiento automatizados.

1.2 Arquitectura general

inicio rápido de la arquitectura de metal3

1.3 Requisitos previos

Existen algunas restricciones específicas relacionadas con el hardware y la red del servidor del clúster descendente:

  • Clúster de gestión

    • Debe tener conectividad de red con la API de gestión/BMC del servidor de destino

    • Debe tener conectividad de red con la red del plano de control del servidor de destino

    • Para clústeres de gestión de varios nodos, se requiere una dirección IP reservada adicional

  • Hosts que se van a controlar

    • Deben admitir la gestión fuera de banda mediante interfaces Redfish, iDRAC o iLO

    • Deben admitir el despliegue mediante medios virtuales (actualmente no se admite PXE)

    • Deben tener conectividad de red con el clúster de gestión para acceder a las API de aprovisionamiento de Metal3

Se requieren algunas herramientas, que se pueden instalar en el clúster de gestión o en un host que pueda acceder a él.

El archivo de imagen de sistema operativo SL-Micro.x86_64-6.1-Base-GM.raw se debe descargar del Centro de servicios al cliente de SUSE o de la página de descargas de SUSE.

1.3.1 Configuración del clúster de gestión

Los pasos básicos para instalar un clúster de gestión y usar Metal3 son:

  1. Instalar un clúster de gestión RKE2

  2. Instalar Rancher

  3. Instalar un proveedor de almacenamiento (opcional)

  4. Instalar las dependencias de Metal3

  5. Instalar las dependencias de CAPI mediante Rancher Turtles

  6. Crear una imagen del sistema operativo SLEMicro para los hosts del clúster descendente

  7. Registrar los CR de BareMetalHost para definir el inventario de bare metal

  8. Crear un clúster descendente definiendo los recursos de CAPI

En esta guía se entiende que ya existe un clúster RKE2 y que se ha instalado Rancher (incluido cert-manager), por ejemplo, utilizando Edge Image Builder (Capítulo 11, Edge Image Builder).

Sugerencia
Sugerencia

Estos pasos también se pueden automatizar por completo, como se describe en la documentación sobre el clúster de gestión (Capítulo 40, Configuración del clúster de gestión).

1.3.2 Instalación de las dependencias de Metal3

Si aún no se ha hecho como parte de la instalación de Rancher, se debe instalar y ejecutar cert-manager.

Se debe instalar un proveedor de almacenamiento persistente. Se recomienda SUSE Storage, pero también se puede utilizar local-pathprovisioner para entornos de desarrollo/PoC. Las instrucciones siguientes dan por sentado que se ha marcado una StorageClass como predeterminada; de lo contrario, se requiere una configuración adicional para el chart de Metal3.

Se requiere una IP adicional, gestionada por MetalLB para proporcionar un punto final coherente para los servicios de gestión de Metal3. Esta IP debe formar parte de la subred del plano de control y estar reservada para la configuración estática (no debe formar parte de ningún grupo DHCP).

Sugerencia
Sugerencia

Si el clúster de gestión es un solo nodo, no es necesario contar con una IP fleetnte adicional gestionada mediante MetalLB. Consulte la Sección 1.6.1, “Configuración de un solo nodo”.

  1. Primero, se instala MetalLB:

    helm install \
      metallb oci://registry.suse.com/edge/charts/metallb \
      --namespace metallb-system \
      --create-namespace
  2. Luego, se definen IPAddressPool y L2Advertisement con la IP reservada, definida como STATIC_IRONIC_IP a continuación:

    export STATIC_IRONIC_IP=<STATIC_IRONIC_IP>
    
    cat <<-EOF | kubectl apply -f -
    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: ironic-ip-pool
      namespace: metallb-system
    spec:
      addresses:
      - ${STATIC_IRONIC_IP}/32
      serviceAllocation:
        priority: 100
        serviceSelectors:
        - matchExpressions:
          - {key: app.kubernetes.io/name, operator: In, values: [metal3-ironic]}
    EOF
    cat <<-EOF | kubectl apply -f -
    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: ironic-ip-pool-l2-adv
      namespace: metallb-system
    spec:
      ipAddressPools:
      - ironic-ip-pool
    EOF
  3. Ya se puede instalar Metal3:

    helm install \
      metal3 oci://registry.suse.com/edge/charts/metal3 \
      --namespace metal3-system \
      --create-namespace \
      --set global.ironicIP="$STATIC_IRONIC_IP"
  4. El contenedor de inicio puede tardar unos dos minutos en ejecutarse en este despliegue, así que asegúrese de que todos los pods estén funcionando antes de continuar:

    kubectl get pods -n metal3-system
    NAME                                                    READY   STATUS    RESTARTS   AGE
    baremetal-operator-controller-manager-85756794b-fz98d   2/2     Running   0          15m
    metal3-metal3-ironic-677bc5c8cc-55shd                   4/4     Running   0          15m
    metal3-metal3-mariadb-7c7d6fdbd8-64c7l                  1/1     Running   0          15m
Aviso
Aviso

No continúe con los siguientes pasos hasta que todos los pods del espacio de nombres metal3-system estén en ejecución.

1.3.3 Instalación de las dependencias de Cluster API

Las dependencias de Cluster API se gestionan mediante el chart de Helm de Rancher Turtles:

cat > values.yaml <<EOF
rancherTurtles:
  features:
    embedded-capi:
      disabled: true
    rancher-webhook:
      cleanup: true
EOF

helm install \
  rancher-turtles oci://registry.suse.com/edge/charts/rancher-turtles \
  --namespace rancher-turtles-system \
  --create-namespace \
  -f values.yaml

Después de un tiempo, los pods del controlador deberían estar ejecutándose en los espacios de nombres capi-system, capm3-system, rke2-bootstrap-system y rke2-control-plane-system.

1.3.4 Preparación de la imagen del clúster descendente

Kiwi (Capítulo 28, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi) y Edge Image Builder (Capítulo 11, Edge Image Builder) se usan para preparar una imagen base de SLEMicro modificada que se aprovisiona en los hosts de clústeres descendentes.

En esta guía, se trata la configuración mínima necesaria para desplegar el clúster descendente.

1.3.4.1 Configuración de la imagen

Nota
Nota

Como primer paso necesario para crear clústeres, cree una imagen nueva siguiendo las instrucciones del Capítulo 28, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi.

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
├── base-images/
│   └ SL-Micro.x86_64-6.1-Base-GM.raw
├── network/
|   └ configure-network.sh
└── custom/
    └ scripts/
        └ 01-fix-growfs.sh
1.3.4.1.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: SLE-Micro-eib-output.raw
operatingSystem:
  time:
    timezone: Europe/London
    ntp:
      forceWait: true
      pools:
        - 2.suse.pool.ntp.org
      servers:
        - 10.0.0.1
        - 10.0.0.2
  kernelArgs:
    - ignition.platform.id=openstack
    - net.ifnames=1
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
  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 obligatorio.

$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

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 SUSE Linux Micro a través de Ignition fallará en el flujo automatizado de Metal3.

La sección time es opcional, pero se recomienda encarecidamente configurarla para evitar posibles problemas con los certificados y la desviación del reloj. Los valores proporcionados en este ejemplo son solo ilustrativos. Ajústelos según sus requisitos específicos.

1.3.4.1.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 /
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.

1.3.4.2 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 de salida denominado SLE-Micro-eib-output.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 multimedia habilitado mediante el chart de Metal3 (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.

Nota
Nota

Al desplegar imágenes de EIB en clústeres descendentes, también es necesario incluir la suma sha256 de la imagen en el objeto Metal3MachineTemplate. Se puede generar de la siguiente manera:

sha256sum <image_file> > <image_file>.sha256
# On this example:
sha256sum SLE-Micro-eib-output.raw > SLE-Micro-eib-output.raw.sha256

1.3.5 Adición del inventario de BareMetalHost

El registro de servidores bare metal para el despliegue automatizado requiere la creación de dos recursos: un secreto que almacena las credenciales de acceso a BMC y un recurso BareMetalHost de Metal3 que define la conexión de BMC y otros detalles:

apiVersion: v1
kind: Secret
metadata:
  name: controlplane-0-credentials
type: Opaque
data:
  username: YWRtaW4=
  password: cGFzc3dvcmQ=
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: controlplane-0
  labels:
    cluster-role: control-plane
spec:
  online: true
  bootMACAddress: "00:f3:65:8a:a3:b0"
  bmc:
    address: redfish-virtualmedia://192.168.125.1:8000/redfish/v1/Systems/68bd0fb6-d124-4d17-a904-cdf33efe83ab
    disableCertificateVerification: true
    credentialsName: controlplane-0-credentials

Tenga en cuenta lo siguiente:

  • El nombre de usuario y la contraseña del secreto deben estar cifrados en base64. No deben incluir saltos de línea al final (por ejemplo, use echo -n, no solo echo)

  • La etiqueta cluster-role se puede establecer ahora o más adelante, durante la creación del clúster. En el ejemplo siguiente, se espera control-plane o worker

  • bootMACAddress debe ser una dirección MAC válida que coincida con la NIC de plano de control del host

  • La dirección bmc es la conexión a la API de gestión de BMC. Se admiten las siguientes:

    • redfish-virtualmedia://<DIRECCIÓN IP>/redfish/v1/Systems/<ID DEL SISTEMA>: medio virtual Redfish, por ejemplo, SuperMicro

    • idrac-virtualmedia://<DIRECCIÓN IP>/redfish/v1/Systems/System.Embedded.1: iDRAC de Dell

  • Consulte la documentación original de la API para obtener más información sobre la API de BareMetalHost

1.3.5.1 Configuración de IP estáticas

El ejemplo anterior de BareMetalHost presupone que DHCP proporciona la configuración de red del plano de control, pero para situaciones en las que se necesite una configuración manual, como en el caso de las IP estáticas, es posible proporcionar una configuración adicional, como se describe a continuación.

1.3.5.1.1 Guion adicional para la configuración de la red estática

Al crear la imagen base con Edge Image Builder, en la carpeta de network, cree el archivo configure-network.sh siguiente.

Esto consume datos de la unidad de configuración en el primer arranque y configura la red del host usando 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
1.3.5.1.2 Secreto adicional con configuración de red de host

Se puede definir un secreto adicional que contenga datos en el formato nmstate compatible con NM Configurator (Capítulo 12, Conexiones de red de Edge) para cada host.

A continuación, se hace referencia al secreto en el recurso BareMetalHost mediante el campo de especificación preprovisioningNetworkDataName.

apiVersion: v1
kind: Secret
metadata:
  name: controlplane-0-networkdata
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: enp1s0
      type: ethernet
      state: up
      mac-address: "00:f3:65:8a:a3:b0"
      ipv4:
        address:
        - ip:  192.168.125.200
          prefix-length: 24
        enabled: true
        dhcp: false
    dns-resolver:
      config:
        server:
        - 192.168.125.1
    routes:
      config:
      - destination: 0.0.0.0/0
        next-hop-address: 192.168.125.1
        next-hop-interface: enp1s0
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: controlplane-0
  labels:
    cluster-role: control-plane
spec:
  preprovisioningNetworkDataName: controlplane-0-networkdata
# Remaining content as in previous example
Nota
Nota

En algunas circunstancias, la dirección MAC puede omitirse. Consulte la Sección 12.5.8, “Configuraciones unificadas de nodos” para obtener más detalles.

1.3.5.2 Preparación de BareMetalHost

Después de crear el recurso BareMetalHost y los secretos asociados como se ha descrito, se activa un flujo de trabajo de preparación del host:

  • Se arranca una imagen ramdisk mediante la conexión de un dispositivo virtual al BMC del host de destino

  • El ramdisk inspecciona los detalles del hardware y prepara el host para el aprovisionamiento (por ejemplo, limpiando los discos de datos anteriores)

  • Una vez completado este proceso, se actualizan los detalles del hardware en el campo status.hardware de BareMetalHost y se pueden verificar

Este proceso puede tardar varios minutos, pero una vez completado, debería ver que el estado de BareMetalHost pasa a ser available (disponible):

% kubectl get baremetalhost
NAME             STATE       CONSUMER   ONLINE   ERROR   AGE
controlplane-0   available              true             9m44s
worker-0         available              true             9m44s

1.3.6 Creación de clústeres descendentes

Ahora creamos recursos de Cluster API que definen el clúster descendente y recursos del equipo que provocarán que se aprovisionen los recursos de BareMetalHost y, a continuación, se arranquen para formar un clúster RKE2.

1.3.7 Despliegue del plano de control

Para desplegar el plano de control, se define un manifiesto YAML similar al que se muestra a continuación, que contiene los siguientes recursos:

  • El recurso Cluster define el nombre del clúster, las redes y el tipo de proveedor de plano de control/infraestructura (en este caso, RKE2/Metal3)

  • Metal3Cluster define el punto final del plano de control (IP del host para un solo nodo, punto final LoadBalancer para varios nodos; en este ejemplo se supone que hay un solo nodo)

  • RKE2ControlPlane define la versión de RKE2 y cualquier configuración adicional necesaria durante el arranque del clúster

  • Metal3MachineTemplate define la imagen del sistema operativo que se aplicará a los recursos BareMetalHost, y hostSelector define qué recursos BareMetalHost se consumirán

  • Metal3DataTemplate define los metadatos adicionales que se pasarán a BareMetalHost (tenga en cuenta que networkData no es compatible actualmente con Edge)

Nota
Nota

Para simplificar, en este ejemplo se entiende que hay un plano de control de un solo nodo en el que BareMetalHost se ha configurado con la IP 192.168.125.200. Para ejemplos más avanzados de varios nodos, consulte el Capítulo 42, Aprovisionamiento de red dirigida totalmente automatizado.

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: sample-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: sample-cluster
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3Cluster
    name: sample-cluster
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
  name: sample-cluster
  namespace: default
spec:
  controlPlaneEndpoint:
    host: 192.168.125.200
    port: 6443
  noCloudProvider: true
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
  name: sample-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: sample-cluster-controlplane
  replicas: 1
  version: v1.32.4+rke2r1
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  agentConfig:
    format: ignition
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    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
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: sample-cluster-controlplane
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: sample-cluster-controlplane-template
      hostSelector:
        matchLabels:
          cluster-role: control-plane
      image:
        checksum: http://imagecache.local:8080/SLE-Micro-eib-output.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/SLE-Micro-eib-output.raw
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: sample-cluster-controlplane-template
  namespace: default
spec:
  clusterName: sample-cluster
  metaData:
    objectNames:
      - key: name
        object: machine
      - key: local-hostname
        object: machine
      - key: local_hostname
        object: machine

Una vez adaptado a su entorno, puede aplicar el ejemplo mediante kubectl y, a continuación, supervisar el estado del clúster mediante clusterctl.

% kubectl apply -f rke2-control-plane.yaml

# Wait for the cluster to be provisioned
% clusterctl describe cluster sample-cluster
NAME                                                    READY  SEVERITY  REASON  SINCE  MESSAGE
Cluster/sample-cluster                                  True                     22m
├─ClusterInfrastructure - Metal3Cluster/sample-cluster  True                     27m
├─ControlPlane - RKE2ControlPlane/sample-cluster        True                     22m
│ └─Machine/sample-cluster-chflc                        True                     23m

1.3.8 Despliegue de trabajadores/computación

De forma similar al despliegue del plano de control, se define un manifiesto YAML que contiene los siguientes recursos:

  • MachineDeployment define el número de réplicas (hosts) y el proveedor de arranque/infraestructura (en este caso, RKE2/Metal3)

  • RKE2ConfigTemplate describe la versión de RKE2 y la configuración de arranque inicial para el arranque del host del agente

  • Metal3MachineTemplate define la imagen del sistema operativo que se aplicará a los recursos BareMetalHost, y el selector de host define qué recursos BareMetalHost se consumirán

  • Metal3DataTemplate define los metadatos adicionales que se pasarán a BareMetalHost (tenga en cuenta que networkData no es compatible actualmente)

apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: sample-cluster
  name: sample-cluster
  namespace: default
spec:
  clusterName: sample-cluster
  replicas: 1
  selector:
    matchLabels:
      cluster.x-k8s.io/cluster-name: sample-cluster
  template:
    metadata:
      labels:
        cluster.x-k8s.io/cluster-name: sample-cluster
    spec:
      bootstrap:
        configRef:
          apiVersion: bootstrap.cluster.x-k8s.io/v1alpha1
          kind: RKE2ConfigTemplate
          name: sample-cluster-workers
      clusterName: sample-cluster
      infrastructureRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
        kind: Metal3MachineTemplate
        name: sample-cluster-workers
      nodeDrainTimeout: 0s
      version: v1.32.4+rke2r1
---
apiVersion: bootstrap.cluster.x-k8s.io/v1alpha1
kind: RKE2ConfigTemplate
metadata:
  name: sample-cluster-workers
  namespace: default
spec:
  template:
    spec:
      agentConfig:
        format: ignition
        version: v1.32.4+rke2r1
        kubelet:
          extraArgs:
            - provider-id=metal3://BAREMETALHOST_UUID
        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
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: sample-cluster-workers
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: sample-cluster-workers-template
      hostSelector:
        matchLabels:
          cluster-role: worker
      image:
        checksum: http://imagecache.local:8080/SLE-Micro-eib-output.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/SLE-Micro-eib-output.raw
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: sample-cluster-workers-template
  namespace: default
spec:
  clusterName: sample-cluster
  metaData:
    objectNames:
      - key: name
        object: machine
      - key: local-hostname
        object: machine
      - key: local_hostname
        object: machine

Una vez copiado y adaptado el ejemplo anterior a su entorno, se puede aplicar mediante kubectl y, a continuación, se puede supervisar el estado del clúster con clusterctl.

% kubectl apply -f rke2-agent.yaml

# Wait for the worker nodes to be provisioned
% clusterctl describe cluster sample-cluster
NAME                                                    READY  SEVERITY  REASON  SINCE  MESSAGE
Cluster/sample-cluster                                  True                     25m
├─ClusterInfrastructure - Metal3Cluster/sample-cluster  True                     30m
├─ControlPlane - RKE2ControlPlane/sample-cluster        True                     25m
│ └─Machine/sample-cluster-chflc                        True                     27m
└─Workers
  └─MachineDeployment/sample-cluster                    True                     22m
    └─Machine/sample-cluster-56df5b4499-zfljj           True                     23m

1.3.9 Desaprovisionamiento del clúster

El clúster descendente se puede desaprovisionar eliminando los recursos aplicados en los pasos anteriores:

% kubectl delete -f rke2-agent.yaml
% kubectl delete -f rke2-control-plane.yaml

Esto activa el desaprovisionamiento de los recursos BareMetalHost, lo que puede tardar varios minutos, tras lo cual deberían volver a estar disponibles:

% kubectl get bmh
NAME             STATE            CONSUMER                            ONLINE   ERROR   AGE
controlplane-0   deprovisioning   sample-cluster-controlplane-vlrt6   false            10m
worker-0         deprovisioning   sample-cluster-workers-785x5        false            10m

...

% kubectl get bmh
NAME             STATE       CONSUMER   ONLINE   ERROR   AGE
controlplane-0   available              false            15m
worker-0         available              false            15m

1.4 Problemas conocidos

  • El controlador de gestión de direcciones IP actualmente no se admite, ya que aún no es compatible con nuestras herramientas de configuración de red y la cadena de herramientas de primer arranque en SLEMicro.

  • Del mismo modo, los recursos IPAM y los campos networkData de Metal3DataTemplate no son compatibles actualmente.

  • Actualmente, solo se admite el despliegue mediante redfish-virtualmedia.

1.5 Cambios previstos

  • Habilitar la compatibilidad con los recursos y la configuración de IPAM a través de los campos networkData.

1.6 Recursos adicionales

La documentación de SUSE Edge for Telco (Capítulo 37, SUSE Edge for Telco) tiene ejemplos de uso más avanzados de Metal3 para casos de uso relacionados con las telecomunicaciones.

1.6.1 Configuración de un solo nodo

En entornos de prueba/PoC en los que el clúster de gestión es de un solo nodo, no se necesita una IP fleetnte adicional gestionada a través de MetalLB.

En este modo, el punto final para las API del clúster de gestión es la IP del clúster de gestión, por lo que debe reservarse cuando se utiliza DHCP o debe configurarse de forma estática para garantizar que la IP del clúster de gestión no cambie, lo que se denomina <MANAGEMENT_CLUSTER_IP> abajo.

Para habilitar este escenario, los valores necesarios del chart de Metal3 son los siguientes:

global:
  ironicIP: <MANAGEMENT_CLUSTER_IP>
metal3-ironic:
  service:
    type: NodePort

1.6.2 Inhabilitación de TLS para la conexión ISO de medios virtuales

Algunos proveedores de servidores verifican la conexión SSL al conectar imágenes ISO de medios virtuales al BMC, lo que puede causar un problema porque los certificados generados para el despliegue de Metal3 son autofirmados. Para solucionar este problema, es posible desactivar TLS solo para la conexión del disco de medios virtuales con los valores del chart de Metal3 de la siguiente manera:

global:
  enable_vmedia_tls: false

Una solución alternativa es configurar los BMC con el certificado de la CA; en este caso, puede leer los certificados del clúster utilizando kubectl:

kubectl get secret -n metal3-system ironic-vmedia-cert -o yaml

A continuación, el certificado se puede configurar en el panel de control del BMC del servidor, aunque ese proceso es específico de cada proveedor (y no es posible para todos los proveedores, en cuyo caso puede ser necesario el indicador enable_vmedia_tls).

1.6.3 Configuración de almacenamiento

Para entornos de prueba/PoC en los que el clúster de gestión es de un solo nodo, no se requiere almacenamiento persistente, pero para casos de uso en producción se recomienda instalar SUSE Storage (Longhorn) en el clúster de gestión para que las imágenes relacionadas con Metal3 puedan conservarse durante el reinicio/reprogramación de un pod.

Para habilitar este almacenamiento persistente, los valores necesarios del chart de Metal3 son los siguientes:

metal3-ironic:
  persistence:
    ironic:
      size: "5Gi"

La documentación sobre el clúster de gestión en SUSE Edge for Telco (Capítulo 40, Configuración del clúster de gestión) contiene más detalles sobre cómo configurar un clúster de gestión con almacenamiento persistente.

Documentation survey