|Index|SUSE Telco Cloud Documentación|Guías de inicio rápido|Despliegues automatizados de BMC con Metal3
Applies to SUSE Telco Cloud 3.6

4 Despliegues automatizados de BMC con Metal3

Metal3 es un proyecto de la CNCF que proporciona capacidades de gestión de infraestructura de equipo sin sistema operativo para Kubernetes.

Metal3 proporciona recursos nativos de Kubernetes para gestionar el ciclo de vida de los servidores de equipo sin sistema operativo que admiten la gestión mediante 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 mediante APIs neutrales al proveedor y ampliamente adoptadas.

4.1 ¿Por qué utilizar este método?

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

Se configura un clúster de gestión para proporcionar APIs declarativas que permitan la gestión del inventario y del estado de los servidores de equipo sin sistema operativo del clúster descendente, incluida la inspección, limpieza y aprovisionamiento/desaprovisionamiento automatizados.

4.2 Arquitectura de alto nivel

quickstart metal3 architecture

4.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 los 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 a través de interfaces Redfish, iDRAC o iLO

    • Deben admitir el despliegue a través de medios virtuales (actualmente no se admite PXE)

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

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

4.4 Distribución

4.4.1 Configurar el clúster de gestión

Los pasos básicos para instalar un clúster de gestión y utilizar 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 del proveedor CAPI

  6. Crear una imagen de SO SLEMicro para los hosts del clúster descendente

  7. Registrar los CR de BareMetalHost para definir el inventario de equipo sin sistema operativo

  8. Crear un clúster descendente definiendo recursos CAPI

Esta guía asume que ya existe un clúster RKE2 y que Rancher (incluido cert-manager) se ha instalado, por ejemplo, mediante Edge Image Builder (Chapter 12, Edge Image Builder).

Tip
Tip

Los pasos aquí descritos también pueden automatizarse por completo tal y como se describe en la Documentación del clúster de gestión (Part V, “Configuración del clúster de gestión”).

4.4.2 Instalación de las dependencias de Metal3

Si no se ha instalado ya como parte de la instalación de Rancher, cert-manager debe estar instalado y en ejecución.

Se requiere una IP adicional, la cual es gestionada por MetalLB para proporcionar un punto final consistente 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).

Tip
Tip

Si el clúster de gestión es un nodo único, se puede evitar el requisito de una IP flotante adicional gestionada a través de MetalLB, véase Section 4.7.1, “Configuración de nodo único”.

  1. Primero, instalamos MetalLB:

    helm install \
      metallb oci://registry.suse.com/edge/charts/metallb \
      --namespace metallb-system \
      --create-namespace
  2. A continuación, definimos un IPAddressPool y L2Advertisement utilizando 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. Ahora Metal3 puede instalarse:

    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 inicialización puede tardar unos dos minutos en ejecutarse en este despliegue, así que aseguraos de que todos los pods estén en ejecución 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
Warning
Warning

No paséis a los siguientes pasos hasta que todos los pods en el espacio de nombres metal3-system estén en ejecución.

4.4.3 Instalación de las dependencias del proveedor de la API del clúster

Las dependencias del proveedor de la API del clúster se gestionan a través del gráfico Helm de Rancher Turtles Providers:

helm install \
  rancher-turtles oci://registry.suse.com/edge/charts/rancher-turtles-providers \
  --namespace cattle-turtles-system \
  --create-namespace

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

4.4.4 Preparar la imagen del clúster descendente

Kiwi (Chapter 64, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi) y Edge Image Builder (Chapter 12, Edge Image Builder) se utilizan para preparar una imagen base de SLEMicro modificada que se aprovisiona en los hosts del clúster descendente.

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

4.4.4.1 Configuración de la imagen

Note
Note

Por favor, seguid Chapter 64, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi primero para crear una imagen nueva como primer paso necesario para crear clústeres.

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 utilizados para definir la imagen de destino.

├── downstream-cluster-config.yaml
├── base-images/
│   └ SL-Micro.x86_64-6.2-Base-GM.raw
├── network/
|   └ configure-network.sh
└── custom/
    └ scripts/
        └ 01-fix-growfs.sh
4.4.4.1.1 Archivo de definición de imagen del clúster descendente

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

apiVersion: 1.3
image:
  imageType: raw
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-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
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
      sshKeys:
      - $USERKEY1
      createHomeDir: true
  packages:
    packageList:
      - jq
    sccRegistrationCode: $SCC_REGISTRATION_CODE

Donde $SCC_REGISTRATION_CODE es el código de registro copiado de SUSE Customer Center, y la lista de paquetes contiene jq, que es necesario.

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

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

Note
Note

Tened en cuenta que ignition.platform.id=openstack es obligatorio; sin este argumento, la configuración de SUSE Linux Micro mediante 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 el desfase horario. Los valores proporcionados en este ejemplo son solo para fines ilustrativos. Ajustadlos para que se adapten a vuestros requisitos específicos.

