documentation.suse.com / Documentación de SUSE Edge / Documentación del producto / Configuración del clúster de gestión

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

40.1 Introducción

El clúster de gestión es la parte de SUSE Edge for Telco que se utiliza para gestionar el aprovisionamiento y el ciclo de vida de las pilas de entorno de ejecución. Desde un punto de vista técnico, el clúster de gestión contiene los siguientes componentes:

  • SUSE Linux Micro como sistema operativo. Dependiendo del caso práctico, será posible personalizar algunas configuraciones como la red, el almacenamiento, los usuarios y los argumentos del kernel.

  • RKE2 como clúster de Kubernetes. Dependiendo del caso práctico, se puede configurar para utilizar complementos de CNI específicos, como Multus, Cilium, Calico, etc.

  • Rancher como plataforma de gestión del ciclo de vida de los clústeres.

  • Metal3 como componente para gestionar el ciclo de vida de los nodos bare metal.

  • CAPI como componente para gestionar el ciclo de vida de los clústeres de Kubernetes (clústeres descendentes). El proveedor CAPI de RKE2 se utiliza para gestionar el ciclo de vida de los clústeres RKE2.

Con todos los componentes mencionados, el clúster de gestión puede gestionar el ciclo de vida de los clústeres descendentes usando un enfoque declarativo para gestionar la infraestructura y las aplicaciones.

Nota
Nota

Para obtener más información sobre SUSE Linux Micro, consulte: SUSE Linux Micro (Capítulo 9, SUSE Linux Micro)

Para obtener más información sobre RKE2, consulte: RKE2 (Capítulo 16, RKE2)

Para obtener más información sobre Rancher, consulte: Rancher (Capítulo 5, Rancher)

Para obtener más información sobre Metal3, consulte: Metal3 (Capítulo 10, Metal3)

40.2 Pasos para configurar el clúster de gestión

Los siguientes pasos son necesarios para configurar el clúster de gestión (usando un único nodo):

clúster gestión de producto atip 1

Estos son los pasos principales para configurar el clúster de gestión usando un enfoque declarativo:

  1. Preparación de imágenes para entornos conectados (Sección 40.3, “Preparación de la imagen para entornos conectados”). El primer paso es preparar los manifiestos y los archivos con todas las configuraciones necesarias para su uso en entornos conectados.

    • Estructura de directorios para entornos conectados (Sección 40.3.1, “Estructura del directorio”). Este paso crea una estructura de directorios que Edge Image Builder utilizará para almacenar los archivos de configuración y la propia imagen.

    • Archivo de definición del clúster de gestión (Sección 40.3.2, “Archivo de definición del clúster de gestión”). El archivo mgmt-cluster.yaml es el archivo de definición principal del clúster de gestión. Contiene la siguiente información sobre la imagen que se va a crear:

      • Información de la imagen: la información relacionada con la imagen que se creará utilizando la imagen base.

      • Sistema operativo: las configuraciones del sistema operativo que se utilizarán en la imagen.

      • Kubernetes: los charts de Helm y los repositorios, la versión de Kubernetes, la configuración de red y los nodos que se utilizarán en el clúster.

    • Carpeta personalizada (Sección 40.3.3, “Carpeta custom”). La carpeta custom contiene los archivos de configuración y los guiones que utilizará Edge Image Builder para desplegar un clúster de gestión totalmente funcional.

      • Archivos: contiene los archivos de configuración que utilizará el clúster de gestión.

      • Guiones: contiene los guiones que utilizará el clúster de gestión.

    • Carpeta de Kubernetes (Sección 40.3.4, “Carpeta kubernetes”). La carpeta kubernetes contiene los archivos de configuración que utilizará el clúster de gestión.

      • Manifiestos: contiene los manifiestos que utilizará el clúster de gestión.

      • Helm: contiene los archivos de valores de Helm que utilizará el clúster de gestión.

      • Config: contiene los archivos de configuración que utilizará el clúster de gestión.

    • Carpeta de red (Sección 40.3.5, “Carpeta network”). La carpeta network contiene los archivos de configuración de red que utilizarán los nodos del clúster de gestión.

  2. Preparación de imágenes para entornos aislados (Sección 40.4, “Preparación de la imagen para entornos aislados”). El paso consiste en mostrar las diferencias para preparar los manifiestos y los archivos que se utilizarán en un entorno aislado.

  3. Creación de la imagen (Sección 40.5, “Creación de la imagen”). Este paso abarca la creación de la imagen mediante la herramienta Edge Image Builder (tanto para escenarios conectados como en entornos aislados). Compruebe los requisitos previos (Capítulo 11, Edge Image Builder) para ejecutar la herramienta Edge Image Builder en su sistema.

  4. Aprovisionamiento del clúster de gestión (Sección 40.6, “Aprovisionamiento del clúster de gestión”). Este paso abarca el aprovisionamiento del clúster de gestión que usa la imagen creada en el paso anterior (tanto para entornos conectados como aislados). Este paso se puede realizar con un ordenador portátil, un servidor, una máquina virtual o cualquier otro sistema AMD64/Intel 64 con un puerto USB.

Nota
Nota

Para obtener más información, consulte la sección sobre Edge Image Builder (Capítulo 11, Edge Image Builder) y la guía de inicio rápido de Edge Image Builder (Capítulo 3, Clústeres independientes con Edge Image Builder).

40.3 Preparación de la imagen para entornos conectados

Edge Image Builder se utiliza para crear la imagen del clúster de gestión. En este documento se describe la configuración mínima necesaria para configurar el clúster de gestión.

Edge Image Builder se ejecuta dentro de un contenedor, por lo que se requiere un entorno de ejecución de contenedores como Podman o Rancher Desktop. En esta guía, se entiende que Podman está disponible.