4.4.4.1.2 Script Growfs

Actualmente, se requiere un script 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 tras el aprovisionamiento. El script 01-fix-growfs.sh incluye la información siguiente:

#!/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 /
Note
Note

Añadid vuestros propios scripts personalizados para que se ejecuten durante el proceso de aprovisionamiento utilizando el mismo enfoque. Para obtener más información, consulte el Chapter 5, Clústeres independientes con Edge Image Builder.

4.4.4.2 Creación de imágenes

Una vez preparada la estructura de directorios siguiendo las secciones anteriores, ejecutad el siguiente comando para compilar la imagen:

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

Esto crea el archivo de imagen de salida llamado SLE-Micro-eib-output.raw, basado en la definición descrita anteriormente.

La imagen de salida debe estar disponible a través de un servidor web, ya sea el contenedor media-server habilitado mediante el gráfico de Metal3 (Note) o algún otro servidor accesible localmente. En los ejemplos siguientes, nos referimos a este servidor como imagecache.local:8080

Note
Note

Al desplegar imágenes EIB en clústeres en sentido descendente, 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

4.4.5 Adición del inventario de BareMetalHost

El registro de servidores de equipo sin sistema operativo para el despliegue automatizado requiere la creación de dos recursos: un Secret que almacene las credenciales de acceso a BMC y un recurso Metal3 BareMetalHost que defina la conexión 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:
  architecture: x86_64
  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

Tened en cuenta lo siguiente:

  • El nombre de usuario/contraseña del Secret debe estar codificado en base64. Tened en cuenta que esto no debe incluir saltos de línea finales (por ejemplo, utilizad echo -n, ¡no solo echo!)

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

  • bootMACAddress debe ser una MAC válida que coincida con la NIC del 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://<IP ADDRESS>/redfish/v1/Systems/<SYSTEM ID>: Medios virtuales Redfish, por ejemplo, SuperMicro

    • idrac-virtualmedia://<IP ADDRESS>/redfish/v1/Systems/System.Embedded.1: Dell iDRAC

  • Consultad la documentación de la API de sentido ascendente para obtener más detalles sobre la API de BareMetalHost

4.4.5.1 Configuración de IP estáticas

El ejemplo de BareMetalHost anterior asume que DHCP proporciona la configuración de red del plano de control, pero para escenarios donde se necesita una configuración manual, como las IP estáticas, es posible proporcionar una configuración adicional, como se describe a continuación.

4.4.5.1.1 Script adicional para la configuración de red estática

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

Esto consume los datos de la unidad de configuración en 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

META_DATA_FILE="/mnt/openstack/latest/meta_data.json"
if [ ! -f "${META_DATA_FILE}" ]; then
  umount /mnt
  echo "No meta_data.json found, skipping hostname 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

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

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
4.4.5.1.2 Secreto adicional con la configuración de red del host

Se puede definir un secreto adicional que contenga datos en el formato nmstate admitido por NM Configurator (Chapter 13, Redes edge) para cada host.

El secreto se referencia entonces en el recurso BareMetalHost a través del campo spec 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
Note
Note

En algunas circunstancias, la dirección MAC puede omitirse. Consulte Section 13.5.8, “Configuraciones de nodo unificadas” para obtener más información.

4.4.5.2 Preparación de BareMetalHost

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

  • Se arranca una imagen de disco RAM mediante la conexión de medios virtuales al BMC del host de destino

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

  • Al finalizar este proceso, los detalles del hardware en el campo status.hardware de BareMetalHost se actualizan y pueden verificarse

Este proceso puede tardar varios minutos, pero cuando finalice debería ver que el estado de BareMetalHost se convierte en available:

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

4.4.6 Creación de clústeres de sentido descendente

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

4.4.7 Despliegue del plano de control

Para desplegar el plano de control definimos un manifiesto yaml similar al que aparece 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 nodo único, punto final de LoadBalancer para nodos múltiples; este ejemplo asume un nodo único)

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

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

  • Metal3DataTemplate define metadatos adicionales que se pasarán al BareMetalHost (tenga en cuenta que networkData no es compatible actualmente en la solución Edge)

Note
Note