Además, como requisito previo para desplegar un clúster de gestión de alta disponibilidad, es necesario reservar tres direcciones IP en la red:

  • apiVIP para la dirección IP virtual de API (utilizada para acceder al servidor API de Kubernetes).

  • ingressVIP para la dirección IP virtual de Ingress (utilizada, por ejemplo, por la interfaz de usuario de Rancher).

  • metal3VIP para la dirección IP virtual de Metal3.

40.3.1 Estructura del directorio

Al ejecutar EIB, se monta un directorio desde el host, por lo que lo primero que hay que hacer es crear una estructura de directorios que EIB utilizará para almacenar los archivos de configuración y la propia imagen. Este directorio tiene la siguiente estructura:

eib
├── mgmt-cluster.yaml
├── network
│ └── mgmt-cluster-node1.yaml
├── kubernetes
│ ├── manifests
│ │ ├── rke2-ingress-config.yaml
│ │ ├── neuvector-namespace.yaml
│ │ ├── ingress-l2-adv.yaml
│ │ └── ingress-ippool.yaml
│ ├── helm
│ │ └── values
│ │     ├── rancher.yaml
│ │     ├── neuvector.yaml
│ │     ├── metal3.yaml
│ │     └── certmanager.yaml
│ └── config
│     └── server.yaml
├── custom
│ ├── scripts
│ │ ├── 99-register.sh
│ │ ├── 99-mgmt-setup.sh
│ │ └── 99-alias.sh
│ └── files
│     ├── rancher.sh
│     ├── mgmt-stack-setup.service
│     ├── metal3.sh
│     └── basic-setup.sh
└── base-images
Nota
Nota

La imagen SL-Micro.x86_64-6.1-Base-SelfInstall-GM.install.iso debe descargarse desde el Centro de servicios al cliente de SUSE o desde la página de descargas de SUSE, y debe estar ubicada en la carpeta base-images.

Debe comprobar la suma de comprobación SHA256 de la imagen para asegurarse de que no ha sido manipulada. La suma de comprobación se encuentra en la misma ubicación en la que se descargó la imagen.

Un ejemplo de estructura del directorios se puede encontrar en el repositorio GitHub de SUSE Edge, en la carpeta "telco-examples".

40.3.2 Archivo de definición del clúster de gestión

El archivo de definición principal del clúster de gestión es mgmt-cluster.yaml. Contiene la siguiente información:

apiVersion: 1.2
image:
  imageType: iso
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.1-Base-SelfInstall-GM.install.iso
  outputImageName: eib-mgmt-cluster-image.iso
operatingSystem:
  isoConfiguration:
    installDevice: /dev/sda
  users:
  - username: root
    encryptedPassword: $ROOT_PASSWORD
  packages:
    packageList:
    - git
    - jq
    sccRegistrationCode: $SCC_REGISTRATION_CODE
kubernetes:
  version: v1.32.4+rke2r1
  helm:
    charts:
      - name: cert-manager
        repositoryName: jetstack
        version: 1.15.3
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: longhorn-crd
        version: 106.2.0+up1.8.1
        repositoryName: rancher-charts
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
      - name: longhorn
        version: 106.2.0+up1.8.1
        repositoryName: rancher-charts
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
      - name: metal3
        version: 303.0.7+up0.11.5
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: rancher-turtles
        version: 303.0.4+up0.20.0
        repositoryName: suse-edge-charts
        targetNamespace: rancher-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 106.0.1+up2.8.6
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 106.0.1+up2.8.6
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.11.2
        repositoryName: rancher-prime
        targetNamespace: cattle-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: rancher.yaml
    repositories:
      - name: jetstack
        url: https://charts.jetstack.io
      - name: rancher-charts
        url: https://charts.rancher.io/
      - name: suse-edge-charts
        url: oci://registry.suse.com/edge/charts
      - name: rancher-prime
        url: https://charts.rancher.com/server-charts/prime
  network:
    apiHost: $API_HOST
    apiVIP: $API_VIP
  nodes:
    - hostname: mgmt-cluster-node1
      initializer: true
      type: server
#   - hostname: mgmt-cluster-node2
#     type: server
#   - hostname: mgmt-cluster-node3
#     type: server

Para explicar los campos y valores del archivo de definición mgmt-cluster.yaml, lo hemos dividido en las siguientes secciones.

  • Sección de imagen (archivo de definición):

image:
  imageType: iso
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.1-Base-SelfInstall-GM.install.iso
  outputImageName: eib-mgmt-cluster-image.iso

Donde baseImage es la imagen original que descargó del Centro de servicios al cliente de SUSE o de la página de descargas de SUSE. outputImageName es el nombre de la nueva imagen que se utilizará para aprovisionar el clúster de gestión.

  • Sección de sistema operativo (archivo de definición):

operatingSystem:
  isoConfiguration:
    installDevice: /dev/sda
  users:
  - username: root
    encryptedPassword: $ROOT_PASSWORD
  packages:
    packageList:
    - jq
    sccRegistrationCode: $SCC_REGISTRATION_CODE

Donde installDevice es el dispositivo que se utilizará para instalar el sistema operativo, username y encryptedPassword son las credenciales que se utilizarán para acceder al sistema, packageList es la lista de paquetes que se instalarán (jq es necesario internamente durante el proceso de instalación), y sccRegistrationCode es el código de registro utilizado para obtener los paquetes y las dependencias en el momento de la creación, que se pueden obtener en el Centro de servicios al cliente de SUSE. La contraseña cifrada se puede generar utilizando el comando openssl de la siguiente manera:

openssl passwd -6 MyPassword!123

El resultado es algo similar a esto:

$6$UrXB1sAGs46DOiSq$HSwi9GFJLCorm0J53nF2Sq8YEoyINhHcObHzX2R8h13mswUIsMwzx4eUzn/rRx0QPV4JIb0eWCoNrxGiKH4R31
  • Sección de Kubernetes (archivo de definición):

kubernetes:
  version: v1.32.4+rke2r1
  helm:
    charts:
      - name: cert-manager
        repositoryName: jetstack
        version: 1.15.3
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: longhorn-crd
        version: 106.2.0+up1.8.1
        repositoryName: rancher-charts
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
      - name: longhorn
        version: 106.2.0+up1.8.1
        repositoryName: rancher-charts
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
      - name: metal3
        version: 303.0.7+up0.11.5
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: rancher-turtles
        version: 303.0.4+up0.20.0
        repositoryName: suse-edge-charts
        targetNamespace: rancher-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 106.0.1+up2.8.6
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 106.0.1+up2.8.6
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.11.2
        repositoryName: rancher-prime
        targetNamespace: cattle-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: rancher.yaml
    repositories:
      - name: jetstack
        url: https://charts.jetstack.io
      - name: rancher-charts
        url: https://charts.rancher.io/
      - name: suse-edge-charts
        url: oci://registry.suse.com/edge/charts
      - name: rancher-prime
        url: https://charts.rancher.com/server-charts/prime
    network:
      apiHost: $API_HOST
      apiVIP: $API_VIP
    nodes:
    - hostname: mgmt-cluster-node1
      initializer: true
      type: server
#   - hostname: mgmt-cluster-node2
#     type: server
#   - hostname: mgmt-cluster-node3
#     type: server

La sección helm contiene la lista de charts de Helm que se instalarán, los repositorios que se utilizarán y la configuración de la versión de todos ellos.

La sección network contiene la configuración de la red, como apiHost y apiVIP, que utilizará el componente RKE2. apiVIP debe ser una dirección IP que no se use en la red y no debe formar parte del pool DHCP (en caso de que se utilice DHCP). Además, si se usa apiVIP en un clúster de varios nodos, se hace para acceder al servidor de API de Kubernetes. apiHost es la resolución de nombres para apiVIP que utilizará el componente RKE2.

La sección nodes contiene la lista de nodos que se utilizarán en el clúster. En este ejemplo, se utiliza un clúster de un solo nodo, pero se puede ampliar a un clúster de varios nodos añadiendo más nodos a la lista (descomentando las líneas).

Nota
Nota
  • Los nombres de los nodos deben ser únicos en el clúster.

  • Si lo desea, puede usar el campo initializer para especificar el host de arranque. Si no lo hace, será el primer nodo de la lista.

  • Si se requiere una configuración de red, los nombres de los nodos deben ser los mismos que los nombres de host definidos en la carpeta network (Sección 40.3.5, “Carpeta network”).

40.3.3 Carpeta custom

La carpeta custom contiene las siguientes subcarpetas:

...
├── custom
│ ├── scripts
│ │ ├── 99-register.sh
│ │ ├── 99-mgmt-setup.sh
│ │ └── 99-alias.sh
│ └── files
│     ├── rancher.sh
│     ├── mgmt-stack-setup.service
│     ├── metal3.sh
│     └── basic-setup.sh
...
  • La carpeta custom/files contiene los archivos de configuración que utilizará el clúster de gestión.

  • La carpeta custom/scripts contiene los guiones que utilizará el clúster de gestión.