Por simplicidad, este ejemplo asume un plano de control de nodo único donde el BareMetalHost está configurado con una IP de 192.168.125.200. Para ejemplos multinodo más avanzados, consulte Part VII, “Aprovisionamiento de red dirigido totalmente automatizado”.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: sample-cluster
  namespace: default
  labels:
    cluster-api.cattle.io/rancher-auto-import: "true"
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
    services:
      cidrBlocks:
        - 10.96.0.0/12
  controlPlaneRef:
    apiGroup: controlplane.cluster.x-k8s.io
    kind: RKE2ControlPlane
    name: sample-cluster
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    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/v1beta2
kind: RKE2ControlPlane
metadata:
  name: sample-cluster
  namespace: default
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: sample-cluster-controlplane
  replicas: 1
  version: v1.35.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"
              ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStartPost=/bin/sh -c "umount /mnt"
              [Install]
              WantedBy=multi-user.target
          # rke2-traefik-deployment.service unit to be removed once "traefik" being the default ingress controller (starting with RKE2 v1.36)
          - name: rke2-traefik-deployment.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-traefik-deployment
              Wants=rke2-preinstall.service
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"
              [Install]
              WantedBy=multi-user.target
        storage:
          directories:
          - path: /var/lib/rancher/rke2/server/manifests
            overwrite: true
          files:
          - path: /var/lib/rancher/rke2/server/manifests/rke2-traefik-config.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: helm.cattle.io/v1
                kind: HelmChartConfig
                metadata:
                  name: rke2-traefik
                  namespace: kube-system
                spec:
                  valuesContent: |-
                    ingressClass:
                      isDefaultClass: true
                    ports:
                      web:
                        hostPort: null    # disallow hostPort
                        exposedPort: 80
                      websecure:
                        hostPort: null    # disallow hostPort
                        exposedPort: 443
                    service:
                      enabled: true
                      type: LoadBalancer
                      spec:
                        externalTrafficPolicy: Local
                        allocateLoadBalancerNodePorts: false  # k8s GA from 1.24; supported by MetalLB
            mode: 0644
            user:
              name: root
            group:
              name: root
---
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
Note
Note

Añadir la etiqueta cluster-api.cattle.io/rancher-auto-import: "true" a los objetos cluster.x-k8s.io importará el clúster a Rancher (creando un objeto clusters.management.cattle.io correspondiente). Consulte la documentación de Cluster API para obtener más información.

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

4.4.8 Ampliación de trabajador/cómputo

De forma similar a la ampliación del plano de control, definimos un manifiesto YAML que contiene los siguientes recursos:

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

  • RKE2ConfigTemplate describe la versión de RKE2 y la configuración de primer arranque para la inicialización del host agente.

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

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

apiVersion: cluster.x-k8s.io/v1beta2
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:
          apiGroup: bootstrap.cluster.x-k8s.io
          kind: RKE2ConfigTemplate
          name: sample-cluster-workers
      clusterName: sample-cluster
      infrastructureRef:
        apiGroup: infrastructure.cluster.x-k8s.io
        kind: Metal3MachineTemplate
        name: sample-cluster-workers
      deletion:
        nodeDrainTimeoutSeconds: 0
      version: v1.35.4+rke2r1
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: RKE2ConfigTemplate
metadata:
  name: sample-cluster-workers
  namespace: default
spec:
  template:
    spec:
      agentConfig:
        format: ignition
        version: v1.35.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"
                  ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
                  ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /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 que se haya copiado y adaptado el ejemplo anterior a su entorno, se puede aplicarlo 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

4.4.9 Desaprovisionamiento del clúster

El clúster descendente puede desaprovisionarse eliminando los recursos aplicados en los pasos de creación 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 llevar varios minutos, tras lo cual deberían volver a estar en estado disponible:

% 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

4.5 Problemas conocidos

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

  • Relacionado con esto, los recursos IPAM y los campos networkData de Metal3DataTemplate no son compatibles actualmente.

  • Solo se admite actualmente el despliegue mediante redfish-virtualmedia.

4.6 Cambios previstos

  • Habilitar la compatibilidad de los recursos IPAM y la configuración mediante campos networkData

4.7 Otros recursos

La Documentación del clúster de gestión de SUSE Telco Cloud (Part V, “Configuración del clúster de gestión”) contiene ejemplos de un uso más avanzado de Metal3 para casos de uso de telecomunicaciones.

4.7.1 Configuración de nodo único

Para entornos de prueba/PoC donde el clúster de gestión es un nodo único, es posible evitar el requisito de una IP flotante 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 tanto, debe reservarse al utilizar DHCP o configurarse de forma estática para garantizar que la IP del clúster de gestión no cambie, denominado <MANAGEMENT_CLUSTER_IP> a continuación.

Para habilitar este escenario, los valores del gráfico Metal3 necesarios son los siguientes:

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

4.7.2 Deshabilitación de TLS para la conexión de ISO de virtualmedia

Algunos proveedores de servidores verifican la conexión SSL al conectar imágenes ISO de virtual-media al BMC, lo que puede causar un problema porque los certificados generados para el despliegue de Metal3 están autofirmados; para solucionar este problema, es posible deshabilitar TLS solo para la conexión de disco de virtualmedia con los valores del gráfico Metal3 de la siguiente manera:

global:
  enable_vmedia_tls: false

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

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

El certificado se puede configurar entonces en la consola BMC del servidor, aunque el proceso para ello es específico del proveedor (y no es posible para todos los proveedores, en cuyo caso puede ser necesario el parámetro enable_vmedia_tls).

4.7.3 Configuración de storage

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

Para habilitar este almacenamiento persistente, los valores del gráfico Metal 3 necesarios son los siguientes:

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

La documentación de SUSE Telco Cloud Management Cluster (Part V, “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.