La carpeta custom/files contiene los siguientes archivos:

  • basic-setup.sh: contiene los parámetros de configuración para Metal3, Rancher y MetalLB. Solo debe modificar este archivo si desea cambiar los espacios de nombres que se van a utilizar.

    #!/bin/bash
    # Pre-requisites. Cluster already running
    export KUBECTL="/var/lib/rancher/rke2/bin/kubectl"
    export KUBECONFIG="/etc/rancher/rke2/rke2.yaml"
    
    ##################
    # METAL3 DETAILS #
    ##################
    export METAL3_CHART_TARGETNAMESPACE="metal3-system"
    
    ###########
    # METALLB #
    ###########
    export METALLBNAMESPACE="metallb-system"
    
    ###########
    # RANCHER #
    ###########
    export RANCHER_CHART_TARGETNAMESPACE="cattle-system"
    export RANCHER_FINALPASSWORD="adminadminadmin"
    
    die(){
      echo ${1} 1>&2
      exit ${2}
    }
  • metal3.sh: contiene la configuración del componente Metal3 que se va a utilizar (no es necesario modificarlo). En futuras versiones, este guion se sustituirá por Rancher Turtles para facilitar su uso.

    #!/bin/bash
    set -euo pipefail
    
    BASEDIR="$(dirname "$0")"
    source ${BASEDIR}/basic-setup.sh
    
    METAL3LOCKNAMESPACE="default"
    METAL3LOCKCMNAME="metal3-lock"
    
    trap 'catch $? $LINENO' EXIT
    
    catch() {
      if [ "$1" != "0" ]; then
        echo "Error $1 occurred on $2"
        ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE}
      fi
    }
    
    # Get or create the lock to run all those steps just in a single node
    # As the first node is created WAY before the others, this should be enough
    # TODO: Investigate if leases is better
    if [ $(${KUBECTL} get cm -n ${METAL3LOCKNAMESPACE} ${METAL3LOCKCMNAME} -o name | wc -l) -lt 1 ]; then
      ${KUBECTL} create configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE} --from-literal foo=bar
    else
      exit 0
    fi
    
    # Wait for metal3
    while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_CHART_TARGETNAMESPACE} $(${KUBECTL} get pods -n ${METAL3_CHART_TARGETNAMESPACE} -l app.kubernetes.io/name=metal3-ironic -o name) --timeout=10s; do sleep 2 ; done
    
    # Get the ironic IP
    IRONICIP=$(${KUBECTL} get cm -n ${METAL3_CHART_TARGETNAMESPACE} ironic-bmo -o jsonpath='{.data.IRONIC_IP}')
    
    # If LoadBalancer, use metallb, else it is NodePort
    if [ $(${KUBECTL} get svc -n ${METAL3_CHART_TARGETNAMESPACE} metal3-metal3-ironic -o jsonpath='{.spec.type}') == "LoadBalancer" ]; then
      # Wait for metallb
      while ! ${KUBECTL} wait --for condition=ready -n ${METALLBNAMESPACE} $(${KUBECTL} get pods -n ${METALLBNAMESPACE} -l app.kubernetes.io/component=controller -o name) --timeout=10s; do sleep 2 ; done
    
      # Do not create the ippool if already created
      ${KUBECTL} get ipaddresspool -n ${METALLBNAMESPACE} ironic-ip-pool -o name || cat <<-EOF | ${KUBECTL} apply -f -
      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        name: ironic-ip-pool
        namespace: ${METALLBNAMESPACE}
      spec:
        addresses:
        - ${IRONICIP}/32
        serviceAllocation:
          priority: 100
          serviceSelectors:
          - matchExpressions:
            - {key: app.kubernetes.io/name, operator: In, values: [metal3-ironic]}
    	EOF
    
      # Same for L2 Advs
      ${KUBECTL} get L2Advertisement -n ${METALLBNAMESPACE} ironic-ip-pool-l2-adv -o name || cat <<-EOF | ${KUBECTL} apply -f -
      apiVersion: metallb.io/v1beta1
      kind: L2Advertisement
      metadata:
        name: ironic-ip-pool-l2-adv
        namespace: ${METALLBNAMESPACE}
      spec:
        ipAddressPools:
        - ironic-ip-pool
    	EOF
    fi
    
    # If rancher is deployed
    if [ $(${KUBECTL} get pods -n ${RANCHER_CHART_TARGETNAMESPACE} -l app=rancher -o name | wc -l) -ge 1 ]; then
      cat <<-EOF | ${KUBECTL} apply -f -
    	apiVersion: management.cattle.io/v3
    	kind: Feature
    	metadata:
    	  name: embedded-cluster-api
    	spec:
    	  value: false
    	EOF
    
      # Disable Rancher webhooks for CAPI
      ${KUBECTL} delete --ignore-not-found=true mutatingwebhookconfiguration.admissionregistration.k8s.io mutating-webhook-configuration
      ${KUBECTL} delete --ignore-not-found=true validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration
      ${KUBECTL} wait --for=delete namespace/cattle-provisioning-capi-system --timeout=300s
    fi
    
    # Clean up the lock cm
    
    ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE}
    • rancher.sh: contiene la configuración del componente Rancher que se va a utilizar (no es necesario modificarlo).

      #!/bin/bash
      set -euo pipefail
      
      BASEDIR="$(dirname "$0")"
      source ${BASEDIR}/basic-setup.sh
      
      RANCHERLOCKNAMESPACE="default"
      RANCHERLOCKCMNAME="rancher-lock"
      
      if [ -z "${RANCHER_FINALPASSWORD}" ]; then
        # If there is no final password, then finish the setup right away
        exit 0
      fi
      
      trap 'catch $? $LINENO' EXIT
      
      catch() {
        if [ "$1" != "0" ]; then
          echo "Error $1 occurred on $2"
          ${KUBECTL} delete configmap ${RANCHERLOCKCMNAME} -n ${RANCHERLOCKNAMESPACE}
        fi
      }
      
      # Get or create the lock to run all those steps just in a single node
      # As the first node is created WAY before the others, this should be enough
      # TODO: Investigate if leases is better
      if [ $(${KUBECTL} get cm -n ${RANCHERLOCKNAMESPACE} ${RANCHERLOCKCMNAME} -o name | wc -l) -lt 1 ]; then
        ${KUBECTL} create configmap ${RANCHERLOCKCMNAME} -n ${RANCHERLOCKNAMESPACE} --from-literal foo=bar
      else
        exit 0
      fi
      
      # Wait for rancher to be deployed
      while ! ${KUBECTL} wait --for condition=ready -n ${RANCHER_CHART_TARGETNAMESPACE} $(${KUBECTL} get pods -n ${RANCHER_CHART_TARGETNAMESPACE} -l app=rancher -o name) --timeout=10s; do sleep 2 ; done
      until ${KUBECTL} get ingress -n ${RANCHER_CHART_TARGETNAMESPACE} rancher > /dev/null 2>&1; do sleep 10; done
      
      RANCHERBOOTSTRAPPASSWORD=$(${KUBECTL} get secret -n ${RANCHER_CHART_TARGETNAMESPACE} bootstrap-secret -o jsonpath='{.data.bootstrapPassword}' | base64 -d)
      RANCHERHOSTNAME=$(${KUBECTL} get ingress -n ${RANCHER_CHART_TARGETNAMESPACE} rancher -o jsonpath='{.spec.rules[0].host}')
      
      # Skip the whole process if things have been set already
      if [ -z $(${KUBECTL} get settings.management.cattle.io first-login -ojsonpath='{.value}') ]; then
        # Add the protocol
        RANCHERHOSTNAME="https://${RANCHERHOSTNAME}"
        TOKEN=""
        while [ -z "${TOKEN}" ]; do
          # Get token
          sleep 2
          TOKEN=$(curl -sk -X POST ${RANCHERHOSTNAME}/v3-public/localProviders/local?action=login -H 'content-type: application/json' -d "{\"username\":\"admin\",\"password\":\"${RANCHERBOOTSTRAPPASSWORD}\"}" | jq -r .token)
        done
      
        # Set password
        curl -sk ${RANCHERHOSTNAME}/v3/users?action=changepassword -H 'content-type: application/json' -H "Authorization: Bearer $TOKEN" -d "{\"currentPassword\":\"${RANCHERBOOTSTRAPPASSWORD}\",\"newPassword\":\"${RANCHER_FINALPASSWORD}\"}"
      
        # Create a temporary API token (ttl=60 minutes)
        APITOKEN=$(curl -sk ${RANCHERHOSTNAME}/v3/token -H 'content-type: application/json' -H "Authorization: Bearer ${TOKEN}" -d '{"type":"token","description":"automation","ttl":3600000}' | jq -r .token)
      
        curl -sk ${RANCHERHOSTNAME}/v3/settings/server-url -H 'content-type: application/json' -H "Authorization: Bearer ${APITOKEN}" -X PUT -d "{\"name\":\"server-url\",\"value\":\"${RANCHERHOSTNAME}\"}"
        curl -sk ${RANCHERHOSTNAME}/v3/settings/telemetry-opt -X PUT -H 'content-type: application/json' -H 'accept: application/json' -H "Authorization: Bearer ${APITOKEN}" -d '{"value":"out"}'
      fi
      
      # Clean up the lock cm
      ${KUBECTL} delete configmap ${RANCHERLOCKCMNAME} -n ${RANCHERLOCKNAMESPACE}
    • mgmt-stack-setup.service: contiene la configuración para crear el servicio systemd que ejecutará los guiones durante el primer arranque (no es necesario modificarlo).

      [Unit]
      Description=Setup Management stack components
      Wants=network-online.target
      # It requires rke2 or k3s running, but it will not fail if those services are not present
      After=network.target network-online.target rke2-server.service k3s.service
      # At least, the basic-setup.sh one needs to be present
      ConditionPathExists=/opt/mgmt/bin/basic-setup.sh
      
      [Service]
      User=root
      Type=forking
      # Metal3 can take A LOT to download the IPA image
      TimeoutStartSec=1800
      
      ExecStartPre=/bin/sh -c "echo 'Setting up Management components...'"
      # Scripts are executed in StartPre because Start can only run a single one
      ExecStartPre=/opt/mgmt/bin/rancher.sh
      ExecStartPre=/opt/mgmt/bin/metal3.sh
      ExecStart=/bin/sh -c "echo 'Finished setting up Management components'"
      RemainAfterExit=yes
      KillMode=process
      # Disable & delete everything
      ExecStartPost=rm -f /opt/mgmt/bin/rancher.sh
      ExecStartPost=rm -f /opt/mgmt/bin/metal3.sh
      ExecStartPost=rm -f /opt/mgmt/bin/basic-setup.sh
      ExecStartPost=/bin/sh -c "systemctl disable mgmt-stack-setup.service"
      ExecStartPost=rm -f /etc/systemd/system/mgmt-stack-setup.service
      
      [Install]
      WantedBy=multi-user.target

La carpeta custom/scripts contiene los siguientes archivos:

  • Guion 99-alias.sh: contiene el alias que usará el clúster de gestión para cargar el archivo kubeconfig en el primer arranque (no es necesario modificarlo).

    #!/bin/bash
    echo "alias k=kubectl" >> /etc/profile.local
    echo "alias kubectl=/var/lib/rancher/rke2/bin/kubectl" >> /etc/profile.local
    echo "export KUBECONFIG=/etc/rancher/rke2/rke2.yaml" >> /etc/profile.local
  • Guion 99-mgmt-setup.sh: contiene la configuración para copiar los guiones durante el primer arranque (no es necesario modificarlo).

    #!/bin/bash
    
    # Copy the scripts from combustion to the final location
    mkdir -p /opt/mgmt/bin/
    for script in basic-setup.sh rancher.sh metal3.sh; do
    	cp ${script} /opt/mgmt/bin/
    done
    
    # Copy the systemd unit file and enable it at boot
    cp mgmt-stack-setup.service /etc/systemd/system/mgmt-stack-setup.service
    systemctl enable mgmt-stack-setup.service
  • Guion 99-register.sh: contiene la configuración para registrar el sistema usando el código de registro del Centro de servicios al cliente de SUSE. Los elementos ${SCC_ACCOUNT_EMAIL} y ${SCC_REGISTRATION_CODE} deben configurarse correctamente para registrar el sistema con su cuenta.

    #!/bin/bash
    set -euo pipefail
    
    # Registration https://www.suse.com/support/kb/doc/?id=000018564
    if ! which SUSEConnect > /dev/null 2>&1; then
    	zypper --non-interactive install suseconnect-ng
    fi
    SUSEConnect --email "${SCC_ACCOUNT_EMAIL}" --url "https://scc.suse.com" --regcode "${SCC_REGISTRATION_CODE}"

40.3.4 Carpeta kubernetes

La carpeta kubernetes contiene las siguientes subcarpetas:

...
├── kubernetes
│ ├── manifests
│ │ ├── rke2-ingress-config.yaml
│ │ ├── neuvector-namespace.yaml
│ │ ├── ingress-l2-adv.yaml
│ │ └── ingress-ippool.yaml
│ ├── helm
│ │ └── values
│ │     ├── rancher.yaml
│ │     ├── neuvector.yaml
│ │     ├── metal3.yaml
│ │     └── certmanager.yaml
│ └── config
│     └── server.yaml
...

La carpeta kubernetes/config contiene los siguientes archivos:

  • server.yaml: de forma predeterminada, el complemento de CNI instalado por defecto es Cilium, por lo que no es necesario crear esta carpeta ni este archivo. En caso de que necesite personalizar el complemento de CNI, puede usar el archivo server.yaml que se encuentra en la carpeta kubernetes/config. Contiene la siguiente información:

    cni:
    - multus
    - cilium
Nota
Nota

Se trata de un archivo opcional para definir ciertas personalizaciones de Kubernetes, como los complementos de CNI que se utilizarán o muchas opciones que puede consultar en la documentación oficial.

La carpeta kubernetes/manifests contiene los siguientes archivos:

  • rke2-ingress-config.yaml: contiene la configuración para crear el servicio Ingress para el clúster de gestión (no es necesario modificarlo).

    apiVersion: helm.cattle.io/v1
    kind: HelmChartConfig
    metadata:
      name: rke2-ingress-nginx
      namespace: kube-system
    spec:
      valuesContent: |-
        controller:
          config:
            use-forwarded-headers: "true"
            enable-real-ip: "true"
          publishService:
            enabled: true
          service:
            enabled: true
            type: LoadBalancer
            externalTrafficPolicy: Local
  • neuvector-namespace.yaml: contiene la configuración para crear el espacio de nombres NeuVector (no es necesario modificarlo).

    apiVersion: v1
    kind: Namespace
    metadata:
      labels:
        pod-security.kubernetes.io/enforce: privileged
      name: neuvector
  • ingress-l2-adv.yaml: contiene la configuración para crear el L2Advertisement para el componente MetalLB (no es necesario modificarlo).

    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: ingress-l2-adv
      namespace: metallb-system
    spec:
      ipAddressPools:
        - ingress-ippool
  • ingress-ippool.yaml: contiene la configuración para crear el IPAddressPool para el componente rke2-ingress-nginx. ${INGRESS_VIP} debe configurarse correctamente para definir la dirección IP reservada para usarse por el componente rke2-ingress-nginx.

    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: ingress-ippool
      namespace: metallb-system
    spec:
      addresses:
        - ${INGRESS_VIP}/32
      serviceAllocation:
        priority: 100
        serviceSelectors:
          - matchExpressions:
              - {key: app.kubernetes.io/name, operator: In, values: [rke2-ingress-nginx]}

La carpeta kubernetes/helm/values contiene los siguientes archivos:

  • rancher.yaml: contiene la configuración para crear el componente Rancher. ${INGRESS_VIP} debe configurarse correctamente para definir la dirección IP que utilizará el componente Rancher. La URL para acceder al componente Rancher será https://rancher-${INGRESS_VIP}.sslip.io.

    hostname: rancher-${INGRESS_VIP}.sslip.io
    bootstrapPassword: "foobar"
    replicas: 1
    global.cattle.psp.enabled: "false"
  • neuvector.yaml: contiene la configuración para crear el componente NeuVector (no es necesario modificarlo).

    controller:
      replicas: 1
      ranchersso:
        enabled: true
    manager:
      enabled: false
    cve:
      scanner:
        enabled: false
        replicas: 1
    k3s:
      enabled: true
    crdwebhook:
      enabled: false
  • metal3.yaml: contiene la configuración para crear el componente Metal3. ${METAL3_VIP} debe configurarse correctamente para definir la dirección IP que utilizará el componente Metal3.

    global:
      ironicIP: ${METAL3_VIP}
      enable_vmedia_tls: false
      additionalTrustedCAs: false
    metal3-ironic:
      global:
        predictableNicNames: "true"
      persistence:
        ironic:
          size: "5Gi"

    Si desea desplegar clústeres descendentes arm64 utilizando este clúster de gestión x86_64, debe añadir la línea deployArchitecture: arm64 siguiente a la sección global del archivo metal3.yaml:

    global:
      ironicIP: ${METAL3_VIP}
      enable_vmedia_tls: false
      additionalTrustedCAs: false
      deployArchitecture: arm64
    metal3-ironic:
      global:
        predictableNicNames: "true"
      persistence:
        ironic:
          size: "5Gi"
Nota
Nota

En la versión actual, existe una limitación con respecto al uso de deployArchitecture: arm64. En concreto, si habilita el despliegue de clústeres arm64 descendentes mediante esta directiva, el clúster de gestión solo podrá desplegar posteriormente esta arquitectura. Para desplegar clústeres en ambas arquitecturas (x86_64 y arm64), deberá aprovisionar dos clústeres de gestión independientes. Esta limitación se eliminará en una versión futura.

Nota
Nota

El servidor de medios es una función opcional incluida en Metal3 (inhabilitada de forma predeterminada). Para utilizar esta función de Metal3, es necesario configurarla en el manifiesto anterior. Para utilizar el servidor de medios de Metal3, especifique la siguiente variable:

  • Defina enable_metal3_media_server como true para habilitar la función de servidor de medios en la sección global.

  • Incluya la siguiente configuración sobre el servidor de medios, donde ${MEDIA_VOLUME_PATH} es la ruta al volumen de medios en el medio (por ejemplo, /home/metal3/bmh-image-cache).

    metal3-media:
      mediaVolume:
        hostPath: ${MEDIA_VOLUME_PATH}

Se puede utilizar un servidor de medios externo para almacenar las imágenes y, en caso de que desee usarlo con TLS, deberá modificar las siguientes configuraciones:

  • Defina true en additionalTrustedCAs en el archivo metal3.yaml anterior para habilitar las CA de confianza adicionales del servidor de medios externo.

  • Incluya la siguiente configuración de secreto en la carpeta kubernetes/manifests/metal3-cacert-secret.yaml para almacenar el certificado de CA del servidor de medios externo.

    apiVersion: v1
    kind: Namespace
    metadata:
      name: metal3-system
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: tls-ca-additional
      namespace: metal3-system
    type: Opaque
    data:
      ca-additional.crt: {{ additional_ca_cert | b64encode }}

additional_ca_cert es el certificado de CA cifrado en base64 del servidor de medios externo. Puede usar el siguiente comando para cifrar el certificado y generar el secreto manualmente:

kubectl -n meta3-system create secret generic tls-ca-additional --from-file=ca-additional.crt=./ca-additional.crt
  • certmanager.yaml: contiene la configuración para crear el componente Cert-Manager (no es necesario modificarlo).

    installCRDs: "true"

40.3.5 Carpeta network

La carpeta network contiene tantos archivos como nodos haya en el clúster de gestión. En nuestro caso, solo tenemos un nodo, por lo que solo tenemos un archivo llamado mgmt-cluster-node1.yaml. El nombre del archivo debe coincidir con el nombre de host definido en el archivo de definición mgmt-cluster.yaml en la sección network/node descrita anteriormente.

Si necesita personalizar la configuración de red, por ejemplo, para utilizar una dirección IP estática específica (si no se usa DHCP), puede utilizar el archivo mgmt-cluster-node1.yaml que se encuentra en la carpeta network. Contiene la siguiente información:

  • ${MGMT_GATEWAY}: la dirección IP del gateway.

  • ${MGMT_DNS}: la dirección IP del servidor DNS.

  • ${MGMT_MAC}: la dirección MAC de la interfaz de red.

  • ${MGMT_NODE_IP}: la dirección IP del clúster de gestión.

routes:
  config:
  - destination: 0.0.0.0/0
    metric: 100
    next-hop-address: ${MGMT_GATEWAY}
    next-hop-interface: eth0
    table-id: 254
dns-resolver:
  config:
    server:
    - ${MGMT_DNS}
    - 8.8.8.8
interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: ${MGMT_MAC}
  ipv4:
    address:
    - ip: ${MGMT_NODE_IP}
      prefix-length: 24
    dhcp: false
    enabled: true
  ipv6:
    enabled: false

Si desea utilizar DHCP para obtener la dirección IP, puede usar la siguiente configuración (la dirección MAC debe configurarse correctamente utilizando la variable ${MGMT_MAC}):

## This is an example of a dhcp network configuration for a management cluster
interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: ${MGMT_MAC}
  ipv4:
    dhcp: true
    enabled: true
  ipv6:
    enabled: false
Nota
Nota
  • Dependiendo del número de nodos del clúster de gestión, puede crear más archivos como mgmt-cluster-node2.yaml, mgmt-cluster-node3.yaml, etc. para configurar el resto de los nodos.

  • La sección routes se utiliza para definir la tabla de enrutamiento del clúster de gestión.

40.4 Preparación de la imagen para entornos aislados

En esta sección se describe cómo preparar la imagen para entornos aislados. Muestra solo las diferencias con respecto a las secciones anteriores. Para preparar la imagen para entornos aislados, es necesario realizar los siguientes cambios con respecto a la sección sobre la preparación de imagen en entornos conectados (Sección 40.3, “Preparación de la imagen para entornos conectados”):

  • El archivo mgmt-cluster.yaml debe modificarse para incluir la sección embeddedArtifactRegistry con el campo images definido con todas las imágenes de contenedor que se incluirán en la imagen de salida de EIB.

  • El archivo mgmt-cluster.yaml debe modificarse para incluir el chart de Helm rancher-turtles-airgap-resources.

  • El guion custom/scripts/99-register.sh debe eliminarse si se utiliza un entorno aislado.

40.4.1 Modificaciones del archivo de definición

El archivo mgmt-cluster.yaml debe modificarse para incluir la sección embeddedArtifactRegistry. En ella, el campo images debe contener la lista de todas las imágenes de contenedor que se incluirán en la imagen de salida.

Nota
Nota

A continuación, se muestra un ejemplo del archivo mgmt-cluster.yaml con la sección embeddedArtifactRegistry incluida. Asegúrese de que las imágenes indicadas contengan las versiones de los componentes que necesita.

También se debe añadir el chart de Helm rancher-turtles-airgap-resources, que crea los recursos descritos en la documentación de Rancher Turtles para entornos aislados. Esto también requiere un archivo de valores turtles.yaml para que el chart de rancher-turtles especifique la configuración necesaria.

apiVersion: 1.2
image:
  imageType: iso
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.1-Base-SelfInstall-GM.install.iso
  outputImageName: eib-mgmt-cluster-image.iso
operatingSystem:
  isoConfiguration:
    installDevice: /dev/sda
  users:
  - username: root
    encryptedPassword: $ROOT_PASSWORD
  packages:
    packageList:
    - jq
    sccRegistrationCode: $SCC_REGISTRATION_CODE
kubernetes:
  version: v1.32.4+rke2r1
  helm:
    charts:
      - name: cert-manager
        repositoryName: jetstack
        version: 1.15.3
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: longhorn-crd
        version: 106.2.0+up1.8.1
        repositoryName: rancher-charts
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
      - name: longhorn
        version: 106.2.0+up1.8.1
        repositoryName: rancher-charts
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
      - name: metal3
        version: 303.0.7+up0.11.5
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: rancher-turtles
        version: 303.0.4+up0.20.0
        repositoryName: suse-edge-charts
        targetNamespace: rancher-turtles-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: turtles.yaml
      - name: rancher-turtles-airgap-resources
        version: 303.0.4+up0.20.0
        repositoryName: suse-edge-charts
        targetNamespace: rancher-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 106.0.1+up2.8.6
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 106.0.1+up2.8.6
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.11.2
        repositoryName: rancher-prime
        targetNamespace: cattle-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: rancher.yaml
    repositories:
      - name: jetstack
        url: https://charts.jetstack.io
      - name: rancher-charts
        url: https://charts.rancher.io/
      - name: suse-edge-charts
        url: oci://registry.suse.com/edge/charts
      - name: rancher-prime
        url: https://charts.rancher.com/server-charts/prime
    network:
      apiHost: $API_HOST
      apiVIP: $API_VIP
    nodes:
    - hostname: mgmt-cluster-node1
      initializer: true
      type: server
#   - hostname: mgmt-cluster-node2
#     type: server
#   - hostname: mgmt-cluster-node3
#     type: server
#       type: server
embeddedArtifactRegistry:
  images:
    - name: registry.suse.com/rancher/hardened-cluster-autoscaler:v1.9.0-build20241203
    - name: registry.suse.com/rancher/hardened-cni-plugins:v1.6.2-build20250306
    - name: registry.suse.com/rancher/hardened-coredns:v1.12.1-build20250401
    - name: registry.suse.com/rancher/hardened-k8s-metrics-server:v0.7.2-build20250110
    - name: registry.suse.com/rancher/hardened-multus-cni:v4.2.0-build20250326
    - name: registry.suse.com/rancher/klipper-helm:v0.9.5-build20250306
    - name: registry.suse.com/rancher/mirrored-cilium-cilium:v1.17.3
    - name: registry.suse.com/rancher/mirrored-cilium-operator-generic:v1.17.3
    - name: registry.suse.com/rancher/mirrored-longhornio-csi-attacher:v4.8.1
    - name: registry.suse.com/rancher/mirrored-longhornio-csi-node-driver-registrar:v2.13.0
    - name: registry.suse.com/rancher/mirrored-longhornio-csi-provisioner:v5.2.0
    - name: registry.suse.com/rancher/mirrored-longhornio-csi-resizer:v1.13.2
    - name: registry.suse.com/rancher/mirrored-longhornio-csi-snapshotter:v8.2.0
    - name: registry.suse.com/rancher/mirrored-longhornio-livenessprobe:v2.15.0
    - name: registry.suse.com/rancher/mirrored-longhornio-longhorn-engine:v1.8.1
    - name: registry.suse.com/rancher/mirrored-longhornio-longhorn-instance-manager:v1.8.1
    - name: registry.suse.com/rancher/mirrored-longhornio-longhorn-manager:v1.8.1
    - name: registry.suse.com/rancher/mirrored-longhornio-longhorn-share-manager:v1.8.1
    - name: registry.suse.com/rancher/mirrored-longhornio-longhorn-ui:v1.8.1
    - name: registry.suse.com/rancher/mirrored-sig-storage-snapshot-controller:v8.2.0
    - name: registry.suse.com/rancher/neuvector-compliance-config:1.0.5
    - name: registry.suse.com/rancher/neuvector-controller:5.4.4
    - name: registry.suse.com/rancher/neuvector-enforcer:5.4.4
    - name: registry.suse.com/rancher/nginx-ingress-controller:v1.12.1-hardened3
    - name: registry.rancher.com/rancher/cluster-api-addon-provider-fleet:v0.10.0
    - name: registry.rancher.com/rancher/cluster-api-operator:v0.17.0
    - name: registry.rancher.com/rancher/fleet-agent:v0.12.3
    - name: registry.rancher.com/rancher/fleet:v0.12.3
    - name: registry.rancher.com/rancher/hardened-node-feature-discovery:v0.15.7-build20250425
    - name: registry.rancher.com/rancher/rancher-webhook:v0.7.2
    - name: registry.rancher.com/rancher/rancher/turtles:v0.20.0
    - name: registry.rancher.com/rancher/rancher:v2.11.2
    - name: registry.rancher.com/rancher/shell:v0.4.1
    - name: registry.rancher.com/rancher/system-upgrade-controller:v0.15.2
    - name: registry.suse.com/rancher/cluster-api-controller:v1.9.5
    - name: registry.suse.com/rancher/cluster-api-provider-metal3:v1.9.3
    - name: registry.suse.com/rancher/cluster-api-provider-rke2-bootstrap:v0.16.1
    - name: registry.suse.com/rancher/cluster-api-provider-rke2-controlplane:v0.16.1
    - name: registry.suse.com/rancher/hardened-sriov-network-operator:v1.5.0-build20250425
    - name: registry.suse.com/rancher/ip-address-manager:v1.9.4
    - name: registry.rancher.com/rancher/kubectl:v1.32.2

40.4.2 Modificaciones de la carpeta custom

  • El guion custom/scripts/99-register.sh debe eliminarse si se utiliza un entorno aislado. Como se puede ver en la estructura del directorio, el guion 99-register.sh no está incluido en la carpeta custom/scripts.

40.4.3 Modificaciones de la carpeta de valores de Helm

  • El archivo turtles.yaml contiene la configuración necesaria para especificar el funcionamiento con aislamiento para Rancher Turtles. Tenga en cuenta que esto depende de la instalación del chart de rancher-turtles-airgap-resources.

    cluster-api-operator:
      cluster-api:
        core:
          fetchConfig:
            selector: "{\"matchLabels\": {\"provider-components\": \"core\"}}"
        rke2:
          bootstrap:
            fetchConfig:
              selector: "{\"matchLabels\": {\"provider-components\": \"rke2-bootstrap\"}}"
          controlPlane:
            fetchConfig:
              selector: "{\"matchLabels\": {\"provider-components\": \"rke2-control-plane\"}}"
        metal3:
          infrastructure:
            fetchConfig:
              selector: "{\"matchLabels\": {\"provider-components\": \"metal3\"}}"

40.5 Creación de la imagen

Una vez preparada la estructura de directorios siguiendo las secciones anteriores (tanto para escenarios conectados como aislados), ejecute el comando siguiente 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 mgmt-cluster.yaml

Esto crea el archivo de imagen ISO de salida que, en nuestro caso, según la definición de imagen descrita anteriormente, es eib-mgmt-cluster-image.iso.

40.6 Aprovisionamiento del clúster de gestión

La imagen anterior contiene todos los componentes explicados anteriormente y se puede utilizar para aprovisionar el clúster de gestión mediante una máquina virtual o un servidor bare metal (usando la función de medios virtuales).

Documentation survey