|Index|SUSE Telco Cloud Documentación
SUSE Telco Cloud 3.6

SUSE Telco Cloud Documentación

Fecha de publicación: 2026-05-27

SUSE Telco Cloud 3.6 Documentación

Bienvenido a la documentación de SUSE Telco Cloud. Encontrará la visión general de la arquitectura de alto nivel, guías de inicio rápido, diseños validados, orientación sobre el uso de componentes, integraciones de terceros y prácticas recomendadas para gestionar la infraestructura y las cargas de trabajo de edge computing.

1 ¿Qué es SUSE Telco Cloud?

SUSE Telco Cloud es una plataforma informática optimizada para telecomunicaciones que permite a los operadores de telecomunicaciones y a los proveedores de redes de telecomunicaciones innovar y acelerar la modernización de sus redes.

SUSE Telco Cloud es una pila completa nativa de la nube habilitada para telecomunicaciones para alojar CNF, que cubre todos los dominios de telecomunicaciones: Packet Core, RAN, OSS y BSS.

  • Automatiza el despliegue sin intervención y la gestión del ciclo de vida de configuraciones complejas de pilas edge a escala de telecomunicaciones.

  • Garantiza continuamente la calidad en hardware de grado de telecomunicaciones, utilizando configuraciones y cargas de trabajo específicas de telecomunicaciones.

  • Consta de componentes diseñados específicamente para el edge y, por lo tanto, tienen una menor huella y un mayor rendimiento por vatio.

  • Mantiene una estrategia de plataforma flexible con API neutrales respecto al proveedor y 100% de código abierto.

2 Filosofía de diseño

La solución se ha diseñado con la idea de que no existe una plataforma edge «única para todos» debido a los requisitos y expectativas tan variados de los clientes. Los despliegues en el edge nos obligan a resolver y a evolucionar continuamente algunos de los problemas más desafiantes, como la escalabilidad masiva, la disponibilidad restringida de la red, las limitaciones de espacio físico, las nuevas amenazas de seguridad y vectores de ataque, las variaciones en la arquitectura de hardware y los recursos del sistema, el requisito de desplegar e interactuar con infraestructuras y aplicaciones heredadas, y las soluciones de cliente que tienen ciclos de vida prolongados. Dado que muchos de estos desafíos son diferentes de las formas tradicionales de pensar, por ejemplo, el despliegue de infraestructura y aplicaciones dentro de centros de datos o en la nube pública, tenemos que examinar el diseño con mucho más detalle y replantearnos muchas suposiciones comunes.

Por ejemplo, encontramos valor en el minimalismo, la modularidad y la facilidad de las operaciones. El minimalismo es importante para los entornos edge, ya que cuanto más complejo es un sistema, más probable es que falle. Al observar cientos de ubicaciones, hasta cientos de miles, los sistemas complejos fallarán de formas complejas. La modularidad en nuestra solución permite una mayor elección por parte del usuario al tiempo que elimina la complejidad innecesaria en la plataforma desplegada. También necesitamos equilibrar esto con la facilidad de las operaciones. Los humanos pueden cometer errores al repetir un proceso miles de veces, por lo que la plataforma debe asegurarse de que cualquier posible error sea recuperable, eliminando la necesidad de visitas de técnicos in situ, pero también esforzarse por lograr la coherencia y la estandarización.

3 Arquitectura de alto nivel

La arquitectura de alto nivel del sistema de SUSE Telco Cloud se divide en dos categorías principales: clústeres de «gestión» y clústeres en sentido descendente. El clúster de gestión es responsable de la gestión remota de uno o más clústeres en sentido descendente, aunque se reconoce que, en determinadas circunstancias, los clústeres en sentido descendente deben funcionar sin gestión remota, por ejemplo, en situaciones en las que un sitio edge no tiene conectividad externa y necesita funcionar de forma independiente. En SUSE Telco Cloud, los componentes técnicos que se utilizan para el funcionamiento tanto del clúster de gestión como de los de sentido descendente son en gran medida comunes, aunque es probable que se diferencien tanto en las especificaciones del sistema como en las aplicaciones que residen en ellos; es decir, el clúster de gestión ejecutaría aplicaciones que permiten la gestión de sistemas y las operaciones de ciclo de vida, mientras que los clústeres en sentido descendente cumplen los requisitos para servir aplicaciones de usuario.

3.1 Componentes utilizados en SUSE Telco Cloud

SUSE Telco Cloud se compone tanto de componentes existentes de SUSE y Rancher como de características y componentes adicionales creados por el equipo de Edge para permitirnos abordar las limitaciones y complejidades necesarias en edge computing. Los componentes utilizados tanto en el clúster de gestión como en los de sentido descendente se explican a continuación, con un diagrama de arquitectura de alto nivel simplificado, señalando que esta no es una lista exhaustiva:

3.1.1 Clúster de gestión

suse edge management cluster
  • Gestión: Esta es la parte centralizada de SUSE Telco Cloud que se utiliza para gestionar el aprovisionamiento y el ciclo de vida de los clústeres en sentido descendente conectados. El clúster de gestión suele incluir los siguientes componentes:

    • Gestión de múltiples clústeres con Rancher Prime (Capítulo 6, Rancher), que permite un panel común para la incorporación de clústeres en sentido descendente y la gestión continua del ciclo de vida de la infraestructura y las aplicaciones, proporcionando además un aislamiento completo de inquilinos e integraciones de IDP (proveedor de identidad), un gran mercado de integraciones y extensiones de terceros, y una API independiente del proveedor.

    • Gestión de sistemas Linux con SUSE Multi-Linux Manager, que permite la gestión automatizada de parches y configuración de Linux del sistema operativo Linux subyacente (*SUSE Linux Micro (Capítulo 10, SUSE Linux Micro)) que se ejecuta en los clústeres en sentido descendente. Tenga en cuenta que, aunque este componente está en contenedores, actualmente necesita ejecutarse en un sistema separado del resto de los componentes de gestión, por lo que aparece etiquetado como "Linux Management" en el diagrama anterior.

    • Un controlador de Lifecycle Management (Capítulo 21, Controlador de actualización) dedicado que gestiona las actualizaciones de los componentes del clúster de gestión a una versión de SUSE Telco Cloud determinada.

    • Un soporte opcional de gestión y ciclo de vida completo para equipo sin sistema operativo con Metal3 (Capítulo 11, Metal3), MetalLB (Capítulo 17, MetalLB) y proveedores de infraestructura CAPI (Cluster API), que permite el aprovisionamiento completo de extremo a extremo de sistemas de equipo sin sistema operativo que tienen capacidades de gestión remota.

    • Un motor GitOps opcional llamado Fleet (Capítulo 9, Fleet) para gestionar el aprovisionamiento y el ciclo de vida de los clústeres en sentido descendente y las aplicaciones que residen en ellos.

    • Como base del propio clúster de gestión se encuentra SUSE Linux Micro (Capítulo 10, SUSE Linux Micro) como sistema operativo base y RKE2 (Capítulo 14, RKE2) como la distribución de Kubernetes que soporta las aplicaciones del clúster de gestión.

3.1.2 Clústeres en sentido descendente

suse edge downstream cluster
  • Sentido descendente: Esta es la parte distribuida de SUSE Telco Cloud que se utiliza para ejecutar las cargas de trabajo del usuario en el edge, es decir, el software que se ejecuta en la propia ubicación del edge, y que normalmente se compone de los siguientes componentes:

    • RKE2, una distribución de Kubernetes reforzada y certificada, optimizada para su uso en el gobierno y en sectores regulados

    • SUSE Security (Capítulo 16, SUSE Security) para habilitar funciones de seguridad como el escaneo de vulnerabilidades de imágenes, la inspección profunda de paquetes y la protección contra amenazas y vulnerabilidades en tiempo real.

    • Almacenamiento en bloques de software con SUSE Storage (Capítulo 15, SUSE Storage) para habilitar un almacenamiento en bloques ligero, persistente, resistente y escalable.

    • Un sistema operativo Linux ligero, optimizado para contenedores y reforzado con SUSE Linux Micro (Capítulo 10, SUSE Linux Micro), que proporciona un SO inmutable y altamente resistente para ejecutar contenedores y máquinas virtuales en el edge. SUSE Linux Micro está disponible tanto para arquitecturas AArch64 como para AMD64/Intel 64, y también es compatible con Real-Time Kernel para aplicaciones sensibles a la latencia (por ejemplo, casos de uso de telecomunicaciones).

    • Para los clústeres conectados (es decir, aquellos que tienen conectividad con el clúster de gestión) se despliegan dos agentes, a saber, Rancher System Agent para gestionar la conectividad con Rancher Prime, y venv-salt-minion para recibir instrucciones de SUSE Multi-Linux Manager para aplicar actualizaciones de software de Linux. Estos agentes no son necesarios para la gestión de clústeres desconectados.

3.2 Conectividad

suse edge connected architecture

La imagen anterior proporciona una visión general de la arquitectura de alto nivel para los clústeres en sentido descendente conectados y su conexión al clúster de gestión. El clúster de gestión puede desplegarse en una amplia variedad de plataformas de infraestructura subyacentes, tanto en capacidades in situ como en la nube, dependiendo de la disponibilidad de red entre los clústeres en sentido descendente y el clúster de gestión de destino. El único requisito para que esto funcione es que las URL de API y de devolución de llamada sean accesibles a través de la red que conecta los nodos del clúster en sentido descendente con la infraestructura de gestión.

Es importante reconocer que existen mecanismos distintos mediante los cuales se establece esta conectividad en relación con el mecanismo de despliegue del clúster en sentido descendente. Los detalles de esto se explican con mucha más profundidad en la siguiente sección, pero para establecer una comprensión básica, existen tres mecanismos principales para que los clústeres en sentido descendente conectados se establezcan como un clúster "gestionado":

  1. Los clústeres en sentido descendente se despliegan inicialmente en una capacidad "desconectada" (por ejemplo, a través de Edge Image Builder (Capítulo 12, Edge Image Builder)) y luego se importan al clúster de gestión si/cuando la conectividad lo permite.

  2. Los clústeres en sentido descendente están configurados para utilizar el mecanismo de incorporación integrado y se registran automáticamente en el clúster de gestión en el primer arranque, lo que permite la vinculación tardía de la configuración del clúster.

  3. Los clústeres en sentido descendente se han aprovisionado con las capacidades de gestión de metal desnudo (CAPI + Metal3) y se importan automáticamente al clúster de gestión una vez que el clúster se ha desplegado y configurado (a través del operador Rancher Turtles).

Nota
Nota

Se recomienda implementar múltiples clústeres de gestión para adaptarse a la escala de grandes despliegues, optimizar las preocupaciones de ancho de banda y latencia en entornos dispersos geográficamente y minimizar la interrupción en caso de una interrupción o actualización del clúster de gestión. Puede encontrar los límites de escalabilidad y los requisitos del sistema actuales del clúster de gestión aquí.

4 Patrones comunes de despliegue edge

Debido al variado conjunto de entornos operativos y requisitos de ciclo de vida, hemos implementado soporte para una serie de patrones de despliegue distintos que se alinean vagamente con los segmentos de mercado y los casos de uso en los que opera SUSE Telco Cloud. Hemos documentado una guía de inicio rápido para cada uno de estos patrones de despliegue para ayudarle a familiarizarse con la plataforma SUSE Telco Cloud en función de sus necesidades. Los tres patrones de despliegue que admitimos hoy se describen a continuación, con un enlace a la página de inicio rápido respectiva.

4.1 Aprovisionamiento de red dirigida

El aprovisionamiento de red dirigido es aquel en el que conoce los detalles del hardware en el que desea realizar el despliegue y tiene acceso directo a la interfaz de gestión fuera de banda para orquestar y automatizar todo el proceso de aprovisionamiento. En este escenario, nuestros clientes esperan que una solución sea capaz de aprovisionar sitios en el borde de forma totalmente automatizada desde una ubicación centralizada, yendo mucho más allá de la creación de una imagen de arranque al minimizar las operaciones manuales en la ubicación en el borde; simplemente coloque en el rack, encienda y conecte las redes necesarias al hardware físico, y el proceso de automatización enciende la máquina a través de la gestión fuera de banda (por ejemplo, a través de la API de Redfish) y maneja el aprovisionamiento, la incorporación y el despliegue de la infraestructura sin intervención del usuario. La clave para que esto funcione es que los sistemas sean conocidos por los administradores; ellos saben qué hardware está en qué ubicación, y se espera que el despliegue se maneje de forma centralizada.

Esta solución es la más robusta, ya que usted interactúa directamente con la interfaz de gestión del hardware, trata con hardware conocido y tiene menos restricciones en cuanto a la disponibilidad de la red. En cuanto a la funcionalidad, esta solución utiliza ampliamente Cluster API y Metal3 para el aprovisionamiento automatizado desde equipo sin sistema operativo, pasando por el sistema operativo, Kubernetes y las aplicaciones en capas, y proporciona la capacidad de vincularse al resto de las capacidades comunes de gestión del ciclo de vida de SUSE Telco Cloud tras el despliegue. La guía de inicio rápido para esta solución se encuentra en Capítulo 4, Despliegues automatizados de BMC con Metal3.

4.2 Provisión basada en imágenes

Para los clientes que necesitan operar en entornos independientes, en entornos aislados o con conectividad de red limitada, SUSE Telco Cloud proporciona una solución que permite generar medios de instalación totalmente personalizados que contienen todos los artefactos de despliegue requeridos para habilitar tanto clústeres de Kubernetes de alta disponibilidad de nodo único como de múltiples nodos en edge, incluyendo cualquier carga de trabajo o componente en capas adicional que se requiera, todo ello sin conectividad de red al mundo exterior y sin la intervención de una plataforma de gestión centralizada. La experiencia del usuario sigue de cerca la solución de «phone home» en el sentido de que se proporcionan medios de instalación a los sistemas de destino, pero la solución se iniciará in situ. En este escenario, es posible conectar los clústeres resultantes a Rancher para su gestión continua (es decir, pasar de un modo de operación «desconectado» a «conectado» sin una reconfiguración o un redespliegue importantes), o pueden seguir operando de forma aislada. Tenga en cuenta que en ambos casos se puede aplicar el mismo mecanismo coherente para automatizar las operaciones del ciclo de vida.

Además, esta solución se puede utilizar para crear rápidamente clústeres de gestión que pueden alojar la infraestructura centralizada que admite tanto los modelos de 'aprovisionamiento de red dirigida' como de 'aprovisionamiento de red «Phone Home»', ya que puede ser la forma más rápida y sencilla de aprovisionar todo tipo de infraestructura edge. Esta solución utiliza intensamente las capacidades de SUSE Telco Cloud Image Builder para crear medios de instalación totalmente personalizados y desatendidos; el inicio rápido se puede encontrar en Capítulo 5, Clústeres independientes con Edge Image Builder.

5 Validación de pila de SUSE Telco Cloud

Todas las versiones de SUSE Telco Cloud se componen de componentes estrechamente integrados y minuciosamente validados que se versionan como uno solo. Como parte de los esfuerzos de integración continua y validación de pila que no solo prueban la integración entre componentes, sino que garantizan que el sistema funcione como se espera en escenarios de fallo forzado, el equipo de SUSE Telco Cloud publica todas las ejecuciones de prueba y los resultados al público. Los resultados junto con todos los parámetros de entrada se pueden encontrar en ci.edge.suse.com.

6 Lista completa de componentes

La lista completa de componentes, junto con un enlace a una descripción de alto nivel de cada uno y cómo se utiliza en SUSE Telco Cloud, se puede encontrar a continuación:

Parte I Concepto y arquitectura

SUSE Telco Cloud es una plataforma diseñada para alojar aplicaciones Telco modernas, nativas de nube, a escala, desde el kernel hasta el edge.

Esta página explica la arquitectura y los componentes utilizados en SUSE Telco Cloud.

  • 1 Arquitectura de SUSE Telco Cloud
  • El siguiente diagrama muestra la arquitectura de alto nivel de SUSE Telco Cloud:

  • 2 Componentes
  • Existen dos bloques diferentes, la pila de gestión y la pila de tiempo de ejecución:

  • 3 Modelo de despliegue
  • SUSE Telco Cloud sigue un modelo de despliegue de dos etapas: el clúster de gestión se despliega utilizando una imagen generada por Edge Image Builder (Capítulo 12, Edge Image Builder), y los clústeres en sentido descendente se aprovisionan mediante el aprovisionamiento de red dirigido. Este capítul…

1 Arquitectura de SUSE Telco Cloud

El siguiente diagrama muestra la arquitectura de alto nivel de SUSE Telco Cloud:

product atip architecture1

2 Componentes

Existen dos bloques diferentes, la pila de gestión y la pila de tiempo de ejecución:

  • Pila de gestión: Esta es la parte de SUSE Telco Cloud que se utiliza para gestionar el aprovisionamiento y el ciclo de vida de las pilas de tiempo de ejecución. gracias a los siguientes componentes:

    • Gestión de clústeres múltiples en entornos de nube pública y privada con Rancher (Capítulo 6, Rancher)

    • Soporte para equipo sin sistema operativo con Metal3 (Capítulo 11, Metal3), MetalLB (Capítulo 17, MetalLB) y proveedores de infraestructura CAPI (Cluster API)

    • Aislamiento integral de inquilinos e integraciones de IDP (proveedor de identidad)

    • Amplio mercado de integraciones y extensiones de terceros

    • API neutral respecto al proveedor y rico ecosistema de proveedores

    • Control de las actualizaciones transaccionales de SUSE Linux Micro

    • Motor GitOps para gestionar el ciclo de vida de los clústeres mediante repositorios Git con Fleet (Capítulo 9, Fleet)

  • Pila de tiempo de ejecución: Esta es la parte de SUSE Telco Cloud que se utiliza para ejecutar las cargas de trabajo.

    • RKE2 (Capítulo 14, RKE2) sirve como la distribución de Kubernetes ligera y reforzada en seguridad, optimizada para entornos de telecomunicaciones edge y centrados en el cumplimiento.

    • (Opcional) SUSE Security (Capítulo 16, SUSE Security) para habilitar funciones de seguridad como el escaneo de vulnerabilidades de imágenes, la inspección profunda de paquetes y el control automático del tráfico intraclúster.

    • (Opcional) Almacenamiento en bloques con SUSE Storage (Capítulo 15, SUSE Storage) para habilitar una forma sencilla y fácil de utilizar una solución de almacenamiento nativo de nube.

    • Sistema operativo optimizado con SUSE Linux Micro (Capítulo 10, SUSE Linux Micro) para habilitar un SO seguro, ligero e inmutable (sistema de archivos transaccional) para ejecutar contenedores. SUSE Linux Micro está disponible en arquitecturas AArch64 y AMD64/Intel 64, y también es compatible con Real-Time Kernel para casos de uso de telecomunicaciones y edge.

3 Modelo de despliegue

SUSE Telco Cloud sigue un modelo de despliegue de dos etapas: el clúster de gestión se despliega utilizando una imagen generada por Edge Image Builder (Capítulo 12, Edge Image Builder), y los clústeres en sentido descendente se aprovisionan mediante el aprovisionamiento de red dirigido. Este capítulo ofrece una visión general de este modelo de despliegue, ya que es el enfoque recomendado y compatible para los entornos de SUSE Telco Cloud.

3.1 ¿Por qué este modelo de despliegue?

El clúster de gestión es un despliegue único en una sola ubicación. El aprovisionamiento basado en imágenes agrupa todos los componentes en una única imagen arrancable. De este modo, el clúster de gestión se iniciará por sí mismo, lo que requiere una complejidad operativa mínima. Es la forma más sencilla y directa de ponerlo en marcha.

Los clústeres descendentes, sin embargo, son otra historia. En entornos de telecomunicaciones, se despliegan a gran escala en muchos centros de datos y en sitios edge, a menudo sin disponer de experiencia técnica in situ. El aprovisionamiento de red dirigido está diseñado para esto: requiere que los servidores de destino admitan una interfaz de gestión fuera de banda como Redfish, a través de la cual el clúster de gestión enciende, inspecciona y aprovisiona de forma remota los nodos bare-metal sin ninguna intervención in situ.

Integrar toda la configuración específica del clúster en una imagen de arranque, como requeriría el aprovisionamiento basado en imágenes, significa que cada variación del sitio exige una imagen diferente, y cualquier cambio de configuración requiere reconstruir y redistribuir las imágenes en todos los sitios. El aprovisionamiento de red dirigido resuelve esto manteniendo la imagen del SO genérica y gestionando toda la configuración específica del clúster, incluidos los perfiles de red, Kubernetes y Telco, desde el clúster de gestión en el momento del aprovisionamiento. Los operadores simplemente instalan en rack, encienden y conectan el hardware, y el clúster de gestión se encarga del resto.

Esta separación también permite una integración completa de GitOps. Dado que toda la definición del clúster en sentido descendente se expresa como manifiestos de Cluster API, puede almacenarse en Git y ser reconciliada por Fleet en todos los sitios, lo que hace que las operaciones de aprovisionamiento, configuración y ciclo de vida sean totalmente auditables y repetibles sin intervención manual.

3.2 Despliegue del clúster de gestión

Uso de Edge Image Builder (Capítulo 12, Edge Image Builder) para crear una nueva imagen ISO con la pila de gestión incluida. A continuación, puede utilizar esta imagen ISO para instalar un nuevo clúster de gestión en máquinas virtuales o en equipo sin sistema operativo.

product atip architecture2
Nota
Nota

Para obtener más información sobre cómo desplegar un nuevo clúster de gestión, consulte la guía del clúster de gestión de SUSE Telco Cloud (Parte V, “Configuración del clúster de gestión”).

Nota
Nota

Para obtener más información sobre cómo utilizar Edge Image Builder, consulte la guía de Edge Image Builder (Capítulo 5, Clústeres independientes con Edge Image Builder).

3.3 Despliegue de un clúster en sentido descendente de nodo único con perfiles de Telco

Una vez que tengamos el clúster de gestión en funcionamiento, podemos utilizarlo para desplegar un clúster en sentido descendente de nodo único con todas las capacidades de Telco habilitadas y configuradas utilizando el flujo de trabajo de aprovisionamiento de red dirigido.

El siguiente diagrama muestra el flujo de trabajo de alto nivel para desplegarlo:

product atip architecture3
Nota
Nota

Para obtener más información sobre cómo desplegar un clúster en sentido descendente, consulte la guía de aprovisionamiento automatizado de SUSE Telco Cloud. (Parte VII, “Aprovisionamiento de red dirigido totalmente automatizado”)

Nota
Nota

Para obtener más información sobre las funciones de Telco, consulte la guía de funciones de Telco de SUSE Telco Cloud. (Parte VI, “Configuración de las funciones Telco”)

3.4 Despliegue de un clúster de alta disponibilidad en sentido descendente

Una vez que tengamos el clúster de gestión en funcionamiento, podemos utilizarlo para desplegar un clúster de alta disponibilidad en sentido descendente con MetalLB como equilibrador de carga utilizando el flujo de trabajo de aprovisionamiento de red dirigida.

El siguiente diagrama muestra el flujo de trabajo de alto nivel para desplegarlo:

product atip architecture4
Nota
Nota

Para obtener más información sobre cómo desplegar un clúster en sentido descendente, consulte la guía de aprovisionamiento automatizado de SUSE Telco Cloud. (Parte VII, “Aprovisionamiento de red dirigido totalmente automatizado”)

Nota
Nota

Para obtener más información sobre MetalLB, consulte aquí: (Capítulo 17, MetalLB)

Parte II Guías de inicio rápido

Inicio rápido aquí

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 (Capítulo 12, Edge Image Builder).

Sugerencia
Sugerencia

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 (Parte 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).

Sugerencia
Sugerencia

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 Sección 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
Aviso
Aviso

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 (Capítulo 64, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi) y Edge Image Builder (Capítulo 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

Nota
Nota

Por favor, seguid Capítulo 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.

Nota
Nota

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 /
Nota
Nota

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 Capítulo 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 (Nota) o algún otro servidor accesible localmente. En los ejemplos siguientes, nos referimos a este servidor como imagecache.local:8080

Nota
Nota

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 (Capítulo 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
Nota
Nota

En algunas circunstancias, la dirección MAC puede omitirse. Consulte Sección 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)

Nota
Nota

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 Parte 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
Nota
Nota

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 (Parte 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 (Parte 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.

5 Clústeres independientes con Edge Image Builder

Edge Image Builder (EIB) es una herramienta que agiliza el proceso de generación de imágenes de disco personalizadas y listas para arrancar (CRB) para el arranque de máquinas, incluso en escenarios totalmente en un entorno aislado. EIB se utiliza para crear imágenes de despliegue que se usarán en las tres modalidades de despliegue de SUSE Telco Cloud, ya que es lo suficientemente flexible como para ofrecer desde las personalizaciones más pequeñas, por ejemplo, añadir un usuario o configurar la zona horaria, hasta proporcionar una imagen configurada de forma integral que establece, por ejemplo, configuraciones de red complejas, despliega clústeres de Kubernetes de varios nodos, despliega cargas de trabajo de clientes y se registra en la plataforma de gestión centralizada a través de Rancher/Elemental y SUSE Multi-Linux Manager. EIB se ejecuta como una imagen de contenedor, lo que lo hace increíblemente portátil entre plataformas y garantiza que todas las dependencias necesarias sean autónomas, teniendo un impacto muy mínimo en los paquetes instalados del sistema que se utiliza para operar la herramienta.

Nota
Nota

Para escenarios de varios nodos, EIB despliega automáticamente MetalLB y Endpoint Copier Operator para que los hosts aprovisionados utilizando la misma imagen compilada se unan automáticamente a un clúster de Kubernetes.

Para obtener más información, lea la Introducción a Edge Image Builder (Capítulo 12, Edge Image Builder).

Aviso
Aviso

Edge Image Builder 1.3.3.1 admite la personalización de imágenes de SUSE Linux Micro 6.2. Las versiones anteriores, como SUSE Linux Enterprise Micro 5.5 o 6.0, no son compatibles.

5.1 Requisitos previos

Nota
Nota

Para fines que no sean de producción, se puede utilizar openSUSE Leap 15.6 o openSUSE Tumbleweed como máquina host de compilación. Otros sistemas operativos pueden funcionar, siempre que haya disponible un entorno de ejecución de contenedor compatible.

5.1.1 Obtención de la imagen de EIB

La imagen de contenedor de EIB está disponible públicamente y se puede descargar desde el registro SUSE Telco Cloud ejecutando el siguiente comando en su host de compilación de imágenes:

podman pull registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1

5.2 Creación del directorio de configuración de la imagen

Como EIB se ejecuta dentro de un contenedor, necesitamos montar un directorio de configuración desde el host, lo que le permite especificar la configuración deseada, y durante el proceso de compilación EIB tiene acceso a cualquier archivo de entrada y artefacto de soporte necesario. Este directorio debe seguir una estructura específica. Vamos a crearlo, asumiendo que este directorio existirá en su directorio personal y se llamará "eib":

export CONFIG_DIR=$HOME/eib
mkdir -p $CONFIG_DIR/base-images

En el paso anterior creamos un directorio "base-images" que albergará la imagen de entrada de SUSE Linux Micro 6.2, asegurémonos de que la imagen se copie al directorio de configuración:

cp /path/to/SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso $CONFIG_DIR/base-images/slemicro.iso
Nota
Nota

Durante la ejecución de EIB, la imagen base original no se modifica; se crea una versión nueva y personalizada con la configuración deseada en la raíz del directorio de configuración de EIB.

El directorio de configuración en este punto debería tener el siguiente aspecto:

└── base-images/
    └── slemicro.iso

5.3 Creación del archivo de definición de imagen

El archivo de definición describe la mayoría de las opciones configurables que admite Edge Image Builder. Puede encontrar un ejemplo completo de opciones aquí, y le recomendamos que eche un vistazo a la guía de creación de imágenes upstream para obtener ejemplos más completos que el que vamos a analizar a continuación. Comencemos con un archivo de definición muy básico para nuestra imagen de SO:

cat << EOF > $CONFIG_DIR/iso-definition.yaml
apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
EOF

Esta definición especifica que estamos generando una imagen de salida para un sistema basado en AMD64/Intel 64. La imagen que se utilizará como base para modificaciones posteriores es una imagen iso llamada slemicro.iso, que se espera que esté ubicada en $CONFIG_DIR/base-images/slemicro.iso. También describe que, una vez que EIB termine de modificar la imagen, la imagen de salida se llamará eib-image.iso y, de forma predeterminada, residirá en $CONFIG_DIR.

Ahora nuestra estructura de directorios debería tener este aspecto:

├── iso-definition.yaml
└── base-images/
    └── slemicro.iso

En las siguientes secciones veremos algunos ejemplos de operaciones comunes:

5.3.1 Configuración del sistema operativo (SO)

La sección operatingSystem de EIB está destinada a configurar dónde se va a instalar el sistema operativo, el tamaño de la imagen, etc. Es una sección opcional y no debe incluirse a menos que se aplique una o más personalizaciones.

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-Base-RT-SelfInstall.iso
operatingSystem:
  isoConfiguration:
    installDevice: /dev/disk/by-id/ata-QEMU_HARDDISK_111-disk1 # first defined disk

Configuración específica del tipo. Dependiendo del tipo de imagen que se esté personalizando, se puede incluir una de las siguientes secciones opcionales.

  • isoConfiguration - Opcional; la configuración en esta sección solo se aplica a imágenes ISO.

  • installDevice - Opcional; especifica el disco que debe utilizarse como dispositivo de instalación. Debe ser un dispositivo de bloques y, por defecto, borrará automáticamente cualquier dato que se encuentre en el disco. Además, especificar este atributo activa una anulación de GRUB para instalar automáticamente el sistema operativo en lugar de solicitar al usuario que inicie la instalación, lo que permite una instalación totalmente desatendida y automatizada. Si se omite, se solicita al usuario que seleccione la opción «Install» en el menú de GRUB, además de tener que seleccionar el disco de instalación y confirmar que el dispositivo se borrará durante el proceso.

    Nota
    Nota

    El dispositivo utilizado en la sección installDevice puede especificarse como /dev/sda o utilizando la nomenclatura /dev/disk/by-id, /dev/disk/by-path para garantizar que se utiliza el dispositivo correcto. Si utiliza máquinas virtuales libvirt, el valor del atributo serial puede especificarse al crear un disco para la máquina virtual (p. ej., serial=111-disk1) para que pueda utilizarse en el valor installDevice con la nomenclatura by-id, como por ejemplo /dev/disk/by-id/ata-QEMU_HARDDISK_111-disk1 si utiliza dispositivos ATA (libvirt añade automáticamente el prefijo ata-QEMU_HARDDISK_ al ID para dispositivos ATA, o virtio- para dispositivos virtio; consulte #17670 problema de virtio para obtener más información).

  • rawConfiguration - Opcional; la configuración de esta sección solo se aplica a imágenes RAW.

  • diskSize - Opcional; establece el tamaño deseado de la imagen de disco sin formato al que EIB redimensionará la imagen resultante. Esto es importante para garantizar que su imagen de disco sea lo suficientemente grande como para albergar cualquier artefacto que se incorpore a la imagen. Se aconseja establecer un tamaño ligeramente inferior al de su tarjeta SD (o dispositivo de bloques si escribe directamente en un disco), ya que el sistema se expandirá automáticamente durante el arranque para ocupar el tamaño del dispositivo de bloques. Esto es opcional, pero muy recomendable. Especifíquelo como un número entero con «M» (megabyte), «G» (gigabyte) o «T» (terabyte) como sufijo (p. ej. "32G").

  • luksKey - Obligatorio para imágenes cifradas; la clave LUKS proporcionada para una imagen sin formato cifrada, necesaria para que EIB pueda completar el proceso de compilación.

  • expandEncryptedPartition - Opcional; desactivado por defecto, cuando se activa, expande automáticamente la partición cifrada a su tamaño máximo. P. ej., si diskSize es 25G y este campo es true, EIB expandirá la partición cifrada a 25G durante el proceso de compilación.

5.3.2 Configuración de usuarios del SO

EIB le permite preconfigurar usuarios con información de inicio de sesión, como contraseñas o claves SSH, incluida la configuración de una contraseña de root fija. Como parte de este ejemplo, vamos a fijar la contraseña de root, y el primer paso es utilizar OpenSSL para crear una contraseña cifrada de una sola vía:

openssl passwd -6 SecurePassword

Esto generará algo similar a:

$6$G392FCbxVgn[...]Y7zTXnC1

A continuación, podemos añadir una sección en el archivo de definición llamada operatingSystem con una matriz users en su interior. El archivo resultante debería tener este aspecto:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$G392FCbxVgn[...]Y7zTXnC1
Nota
Nota

También es posible añadir usuarios adicionales, crear los directorios de inicio, establecer los ID de usuario, añadir autenticación mediante claves SSH y modificar la información de los grupos. Consulte la guía de compilación de imágenes upstream para obtener más ejemplos.

5.3.3 Configuración de la hora del SO

La sección time es opcional, pero se recomienda encarecidamente configurarla para evitar posibles problemas con los certificados y el desfase del reloj. EIB configurará chronyd y /etc/localtime dependiendo de los parámetros aquí indicados.

operatingSystem:
  time:
    timezone: Europe/London
    ntp:
      forceWait: true
      pools:
        - 2.suse.pool.ntp.org
      servers:
        - 10.0.0.1
        - 10.0.0.2
  • El timezone especifica la zona horaria en el formato "Región/Localidad" (p. ej. "Europe/London"). La lista completa se puede encontrar ejecutando timedatectl list-timezones en un sistema Linux.

  • ntp - Define los atributos relacionados con la configuración de NTP (usando chronyd):

  • forceWait - Solicita que chronyd intente sincronizar las fuentes de tiempo antes de iniciar otros servicios, con un tiempo de espera de 180 s.

  • pools - Especifica una lista de grupos que chronyd utilizará como fuentes de datos (usando iburst para mejorar el tiempo necesario para la sincronización inicial).

  • servers - Especifica una lista de servidores que chronyd utilizará como fuentes de datos (usando iburst para mejorar el tiempo necesario para la sincronización inicial).

Nota
Nota

Los valores proporcionados en este ejemplo son solo para fines ilustrativos. Ajústelos para que se adapten a sus requisitos específicos.

5.3.4 Añadir certificados

Los archivos de certificado con la extensión ".pem" o ".crt" almacenados en el directorio certificates se instalarán en el almacén de certificados de todo el sistema del nodo:

.
├── definition.yaml
└── certificates
    ├── my-ca.pem
    └── my-ca.crt

Consultad la guía "Asegurar la comunicación con certificados TLS" para obtener más información.

5.3.5 Añadir archivos de sistema operativo

Los archivos colocados en el directorio os-files dentro del directorio de configuración de la imagen se copian automáticamente en el sistema de archivos de la imagen compilada. El directorio exacto se conservará cuando se copien. Por ejemplo, si un archivo existe en un subdirectorio llamado os-files/etc, se coloca en el directorio /etc de la imagen compilada.

Nota
Nota

Si el directorio os-files existe, no puede estar vacío.

.
├── definition.yaml
└── os-files
    └── etc
        └── ssh
            └── sshd_config

5.3.6 Configuración de paquetes RPM

Una de las principales características de EIB es proporcionar un mecanismo para añadir paquetes de software adicionales a la imagen, de modo que cuando finalice la instalación, el sistema pueda aprovechar los paquetes instalados de inmediato. EIB permite a los usuarios especificar lo siguiente:

  • Paquetes por su nombre dentro de una lista en la definición de la imagen

  • Repositorios de red en los que buscar estos paquetes

  • Credenciales del SUSE Customer Center (SCC) para buscar en los repositorios oficiales de SUSE los paquetes enumerados

  • A través de un directorio $CONFIG_DIR/rpms, cargar paquetes RPM personalizados que no existen en los repositorios de red

  • A través del mismo directorio ($CONFIG_DIR/rpms/gpg-keys), claves GPG para permitir la validación de paquetes de terceros

EIB llevará a cabo entonces un proceso de resolución de paquetes durante el tiempo de compilación de la imagen, tomando la imagen base como entrada, e intentará extraer e instalar todos los paquetes suministrados, ya sea especificados a través de la lista o proporcionados localmente. EIB descarga todos los paquetes, incluidas las dependencias, en un repositorio que existe dentro de la imagen de salida e indica al sistema que los instale durante el primer proceso de arranque. Realizar este proceso durante la compilación de la imagen garantiza que los paquetes se instalarán correctamente durante el primer arranque en la plataforma deseada, por ejemplo, el nodo en el extremo. Esto también es ventajoso en entornos en los que desea integrar los paquetes adicionales en la imagen en lugar de extraerlos a través de la red cuando están en funcionamiento, por ejemplo, para entornos aislados o con red restringida.

Como ejemplo sencillo para demostrar esto, vamos a instalar el paquete RPM nvidia-container-toolkit que se encuentra en el repositorio de NVIDIA compatible con proveedores externos:

  packages:
    packageList:
      - nvidia-container-toolkit
    additionalRepos:
      - url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64

El archivo de definición resultante tiene el siguiente aspecto:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$G392FCbxVgn[...]Y7zTXnC1
  packages:
    packageList:
      - nvidia-container-toolkit
    additionalRepos:
      - url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64

Lo anterior es un ejemplo sencillo, pero para mayor exhaustividad, descargue la clave de firma del paquete NVIDIA antes de ejecutar la generación de la imagen:

$ mkdir -p $CONFIG_DIR/rpms/gpg-keys
$ curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey > $CONFIG_DIR/rpms/gpg-keys/nvidia.gpg
Aviso
Aviso

La adición de RPM adicionales mediante este método está pensada para la incorporación de componentes de terceros compatibles o paquetes suministrados (y mantenidos) por el usuario; este mecanismo no debe utilizarse para añadir paquetes que normalmente no serían compatibles con SUSE Linux Micro. Si se utiliza este mecanismo para añadir componentes de repositorios de openSUSE (que no son compatibles), incluidos los de versiones o paquetes de servicio más recientes, puede acabar con una configuración no compatible, especialmente cuando la resolución de dependencias da lugar a la sustitución de partes fundamentales del sistema operativo, aunque el sistema resultante pueda parecer que funciona como se espera. Si no está seguro, póngase en contacto con su representante de SUSE para obtener ayuda a la hora de determinar la compatibilidad de la configuración que desea.

Nota
Nota

Puede encontrar una guía más completa con ejemplos adicionales en la guía de instalación de paquetes en sentido ascendente.

5.3.7 Configuración del clúster de Kubernetes y de las cargas de trabajo de los usuarios

Otra característica de EIB es la capacidad de utilizarlo para automatizar el despliegue de clústeres de Kubernetes de alta disponibilidad tanto de nodo único como de varios nodos que se "inician en el lugar" (es decir, que no requieren ningún tipo de infraestructura de gestión centralizada para coordinarse). El principal motor de este enfoque son los despliegues en entornos aislados o en entornos con red restringida, pero también sirve para iniciar clústeres independientes de forma rápida, incluso si se dispone de acceso completo y sin restricciones a la red.

Este método permite no solo el despliegue del sistema operativo personalizado, sino también la capacidad de especificar la configuración de Kubernetes, cualquier componente en capas adicional mediante charts de Helm y cualquier carga de trabajo del usuario mediante los manifiestos de Kubernetes suministrados. Sin embargo, el principio de diseño detrás de este método es asumir por defecto que el usuario desea un entorno aislado. Por lo tanto, cualquier elemento especificado en la definición de la imagen se incluirá en la imagen, lo que incluye las cargas de trabajo suministradas por el usuario. EIB garantiza que todas las imágenes detectadas que requieran las definiciones se copien localmente y sean servidas por el registro de imágenes integrado en el sistema desplegado resultante.

En este siguiente ejemplo, vamos a tomar nuestra definición de imagen existente y especificaremos una configuración de Kubernetes (en este ejemplo no se enumeran los sistemas ni sus funciones, por lo que asumimos por defecto que se trata de un solo nodo), lo que indicará a EIB que aprovisione un clúster de Kubernetes RKE2 de un solo nodo. Para mostrar la automatización tanto del despliegue de cargas de trabajo suministradas por el usuario (mediante manifiesto) como de los componentes en capas (mediante Helm), vamos a instalar KubeVirt a través del chart de Helm SUSE Telco Cloud, así como NGINX mediante un manifiesto de Kubernetes. La configuración adicional que debemos añadir a la definición de imagen existente es la siguiente:

kubernetes:
  version: v1.35.4+rke2r1
  manifests:
    urls:
      - https://k8s.io/examples/application/nginx-app.yaml
  helm:
    charts:
      - name: kubevirt
        version: 306.0.2+up0.7.0
        repositoryName: suse-edge
    repositories:
      - name: suse-edge
        url: oci://registry.suse.com/edge/charts

El archivo de definición completo resultante debería tener ahora este aspecto:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$G392FCbxVgn[...]Y7zTXnC1
  packages:
    packageList:
      - nvidia-container-toolkit
    additionalRepos:
      - url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64
kubernetes:
  version: v1.35.4+k3s1
  manifests:
    urls:
      - https://k8s.io/examples/application/nginx-app.yaml
  helm:
    charts:
      - name: kubevirt
        version: 306.0.2+up0.7.0
        repositoryName: suse-edge
    repositories:
      - name: suse-edge
        url: oci://registry.suse.com/edge/charts
Nota
Nota

Puede encontrar más ejemplos de opciones como despliegues de varios nodos, redes personalizadas y opciones/valores de charts de Helm en la documentación upstream.

5.3.8 Configuración de la red

En el último ejemplo de esta guía de inicio rápido, vamos a configurar la red que se activará cuando se aprovisione un sistema con la imagen generada por EIB. Es importante entender que, a menos que se proporcione una configuración de red, el modelo predeterminado es que se utilizará DHCP en todas las interfaces detectadas en el momento del arranque. Sin embargo, esta no siempre es una configuración deseable, especialmente si DHCP no está disponible y necesita proporcionar configuraciones estáticas, o si necesita configurar construcciones de red más complejas, por ejemplo, enlaces, LACP y VLAN, o necesita anular ciertos parámetros, por ejemplo, nombres de host, servidores DNS y rutas.

EIB ofrece la posibilidad de proporcionar configuraciones por nodo (donde el sistema en cuestión se identifica de forma única por su dirección MAC), o una anulación para suministrar una configuración idéntica a cada máquina, lo cual es más útil cuando no se conocen las direcciones MAC del sistema. EIB utiliza una herramienta adicional llamada Network Manager Configurator, o nmc para abreviar, que es una herramienta creada por el equipo de SUSE Telco Cloud para permitir que se apliquen configuraciones de red personalizadas basadas en el esquema de red declarativo nmstate.io, y en el momento del arranque identificará el nodo en el que se está iniciando y aplicará la configuración de red deseada antes de que se activen los servicios.

Ahora vamos a aplicar una configuración de red estática para un sistema con una única interfaz describiendo el estado de red deseado en un archivo específico del nodo (basado en el nombre de host deseado) en el directorio network requerido:

mkdir $CONFIG_DIR/network

cat << EOF > $CONFIG_DIR/network/host1.local.yaml
routes:
  config:
  - destination: 0.0.0.0/0
    metric: 100
    next-hop-address: 192.168.122.1
    next-hop-interface: eth0
    table-id: 254
  - destination: 192.168.122.0/24
    metric: 100
    next-hop-address: 192.168.122.1
    next-hop-interface: eth0
    table-id: 254
dns-resolver:
  config:
    server:
    - 192.168.122.1
    - 8.8.8.8
interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: 34:8A:B1:4B:16:E7
  ipv4:
    address:
    - ip: 192.168.122.50
      prefix-length: 24
    dhcp: false
    enabled: true
  ipv6:
    enabled: false
EOF
Aviso
Aviso

El ejemplo anterior está configurado para la subred 192.168.122.0/24 predeterminada asumiendo que la prueba se está ejecutando en una máquina virtual. Por favor, adáptelo a su entorno, sin olvidar la dirección MAC. Como la misma imagen puede utilizarse para aprovisionar múltiples nodos, la red configurada por EIB (a través de nmc) depende de que sea capaz de identificar de forma única el nodo por su dirección MAC, y por tanto, durante el arranque, nmc aplicará la configuración de red correcta a cada máquina. Esto significa que necesitará conocer las direcciones MAC de los sistemas en los que desea realizar la instalación. Alternativamente, el comportamiento predeterminado es depender de DHCP, pero puede utilizar el hook configure-network.sh para aplicar una configuración común a todos los nodos; consulte la guía de red (Capítulo 13, Redes edge) para obtener más detalles.

La estructura de archivos resultante debería ser:

├── iso-definition.yaml
├── base-images/
│   └── slemicro.iso
└── network/
    └── host1.local.yaml

La configuración de red que acabamos de crear será analizada y los archivos de conexión de NetworkManager necesarios se generarán automáticamente e insertarán en la nueva imagen de instalación que creará EIB. Estos archivos se aplicarán durante el aprovisionamiento del host, lo que dará como resultado una configuración de red completa.

Nota
Nota

Por favor, consulte el componente de red edge (Capítulo 13, Redes edge) para obtener una explicación más completa de la configuración anterior y ejemplos de esta funcionalidad.

5.4 Compilación de la imagen

Ahora que tenemos una imagen base y una definición de imagen para que EIB la utilice, procedamos a compilar la imagen. Para ello, simplemente utilizamos podman para llamar al contenedor EIB con el comando \"build\", especificando el archivo de definición:

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

La salida del comando debería ser similar a:

Setting up Podman API listener...
Downloading file: dl-manifest-1.yaml 100% (498/498 B, 9.5 MB/s)
Pulling selected Helm charts... 100% (1/1, 43 it/min)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Resolving package dependencies...
Rpm .......................... [SUCCESS]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% (3/3, 10 it/min)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Downloading file: rke2-images-core.linux-amd64.tar.zst 100% (657/657 MB, 48 MB/s)
Downloading file: rke2-images-cilium.linux-amd64.tar.zst 100% (368/368 MB, 48 MB/s)
Downloading file: rke2.linux-amd64.tar.gz 100% (35/35 MB, 50 MB/s)
Downloading file: sha256sum-amd64.txt 100% (4.3/4.3 kB, 6.2 MB/s)
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

La imagen ISO compilada se almacena en $CONFIG_DIR/eib-image.iso:

├── iso-definition.yaml
├── eib-image.iso
├── _build
│   └── cache/
│       └── ...
│   └── build-<timestamp>/
│       └── ...
├── base-images/
│   └── slemicro.iso
└── network/
    └── host1.local.yaml

Cada compilación crea una carpeta con marca de tiempo en $CONFIG_DIR/_build/ que incluye los registros de la compilación, los artefactos utilizados durante la misma, y los directorios combustion y artefacts que contienen todos los scripts y artefactos que se añaden a la imagen CRB.

El contenido de este directorio debería ser similar a:

├── build-<timestamp>/
│   │── combustion/
│   │   ├── 05-configure-network.sh
│   │   ├── 10-rpm-install.sh
│   │   ├── 12-keymap-setup.sh
│   │   ├── 13b-add-users.sh
│   │   ├── 20-k8s-install.sh
│   │   ├── 26-embedded-registry.sh
│   │   ├── 48-message.sh
│   │   ├── network/
│   │   │   ├── host1.local/
│   │   │   │   └── eth0.nmconnection
│   │   │   └── host_config.yaml
│   │   ├── nmc
│   │   └── script
│   │── artefacts/
│   │   │── registry/
│   │   │   ├── hauler
│   │   │   ├── nginx:<version>-registry.tar.zst
│   │   │   ├── rancher_kubectl:<version>-registry.tar.zst
│   │   │   └── registry.suse.com_suse_sles_15.6_virt-operator:<version>-registry.tar.zst
│   │   │── rpms/
│   │   │   └── rpm-repo
│   │   │       ├── addrepo0
│   │   │       │   ├── nvidia-container-toolkit-<version>.rpm
│   │   │       │   ├── nvidia-container-toolkit-base-<version>.rpm
│   │   │       │   ├── libnvidia-container1-<version>.rpm
│   │   │       │   └── libnvidia-container-tools-<version>.rpm
│   │   │       ├── repodata
│   │   │       │   ├── ...
│   │   │       └── zypper-success
│   │   └── kubernetes/
│   │       ├── rke2_installer.sh
│   │       ├── registries.yaml
│   │       ├── server.yaml
│   │       ├── images/
│   │       │   ├── rke2-images-cilium.linux-amd64.tar.zst
│   │       │   └── rke2-images-core.linux-amd64.tar.zst
│   │       ├── install/
│   │       │   ├── rke2.linux-amd64.tar.gz
│   │       │   └── sha256sum-amd64.txt
│   │       └── manifests/
│   │           ├── dl-manifest-1.yaml
│   │           └── kubevirt.yaml
│   ├── createrepo.log
│   ├── eib-build.log
│   ├── embedded-registry.log
│   ├── helm
│   │   └── kubevirt
│   │       └── kubevirt-0.4.0.tgz
│   ├── helm-pull.log
│   ├── helm-template.log
│   ├── iso-build.log
│   ├── iso-build.sh
│   ├── iso-extract
│   │   └── ...
│   ├── iso-extract.log
│   ├── iso-extract.sh
│   ├── modify-raw-image.sh
│   ├── network-config.log
│   ├── podman-image-build.log
│   ├── podman-system-service.log
│   ├── prepare-resolver-base-tarball-image.log
│   ├── prepare-resolver-base-tarball-image.sh
│   ├── raw-build.log
│   ├── raw-extract
│   │   └── ...
│   └── resolver-image-build
│       └──...
└── cache
    └── ...

Si la compilación falla, eib-build.log es el primer registro que contiene información. A partir de ahí, le dirigirá al componente que falló para su depuración.

En este punto, debería tener una imagen lista para usar que:

  1. Deploy SUSE Linux Micro 6.2

  2. Configurar la contraseña de root

  3. Instale el paquete nvidia-container-toolkit

  4. Configure un registro de contenedor integrado para servir contenido localmente

  5. Instale RKE2 de nodo único

  6. Configure redes estáticas

  7. Install KubeVirt

  8. Despliegue un manifiesto suministrado por el usuario

5.5 Depuración del proceso de compilación de la imagen

Si el proceso de compilación de la imagen falla, consulte la guía de depuración en sentido ascendente.

5.6 Prueba de su imagen recién creada

Para obtener instrucciones sobre cómo probar la imagen CRB recién creada, consulte la guía de pruebas de imágenes en sentido ascendente.

Parte III Componentes

Lista de componentes para Edge

6 Rancher

Consulte la documentación de Rancher en https://ranchermanager.docs.rancher.com/v2.14.

Rancher es una potente plataforma de gestión de Kubernetes de código abierto que agiliza la implementación, las operaciones y la supervisión de clústeres de Kubernetes en múltiples entornos. Tanto si gestiona clústeres in situ, en la nube o en el edge, Rancher proporciona una plataforma unificada y centralizada para todas sus necesidades de Kubernetes.

6.1 Características clave de Rancher

  • Gestión de múltiples clústeres: La interfaz intuitiva de Rancher le permite gestionar clústeres de Kubernetes desde cualquier lugar: nubes públicas, centros de datos privados y ubicaciones edge.

  • Seguridad y conformidad con las normas: Rancher aplica políticas de seguridad, control de acceso basado en funciones (RBAC) y estándares de cumplimiento en todo su entorno de Kubernetes.

  • Operaciones de clúster simplificadas: Rancher automatiza el aprovisionamiento, las actualizaciones y la resolución de problemas de los clústeres, simplificando las operaciones de Kubernetes para equipos de todos los tamaños.

  • Catálogo de aplicaciones centralizado: El catálogo de aplicaciones de Rancher ofrece una amplia gama de gráficos de Helm y operadores de Kubernetes, lo que facilita la implementación y gestión de aplicaciones en contenedores.

  • Entrega continua: Rancher admite GitOps y canalizaciones de CI/CD, lo que permite procesos de entrega de aplicaciones automatizados y optimizados.

6.2 Uso de Rancher en SUSE Telco Cloud

Rancher proporciona varias funcionalidades principales a la pila SUSE Telco Cloud:

6.2.1 Gestión centralizada de Kubernetes

En implementaciones edge típicas con numerosos clústeres distribuidos, Rancher actúa como un plano de control central para gestionar estos clústeres de Kubernetes. Ofrece una interfaz unificada para el aprovisionamiento, la actualización, la supervisión y la resolución de problemas, lo que simplifica las operaciones y garantiza la coherencia.

6.2.2 Despliegue simplificado de clústeres

Rancher agiliza la creación de clústeres de Kubernetes en el sistema operativo ligero SUSE Linux Micro, facilitando el despliegue de infraestructura edge con capacidades robustas de Kubernetes.

6.2.3 Despliegue y gestión de aplicaciones

El catálogo de aplicaciones integrado de Rancher puede simplificar el despliegue y la gestión de aplicaciones en contenedores en clústeres SUSE Telco Cloud, lo que permite un despliegue fluido de cargas de trabajo edge.

6.2.4 Seguridad y aplicación de políticas

Rancher proporciona herramientas de gobernanza basadas en políticas, control de acceso basado en funciones (RBAC) e integración con proveedores de autenticación externos. Esto ayuda a que las implementaciones de SUSE Telco Cloud mantengan la seguridad y el cumplimiento, algo fundamental en entornos distribuidos.

6.3 Prácticas recomendadas

6.3.1 GitOps

Rancher incluye Fleet como componente integrado para permitir la gestión de configuraciones de clúster y despliegues de aplicaciones con código almacenado en git.

6.3.2 Observabilidad

Rancher incluye herramientas de supervisión y registro integradas como Prometheus y Grafana para obtener información exhaustiva sobre el estado y el rendimiento de su clúster.

6.4 Instalación con Edge Image Builder

SUSE Telco Cloud utiliza Capítulo 12, Edge Image Builder para personalizar las imágenes base del sistema operativo SUSE Linux Micro. Siga Sección 63.6, “Instalación de Rancher” para una instalación de Rancher en entorno aislado sobre clústeres de Kubernetes aprovisionados por EIB.

6.5 Recursos adicionales

7 Extensiones de Rancher Dashboard

Las extensiones permiten a los usuarios, desarrolladores, socios y clientes ampliar y mejorar la interfaz de usuario de Rancher. SUSE Telco Cloud proporciona extensiones del Dashboard de KubeVirt.

Consulte Rancher documentation para obtener información general sobre las extensiones de Rancher Dashboard.

7.1 Instalación

Todos los componentes de SUSE Telco Cloud 3.6 , incluidas las extensiones del Dashboard, se distribuyen como artefactos OCI. Para instalar las extensiones SUSE Telco Cloud, puede utilizar la interfaz de usuario de Rancher Dashboard, Helm o Fleet:

7.1.1 Instalación con Rancher Dashboard UI

  1. Haga clic en Extensiones en la sección Configuración de la barra lateral de navegación.

  2. En la página de Extensiones, haga clic en el menú de tres puntos en la parte superior derecha y seleccione Gestionar repositorios.

    Cada extensión se distribuye a través de su propio artefacto OCI. Están disponibles en el repositorio de charts de Helm de SUSE Telco Cloud.

  3. En la página de repositorios, haga clic en Create.

  4. En el formulario, especifique el nombre y la URL del repositorio y haga clic en Create.

    SUSE Telco Cloud URL del repositorio de Helm charts de: oci://registry.suse.com/edge/charts

    dashboard extensions create oci repository
  5. Puede ver que el repositorio de extensiones se ha añadido a la lista y se encuentra en estado Active.

    dashboard extensions repositories list
  6. Vuelva a Extensiones en la sección Configuración de la barra lateral de navegación.

    En la pestaña Disponibles puede ver las extensiones disponibles para su instalación.

    dashboard extensions available extensions
  7. En la tarjeta de la extensión, haga clic en Install y confirme la instalación.

    Una vez instalada la extensión, la interfaz de usuario de Rancher solicita recargar la página como se describe en https://ranchermanager.docs.rancher.com/v2.14/integrations-in-rancher/rancher-extensions#installing-extensions.

7.1.2 Instalación con Helm

# KubeVirt extension
helm install kubevirt-dashboard-extension oci://registry.suse.com/edge/charts/kubevirt-dashboard-extension --version 306.0.4+up1.3.3 --namespace cattle-ui-plugin-system
Nota
Nota

Las extensiones deben instalarse en el espacio de nombres cattle-ui-plugin-system.

Nota
Nota

Después de instalar una extensión, es necesario recargar la interfaz de usuario de Rancher Dashboard.

7.1.3 Instalación con Fleet

La instalación de extensiones de Dashboard con Fleet requiere definir un recurso gitRepo que apunte a un repositorio Git con archivo(s) de configuración de paquete fleet.yaml personalizado(s).

# KubeVirt extension fleet.yaml
defaultNamespace: cattle-ui-plugin-system
helm:
  releaseName: kubevirt-dashboard-extension
  chart: oci://registry.suse.com/edge/charts/kubevirt-dashboard-extension
  version: "306.0.4+up1.3.3"
Nota
Nota

La propiedad releaseName es obligatoria y debe coincidir con el nombre de la extensión para que esta se instale correctamente.

cat <<- EOF | kubectl apply -f -
apiVersion: fleet.cattle.io/v1alpha1
metadata:
  name: edge-dashboard-extensions
  namespace: fleet-local
spec:
  repo: https://github.com/suse-edge/fleet-examples.git
  branch: main
  paths:
  - fleets/kubevirt-dashboard-extension/
EOF

Para obtener más información, consulte Capítulo 9, Fleet y el repositorio fleet-examples.

Una vez instaladas las extensiones, aparecen en la sección Extensiones bajo la pestaña Instaladas. Dado que no se instalan a través de Aplicaciones/Marketplace, están marcadas con la etiqueta Third-Party.

installed dashboard extensions

7.2 Extensión de Dashboard de KubeVirt

La extensión de KubeVirt proporciona una gestión básica de máquinas virtuales para la interfaz de usuario de Rancher Dashboard. Sus capacidades se describen en Sección 19.7.2, “Uso de la extensión de la UI de KubeVirt Rancher”.

8 Rancher Turtles

Consulte la documentación de Rancher Turtles en https://documentation.suse.com/cloudnative/cluster-api/

Rancher Turtles es un operador de Kubernetes que proporciona integración entre Rancher Manager y Cluster API (CAPI) con el objetivo de brindar soporte de CAPI completo a Rancher

8.1 Características clave de Rancher Turtles

  • Importación automática de clústeres CAPI en Rancher mediante la instalación del agente de clúster de Rancher en clústeres aprovisionados por CAPI.

  • Instale y configure las dependencias del controlador CAPI a través del Operador CAPI.

  • Gestione las dependencias instaladas del proveedor CAPI a través de CAPIProvider la API

8.2 Uso de Rancher Turtles en SUSE Telco Cloud

La pila SUSE Telco Cloud proporciona un chart de Helm rancher-turtles-providers que habilita ciertos proveedores CAPI a través de la API CAPIProvider:

  • Proveedor del plano de control e iniciar de RKE2

  • Proveedor de infraestructura Metal3 (Capítulo 11, Metal3)

  • Proveedor de IPAM Metal3 (Capítulo 11, Metal3) (actualmente no es compatible)

  • Proveedor de complementos de Fleet

Solo se admiten los proveedores predeterminados instalados a través del wrapper chart; los proveedores alternativos de plano de control, iniciar e infraestructura no se admiten actualmente como parte de la pila SUSE Telco Cloud.

8.3 Instalación de Rancher Turtles

Desde Rancher 2.13, Rancher Turtles está habilitado de forma predeterminada al instalar Rancher.

Los proveedores de Rancher Turtles pueden instalarse siguiendo la guía Metal3 Quickstart (Capítulo 4, Despliegues automatizados de BMC con Metal3) o la documentación del clúster de gestión (Parte V, “Configuración del clúster de gestión”).

8.4 Recursos adicionales

9 Fleet

Fleet es un motor de gestión y ampliación de contenedores diseñado para ofrecer a los usuarios un mayor control sobre el clúster local y una supervisión constante a través de GitOps. Fleet no solo se centra en la capacidad de escalado, sino que también ofrece a los usuarios un alto grado de control y visibilidad para supervisar exactamente lo que está instalado en el clúster.

Fleet puede gestionar ampliaciones desde Git de YAML de Kubernetes sin procesar, gráficos de Helm, Kustomize o cualquier combinación de los tres. Independientemente de la fuente, todos los recursos se convierten dinámicamente en gráficos de Helm, y Helm se utiliza como motor para desplegar todos los recursos en el clúster. Como resultado, los usuarios pueden disfrutar de un alto grado de control, coherencia y auditabilidad de sus clústeres.

Para obtener información sobre cómo funciona Fleet, consulte Arquitectura de Fleet.

9.1 Instalación de Fleet con Helm

Fleet viene integrado en Rancher, pero también puede instalarse como una aplicación independiente en cualquier clúster de Kubernetes mediante Helm.

9.2 Uso de Fleet con Rancher

Rancher utiliza Fleet para desplegar aplicaciones en clústeres gestionados. La entrega continua con Fleet introduce GitOps a escala, diseñado para gestionar aplicaciones que se ejecutan en un gran número de clústeres.

Fleet destaca como parte integrada de Rancher. Los clústeres gestionados con Rancher obtienen automáticamente el agente de Fleet desplegado como parte del proceso de instalación/importación y el clúster está disponible inmediatamente para ser gestionado por Fleet.

9.3 Acceso a Fleet en la interfaz de usuario de Rancher

Fleet viene preinstalado en Rancher y se gestiona mediante la opción Entrega continua en la interfaz de usuario de Rancher.

fleet dashboard

La sección de Entrega continua consta de los siguientes elementos:

9.3.1 Consola

Una página de resumen de todos los repositorios GitOps en todos los espacios de trabajo. Solo se muestran los espacios de trabajo con repositorios.

9.3.2 Repositorios Git

Una lista de repositorios GitOps en el espacio de trabajo seleccionado. Seleccione el espacio de trabajo activo mediante la lista desplegable en la parte superior de la página.

9.3.3 Clústeres

Una lista de clústeres gestionados. De forma predeterminada, todos los clústeres gestionados por Rancher se añaden al espacio de trabajo fleet-default. El espacio de trabajo fleet-local incluye el clúster local. Desde aquí, es posible Pause o Force update los clústeres o mover el clúster a otro espacio de trabajo. La edición del clúster permite actualizar las etiquetas y anotaciones utilizadas para agrupar los clústeres.

9.3.4 Grupos de clústeres

Esta sección permite la agrupación personalizada de los clústeres dentro del espacio de trabajo mediante selectores.

9.3.5 Avanzadas

La sección «Avanzado» permite gestionar espacios de trabajo y otros recursos de Fleet relacionados.

9.4 Ejemplo de instalación de KubeVirt con Rancher y Fleet mediante el panel de control de Rancher

  1. Cree un repositorio Git que contenga el archivo fleet.yaml:

    defaultNamespace: kubevirt
    helm:
      chart: "oci://registry.suse.com/edge/charts/kubevirt"
      version: "306.0.2+up0.7.0"
      # kubevirt namespace is created by kubevirt as well, we need to take ownership of it
      takeOwnership: true
  2. En el panel de control de Rancher, navegue hasta ☰ > Entrega continua > Repositorios Git y haga clic en Add Repository.

  3. El asistente de creación de repositorios le guía a través de la creación del repositorio Git. Proporcione el Nombre, la URL del repositorio (haciendo referencia al repositorio Git creado en el paso anterior) y seleccione la rama o revisión adecuada. En el caso de un repositorio más complejo, especifique las Vías para utilizar varios directorios en un solo repositorio.

    fleet create repo1
  4. Haga clic en Next.

  5. En el siguiente paso, puede definir dónde se desplegarán las cargas de trabajo. La selección de clústeres ofrece varias opciones básicas: puede no seleccionar ningún clúster, seleccionar todos los clústeres o elegir directamente un clúster gestionado o un grupo de clústeres específico (si está definido). La opción «Avanzado» permite editar directamente los selectores mediante YAML.

    fleet create repo2
  6. Haga clic en Create. El repositorio se crea. A partir de ahora, las cargas de trabajo se instalan y se mantienen sincronizadas en los clústeres que coinciden con la definición del repositorio.

9.5 Depuración y solución de problemas

La sección de navegación «Avanzado» proporciona información general sobre los recursos de Fleet de bajo nivel. Un bundle es un recurso interno utilizado para la orquestación de recursos desde Git. Cuando se escanea un repositorio Git, este produce uno o más bundles.

Para encontrar los bundles relevantes para un repositorio específico, vaya a la página de detalles del repositorio Git y haga clic en la pestaña Bundles.

fleet repo bundles

Para cada clúster, el bundle se aplica a un recurso BundleDeployment que se crea. Para ver los detalles de BundleDeployment, haga clic en el botón Graph en la parte superior derecha de la página de detalles del repositorio Git. Se carga un gráfico de Repo > Bundles > BundleDeployments. Haga clic en el BundleDeployment en el gráfico para ver sus detalles y haga clic en Id para ver el YAML de BundleDeployment.

fleet repo graph

Para obtener información adicional sobre consejos de solución de problemas de Fleet, consulte aquí.

9.6 Ejemplos de Fleet

El equipo de Edge mantiene un repositorio con ejemplos de instalación de proyectos Edge con Fleet.

El proyecto Fleet incluye un repositorio fleet-examples que cubre todos los casos de uso para la estructura del repositorio Git.

10 SUSE Linux Micro

Consultad la documentación oficial de SUSE Linux Micro

SUSE Linux Micro es un sistema operativo ligero y seguro para el edge. Fusiona los componentes empresariales reforzados de SUSE Linux Enterprise con las funciones que los desarrolladores desean en un sistema operativo moderno e inmutable. Como resultado, se obtiene una plataforma de infraestructura fiable con la mejor conformidad normativa y fácil de usar.

10.1 ¿Cómo utiliza SUSE Telco Cloud SUSE Linux Micro?

Utilizamos SUSE Linux Micro como sistema operativo base para nuestra pila de plataforma. Esto nos proporciona una base segura, estable y mínima sobre la que construir.

SUSE Linux Micro es único en su uso de instantáneas del sistema de archivos (Btrfs) para permitir reversiones sencillas en caso de que algo salga mal con una actualización. Esto permite realizar actualizaciones remotas seguras de toda la plataforma incluso sin acceso físico en caso de problemas.

10.2 Prácticas recomendadas

10.2.1 Medios de instalación

SUSE Telco Cloud utiliza el Edge Image Builder (Capítulo 12, Edge Image Builder) para preconfigurar la imagen de instalación auto-instalable de SUSE Linux Micro.

10.2.2 Administración local

SUSE Linux Micro viene con Cockpit para permitir la gestión local del host a través de una aplicación web.

Este servicio está desactivado por defecto, pero puede iniciarse habilitando el servicio systemd cockpit.socket. Como Cockpit prohíbe el inicio de sesión como root por defecto, se recomienda la creación de un usuario con privilegios administrativos; consultad la documentación oficial de SUSE Linux Micro para obtener más información.

10.3 Problemas conocidos

  • Actualmente no hay ningún entorno de escritorio disponible en SUSE Linux Micro, pero se está desarrollando una solución en contenedores.

11 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 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). Esto permite la gestión de recursos de hardware a través de múltiples proveedores de infraestructura mediante API neutrales respecto al proveedor y ampliamente adoptadas. Cluster API utiliza Metal3 como backend de infraestructura para objetos Machine.

11.1 ¿Cómo utiliza SUSE Telco Cloud Metal3?

SUSE Telco Cloud utiliza Metal3 para gestionar el ciclo de vida del hardware físico, como los servidores. El hardware debe admitir un protocolo de gestión fuera de banda compatible con Metal3 (p. ej., Redfish). Cuando un clúster de gestión SUSE Telco Cloud aprovisiona o desaprovisiona clústeres de sentido descendente, Metal3 interactuará con la BMC de un servidor a través de Redfish. Las siguientes acciones suelen formar parte de esta interacción:

  • Montar y desmontar soportes virtuales (Virtual Media).

  • Encender, apagar y reiniciar servidores.

Este enfoque 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.

Metal3 y CAPI proporcionan API declarativas que permiten la gestión del inventario y del estado de servidores de equipo sin sistema operativo, incluyendo la inspección, limpieza y aprovisionamiento/desaprovisionamiento automatizados.

11.2 Problemas conocidos

  • El controlador IP Address Management de sentido ascendente no es compatible actualmente, ya que todavía no es compatible con nuestra elección de herramientas de configuración de red. Sin embargo, el pod ipam-controller-manager alojado en el espacio de nombres metal3-ipam-system es necesario, ya que CAPM3 requiere que existan los CRD ipam.

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

  • Actualmente solo se admite la ampliación mediante redfish-virtualmedia.

12 Edge Image Builder

Consulte el Repositorio oficial.

Edge Image Builder (EIB) es una herramienta que agiliza la generación de imágenes de disco personalizadas y listas para arrancar (CRB) para iniciar máquinas. Estas imágenes permiten la implementación integral de toda la pila de software de SUSE con una sola imagen.

Aunque EIB puede crear imágenes CRB para todos los escenarios de aprovisionamiento, EIB demuestra un valor tremendo en implementaciones en entornos aislados con redes limitadas o completamente aisladas.

12.1 ¿Cómo utiliza SUSE Telco Cloud Edge Image Builder?

SUSE Telco Cloud utiliza EIB para la configuración simplificada y rápida de imágenes personalizadas de SUSE Linux Micro para una variedad de escenarios. Estos escenarios incluyen el inicio de máquinas virtuales y de equipos sin sistema operativo con:

  • Implementaciones totalmente aisladas (air-gapped) de Kubernetes K3s/RKE2 (nodo único y multinodo)

  • Implementaciones totalmente aisladas (air-gapped) de gráficos Helm y manifiestos de Kubernetes

  • Registro en Rancher a través de la API de Elemental

  • Metal3

  • Redes personalizadas (por ejemplo, IP estática, nombre de host, VLAN, bonding, etc.)

  • Configuraciones personalizadas del sistema operativo (por ejemplo, usuarios, grupos, contraseñas, claves SSH, proxies, NTP, certificados SSL personalizados, etc.)

  • Instalación en entorno aislado de paquetes RPM a nivel de host y cargados lateralmente (incluida la resolución de dependencias)

  • Registro en SUSE Multi-Linux Manager para la gestión del SO

  • Imágenes de contenedor integradas

  • Argumentos de la línea de comandos del núcleo de Linux

  • Unidades de systemd que se deben habilitar/deshabilitar en el momento del arranque

  • Guiones y archivos personalizados para cualquier tarea manual

12.2 Introducción

Puede encontrar documentación completa sobre el uso y las pruebas de Edge Image Builder aquí.

Además, consulte Capítulo 5, Clústeres independientes con Edge Image Builder que cubre un escenario de ampliación básico.

Una vez que esté familiarizado con esta herramienta, encontrará información más útil en nuestra página Sección de Consejos y Trucos de EIB (Parte X, “Consejos y trucos”).

12.3 Problemas conocidos

  • EIB aísla los gráficos de Helm mediante la creación de plantillas de los gráficos de Helm y el análisis de todas las imágenes dentro de la plantilla. Si un gráfico de Helm no mantiene todas sus imágenes dentro de la plantilla y, en su lugar, carga las imágenes de forma lateral, EIB no podrá aislar esas imágenes automáticamente. La solución para esto es añadir manualmente cualquier imagen no detectada a la sección embeddedArtifactRegistry del archivo de definición.

13 Redes edge

Esta sección describe el enfoque de la configuración de red en la solución SUSE Telco Cloud. Mostraremos cómo configurar NetworkManager en SUSE Linux Micro de forma declarativa y explicaremos cómo se integran las herramientas relacionadas.

13.1 Visión general de NetworkManager

NetworkManager es una herramienta que gestiona la conexión de red primaria y otras interfaces de conexión.

NetworkManager almacena las configuraciones de red como archivos de conexión que contienen el estado deseado. Estas conexiones se almacenan como archivos en el directorio /etc/NetworkManager/system-connections/.

Puede encontrar detalles sobre NetworkManager en la documentación de SUSE Linux Micro.

13.2 Visión general de nmstate

nmstate es una biblioteca ampliamente adoptada (con una herramienta CLI complementaria) que ofrece una API declarativa para configuraciones de red mediante un esquema predefinido.

Puede encontrar detalles sobre nmstate en la documentación upstream.

13.3 Escriba: Configurador de NetworkManager (nmc)

Las opciones de personalización de red disponibles en SUSE Telco Cloud se consiguen mediante una herramienta CLI llamada Configurador de NetworkManager o nmc para abreviar. Aprovecha la funcionalidad proporcionada por la biblioteca nmstate y, como tal, es totalmente capaz de configurar direcciones IP estáticas, servidores DNS, VLAN, vinculación, puentes, etc. Esta herramienta nos permite generar configuraciones de red a partir de estados deseados predefinidos y aplicarlas en muchos nodos diferentes de forma automatizada.

Puede encontrar detalles sobre el Configurador de NetworkManager (nmc) en el repositorio upstream.

13.4 ¿Cómo utiliza SUSE Telco Cloud el Configurador de NetworkManager?

SUSE Telco Cloud utiliza nmc para las personalizaciones de red en los diversos modelos de aprovisionamiento: * Configuraciones de red personalizadas en los escenarios de aprovisionamiento de red dirigida (Capítulo 4, Despliegues automatizados de BMC con Metal3) * Configuraciones estáticas declarativas en los escenarios de aprovisionamiento basado en imágenes (Capítulo 5, Clústeres independientes con Edge Image Builder)

13.5 Configuración con Edge Image Builder

Edge Image Builder (EIB) es una herramienta que permite configurar varios hosts con una única imagen de SO. En esta sección mostraremos cómo se puede utilizar un enfoque declarativo para describir los estados de red deseados, cómo se convierten en las respectivas conexiones de NetworkManager y cómo se aplican durante el proceso de aprovisionamiento.

13.5.1 Requisitos previos

Si sigue esta guía, se asume que ya dispone de lo siguiente:

  • Un AMD64/Intel 64 host físico (o máquina virtual) que ejecute SLES 15 SP6 o openSUSE Leap 15.6

  • Un entorno de ejecución de contenedor disponible (p. ej., Podman)

  • Una copia de la imagen RAW de SUSE Linux Micro 6.2 que se encuentra aquí

13.5.2 Obtención de la imagen de contenedor de Edge Image Builder

La imagen de contenedor de EIB está disponible públicamente y se puede descargar desde el registro SUSE Telco Cloud ejecutando:

podman pull registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1

13.5.3 Creación del directorio de configuración de la imagen

Empecemos creando el directorio de configuración:

export CONFIG_DIR=$HOME/eib
mkdir -p $CONFIG_DIR/base-images

Ahora nos aseguraremos de que la copia de la imagen base descargada se mueva al directorio de configuración:

mv /path/to/downloads/SL-Micro.x86_64-6.2-Base-GM.raw $CONFIG_DIR/base-images/
Nota
Nota

EIB nunca modificará la entrada de la imagen base. Creará una nueva imagen con sus modificaciones.

El directorio de configuración en este punto debería tener el siguiente aspecto:

└── base-images/
    └── SL-Micro.x86_64-6.2-Base-GM.raw

13.5.4 Creación del archivo de definición de la imagen

El archivo de definición describe la mayoría de las opciones configurables que admite Edge Image Builder.

Empecemos con un archivo de definición muy básico para nuestra imagen de SO:

cat << EOF > $CONFIG_DIR/definition.yaml
apiVersion: 1.3
image:
  arch: x86_64
  imageType: raw
  baseImage: SL-Micro.x86_64-6.2-Base-GM.raw
  outputImageName: modified-image.raw
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
EOF

La sección image es obligatoria y especifica la imagen de entrada, su arquitectura y tipo, así como cómo se llamará la imagen de salida. La sección operatingSystem es opcional y contiene la configuración para habilitar el inicio de sesión en los sistemas aprovisionados con el nombre de usuario/contraseña root/eib.

Nota
Nota

Siéntase libre de usar su propia contraseña cifrada ejecutando openssl passwd -6 <password>.

El directorio de configuración en este punto debería tener el siguiente aspecto:

├── definition.yaml
└── base-images/
    └── SL-Micro.x86_64-6.2-Base-GM.raw

13.5.5 Definición de las configuraciones de red

Las configuraciones de red deseadas no forman parte del archivo de definición de imagen que acabamos de crear. Ahora poblaremos esas bajo el directorio especial network/. Creémoslo:

mkdir -p $CONFIG_DIR/network

Como se mencionó anteriormente, la herramienta NetworkManager Configurator (nmc) espera una entrada en forma de esquema predefinido. Puedes encontrar cómo configurar una amplia variedad de opciones de red en la documentación de ejemplos upstream de NMState.

Esta guía explicará cómo configurar la red en tres nodos diferentes:

  • Un nodo que utiliza dos interfaces Ethernet

  • Un nodo que utiliza vinculación de interfaces de red

  • Un nodo que utiliza un puente de red (bridge)

Aviso
Aviso

No se recomienda utilizar configuraciones de red completamente diferentes en compilaciones de producción, especialmente si se configuran clústeres de Kubernetes. Las configuraciones de red generalmente deben ser homogéneas entre los nodos o, al menos, entre los roles dentro de un clúster determinado. Esta guía incluye varias opciones diferentes solo para servir como referencia de ejemplo.

Nota
Nota

Lo siguiente asume una libvirt red predeterminada con un rango de direcciones IP 192.168.122.1/24. Ajuste en consecuencia si esto difiere en su entorno.

Creemos los estados deseados para el primer nodo al que llamaremos node1.suse.com:

cat << EOF > $CONFIG_DIR/network/node1.suse.com.yaml
routes:
  config:
    - destination: 0.0.0.0/0
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: eth0
      table-id: 254
    - destination: 192.168.122.0/24
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: eth0
      table-id: 254
dns-resolver:
  config:
    server:
      - 192.168.122.1
      - 8.8.8.8
interfaces:
  - name: eth0
    type: ethernet
    state: up
    mac-address: 34:8A:B1:4B:16:E1
    ipv4:
      address:
        - ip: 192.168.122.50
          prefix-length: 24
      dhcp: false
      enabled: true
    ipv6:
      enabled: false
  - name: eth3
    type: ethernet
    state: down
    mac-address: 34:8A:B1:4B:16:E2
    ipv4:
      address:
        - ip: 192.168.122.55
          prefix-length: 24
      dhcp: false
      enabled: true
    ipv6:
      enabled: false
EOF

En este ejemplo definimos un estado deseado de dos interfaces Ethernet (eth0 y eth3), sus direcciones IP solicitadas, el enrutamiento y la resolución DNS.

Aviso
Aviso

Debe asegurarse de que las direcciones MAC de todas las interfaces Ethernet estén enumeradas. Estas se utilizan durante el proceso de aprovisionamiento como identificadores de los nodos y sirven para determinar qué configuraciones deben aplicarse. Así es como podemos configurar múltiples nodos utilizando una única imagen ISO o RAW.

A continuación, el segundo nodo, al que llamaremos node2.suse.com y que utilizará vinculación de interfaces de red:

cat << EOF > $CONFIG_DIR/network/node2.suse.com.yaml
routes:
  config:
    - destination: 0.0.0.0/0
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: bond99
      table-id: 254
    - destination: 192.168.122.0/24
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: bond99
      table-id: 254
dns-resolver:
  config:
    server:
      - 192.168.122.1
      - 8.8.8.8
interfaces:
  - name: bond99
    type: bond
    state: up
    ipv4:
      address:
        - ip: 192.168.122.60
          prefix-length: 24
      enabled: true
    link-aggregation:
      mode: balance-rr
      options:
        miimon: '140'
      port:
        - eth0
        - eth1
  - name: eth0
    type: ethernet
    state: up
    mac-address: 34:8A:B1:4B:16:E3
    ipv4:
      enabled: false
    ipv6:
      enabled: false
  - name: eth1
    type: ethernet
    state: up
    mac-address: 34:8A:B1:4B:16:E4
    ipv4:
      enabled: false
    ipv6:
      enabled: false
EOF

En este ejemplo definimos un estado deseado de dos interfaces Ethernet (eth0 y eth1) que no habilitan el direccionamiento IP, así como una vinculación con una directiva round-robin y su dirección respectiva que se utilizará para reenviar el tráfico de red.

Por último, crearemos el tercer y último archivo de estado deseado que utilizará un puente de red y al que llamaremos node3.suse.com:

cat << EOF > $CONFIG_DIR/network/node3.suse.com.yaml
routes:
  config:
    - destination: 0.0.0.0/0
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: linux-br0
      table-id: 254
    - destination: 192.168.122.0/24
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: linux-br0
      table-id: 254
dns-resolver:
  config:
    server:
      - 192.168.122.1
      - 8.8.8.8
interfaces:
  - name: eth0
    type: ethernet
    state: up
    mac-address: 34:8A:B1:4B:16:E5
    ipv4:
      enabled: false
    ipv6:
      enabled: false
  - name: linux-br0
    type: linux-bridge
    state: up
    ipv4:
      address:
        - ip: 192.168.122.70
          prefix-length: 24
      dhcp: false
      enabled: true
    bridge:
      options:
        group-forward-mask: 0
        mac-ageing-time: 300
        multicast-snooping: true
        stp:
          enabled: true
          forward-delay: 15
          hello-time: 2
          max-age: 20
          priority: 32768
      port:
        - name: eth0
          stp-hairpin-mode: false
          stp-path-cost: 100
          stp-priority: 32
EOF

El directorio de configuración en este punto debería tener el siguiente aspecto:

├── definition.yaml
├── network/
│   │── node1.suse.com.yaml
│   │── node2.suse.com.yaml
│   └── node3.suse.com.yaml
└── base-images/
    └── SL-Micro.x86_64-6.2-Base-GM.raw
Nota
Nota

Los nombres de los archivos en el directorio network/ son intencionados. Corresponden a los nombres de host que se establecerán durante el proceso de aprovisionamiento.

13.5.6 Creación de la imagen del SO

Ahora que todas las configuraciones necesarias están listas, podemos crear la imagen simplemente ejecutando:

podman run --rm -it -v $CONFIG_DIR:/eib registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 build --definition-file definition.yaml

La salida debería ser similar a la siguiente:

Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Rpm .......................... [SKIPPED]
Systemd ...................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Embedded Artifact Registry ... [SKIPPED]
Keymap ....................... [SUCCESS]
Kubernetes ................... [SKIPPED]
Certificates ................. [SKIPPED]
Building RAW image...
Kernel Params ................ [SKIPPED]
Image build complete!

El fragmento anterior nos indica que el componente Network se ha configurado correctamente y podemos proceder con el aprovisionamiento de nuestros nodos periféricos.

Nota
Nota

Se puede inspeccionar un archivo de registro (network-config.log) y los respectivos archivos de conexión de NetworkManager en el directorio _build resultante, dentro de un directorio con marca de tiempo para la ejecución de la imagen.

13.5.7 Aprovisionamiento de los nodos periféricos

Vamos a copiar la imagen RAW resultante:

mkdir edge-nodes && cd edge-nodes
for i in {1..4}; do cp $CONFIG_DIR/modified-image.raw node$i.raw; done

Notará que hemos copiado la imagen creada cuatro veces, pero solo hemos especificado las configuraciones de red para tres nodos. Esto es porque también queremos mostrar qué sucederá si aprovisionamos un nodo que no coincide con ninguna de las configuraciones deseadas.

Nota
Nota

Esta guía utilizará virtualización para los ejemplos de aprovisionamiento de nodos. Asegúrese de que las extensiones necesarias estén habilitadas en el BIOS (consulte aquí para obtener más detalles).

Utilizaremos virt-install para crear máquinas virtuales usando los discos raw copiados. Cada máquina virtual utilizará 10 GB de RAM y 6 vCPUs.

13.5.7.1 Aprovisionamiento del primer nodo

Creemos la máquina virtual:

virt-install --name node1 --ram 10000 --vcpus 6 --disk path=node1.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default,mac=34:8A:B1:4B:16:E1 --network default,mac=34:8A:B1:4B:16:E2 --virt-type kvm --import
Nota
Nota

Es importante crear las interfaces de red con las mismas direcciones MAC que las del estado deseado descrito anteriormente.

Una vez completada la operación, se observará algo similar a lo siguiente:

Starting install...
Creating domain...

Running text console command: virsh --connect qemu:///system console node1
Connected to domain 'node1'
Escape character is ^] (Ctrl + ])


Welcome to SUSE Linux Micro 6.0 (x86_64) - Kernel 6.4.0-18-default (tty1).

SSH host key: SHA256:XN/R5Tw43reG+QsOw480LxCnhkc/1uqMdwlI6KUBY70 (RSA)
SSH host key: SHA256:/96yGrPGKlhn04f1rb9cXv/2WJt4TtrIN5yEcN66r3s (DSA)
SSH host key: SHA256:Dy/YjBQ7LwjZGaaVcMhTWZNSOstxXBsPsvgJTJq5t00 (ECDSA)
SSH host key: SHA256:TNGqY1LRddpxD/jn/8dkT/9YmVl9hiwulqmayP+wOWQ (ED25519)
eth0: 192.168.122.50
eth1:


Configured with the Edge Image Builder
Activate the web console with: systemctl enable --now cockpit.socket

node1 login:

Ahora puede iniciar sesión con el par de credenciales root:eib. También se puede acceder al host por SSH si se prefiere ello a la virsh console que se presenta aquí.

Una vez iniciada la sesión, confirme que todos los ajustes están en su lugar.

Verifique que el nombre de host esté configurado correctamente:

node1:~ # hostnamectl
 Static hostname: node1.suse.com
 ...

Verifique que el enrutamiento esté configurado correctamente:

node1:~ # ip r
default via 192.168.122.1 dev eth0 proto static metric 100
192.168.122.0/24 dev eth0 proto static scope link metric 100
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.50 metric 100

Verifique que la conexión a Internet esté disponible:

node1:~ # ping google.com
PING google.com (142.250.72.78) 56(84) bytes of data.
64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=1 ttl=56 time=13.2 ms
64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=2 ttl=56 time=13.4 ms
^C
--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 13.248/13.304/13.361/0.056 ms

Verifique que haya exactamente dos interfaces Ethernet configuradas y que solo una de ellas esté activa:

node1:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e1 brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
    inet 192.168.122.50/24 brd 192.168.122.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e2 brd ff:ff:ff:ff:ff:ff
    altname enp0s3
    altname ens3

node1:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME  UUID                                  TYPE      DEVICE  FILENAME
eth0  dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0    /etc/NetworkManager/system-connections/eth0.nmconnection
eth1  7e211aea-3d14-59cf-a4fa-be91dac5dbba  ethernet  --      /etc/NetworkManager/system-connections/eth1.nmconnection

Notará que la segunda interfaz de red es eth1 en lugar de la eth3 predefinida en nuestro estado de red deseado. Esto sucede porque el Configurador de NetworkManager (nmc) es capaz de detectar que el sistema operativo ha asignado un nombre distinto a la NIC con la dirección MAC 34:8a:b1:4b:16:e2 y ajusta su configuración en consecuencia.

Verifique que esto ha ocurrido realmente inspeccionando la fase de combustión del aprovisionamiento:

node1:~ # journalctl -u combustion | grep nmc
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Identified host: node1.suse.com
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Set hostname: node1.suse.com
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Processing interface 'eth0'...
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Processing interface 'eth3'...
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Using interface name 'eth1' instead of the preconfigured 'eth3'
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc] Successfully applied config

Aprovisione ahora el resto de los nodos, pero se mostrarán únicamente las diferencias en la configuración final. Sentíos libres de aplicar cualquiera o todas las comprobaciones anteriores para todos los nodos que vais a aprovisionar.

13.5.7.2 Aprovisionamiento del segundo nodo

Vamos a crear la máquina virtual:

virt-install --name node2 --ram 10000 --vcpus 6 --disk path=node2.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default,mac=34:8A:B1:4B:16:E3 --network default,mac=34:8A:B1:4B:16:E4 --virt-type kvm --import

Una vez que la máquina virtual esté en funcionamiento, podemos confirmar que este nodo utiliza una interfaz de enlace:

node2:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond99 state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e3 brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
3: eth1: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond99 state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e3 brd ff:ff:ff:ff:ff:ff permaddr 34:8a:b1:4b:16:e4
    altname enp0s3
    altname ens3
4: bond99: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.60/24 brd 192.168.122.255 scope global noprefixroute bond99
       valid_lft forever preferred_lft forever

Confirma que el enrutamiento está utilizando el enlace:

node2:~ # ip r
default via 192.168.122.1 dev bond99 proto static metric 100
192.168.122.0/24 dev bond99 proto static scope link metric 100
192.168.122.0/24 dev bond99 proto kernel scope link src 192.168.122.60 metric 300

Asegúrate de que los archivos de conexión estática se utilicen correctamente:

node2:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME    UUID                                  TYPE      DEVICE  FILENAME
bond99  4a920503-4862-5505-80fd-4738d07f44c6  bond      bond99  /etc/NetworkManager/system-connections/bond99.nmconnection
eth0    dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0    /etc/NetworkManager/system-connections/eth0.nmconnection
eth1    0523c0a1-5f5e-5603-bcf2-68155d5d322e  ethernet  eth1    /etc/NetworkManager/system-connections/eth1.nmconnection

13.5.7.3 Aprovisionamiento del tercer nodo

Vamos a crear la máquina virtual:

virt-install --name node3 --ram 10000 --vcpus 6 --disk path=node3.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default,mac=34:8A:B1:4B:16:E5 --virt-type kvm --import

Una vez que la máquina virtual esté en funcionamiento, podemos confirmar que este nodo está utilizando un puente de red:

node3:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master linux-br0 state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e5 brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
3: linux-br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.70/24 brd 192.168.122.255 scope global noprefixroute linux-br0
       valid_lft forever preferred_lft forever

Confirma que el enrutamiento está utilizando el puente:

node3:~ # ip r
default via 192.168.122.1 dev linux-br0 proto static metric 100
192.168.122.0/24 dev linux-br0 proto static scope link metric 100
192.168.122.0/24 dev linux-br0 proto kernel scope link src 192.168.122.70 metric 425

Asegúrate de que los archivos de conexión estática se utilicen correctamente:

node3:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME       UUID                                  TYPE      DEVICE     FILENAME
linux-br0  1f8f1469-ed20-5f2c-bacb-a6767bee9bc0  bridge    linux-br0  /etc/NetworkManager/system-connections/linux-br0.nmconnection
eth0       dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0       /etc/NetworkManager/system-connections/eth0.nmconnection

13.5.7.4 Aprovisionamiento del cuarto nodo

Por último, aprovisionaremos un nodo que no coincidirá con ninguna de las configuraciones predefinidas por dirección MAC. En estos casos, utilizaremos DHCP por defecto para configurar las interfaces de red.

Vamos a crear la máquina virtual:

virt-install --name node4 --ram 10000 --vcpus 6 --disk path=node4.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default --virt-type kvm --import

Una vez que la máquina virtual esté en funcionamiento, podemos confirmar que este nodo está utilizando una dirección IP aleatoria para su interfaz de red:

localhost:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:56:63:71 brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
    inet 192.168.122.86/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0
       valid_lft 3542sec preferred_lft 3542sec
    inet6 fe80::5054:ff:fe56:6371/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

Verifica que nmc no pudo aplicar las configuraciones estáticas para este nodo:

localhost:~ # journalctl -u combustion | grep nmc
Apr 23 12:15:45 localhost.localdomain combustion[1357]: [2024-04-23T12:15:45Z ERROR nmc] Applying config failed: None of the preconfigured hosts match local NICs

Verifica que la interfaz Ethernet se configuró mediante DHCP:

localhost:~ # journalctl | grep eth0
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7801] manager: (eth0): new Ethernet device (/org/freedesktop/NetworkManager/Devices/2)
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7802] device (eth0): state change: unmanaged -> unavailable (reason 'managed', sys-iface-state: 'external')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7929] device (eth0): carrier: link connected
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7931] device (eth0): state change: unavailable -> disconnected (reason 'carrier-changed', sys-iface-state: 'managed')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7944] device (eth0): Activation: starting connection 'Wired Connection' (300ed658-08d4-4281-9f8c-d1b8882d29b9)
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7945] device (eth0): state change: disconnected -> prepare (reason 'none', sys-iface-state: 'managed')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7947] device (eth0): state change: prepare -> config (reason 'none', sys-iface-state: 'managed')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7953] device (eth0): state change: config -> ip-config (reason 'none', sys-iface-state: 'managed')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7964] dhcp4 (eth0): activation: beginning transaction (timeout in 90 seconds)
Apr 23 12:15:33 localhost.localdomain NetworkManager[704]: <info>  [1713874533.1272] dhcp4 (eth0): state changed new lease, address=192.168.122.86

localhost:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME              UUID                                  TYPE      DEVICE  FILENAME
Wired Connection  300ed658-08d4-4281-9f8c-d1b8882d29b9  ethernet  eth0    /var/run/NetworkManager/system-connections/default_connection.nmconnection

13.5.8 Configuraciones de nodo unificadas

Hay ocasiones en las que depender de direcciones MAC conocidas no es una opción. En estos casos podemos optar por la denominada configuración unificada que nos permite especificar ajustes en un archivo _all.yaml que luego se aplicarán a todos los nodos aprovisionados.

Construiremos y aprovisionaremos un nodo edge utilizando una estructura de configuración diferente. Sigue todos los pasos desde Sección 13.5.3, “Creación del directorio de configuración de la imagen” hasta Sección 13.5.5, “Definición de las configuraciones de red”.

En este ejemplo definimos un estado deseado de dos interfaces Ethernet (eth0 y eth1): una utilizando DHCP y otra con una dirección IP estática asignada.

mkdir -p $CONFIG_DIR/network

cat <<- EOF > $CONFIG_DIR/network/_all.yaml
interfaces:
- name: eth0
  type: ethernet
  state: up
  ipv4:
    dhcp: true
    enabled: true
  ipv6:
    enabled: false
- name: eth1
  type: ethernet
  state: up
  ipv4:
    address:
    - ip: 10.0.0.1
      prefix-length: 24
    enabled: true
    dhcp: false
  ipv6:
    enabled: false
EOF

Vamos a construir la imagen:

podman run --rm -it -v $CONFIG_DIR:/eib registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 build --definition-file definition.yaml

Una vez que la imagen se haya construido correctamente, vamos a crear una máquina virtual utilizándola:

virt-install --name node1 --ram 10000 --vcpus 6 --disk path=$CONFIG_DIR/modified-image.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default --network default --virt-type kvm --import

El proceso de aprovisionamiento puede tardar unos minutos. Una vez finalizado, iniciad sesión en el sistema con las credenciales proporcionadas.

Verificad que el enrutamiento esté configurado correctamente:

localhost:~ # ip r
default via 192.168.122.1 dev eth0 proto dhcp src 192.168.122.100 metric 100
10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.1 metric 101
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.100 metric 100

Verificad que la conexión a Internet esté disponible:

localhost:~ # ping google.com
PING google.com (142.250.72.46) 56(84) bytes of data.
64 bytes from den16s08-in-f14.1e100.net (142.250.72.46): icmp_seq=1 ttl=56 time=14.3 ms
64 bytes from den16s08-in-f14.1e100.net (142.250.72.46): icmp_seq=2 ttl=56 time=14.2 ms
^C
--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 14.196/14.260/14.324/0.064 ms

Verificad que las interfaces Ethernet estén configuradas y activas:

localhost:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:26:44:7a brd ff:ff:ff:ff:ff:ff
    altname enp1s0
    inet 192.168.122.100/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0
       valid_lft 3505sec preferred_lft 3505sec
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:ec:57:9e brd ff:ff:ff:ff:ff:ff
    altname enp7s0
    inet 10.0.0.1/24 brd 10.0.0.255 scope global noprefixroute eth1
       valid_lft forever preferred_lft forever

localhost:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME  UUID                                  TYPE      DEVICE  FILENAME
eth0  dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0    /etc/NetworkManager/system-connections/eth0.nmconnection
eth1  0523c0a1-5f5e-5603-bcf2-68155d5d322e  ethernet  eth1    /etc/NetworkManager/system-connections/eth1.nmconnection

localhost:~ # cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
autoconnect=true
autoconnect-slaves=-1
id=eth0
interface-name=eth0
type=802-3-ethernet
uuid=dfd202f5-562f-5f07-8f2a-a7717756fb70

[ipv4]
dhcp-client-id=mac
dhcp-send-hostname=true
dhcp-timeout=2147483647
ignore-auto-dns=false
ignore-auto-routes=false
method=auto
never-default=false

[ipv6]
addr-gen-mode=0
dhcp-timeout=2147483647
method=disabled

localhost:~ # cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
autoconnect=true
autoconnect-slaves=-1
id=eth1
interface-name=eth1
type=802-3-ethernet
uuid=0523c0a1-5f5e-5603-bcf2-68155d5d322e

[ipv4]
address0=10.0.0.1/24
dhcp-timeout=2147483647
method=manual

[ipv6]
addr-gen-mode=0
dhcp-timeout=2147483647
method=disabled

13.5.9 Configuraciones de red personalizadas

Ya hemos cubierto la configuración de red predeterminada para Edge Image Builder, que depende de NetworkManager Configurator. Sin embargo, también existe la opción de modificarla mediante un guion personalizado. Aunque esta opción es muy flexible y tampoco depende de la dirección MAC, su limitación radica en el hecho de que utilizarla es mucho menos cómodo al arrancar múltiples nodos con una única imagen.

Nota
Nota

Se recomienda utilizar la configuración de red predeterminada mediante archivos que describan los estados de red deseados en el directorio /network. Optad por el scripting personalizado solo cuando ese comportamiento no sea aplicable a vuestro caso de uso.

Construiremos y aprovisionaremos un nodo edge utilizando una estructura de configuración diferente. Sigue todos los pasos desde Sección 13.5.3, “Creación del directorio de configuración de la imagen” hasta Sección 13.5.5, “Definición de las configuraciones de red”.

En este ejemplo, crearemos un guion personalizado que aplique una configuración estática para la interfaz eth0 en todos los nodos aprovisionados, además de eliminar y deshabilitar las conexiones cableadas creadas automáticamente por NetworkManager. Esto resulta beneficioso en situaciones en las que se desea asegurar que cada nodo del clúster tenga una configuración de red idéntica y, por tanto, no es necesario preocuparse por la dirección MAC de cada nodo antes de la creación de la imagen.

Empecemos almacenando el archivo de conexión en el directorio /custom/files:

mkdir -p $CONFIG_DIR/custom/files

cat << EOF > $CONFIG_DIR/custom/files/eth0.nmconnection
[connection]
autoconnect=true
autoconnect-slaves=-1
autoconnect-retries=1
id=eth0
interface-name=eth0
type=802-3-ethernet
uuid=dfd202f5-562f-5f07-8f2a-a7717756fb70
wait-device-timeout=60000

[ipv4]
dhcp-timeout=2147483647
method=auto

[ipv6]
addr-gen-mode=eui64
dhcp-timeout=2147483647
method=disabled
EOF

Ahora que la configuración estática está creada, también crearemos nuestro guion de red personalizado:

mkdir -p $CONFIG_DIR/network

cat << EOF > $CONFIG_DIR/network/configure-network.sh
#!/bin/bash
set -eux

# Remove and disable wired connections
mkdir -p /etc/NetworkManager/conf.d/
printf "[main]\nno-auto-default=*\n" > /etc/NetworkManager/conf.d/no-auto-default.conf
rm -f /var/run/NetworkManager/system-connections/* || true

# Copy pre-configured network configuration files into NetworkManager
mkdir -p /etc/NetworkManager/system-connections/
cp eth0.nmconnection /etc/NetworkManager/system-connections/
chmod 600 /etc/NetworkManager/system-connections/*.nmconnection
EOF

chmod a+x $CONFIG_DIR/network/configure-network.sh
Nota
Nota

El binario nmc seguirá incluyéndose por defecto, por lo que también puede utilizarse en el guion configure-network.sh si fuera necesario.

Aviso
Aviso

El guion personalizado debe proporcionarse siempre en /network/configure-network.sh dentro del directorio de configuración. Si está presente, se ignorarán todos los demás archivos. NO es posible configurar una red trabajando simultáneamente con configuraciones estáticas en formato YAML y un script personalizado.

El directorio de configuración en este punto debería tener el siguiente aspecto:

├── definition.yaml
├── custom/
│   └── files/
│       └── eth0.nmconnection
├── network/
│   └── configure-network.sh
└── base-images/
    └── SL-Micro.x86_64-6.2-Base-GM.raw

Vamos a construir la imagen:

podman run --rm -it -v $CONFIG_DIR:/eib registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 build --definition-file definition.yaml

Una vez que la imagen se haya construido correctamente, vamos a crear una máquina virtual utilizándola:

virt-install --name node1 --ram 10000 --vcpus 6 --disk path=$CONFIG_DIR/modified-image.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default --virt-type kvm --import

El proceso de aprovisionamiento puede tardar unos minutos. Una vez finalizado, iniciad sesión en el sistema con las credenciales proporcionadas.

Verificad que el enrutamiento esté configurado correctamente:

localhost:~ # ip r
default via 192.168.122.1 dev eth0 proto dhcp src 192.168.122.185 metric 100
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.185 metric 100

Verificad que la conexión a Internet esté disponible:

localhost:~ # ping google.com
PING google.com (142.250.72.78) 56(84) bytes of data.
64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=1 ttl=56 time=13.6 ms
64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=2 ttl=56 time=13.6 ms
^C
--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 13.592/13.599/13.606/0.007 ms

Verificad que una interfaz Ethernet esté configurada estáticamente utilizando nuestro archivo de conexión y que esté activa:

localhost:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:31:d0:1b brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
    inet 192.168.122.185/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0

localhost:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME  UUID                                  TYPE      DEVICE  FILENAME
eth0  dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0    /etc/NetworkManager/system-connections/eth0.nmconnection

localhost:~ # cat  /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
autoconnect=true
autoconnect-slaves=-1
autoconnect-retries=1
id=eth0
interface-name=eth0
type=802-3-ethernet
uuid=dfd202f5-562f-5f07-8f2a-a7717756fb70
wait-device-timeout=60000

[ipv4]
dhcp-timeout=2147483647
method=auto

[ipv6]
addr-gen-mode=eui64
dhcp-timeout=2147483647
method=disabled

14 RKE2

Consulte la documentación oficial de RKE2.

RKE2 es una distribución de Kubernetes totalmente conforme que se centra en la seguridad y el cumplimiento mediante:

  • Proporcionando opciones predeterminadas y de configuración que permiten a los clústeres pasar el benchmark CIS de Kubernetes v1.6 o v1.23 con una mínima intervención del operador

  • Habilitando el cumplimiento de FIPS 140-2

  • Analizando periódicamente los componentes en busca de CVEs mediante trivy en la canalización de compilación de RKE2

RKE2 lanza los componentes del plano de control como pods estáticos, gestionados por kubelet. El entorno de ejecución de contenedor integrado es containerd.

Nota: RKE2 también se conoce como RKE Government para transmitir otro caso de uso y sector al que se dirige actualmente.

14.1 RKE2 vs K3s

K3s es una distribución de Kubernetes totalmente conforme y ligera, centrada en Edge, IoT y en la familia de arquitecturas ARM, optimizada para facilitar su uso y para entornos con recursos limitados

RKE2 combina lo mejor de ambos mundos de la versión 1.x de RKE (en adelante denominada RKE1) y K3s.

De K3s, hereda la facilidad de uso, la sencillez de funcionamiento y el modelo de despliegue.

De RKE1, hereda una estrecha alineación con Kubernetes upstream. En algunos aspectos, K3s se ha desviado de Kubernetes upstream para optimizar despliegues en edge, pero RKE1 y RKE2 pueden mantenerse estrechamente alineados con upstream

14.2 ¿Cómo utiliza SUSE Telco Cloud RKE2?

RKE2 es una pieza fundamental de la pila SUSE Telco Cloud. Se asienta sobre SUSE Linux Micro (Capítulo 10, SUSE Linux Micro), proporcionando una interfaz de Kubernetes estándar necesaria para desplegar cargas de trabajo de Edge.

14.3 Prácticas recomendadas

14.3.1 Instalación

La forma recomendada de instalar RKE2 como parte de la pila SUSE Telco Cloud es mediante el uso de Edge Image Builder (EIB). Consulte la documentación de EIB (Capítulo 12, Edge Image Builder) para obtener más detalles sobre cómo configurarlo para desplegar RKE2.

EIB es lo suficientemente flexible como para admitir cualquier parámetro requerido por RKE2, como especificar la versión de RKE2, la configuración de los servidores o de los agentes, cubriendo todos los casos de uso de Edge.

Para otros casos de uso que involucran a Metal3, RKE2 también se está utilizando e instalando. En esos casos particulares, el Cluster API Provider RKE2 despliega automáticamente RKE2 en los clústeres que se están aprovisionando con Metal3 utilizando la pila Edge.

En esos casos, la configuración de RKE2 debe aplicarse en los diferentes CRDs involucrados. Un ejemplo de cómo proporcionar una CNI diferente utilizando el CRD RKE2ControlPlane es el siguiente:

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  serverConfig:
    cni: calico
    cniMultusEnable: true
...

Para más información sobre los casos de uso de Metal3, consulte Capítulo 11, Metal3.

14.3.2 Gran disponibilidad

Para despliegues de alta disponibilidad, EIB despliega y configura automáticamente MetalLB (Capítulo 17, MetalLB) y el Endpoint Copier Operator (Capítulo 18, Operador de Endpoint Copier) para exponer el punto de conexión de la API de RKE2 externamente.

14.3.3 Conectividad

La pila SUSE Telco Cloud admite Cilium, Calico, siendo Cilium su CNI predeterminado. También se puede utilizar el metaplugin Multus cuando los pods requieran múltiples interfaces de red. RKE2 independiente admite una gama más amplia de opciones de CNI.

14.3.4 Almacenamiento

RKE2 no proporciona ningún tipo de clase de almacenamiento persistente ni operadores. Para clústeres que abarcan varios nodos, se recomienda utilizar SUSE Storage (Capítulo 15, SUSE Storage).

SUSE Storage es un sistema de almacenamiento distribuido en bloques ligero, fiable y fácil de usar diseñado para Kubernetes. Es un producto basado en Longhorn, un proyecto de código abierto desarrollado inicialmente por Rancher Labs y actualmente incubado bajo la CNCF.

15.1 Requisitos previos

Si estáis siguiendo esta guía, se asume que ya disponéis de lo siguiente:

  • Al menos un host con SUSE Linux Micro 6.2 instalado; puede ser físico o virtual

  • Un clúster de Kubernetes instalado; ya sea K3s o RKE2

  • Helm

15.2 Instalación manual de SUSE Storage

15.2.1 Instalación de Open-iSCSI

Un requisito fundamental para desplegar y utilizar SUSE Storage es la instalación del paquete open-iscsi y que el daemon iscsid se ejecute en todos los nodos de Kubernetes. Esto es necesario, ya que Longhorn depende de iscsiadm en el host para proporcionar volúmenes persistentes a Kubernetes.

Vamos a instalarlo:

transactional-update pkg install open-iscsi

Es importante señalar que, una vez completada la operación, el paquete solo se instala en una nueva instantánea, ya que SUSE Linux Micro es un sistema operativo inmutable. Para cargarlo y que el daemon iscsid comience a ejecutarse, debemos reiniciar en esa nueva instantánea que acabamos de crear. Ejecutad el comando de reinicio cuando estéis listos:

reboot
Sugerencia
Sugerencia

Para obtener ayuda adicional sobre la instalación de open-iscsi, consultad la documentación oficial de Longhorn.

15.2.2 Instalación de SUSE Storage

Existen varias formas de instalar SUSE Storage en vuestros clústeres de Kubernetes. Esta guía seguirá la instalación mediante Helm; no obstante, sentíos libres de seguir la documentación oficial si deseáis utilizar otro enfoque.

  1. Iniciad sesión en la colección de aplicaciones de Rancher:

    helm registry login dp.apps.rancher.io --username $APPS.RANCHER.IO_USERNAME --password $APPS.RANCHER.IO_ACCESS_TOKEN
  2. Instalad SUSE Storage en el espacio de nombres longhorn-system y añadid vuestras credenciales del registro de contenedores:

    helm install longhorn oci://dp.apps.rancher.io/charts/suse-storage \
      --version 1.11.2 \
      --namespace longhorn-system \
      --create-namespace \
      --set privateRegistry.createSecret=true \
      --set privateRegistry.registryUrl=dp.apps.rancher.io \
      --set privateRegistry.registryUser=$APPS.RANCHER.IO_USERNAME \
      --set privateRegistry.registryPasswd=$APPS.RANCHER.IO_ACCESS_TOKEN \
      --set privateRegistry.registrySecret=application-collection
  3. Confirmad que el despliegue se ha realizado correctamente:

    kubectl -n longhorn-system get pods
    localhost:~ # kubectl -n longhorn-system get pods
    NAME                                                READY   STATUS    RESTARTS        AGE
    csi-attacher-7656559cf4-pkhh6                       1/1     Running   0               103s
    csi-attacher-7656559cf4-pnzw5                       1/1     Running   0               103s
    csi-attacher-7656559cf4-z94mm                       1/1     Running   0               103s
    csi-provisioner-6d9cf6456d-kcwtq                    1/1     Running   0               103s
    csi-provisioner-6d9cf6456d-mvvml                    1/1     Running   0               103s
    csi-provisioner-6d9cf6456d-q4f88                    1/1     Running   0               103s
    csi-resizer-f587cd467-clr2n                         1/1     Running   0               103s
    csi-resizer-f587cd467-z28v4                         1/1     Running   0               103s
    csi-resizer-f587cd467-zxmtx                         1/1     Running   0               103s
    csi-snapshotter-6dcdf78684-757mg                    1/1     Running   0               103s
    csi-snapshotter-6dcdf78684-8ktgc                    1/1     Running   0               103s
    csi-snapshotter-6dcdf78684-ffsqr                    1/1     Running   0               103s
    engine-image-ei-099f845a-lvdtr                      1/1     Running   0               2m21s
    instance-manager-4adffddaffe02374cd5635b8a6113de7   1/1     Running   0               111s
    longhorn-csi-plugin-w7pwr                           3/3     Running   0               103s
    longhorn-driver-deployer-6886fb84bc-wm9h6           1/1     Running   2 (2m32s ago)   2m45s
    longhorn-manager-zblbl                              2/2     Running   0               2m45s
    longhorn-ui-6bcc65d4bd-mcn6r                        1/1     Running   0               2m45s
    longhorn-ui-6bcc65d4bd-rwf97                        1/1     Running   0               2m45s

15.3 Creación de volúmenes de SUSE Storage

SUSE Storage utiliza recursos de Kubernetes llamados StorageClass para aprovisionar automáticamente objetos PersistentVolume para los pods. Pensad en StorageClass como una forma en que los administradores describen las clases o perfiles de almacenamiento que ofrecen.

Vamos a crear un StorageClass con algunas opciones predeterminadas:

kubectl apply -f - <<EOF
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: longhorn-example
provisioner: driver.longhorn.io
allowVolumeExpansion: true
parameters:
  numberOfReplicas: "3"
  staleReplicaTimeout: "2880" # 48 hours in minutes
  fromBackup: ""
  fsType: "ext4"
EOF

Ahora que tenemos nuestro StorageClass en su lugar, necesitamos un PersistentVolumeClaim que haga referencia a él. Una PersistentVolumeClaim (PVC) es una solicitud de almacenamiento por parte de un usuario. Los PVC consumen recursos PersistentVolume. Las reclamaciones pueden solicitar tamaños y modos de acceso específicos (por ejemplo, pueden montarse una vez en lectura-escritura o muchas veces en solo lectura).

Vamos a crear una PersistentVolumeClaim:

kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: longhorn-volv-pvc
  namespace: longhorn-system
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn-example
  resources:
    requests:
      storage: 2Gi
EOF

Es así de sencillo. Una vez que hayamos creado la PersistentVolumeClaim, podemos proceder a adjuntarla a un Pod. Cuando se despliega el Pod, Kubernetes crea el volumen de Longhorn y lo vincula a la Pod si hay almacenamiento disponible.

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: volume-test
  namespace: longhorn-system
spec:
  containers:
  - name: volume-test
    image: nginx:stable-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: volv
      mountPath: /data
    ports:
    - containerPort: 80
  volumes:
  - name: volv
    persistentVolumeClaim:
      claimName: longhorn-volv-pvc
EOF
Sugerencia
Sugerencia

El concepto de almacenamiento en Kubernetes es un tema complejo, pero importante. Hemos mencionado brevemente algunos de los recursos de Kubernetes más comunes; no obstante, os sugerimos que os familiaricéis con la documentación de terminología que ofrece Longhorn.

En este ejemplo, el resultado debería ser parecido a esto:

localhost:~ # kubectl get storageclass
NAME                 PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
longhorn (default)   driver.longhorn.io   Delete          Immediate           true                   12m
longhorn-example     driver.longhorn.io   Delete          Immediate           true                   24s

localhost:~ # kubectl get pvc -n longhorn-system
NAME                STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
longhorn-volv-pvc   Bound    pvc-f663a92e-ac32-49ae-b8e5-8a6cc29a7d1e   2Gi        RWO            longhorn-example   54s

localhost:~ # kubectl get pods -n longhorn-system
NAME                                                READY   STATUS    RESTARTS      AGE
csi-attacher-5c4bfdcf59-qmjtz                       1/1     Running   0             14m
csi-attacher-5c4bfdcf59-s7n65                       1/1     Running   0             14m
csi-attacher-5c4bfdcf59-w9xgs                       1/1     Running   0             14m
csi-provisioner-667796df57-fmz2d                    1/1     Running   0             14m
csi-provisioner-667796df57-p7rjr                    1/1     Running   0             14m
csi-provisioner-667796df57-w9fdq                    1/1     Running   0             14m
csi-resizer-694f8f5f64-2rb8v                        1/1     Running   0             14m
csi-resizer-694f8f5f64-z9v9x                        1/1     Running   0             14m
csi-resizer-694f8f5f64-zlncz                        1/1     Running   0             14m
csi-snapshotter-959b69d4b-5dpvj                     1/1     Running   0             14m
csi-snapshotter-959b69d4b-lwwkv                     1/1     Running   0             14m
csi-snapshotter-959b69d4b-tzhwc                     1/1     Running   0             14m
engine-image-ei-5cefaf2b-hvdv5                      1/1     Running   0             14m
instance-manager-0ee452a2e9583753e35ad00602250c5b   1/1     Running   0             14m
longhorn-csi-plugin-gd2jx                           3/3     Running   0             14m
longhorn-driver-deployer-9f4fc86-j6h2b              1/1     Running   0             15m
longhorn-manager-z4lnl                              1/1     Running   0             15m
longhorn-ui-5f4b7bbf69-bln7h                        1/1     Running   3 (14m ago)   15m
longhorn-ui-5f4b7bbf69-lh97n                        1/1     Running   3 (14m ago)   15m
volume-test                                         1/1     Running   0             26s

15.4 Acceso a la interfaz de usuario

Si habéis instalado SUSE Storage con kubectl o Helm, debéis configurar un controlador de Ingress para permitir el tráfico externo al clúster. La autenticación no está habilitada de forma predeterminada. Si se utilizó la aplicación de catálogo de Rancher, Rancher creó automáticamente un controlador de Ingress con control de acceso (el rancher-proxy).

  1. Obtened la dirección IP del servicio externo de Longhorn:

    kubectl -n longhorn-system get svc
  2. Una vez que hayáis recuperado la dirección IP longhorn-frontend, podéis empezar a utilizar la interfaz de usuario navegando hasta ella en vuestro navegador.

15.5 Instalación con Edge Image Builder

SUSE Telco Cloud utiliza Capítulo 12, Edge Image Builder para personalizar las imágenes base del SO SUSE Linux Micro. Vamos a demostrar cómo hacerlo para aprovisionar un clúster RKE2 con SUSE Storage sobre él.

Vamos a crear el archivo de definición:

export CONFIG_DIR=$HOME/eib
mkdir -p $CONFIG_DIR

cat << EOF > $CONFIG_DIR/iso-definition.yaml
apiVersion: 1.3
image:
  imageType: iso
  baseImage: SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso
  arch: x86_64
  outputImageName: eib-image.iso
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: suse-storage
        releaseName: longhorn
        version: 1.11.2
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
    repositories:
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
embeddedArtifactRegistry:
  registries:
    - uri: dp.apps.rancher.io
      authentication:
        username: $APPS.RANCHER.IO_USERNAME
        password: $APPS.RANCHER.IO_ACCESS_TOKEN
  images:
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-attacher:4.11.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-provisioner:5.3.0-14.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-resizer:2.1.0-6.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-snapshotter:8.5.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-livenessprobe:2.18.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-node-driver-registrar:2.16.0-13.2
    - name: dp.apps.rancher.io/containers/longhorn-backing-image-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-engine:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-instance-manager:1.11.2-4.3
    - name: dp.apps.rancher.io/containers/longhorn-manager:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-share-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-ui:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/rancher-support-bundle-kit:0.0.84-9.4
operatingSystem:
  packages:
    sccRegistrationCode: <reg-code>
    packageList:
      - open-iscsi
  users:
  - username: root
    encryptedPassword: \$6\$jHugJNNd3HElGsUZ\$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
EOF
Nota
Nota

Es posible personalizar cualquiera de los valores del gráfico de Helm mediante un archivo independiente proporcionado en helm.charts[].valuesFile. Consulte la documentación en sentido ascendente para obtener información detallada.

Vamos a compilar la imagen:

podman run --rm --privileged -it -v $CONFIG_DIR:/eib registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 build --definition-file $CONFIG_DIR/iso-definition.yaml

Una vez compilada la imagen, podéis utilizarla para instalar vuestro SO en un host físico o virtual. Una vez completado el aprovisionamiento, podéis iniciar sesión en el sistema utilizando el par de credenciales root:eib.

Aseguraos de que SUSE Storage se haya desplegado correctamente:

localhost:~ # /var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml -n longhorn-system get pods
NAME                                                READY   STATUS    RESTARTS        AGE
csi-attacher-5c4bfdcf59-qmjtz                       1/1     Running   0               103s
csi-attacher-5c4bfdcf59-s7n65                       1/1     Running   0               103s
csi-attacher-5c4bfdcf59-w9xgs                       1/1     Running   0               103s
csi-provisioner-667796df57-fmz2d                    1/1     Running   0               103s
csi-provisioner-667796df57-p7rjr                    1/1     Running   0               103s
csi-provisioner-667796df57-w9fdq                    1/1     Running   0               103s
csi-resizer-694f8f5f64-2rb8v                        1/1     Running   0               103s
csi-resizer-694f8f5f64-z9v9x                        1/1     Running   0               103s
csi-resizer-694f8f5f64-zlncz                        1/1     Running   0               103s
csi-snapshotter-959b69d4b-5dpvj                     1/1     Running   0               103s
csi-snapshotter-959b69d4b-lwwkv                     1/1     Running   0               103s
csi-snapshotter-959b69d4b-tzhwc                     1/1     Running   0               103s
engine-image-ei-5cefaf2b-hvdv5                      1/1     Running   0               109s
instance-manager-0ee452a2e9583753e35ad00602250c5b   1/1     Running   0               109s
longhorn-csi-plugin-gd2jx                           3/3     Running   0               103s
longhorn-driver-deployer-9f4fc86-j6h2b              1/1     Running   0               2m28s
longhorn-manager-z4lnl                              1/1     Running   0               2m28s
longhorn-ui-5f4b7bbf69-bln7h                        1/1     Running   3 (2m7s ago)    2m28s
longhorn-ui-5f4b7bbf69-lh97n                        1/1     Running   3 (2m10s ago)   2m28s
Nota
Nota

Esta instalación no funcionará en entornos completamente aislados. En esos casos, consultad Sección 63.8, “Instalación de SUSE Storage”.

SUSE Security es una solución de seguridad para Kubernetes que proporciona seguridad de red L7, seguridad en tiempo de ejecución, seguridad del sistema de suministro y comprobaciones de cumplimiento en un paquete cohesivo.

SUSE Security es un producto que se despliega como una plataforma de múltiples contenedores, cada uno de los cuales se comunica a través de varios puertos e interfaces. Internamente, utiliza NeuVector como su componente de seguridad de contenedores subyacente. Los siguientes contenedores conforman la plataforma SUSE Security:

  • . Un contenedor sin estado que presenta la consola basada en web. Normalmente, solo se necesita uno y puede ejecutarse en cualquier lugar. El fallo del gestor no afecta a ninguna de las operaciones del controlador o del Enforcer. Sin embargo, ciertas notificaciones (eventos) y datos de conexión recientes son almacenados en caché en la memoria por el gestor, por lo que su visualización se vería afectada.

  • Controlador. El «plano de control» para SUSE Security debe desplegarse en una configuración de alta disponibilidad (HA), para que la configuración no se pierda en caso de fallo de un nodo. Estos pueden ejecutarse en cualquier lugar, aunque los clientes suelen optar por colocarlos en nodos de «gestión», maestros o de infraestructura debido a su criticidad.

  • Enforcer. Este contenedor se despliega como un DaemonSet, por lo que hay un Enforcer en cada nodo que se debe proteger. Normalmente se despliega en todos los nodos de trabajo, pero se puede habilitar la programación para que también se despliegue en los nodos maestros e infra. Nota: Si el Enforcer no está en un nodo del clúster y las conexiones provienen de un pod en ese nodo, SUSE Security las etiqueta como cargas de trabajo «no gestionadas».

  • Escáner. Realiza el escaneo de vulnerabilidades utilizando la base de datos de CVE integrada, según las instrucciones del controlador. Se pueden desplegar múltiples escáneres para aumentar la capacidad de escaneo. Los escáneres pueden ejecutarse en cualquier lugar, pero a menudo se ejecutan en los nodos donde se ejecutan los controladores. Véase a continuación las consideraciones de dimensionamiento de los nodos del escáner. Un escáner también puede invocarse de forma independiente cuando se utiliza para el escaneo en la fase de compilación, por ejemplo, dentro de una canalización que activa un escaneo, recupera los resultados y termina el escáner. El escáner contiene la base de datos de CVE más reciente, por lo que debe actualizarse diariamente.

  • Actualizador. El actualizador activa una actualización del escáner mediante un trabajo cron de Kubernetes cuando se desea una actualización de la base de datos de CVE. Asegúrense de configurar esto para su entorno.

Se puede encontrar una documentación más detallada sobre la incorporación y las mejores prácticas de SUSE Security aquí.

16.1 ¿Cómo utiliza SUSE Telco Cloud SUSE Security?

SUSE Telco Cloud proporciona una configuración más ligera de SUSE Security como punto de partida para despliegues edge.

16.2 Notas importantes

  • El contenedor Scanner debe tener suficiente memoria para extraer la imagen que se va a escanear a la memoria y expandirla. Para escanear imágenes que superen 1 GB, aumenten la memoria del escáner ligeramente por encima del tamaño de imagen esperado más grande.

  • Se esperan muchas conexiones de red en el modo Protect. El Enforcer requiere CPU y memoria cuando está en modo Protect (bloqueo de firewall en línea) para mantener e inspeccionar las conexiones y la posible carga útil (DLP). Aumentar la memoria y dedicar un núcleo de CPU al Enforcer puede garantizar una capacidad de filtrado de paquetes adecuada.

16.3 Instalación con Edge Image Builder

SUSE Telco Cloud utiliza Capítulo 12, Edge Image Builder para personalizar las imágenes base de SUSE Linux Micro OS. Sigan Sección 63.7, “Instalación de SUSE Security” para una instalación en entorno aislado de SUSE Security sobre clústeres de Kubernetes aprovisionados por EIB.

17 MetalLB

Véase la documentación oficial de MetalLB.

MetalLB es una implementación de balance de la carga para clústeres de Kubernetes en equipo sin sistema operativo, que utiliza protocolos de enrutamiento estándar.

En entornos de equipo sin sistema operativo, configurar balanceadores de carga de red es notablemente más complejo que en entornos en la nube. A diferencia de las sencillas llamadas a la API en configuraciones en la nube, el entorno de equipo sin sistema operativo requiere dispositivos de red dedicados o una combinación de balanceadores de carga y configuraciones de IP virtual (VIP) para gestionar la alta disponibilidad (HA) o resolver el posible punto único de fallo (SPOF) inherente a un balanceador de carga de un solo nodo. Estas configuraciones no se automatizan fácilmente, lo que plantea desafíos en los despliegues de Kubernetes donde los componentes se escalan dinámicamente.

MetalLB aborda estos desafíos aprovechando el modelo de Kubernetes para crear servicios del tipo LoadBalancer como si estuvieran operando en un entorno en la nube, incluso en configuraciones de equipo sin sistema operativo.

Existen dos enfoques diferentes, mediante modo L2 (usando trucos ARP) o mediante BGP. Principalmente, L2 no necesita ningún equipo de red especial, pero BGP es, en general, mejor. Depende de los casos de uso.

17.1 ¿Cómo utiliza SUSE Telco Cloud MetalLB?

SUSE Telco Cloud utiliza MetalLB de tres formas clave:

  • Como solución de balance de la carga: MetalLB sirve como solución de balance de la carga para máquinas de equipo sin sistema operativo.

  • Para una configuración de HA K3s/RKE2: MetalLB permite equilibrar la carga de la API de Kubernetes mediante una dirección IP virtual.

  • Como solución BGP de capa 3, MetalLB anuncia rutas a las IP de servicio a los routers cercanos.

Nota
Nota

Para poder exponer la API, se utiliza el Endpoint Copier Operator (Capítulo 18, Operador de Endpoint Copier) para mantener sincronizados los endpoints de la API de K8s desde el servicio kubernetes a un servicio del tipo LoadBalancer kubernetes-vip.

17.2 Prácticas recomendadas

La instalación de MetalLB en modo L2 se describe en Capítulo 60, MetalLB en K3s (usando el modo de capa 2) y para el modo L3 en Capítulo 61, MetalLB en K3s (usando el modo de capa 3).

Puede encontrar una guía sobre la instalación de MetalLB delante de kube-api-server para lograr una topología de alta disponibilidad en Capítulo 62, MetalLB delante del servidor de API de Kubernetes.

17.3 Problemas conocidos

  • K3s incluye su propia solución de balance de la carga llamada Klipper. Para utilizar Klipper`MetalLB, debe desactivarse. Esto puede hacerse iniciando el servidor K3s con la opción `--disable servicelb, tal como se describe en la documentación de K3s.

18 Operador de Endpoint Copier

Endpoint Copier Operator es un operador de Kubernetes cuyo propósito es crear una copia de un Servicio y un Endpoint de Kubernetes y mantenerlos sincronizados.

18.1 ¿Cómo utiliza SUSE Telco Cloud el Operador de Endpoint Copier?

En SUSE Telco Cloud, el Operador de Endpoint Copier desempeña un papel crucial para lograr una configuración de alta disponibilidad (HA) para clústeres K3s/RKE2. Esto se logra creando un servicio kubernetes-vip de tipo LoadBalancer, asegurando que su Endpoint permanezca en sincronización constante con el Endpoint de Kubernetes. Se aprovecha MetalLB (Capítulo 17, MetalLB) para gestionar el servicio kubernetes-vip, ya que la dirección IP expuesta se utiliza desde otros nodos para unirse al clúster.

18.2 Mejores prácticas

La documentación completa para utilizar el Operador de Endpoint Copier se puede encontrar aquí.

Además, consulte nuestra guía (Capítulo 60, MetalLB en K3s (usando el modo de capa 2)) sobre cómo lograr una configuración de alta disponibilidad (HA) de K3s/RKE2 utilizando el Operador de Endpoint Copier y MetalLB.

18.3 Problemas conocidos

Actualmente, el Operador de Endpoint Copier está limitado a trabajar con un solo Servicio/Endpoint. Se planean mejoras para admitir múltiples Servicios/Endpoints en el futuro.

19 Virtualización de borde

Esta sección describe cómo puede utilizar la virtualización de borde para ejecutar máquinas virtuales en sus nodos de borde. La virtualización de borde está diseñada para casos de uso de virtualización ligera, donde se espera que se utilice un flujo de trabajo común para el despliegue y la gestión de aplicaciones tanto virtualizadas como en contenedores.

SUSE Telco Cloud La virtualización admite dos métodos para ejecutar máquinas virtuales:

  1. Despliegue manual de las máquinas virtuales mediante libvirt+qemu-kvm a nivel de host (donde Kubernetes no interviene)

  2. Despliegue del operador KubeVirt para la gestión de máquinas virtuales basada en Kubernetes

Ambas opciones son válidas, pero a continuación solo se trata la segunda. Si desea utilizar los mecanismos de virtualización estándar listos para usar que proporciona SUSE Linux Micro, puede encontrar una guía completa aquí, y aunque se redactó principalmente para SUSE Linux Enterprise Server, los conceptos son casi idénticos.

Esta guía explica inicialmente cómo desplegar los componentes de virtualización adicionales en un sistema que ya ha sido predesplegado, pero continúa con una sección que describe cómo integrar esta configuración en el despliegue inicial mediante Edge Image Builder. Si no desea repasar los conceptos básicos y configurar las cosas manualmente, pase directamente a esa sección.

19.1 Visión general de KubeVirt

KubeVirt permite gestionar máquinas virtuales con Kubernetes junto con el resto de sus cargas de trabajo en contenedores. Lo hace ejecutando la parte del espacio de usuario de la pila de virtualización de Linux en un contenedor. Esto minimiza los requisitos del sistema host, lo que permite una configuración y gestión más sencillas.

Los detalles sobre la arquitectura de KubeVirt se pueden encontrar en la documentación de sentido ascendente.

19.2 Requisitos previos

Si está siguiendo esta guía, asumimos que ya tiene disponible lo siguiente:

  • Al menos un host físico con SUSE Linux Micro 6.2 instalado y con las extensiones de virtualización habilitadas en la BIOS (consulte aquí para obtener más detalles).

  • En sus nodos, un clúster de Kubernetes K3s/RKE2 ya desplegado y con un kubeconfig adecuado que permita el acceso de superusuario al clúster.

  • Acceso al usuario raíz: estas instrucciones asumen que usted es el usuario raíz y no que está escalando sus privilegios mediante sudo.

  • Tiene Helm disponible localmente con una conexión de red adecuada para poder enviar configuraciones a su clúster de Kubernetes y descargar las imágenes necesarias.

19.3 Instalación manual de la virtualización de borde

Esta guía no le explicará el despliegue de Kubernetes, pero asume que ha instalado la versión adecuada de SUSE Telco Cloud de K3s o RKE2 y que tiene su kubeconfig configurado en consecuencia para que los comandos estándar de kubectl se puedan ejecutar como superusuario. Asumimos que su nodo forma un clúster de un solo nodo, aunque no se esperan diferencias significativas para los despliegues de varios nodos.

SUSE Telco Cloud Virtualization se despliega mediante tres gráficos de Helm independientes, concretamente:

  • KubeVirt: Los componentes fundamentales de la virtualización, es decir, los CRD de Kubernetes, operadores y otros componentes necesarios para permitir que Kubernetes despliegue y gestione máquinas virtuales.

  • Extensión del panel de control de KubeVirt: Una extensión opcional de la interfaz de usuario de Rancher que permite la gestión básica de máquinas virtuales, por ejemplo, iniciar/detener máquinas virtuales, así como acceder a la consola.

  • Importador de datos en contenedores (CDI): Un componente adicional que permite la integración de almacenamiento persistente para KubeVirt, proporcionando capacidades para que las máquinas virtuales utilicen sistemas secundarios de almacenamiento de Kubernetes existentes para los datos, pero que también permite a los usuarios importar o clonar volúmenes de datos para las máquinas virtuales.

Cada uno de estos charts de Helm tiene una versión correspondiente a la versión de SUSE Telco Cloud que esté utilizando actualmente. Para un uso en producción o con soporte, emplee los artefactos que se pueden encontrar en el registro de SUSE.

Primero, asegúrese de que su acceso a kubectl funciona:

$ kubectl get nodes

Esto debería mostrar algo similar a lo siguiente:

NAME                   STATUS   ROLES                       AGE     VERSION
node1.edge.rdo.wales   Ready    control-plane,etcd,master   4h20m   v1.30.5+rke2r1
node2.edge.rdo.wales   Ready    control-plane,etcd,master   4h15m   v1.30.5+rke2r1
node3.edge.rdo.wales   Ready    control-plane,etcd,master   4h15m   v1.30.5+rke2r1

Ahora puede proceder a instalar los charts de Helm de KubeVirt y Containerized Data Importer (CDI):

$ helm install kubevirt oci://registry.suse.com/edge/charts/kubevirt --namespace kubevirt-system --create-namespace
$ helm install cdi oci://registry.suse.com/edge/charts/cdi --namespace cdi-system --create-namespace

En unos minutos, debería tener todos los componentes de KubeVirt y CDI desplegados. Puede validarlo comprobando todos los recursos desplegados en el espacio de nombres kubevirt-system y cdi-system.

Verificar los recursos de KubeVirt:

$ kubectl get all -n kubevirt-system

Esto debería mostrar algo similar a lo siguiente:

NAME                                   READY   STATUS    RESTARTS      AGE
pod/virt-operator-5fbcf48d58-p7xpm     1/1     Running   0             2m24s
pod/virt-operator-5fbcf48d58-wnf6s     1/1     Running   0             2m24s
pod/virt-handler-t594x                 1/1     Running   0             93s
pod/virt-controller-5f84c69884-cwjvd   1/1     Running   1 (64s ago)   93s
pod/virt-controller-5f84c69884-xxw6q   1/1     Running   1 (64s ago)   93s
pod/virt-api-7dfc54cf95-v8kcl          1/1     Running   1 (59s ago)   118s

NAME                                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubevirt-prometheus-metrics   ClusterIP   None            <none>        443/TCP   2m1s
service/virt-api                      ClusterIP   10.43.56.140    <none>        443/TCP   2m1s
service/kubevirt-operator-webhook     ClusterIP   10.43.201.121   <none>        443/TCP   2m1s
service/virt-exportproxy              ClusterIP   10.43.83.23     <none>        443/TCP   2m1s

NAME                          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/virt-handler   1         1         1       1            1           kubernetes.io/os=linux   93s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/virt-operator     2/2     2            2           2m24s
deployment.apps/virt-controller   2/2     2            2           93s
deployment.apps/virt-api          1/1     1            1           118s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/virt-operator-5fbcf48d58     2         2         2       2m24s
replicaset.apps/virt-controller-5f84c69884   2         2         2       93s
replicaset.apps/virt-api-7dfc54cf95          1         1         1       118s

NAME                            AGE     PHASE
kubevirt.kubevirt.io/kubevirt   2m24s   Deployed

Verificar los recursos de CDI:

$ kubectl get all -n cdi-system

Esto debería mostrar algo similar a lo siguiente:

NAME                                   READY   STATUS    RESTARTS   AGE
pod/cdi-operator-55c74f4b86-692xb      1/1     Running   0          2m24s
pod/cdi-apiserver-db465b888-62lvr      1/1     Running   0          2m21s
pod/cdi-deployment-56c7d74995-mgkfn    1/1     Running   0          2m21s
pod/cdi-uploadproxy-7d7b94b968-6kxc2   1/1     Running   0          2m22s

NAME                             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/cdi-uploadproxy          ClusterIP   10.43.117.7    <none>        443/TCP    2m22s
service/cdi-api                  ClusterIP   10.43.20.101   <none>        443/TCP    2m22s
service/cdi-prometheus-metrics   ClusterIP   10.43.39.153   <none>        8080/TCP   2m21s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cdi-operator      1/1     1            1           2m24s
deployment.apps/cdi-apiserver     1/1     1            1           2m22s
deployment.apps/cdi-deployment    1/1     1            1           2m21s
deployment.apps/cdi-uploadproxy   1/1     1            1           2m22s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/cdi-operator-55c74f4b86      1         1         1       2m24s
replicaset.apps/cdi-apiserver-db465b888      1         1         1       2m21s
replicaset.apps/cdi-deployment-56c7d74995    1         1         1       2m21s
replicaset.apps/cdi-uploadproxy-7d7b94b968   1         1         1       2m22s

Para verificar que las definiciones de recursos personalizadas (CRD) de VirtualMachine están desplegadas, puede validar con:

$ kubectl explain virtualmachine

Esto debería imprimir la definición del objeto VirtualMachine, que debería mostrarse de la siguiente manera:

GROUP:      kubevirt.io
KIND:       VirtualMachine
VERSION:    v1

DESCRIPTION:
    VirtualMachine handles the VirtualMachines that are not running or are in a
    stopped state The VirtualMachine contains the template to create the
    VirtualMachineInstance. It also mirrors the running state of the created
    VirtualMachineInstance in its status.
(snip)

19.4 Despliegue de máquinas virtuales

Ahora que KubeVirt y CDI están desplegados, defina una máquina virtual sencilla basada en openSUSE Tumbleweed. Esta máquina virtual tiene la configuración más sencilla, utilizando la «red de pod» estándar para una configuración de red idéntica a la de cualquier otro pod. También emplea almacenamiento no persistente, lo que garantiza que el almacenamiento sea efímero, igual que en cualquier contenedor que no tenga un PVC.

$ cat <<EOF > user-data.yaml
#cloud-config
disable_root: false
ssh_pwauth: True
users:
  - default
  - name: suse
    groups: sudo
    shell: /bin/bash
    sudo:  ALL=(ALL) NOPASSWD:ALL
    lock_passwd: False
    plain_text_passwd: 'suse'
EOF
$ kubectl apply -f - <<EOF
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: tumbleweed
  namespace: default
spec:
  runStrategy: Always
  template:
    spec:
      domain:
        devices: {}
        machine:
          type: q35
        memory:
          guest: 2Gi
        resources: {}
      volumes:
      - containerDisk:
          image: quay.io/containerdisks/opensuse-tumbleweed:1.0.0
        name: tumbleweed-containerdisk-0
      - cloudInitNoCloud:
          userDataBase64: $(cat user-data.yaml | base64 -w 0)
        name: cloudinitdisk
EOF

Esto debería mostrar que se ha creado un VirtualMachine:

virtualmachine.kubevirt.io/tumbleweed created

Esta definición de VirtualMachine es mínima y especifica poco sobre la configuración. Simplemente describe que es un tipo de máquina « q35» con 2 GB de memoria que utiliza una imagen de disco basada en un containerDisk efímero (es decir, una imagen de disco que se almacena en una imagen de contenedor desde un repositorio de imágenes remoto), y especifica un disco cloudInit codificado en base64, que solo utilizamos para la creación de usuarios y la aplicación de contraseñas en el momento del arranque (utilice base64 -d para decodificarlo).

Nota
Nota

Esta imagen de máquina virtual es solo para pruebas. La imagen no cuenta con soporte oficial y solo pretende ser un ejemplo de documentación.

Esta máquina tarda unos minutos en arrancar, ya que necesita descargar la imagen de disco de openSUSE Tumbleweed, pero una vez hecho esto, puede ver más detalles sobre la máquina virtual comprobando la información de la máquina virtual:

$ kubectl get vmi

Esto debería mostrar el nodo en el que se inició la máquina virtual y la dirección IP de la máquina virtual. Recuerde que, dado que utiliza la red de pod, la dirección IP notificada será igual que la de cualquier otro pod, y enrutable como tal:

NAME         AGE     PHASE     IP           NODENAME               READY
tumbleweed   4m24s   Running   10.42.2.98   node3.edge.rdo.wales   True

Al ejecutar estos comandos en los propios nodos del clúster de Kubernetes, con una CNI que enruta el tráfico directamente a los pods (por ejemplo, Cilium), debería poder ssh directamente a la propia máquina. Sustituya la siguiente dirección IP por la que se ha asignado a su máquina virtual:

$ ssh suse@10.42.2.98
(password is "suse")

Una vez que esté en esta máquina virtual, podrá experimentar, pero recuerde que está limitada en cuanto a recursos y solo tiene 1 GB de espacio en disco. Cuando haya terminado, Ctrl-D o exit para desconectarse de la sesión SSH.

El proceso de la máquina virtual sigue estando envuelto en un pod estándar de Kubernetes. El CRD VirtualMachine es una representación de la máquina virtual deseada, pero el proceso en el que la máquina virtual se inicia realmente es a través del pod virt-launcher, un pod estándar de Kubernetes, igual que cualquier otra aplicación. Para cada máquina virtual iniciada, puede ver que hay un pod virt-launcher:

$ kubectl get pods

Esto debería mostrar entonces el pod virt-launcher para la máquina Tumbleweed que ha definido:

NAME                             READY   STATUS    RESTARTS   AGE
virt-launcher-tumbleweed-8gcn4   3/3     Running   0          10m

Si echa un vistazo a este pod virt-launcher, verá que está ejecutando los procesos libvirt y qemu-kvm. Puede entrar en el propio pod y echar un vistazo a lo que hay debajo, teniendo en cuenta que debe adaptar el siguiente comando para el nombre de su pod:

$ kubectl exec -it virt-launcher-tumbleweed-8gcn4 -- bash

Una vez que esté en el pod, intente ejecutar los comandos virsh además de observar los procesos. Verá el binario qemu-system-x86_64 en ejecución, junto con ciertos procesos para supervisar la máquina virtual. También verá la ubicación de la imagen de disco y cómo está conectada la red (como un dispositivo tap):

qemu@tumbleweed:/> ps ax
  PID TTY      STAT   TIME COMMAND
    1 ?        Ssl    0:00 /usr/bin/virt-launcher-monitor --qemu-timeout 269s --name tumbleweed --uid b9655c11-38f7-4fa8-8f5d-bfe987dab42c --namespace default --kubevirt-share-dir /var/run/kubevirt --ephemeral-disk-dir /var/run/kubevirt-ephemeral-disks --container-disk-dir /var/run/kube
   12 ?        Sl     0:01 /usr/bin/virt-launcher --qemu-timeout 269s --name tumbleweed --uid b9655c11-38f7-4fa8-8f5d-bfe987dab42c --namespace default --kubevirt-share-dir /var/run/kubevirt --ephemeral-disk-dir /var/run/kubevirt-ephemeral-disks --container-disk-dir /var/run/kubevirt/con
   24 ?        Sl     0:00 /usr/sbin/virtlogd -f /etc/libvirt/virtlogd.conf
   25 ?        Sl     0:01 /usr/sbin/virtqemud -f /var/run/libvirt/virtqemud.conf
   83 ?        Sl     0:31 /usr/bin/qemu-system-x86_64 -name guest=default_tumbleweed,debug-threads=on -S -object {"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/run/kubevirt-private/libvirt/qemu/lib/domain-1-default_tumbleweed/master-key.aes"} -machine pc-q35-7.1,usb
  286 pts/0    Ss     0:00 bash
  320 pts/0    R+     0:00 ps ax

qemu@tumbleweed:/> virsh list --all
 Id   Name                 State
------------------------------------
 1    default_tumbleweed   running

qemu@tumbleweed:/> virsh domblklist 1
 Target   Source
---------------------------------------------------------------------------------------------
 sda      /var/run/kubevirt-ephemeral-disks/disk-data/tumbleweed-containerdisk-0/disk.qcow2
 sdb      /var/run/kubevirt-ephemeral-disks/cloud-init-data/default/tumbleweed/noCloud.iso

qemu@tumbleweed:/> virsh domiflist 1
 Interface   Type       Source   Model                     MAC
------------------------------------------------------------------------------
 tap0        ethernet   -        virtio-non-transitional   e6:e9:1a:05:c0:92

qemu@tumbleweed:/> exit
exit

Por último, elimine esta máquina virtual para realizar una limpieza:

$ kubectl delete vm/tumbleweed
virtualmachine.kubevirt.io "tumbleweed" deleted

19.5 Uso de virtctl

Junto con las herramientas CLI estándar de Kubernetes, es decir, kubectl, KubeVirt incluye una utilidad CLI complementaria que le permite interactuar con su clúster de una forma que salva algunas diferencias entre el mundo de la virtualización y el mundo para el que se diseñó Kubernetes. Por ejemplo, la herramienta virtctl ofrece la capacidad de gestionar el ciclo de vida de las máquinas virtuales (iniciar, detener, reiniciar, etc.), proporcionando acceso a las consolas virtuales, cargando imágenes de máquinas virtuales, así como interactuando con construcciones de Kubernetes como servicios, sin utilizar directamente la API o los CRD.

Descarguemos la última versión estable de la herramienta virtctl:

$ export VERSION=v0.7.0
$ wget https://github.com/kubevirt/kubevirt/releases/download/$VERSION/virtctl-$VERSION-linux-amd64

Si utilizáis una arquitectura diferente o una máquina que no sea Linux, podéis encontrar otras versiones aquí. Debes hacerlo ejecutable antes de continuar, y puede ser útil moverlo a una ubicación dentro de tu $PATH:

$ mv virtctl-$VERSION-linux-amd64 /usr/local/bin/virtctl
$ chmod a+x /usr/local/bin/virtctl

Entonces podrás utilizar la herramienta de línea de comandos virtctl para crear máquinas virtuales. Repliquemos nuestra máquina virtual anterior, teniendo en cuenta que estamos redirigiendo la salida directamente a kubectl apply:

$ cat <<EOF >  user-data.yaml
#cloud-config
disable_root: false
ssh_pwauth: True
users:
  - default
  - name: suse
    groups: sudo
    shell: /bin/bash
    sudo:  ALL=(ALL) NOPASSWD:ALL
    lock_passwd: False
    plain_text_passwd: 'suse'
EOF
$ alias virtctl=echo
$ virtctl create vm --name virtctl-example --memory=1Gi \
    --volume-containerdisk=src:quay.io/containerdisks/opensuse-tumbleweed:1.0.0 \
    --cloud-init-user-data "$(cat user-data.yaml | base64 -w 0)"

Esto debería mostrar entonces la máquina virtual ejecutándose (debería iniciarse mucho más rápido esta vez dado que la imagen del contenedor estará en caché):

$ kubectl get vmi
NAME              AGE   PHASE     IP           NODENAME               READY
virtctl-example   52s   Running   10.42.2.29   node3.edge.rdo.wales   True

Ahora podemos usar virtctl para conectar directamente a la máquina virtual:

$ virtctl ssh suse@virtctl-example
(password is "suse" - Ctrl-D to exit)

Hay muchos otros comandos que pueden ser utilizados por virtctl. Por ejemplo, virtctl console puede darte acceso a la consola serie si la red no funciona, y puedes usar virtctl guestosinfo para obtener información completa del sistema operativo, siempre que el invitado tenga instalado y en ejecución qemu-guest-agent.

Finalmente, pausemos y reanudemos la máquina virtual:

$ virtctl pause vm virtctl-example
VMI virtctl-example was scheduled to pause

Encuentras que el objeto VirtualMachine se muestra como Paused y el objeto VirtualMachineInstance se muestra como Running pero READY=False:

$ kubectl get vm
NAME              AGE     STATUS   READY
virtctl-example   8m14s   Paused   False

$ kubectl get vmi
NAME              AGE     PHASE     IP           NODENAME               READY
virtctl-example   8m15s   Running   10.42.2.29   node3.edge.rdo.wales   False

También encuentras que ya no puedes conectar a la máquina virtual:

$ virtctl ssh suse@virtctl-example
can't access VMI virtctl-example: Operation cannot be fulfilled on virtualmachineinstance.kubevirt.io "virtctl-example": VMI is paused

Reanudemos la máquina virtual e intentémoslo de nuevo:

$ virtctl unpause vm virtctl-example
VMI virtctl-example was scheduled to unpause

Ahora deberíamos poder restablecer una conexión:

$ virtctl ssh suse@virtctl-example
suse@vmi/virtctl-example.default's password:
suse@virtctl-example:~> exit
logout

Finalmente, eliminemos la máquina virtual:

$ kubectl delete vm/virtctl-example
virtualmachine.kubevirt.io "virtctl-example" deleted

19.6 Redes de ingress simples

En esta sección, mostramos cómo puedes exponer máquinas virtuales como servicios estándar de Kubernetes y hacerlas disponibles a través del servicio Ingress de Kubernetes, por ejemplo, Traefik con RKE2 o Traefik con K3s. Este documento asume que estos componentes ya están configurados adecuadamente y que tienes un puntero DNS apropiado, por ejemplo, mediante un carácter comodín, para apuntar a tus nodos de servidor de Kubernetes o a tu IP virtual de ingress para una adecuada resolución de ingress.

Nota
Nota

En SUSE Telco Cloud 3.1+, si estás usando K3s en una configuración de nodo multiservidor, es posible que hayas necesitado configurar una VIP basada en MetalLB para Ingress; esto no es necesario para RKE2.

En el entorno de ejemplo, se despliega otra máquina virtual openSUSE Tumbleweed, se utiliza cloud-init para instalar NGINX como un servidor web simple en el momento del arranque, y se configura un mensaje simple para que se devuelva y verificar que funciona como se espera cuando se realiza una llamada. Para ver cómo se hace esto, simplemente base64 -d la sección cloud-init en la salida siguiente.

Creemos esta máquina virtual ahora:

$ cat <<EOF > user-data.yaml
#cloud-config
disable_root: false
ssh_pwauth: True
users:
  - default
  - name: suse
    groups: sudo
    shell: /bin/bash
    sudo:  ALL=(ALL) NOPASSWD:ALL
    lock_passwd: False
    plain_text_passwd: 'suse'
EOF
$ kubectl apply -f - <<EOF
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: ingress-example
  namespace: default
spec:
  runStrategy: Always
  template:
    metadata:
      labels:
        app: nginx
    spec:
      domain:
        devices: {}
        machine:
          type: q35
        memory:
          guest: 2Gi
        resources: {}
      volumes:
      - containerDisk:
          image: quay.io/containerdisks/opensuse-tumbleweed:1.0.0
        name: tumbleweed-containerdisk-0
      - cloudInitNoCloud:
          userDataBase64: $(cat user-data.yaml | base64 -w 0)
        name: cloudinitdisk
EOF

Cuando esta máquina virtual se haya iniciado correctamente, podemos usar el comando virtctl para exponer la VirtualMachineInstance con un puerto externo de 8080 y un puerto de destino de 80 (donde NGINX escucha por defecto). Usamos el comando virtctl aquí ya que entiende la asignación entre el objeto de la máquina virtual y el pod. Esto crea un nuevo servicio para nosotros:

$ virtctl expose vmi ingress-example --port=8080 --target-port=80 --name=ingress-example
Service ingress-example successfully exposed for vmi ingress-example

Entonces tendremos un servicio apropiado creado automáticamente:

$ kubectl get svc/ingress-example
NAME              TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)                         AGE
ingress-example   ClusterIP      10.43.217.19    <none>            8080/TCP                        9s

A continuación, si utilizas kubectl create ingress, podemos crear un objeto Ingress que apunte a este servicio. Adaptad la URL (conocida como "host" en el objeto ingress) aquí para que coincida con vuestra configuración DNS y aseguraos de apuntarla al puerto 8080:

$ kubectl create ingress ingress-example --rule=ingress-example.suse.local/=ingress-example:8080

Con el DNS configurado correctamente, deberíais poder hacer curl a la URL inmediatamente:

$ curl ingress-example.suse.local
It works!

Vamos a realizar una limpieza eliminando esta máquina virtual y sus recursos de servicio e ingress:

$ kubectl delete vm/ingress-example svc/ingress-example ingress/ingress-example
virtualmachine.kubevirt.io "ingress-example" deleted
service "ingress-example" deleted
ingress.networking.k8s.io "ingress-example" deleted

19.7 Uso de la extensión de la UI de Rancher

SUSE Telco Cloud Virtualization proporciona una extensión de la UI para Rancher Manager, que permite la gestión básica de máquinas virtuales mediante la interfaz del panel de control de Rancher.

19.7.1 Instalación

Consultad Extensiones del panel de control de Rancher (Capítulo 7, Extensiones de Rancher Dashboard) para obtener orientación sobre la instalación.

19.7.2 Uso de la extensión de la UI de KubeVirt Rancher

La extensión introduce una nueva sección KubeVirt en el Explorador de clústeres. Esta sección se añade a cualquier clúster downstream que tenga KubeVirt instalado.

La extensión os permite interactuar directamente con los recursos de máquinas virtuales de KubeVirt para gestionar el ciclo de vida de las máquinas virtuales.

19.7.2.1 Creación de una máquina virtual

  1. Navegad al Explorador de clústeres haciendo clic en el clúster downstream habilitado para KubeVirt en la navegación de la izquierda.

  2. Navegad a la página KubeVirt > Máquinas virtuales y haced clic en Create from YAML en la parte superior derecha de la pantalla.

  3. Rellenad o pegad una definición de máquina virtual y pulsad Create. Utilizad la definición de máquina virtual de la sección Desplegar máquinas virtuales como inspiración.

virtual machines page

19.7.2.2 Acciones de la máquina virtual

Podéis utilizar el menú de acciones al que se accede desde la lista desplegable ⋮ a la derecha de cada máquina virtual para realizar acciones de inicio, terminar, pausa o reinicio suave. Alternativamente, también podéis utilizar las acciones de grupo en la parte superior de la lista seleccionando las máquinas virtuales sobre las que realizar la acción.

Realizar las acciones puede tener un efecto en la Estrategia de ejecución de la máquina virtual. Consultad la tabla en la documentación de KubeVirt para obtener más detalles.

19.7.2.3 Acceso a la consola de la máquina virtual

La lista de «Máquinas virtuales» proporciona una lista desplegable Console que permite conectar a la máquina utilizando VNC o consola serie. Esta acción solo está disponible para máquinas en ejecución.

En algunos casos, pasa un breve periodo de tiempo antes de que la consola esté accesible en una máquina virtual recién iniciada.

vnc console ui

19.8 Instalación con Edge Image Builder

SUSE Telco Cloud utiliza Capítulo 12, Edge Image Builder para personalizar las imágenes base del SO SUSE Linux Micro. Seguid Sección 63.9, “Instalación de KubeVirt y CDI” para una instalación en un entorno aislado tanto de KubeVirt como de CDI sobre clústeres de Kubernetes aprovisionados por EIB.

20 Controlador de actualización del sistema

Consultad la documentación del controlador de actualización del sistema.

El controlador de actualización del sistema (SUC) tiene como objetivo proporcionar un controlador de actualización de propósito general y nativo de Kubernetes (para nodos). Introduce una nueva CRD, el Plan, para definir todas y cada una de vuestras políticas/requisitos de actualización. Un Plan es una intención pendiente de mutar los nodos en vuestro clúster.

20.1 ¿Cómo utiliza SUSE Telco Cloud el controlador de actualización del sistema?

SUSE Telco Cloud utiliza SUC para facilitar diversas operaciones de "Día 2" relacionadas con las actualizaciones de la versión del SO y de Kubernetes en los clústeres de gestión y de sentido descendente.

Las operaciones de "Día 2" se definen a través de SUC Plans. Basándose en estos planes, SUC despliega cargas de trabajo en cada nodo para ejecutar la operación de "Día 2" correspondiente.

SUC también se utiliza dentro de Capítulo 21, Controlador de actualización. Para obtener más información sobre las diferencias clave entre SUC y el controlador de actualización del sistema, véase Sección 21.2, “Controlador de actualización frente a System Upgrade Controller”.

20.2 Instalación del controlador de actualización del sistema

Importante
Importante

A partir de Rancher v2.10.0, el System Upgrade Controller se instala automáticamente.

Seguid los pasos a continuación solo si vuestro entorno no está gestionado por Rancher, o si vuestra versión de Rancher es inferior a v2.10.0.

Recomendamos que instaléis SUC a través de Fleet (Capítulo 9, Fleet) ubicado en el repositorio suse-edge/fleet-examples.

Nota
Nota

Los recursos ofrecidos por el repositorio suse-edge/fleet-examples deben utilizarse siempre desde una versión de fleet-examples válida. Para determinar qué versión necesitáis utilizar, consultad las Notas de la versión (Capítulo 75, Notas de la versión).

Si no podéis utilizar Fleet para la instalación de SUC, podéis instalarlo a través del repositorio de charts de Helm de Rancher, o incorporar el chart de Helm de Rancher en vuestro propio flujo de trabajo GitOps de terceros.

Esta sección cubre:

20.2.1 Instalación de Fleet del controlador de actualización del sistema

Utilizando Fleet, hay dos recursos posibles que se pueden usar para desplegar SUC:

20.2.1.1 Instalación del controlador de actualización del sistema - GitRepo

Nota
Nota

Este proceso también puede realizarse a través de la interfaz de usuario de Rancher, si está disponible. Para obtener más información, consultad Acceso a Fleet en la interfaz de usuario de Rancher.

En vuestro clúster de gestión:

  1. Determinad en qué clústeres queréis desplegar SUC. Esto se hace desplegando un recurso GitRepo de SUC en el espacio de trabajo de Fleet correcto en vuestro clúster de gestión. Por defecto, Fleet tiene dos espacios de trabajo:

    • fleet-local - para recursos que deban desplegarse en el clúster de gestión.

    • fleet-default - para recursos que deban desplegarse en clústeres sentido descendente.

      Para obtener más información sobre los espacios de trabajo de Fleet, consultad la documentación sentido ascendente.

  2. Despliega el recurso GitRepo:

    • Para desplegar SUC en vuestro clúster de gestión:

      kubectl apply -n fleet-local -f - <<EOF
      apiVersion: fleet.cattle.io/v1alpha1
      kind: GitRepo
      metadata:
        name: system-upgrade-controller
      spec:
        revision: release-3.6.1
        paths:
        - fleets/day2/system-upgrade-controller
        repo: https://github.com/suse-edge/fleet-examples.git
      EOF
    • Para desplegar SUC en vuestros clústeres de sentido descendente:

      Nota
      Nota

      Antes de desplegar el recurso siguiente, debéis proporcionar una configuración targets válida, para que Fleet sepa en qué clústeres de sentido descendente desplegar vuestro recurso. Para obtener información sobre cómo realizar el mapeo a clústeres de sentido descendente, consultad Mapping to Downstream Clusters.

      kubectl apply -n fleet-default -f - <<EOF
      apiVersion: fleet.cattle.io/v1alpha1
      kind: GitRepo
      metadata:
        name: system-upgrade-controller
      spec:
        revision: release-3.6.1
        paths:
        - fleets/day2/system-upgrade-controller
        repo: https://github.com/suse-edge/fleet-examples.git
        targets:
        - clusterSelector: CHANGEME
        # Example matching all clusters:
        # targets:
        # - clusterSelector: {}
      EOF
  3. Validad que el recurso GitRepo esté desplegado:

    # Namespace will vary based on where you want to deploy SUC
    kubectl get gitrepo system-upgrade-controller -n <fleet-local/fleet-default>
    
    NAME                        REPO                                              COMMIT          BUNDLEDEPLOYMENTS-READY   STATUS
    system-upgrade-controller   https://github.com/suse-edge/fleet-examples.git   release-3.6.1   1/1
  4. Validad el despliegue del controlador de actualización del sistema:

    kubectl get deployment system-upgrade-controller -n cattle-system
    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    system-upgrade-controller   1/1     1            1           2m20s

20.2.1.2 Instalación del controlador de actualización del sistema - Bundle

Esta sección ilustra cómo crear y desplegar un recurso Bundle a partir de una configuración estándar de Fleet utilizando la fleet-cli.

  1. En una máquina con acceso a la red, descarga el fleet-cli:

    Nota
    Nota

    Aseguraos de que la versión de fleet-cli que descarguéis coincida con la versión de Fleet que se ha desplegado en vuestro clúster.

    • Para usuarios de Mac, existe una fleet-cli Homebrew Formulae.

    • Para usuarios de Linux y Windows, los binarios están presentes como assets en cada release de Fleet.

      • Linux AMD:

        curl -L -o fleet-cli https://github.com/rancher/fleet/releases/download/vv0.15.2/fleet-linux-amd64
      • Linux ARM:

        curl -L -o fleet-cli https://github.com/rancher/fleet/releases/download/vv0.15.2/fleet-linux-arm64
  2. Haced que fleet-cli sea ejecutable:

    chmod +x fleet-cli
  3. Clonad la suse-edge/fleet-examples release que deseéis utilizar:

    git clone -b release-3.6.1 https://github.com/suse-edge/fleet-examples.git
  4. Navegad al repositorio SUC fleet, ubicado en el fleet-examples:

    cd fleet-examples/fleets/day2/system-upgrade-controller
  5. Determinad en qué clústeres queréis desplegar SUC. Esto se hace desplegando el Bundle de SUC en el espacio de trabajo de Fleet correcto dentro de vuestro clúster de gestión. Por defecto, Fleet tiene dos espacios de trabajo:

    • fleet-local - para recursos que deban desplegarse en el clúster de gestión.

    • fleet-default - para recursos que deban desplegarse en clústeres downstream.

      Para obtener más información sobre los espacios de trabajo de Fleet, consulta la documentación sentido ascendente.

  6. Si tenéis la intención de desplegar SUC solo en clústeres de sentido descendente, cread un archivo targets.yaml que coincida con los clústeres específicos:

    cat > targets.yaml <<EOF
    targets:
    - clusterSelector: CHANGEME
    EOF

    Para obtener información sobre cómo realizar el mapeo a clústeres de sentido descendente, consultad Mapping to Downstream Clusters

  7. Proceded a compilar el Bundle:

    Nota
    Nota

    Aseguraos de no descargar fleet-cli en el directorio fleet-examples/fleets/day2/system-upgrade-controller, de lo contrario se empaquetará con el Bundle, lo cual no es recomendable.

    • Para desplegar SUC en vuestro clúster de gestión, ejecutad:

      fleet-cli apply --compress -n fleet-local -o - system-upgrade-controller . > system-upgrade-controller-bundle.yaml
    • Para desplegar SUC en vuestros clústeres de sentido descendente, ejecutad:

      fleet-cli apply --compress --targets-file=targets.yaml -n fleet-default -o - system-upgrade-controller . > system-upgrade-controller-bundle.yaml

      Para obtener más información sobre este proceso, consultad Convert a Helm Chart into a Bundle.

      Para obtener más información sobre el comando fleet-cli apply, consultad fleet apply.

  8. Transferid el Bundle system-upgrade-controller-bundle.yaml a la máquina de vuestro clúster de gestión:

    scp system-upgrade-controller-bundle.yaml <machine-address>:<filesystem-path>
  9. En vuestro clúster de gestión, desplegad el Bundle system-upgrade-controller-bundle.yaml:

    kubectl apply -f system-upgrade-controller-bundle.yaml
  10. En vuestro clúster de gestión, validad que el Bundle esté desplegado:

    # Namespace will vary based on where you want to deploy SUC
    kubectl get bundle system-upgrade-controller -n <fleet-local/fleet-default>
    
    NAME                        BUNDLEDEPLOYMENTS-READY   STATUS
    system-upgrade-controller   1/1
  11. Según el espacio de trabajo de Fleet en el que hayáis desplegado vuestro Bundle, navegad al clúster y validad el despliegue de SUC:

    Nota
    Nota

    SUC siempre se despliega en el espacio de nombres cattle-system.

    kubectl get deployment system-upgrade-controller -n cattle-system
    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    system-upgrade-controller   1/1     1            1           111s

20.2.2 Instalación de Helm del controlador de actualización del sistema

  1. Añadid el repositorio de charts de Rancher:

    helm repo add rancher-charts https://charts.rancher.io/
  2. Desplegad el chart de SUC:

    helm install system-upgrade-controller rancher-charts/system-upgrade-controller --version 109.0.1 --set global.cattle.psp.enabled=false -n cattle-system --create-namespace

    Esto instalará la versión v0.19.1 de SUC, necesaria para la plataforma Edge 3.6.

  3. Validad el despliegue de SUC:

    kubectl get deployment system-upgrade-controller -n cattle-system
    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    system-upgrade-controller   1/1     1            1           37s

20.3 Monitorización de los planes del controlador de actualización del sistema

Los planes SUC pueden visualizarse de las siguientes formas:

Importante
Importante

Los Pods desplegados para los planes SUC se mantienen activos 15 minutos después de una ejecución correcta. Después de eso, son eliminados por el Job correspondiente que los creó. Para tener acceso a los registros del Pod después de este periodo de tiempo, debéis habilitar el registro para vuestro clúster. Para obtener información sobre cómo hacerlo en Rancher, consultad Rancher Integration with Logging Services.

20.3.1 Monitorización de los planes del controlador de actualización del sistema - Interfaz de usuario de Rancher

Para consultar los registros de Pod de un plan SUC específico:

  1. En la esquina superior izquierda, ☰ → <your-cluster-name>

  2. Seleccionad Workloads → Pods

  3. Seleccionad el menú desplegable Only User Namespaces y añadid el espacio de nombres cattle-system

  4. En la barra de filtro de Pods, escribid el nombre de vuestro Pod del plan SUC. El nombre seguirá el siguiente formato de plantilla: apply-<plan_name>-on-<node_name>

    Nota
    Nota

    Puede haber Pods Completed y Unknown para un plan SUC específico. Esto es normal y ocurre debido a la naturaleza de algunas de las actualizaciones.

  5. Seleccionad el pod cuyos registros queréis revisar y navegad a ⋮ → View Logs

20.3.2 Planes del Upgrade Controller del sistema de monitorización - Manual

Nota
Nota

Los siguientes pasos asumen que kubectl se ha configurado para conectarse al clúster donde se han desplegado los SUC Plans.

  1. Listar los planes SUC desplegados:

    kubectl get plans -n cattle-system
  2. Obtener el pod para el plan SUC:

    kubectl get pods -l upgrade.cattle.io/plan=<plan_name> -n cattle-system
    Nota
    Nota

    Puede haber ambos pods Completed y Unknown para un plan SUC específico. Esto es normal y ocurre debido a la naturaleza de algunas de las actualizaciones.

  3. Obtener los registros del pod:

    kubectl logs <pod_name> -n cattle-system

21 Controlador de actualización

Un controlador de Kubernetes capaz de realizar actualizaciones en los siguientes SUSE Telco Cloud componentes de la plataforma:

  • Sistema operativo (SUSE Linux Micro)

  • Kubernetes (K3s y RKE2)

  • Componentes adicionales (Rancher, Elemental, SUSE Security, etc.)

El Controlador de actualización agiliza el proceso de actualización de los componentes mencionados anteriormente al encapsular sus complejidades dentro de un único user-facing recurso que sirve como desencadenante para la actualización. Los usuarios solo necesitan configurar este recurso y el Upgrade Controller se encarga del resto.

Nota
Nota

El Upgrade Controller actualmente admite actualizaciones de plataforma SUSE Telco Cloud solo para clústeres de gestión sin entorno aislado. Consulte la sección Sección 21.8, “Limitaciones conocidas” para obtener más información.

21.1 ¿Cómo utiliza SUSE Telco Cloud el Controlador de actualización?

El Controlador de actualización es esencial para automatizar las operaciones de «Día 2» (anteriormente manuales) necesarias para actualizar los clústeres de gestión de una versión de lanzamiento SUSE Telco Cloud a la siguiente.

Para lograr esta automatización, el Controlador de actualización utiliza herramientas como el System Upgrade Controller (Capítulo 20, Controlador de actualización del sistema) y el Helm Controller.

Para obtener más detalles sobre cómo funciona el Controlador de actualización, consulte Sección 21.5, “¿Cómo funciona el Controlador de actualización?”.

Para conocer las limitaciones que tiene el Controlador de actualización, consulte Sección 21.8, “Limitaciones conocidas”.

Para obtener información sobre la diferencia entre el Controlador de actualización y el System Upgrade Controller, consulte Sección 21.2, “Controlador de actualización frente a System Upgrade Controller”.

21.2 Controlador de actualización frente a System Upgrade Controller

El System Upgrade Controller (SUC) (Capítulo 20, Controlador de actualización del sistema) es una herramienta de propósito general que propaga instrucciones de actualización a nodos específicos de Kubernetes.

Aunque admite algunas operaciones de «Día 2» para la plataforma SUSE Telco Cloud, no las cubre todas. Además, incluso para las operaciones admitidas, los usuarios deben configurar, mantener y desplegar manualmente múltiples SUC Plans: un proceso propenso a errores que puede dar lugar a problemas inesperados.

Esto llevó a la necesidad de una herramienta que automatice y abstraiga la complejidad de gestionar diversas operaciones de «Día 2» para la plataforma SUSE Telco Cloud. Por tanto, se desarrolló el Upgrade Controller. Simplifica el proceso de actualización al introducir un único user-facing resource que dirige la actualización. Los usuarios solo necesitan gestionar este recurso, mientras que el Upgrade Controller se encarga del resto.

21.3 Instalación del Controlador de actualización

21.3.1 Requisitos previos

21.3.2 Pasos

  1. Instale el gráfico de Helm del Controlador de actualización en su clúster de gestión:

    helm install upgrade-controller oci://registry.suse.com/edge/charts/upgrade-controller --version 306.0.4+up0.1.3 --create-namespace --namespace upgrade-controller-system
  2. Valide el despliegue del Upgrade Controller:

    kubectl get deployment -n upgrade-controller-system
  3. Valide el pod del Upgrade Controller:

    kubectl get pods -n upgrade-controller-system
  4. Valide los registros del pod del Upgrade Controller:

    kubectl logs <pod_name> -n upgrade-controller-system

21.4 Instalación del Controlador de actualización mediante Edge Image Builder

Como alternativa a la instalación manual descrita anteriormente, es posible instalar el Controlador de actualización como parte del despliegue inicial orquestado por Edge Image Builder (Capítulo 12, Edge Image Builder).

En este caso, es necesario añadir la siguiente configuración de helm chart al archivo de configuración de EIB:

kubernetes:
  helm:
    charts:
      - name: cert-manager
        repositoryName: jetstack
        version: {version-cert-manager}
        targetNamespace: cert-manager
        valuesFile: certmanager-values.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: upgrade-controller
        version: {version-upgrade-controller-chart}
        repositoryName: suse-edge-charts
        targetNamespace: upgrade-controller-system
        createNamespace: true
        installationNamespace: kube-system

21.5 ¿Cómo funciona el Controlador de actualización?

Para realizar una actualización de la versión de Edge, el Upgrade Controller introduce dos nuevos recursos personalizados de Kubernetes:

  • UpgradePlan (Sección 21.6.1, “UpgradePlan”) - creado por el usuario; contiene configuraciones relativas a una actualización de la versión de Edge.

  • ReleaseManifest (Sección 21.6.2, “ReleaseManifest”) - creado por el Controlador de actualización; contiene versiones de componentes específicas para una versión de Edge concreta. Este archivo no debe ser editado por los usuarios.

El Upgrade Controller procede a crear un recurso ReleaseManifest que contiene los datos de los componentes para la versión de Edge especificada por el usuario en la propiedad releaseVersion del recurso UpgradePlan.

Utilizando los datos de los componentes del ReleaseManifest, el Upgrade Controller procede a actualizar los componentes de la versión de Edge en el siguiente orden:

Nota
Nota

Durante el proceso de actualización, el Upgrade Controller envía continuamente información de actualización al UpgradePlan creado. Para obtener más información sobre cómo realizar el seguimiento del proceso de actualización, véase Seguimiento del proceso de actualización (Sección 21.7, “Seguimiento del proceso de actualización”).

21.5.1 Actualización del sistema operativo

Para actualizar el sistema operativo, el Controlador de actualización crea planes SUC (Capítulo 20, Controlador de actualización del sistema) que tienen la siguiente plantilla de nomenclatura:

  • Para planes SUC relacionados con actualizaciones del SO de los nodos del plano de control: control-plane-<os-name>-<os-version>-<suffix>.

  • Para planes SUC relacionados con actualizaciones del SO de los nodos trabajadores: workers-<os-name>-<os-version>-<suffix>.

Basándose en estos planes, SUC procede a crear cargas de trabajo en cada nodo del clúster que realizan la actualización real del SO.

Dependiendo del ReleaseManifest, la actualización del SO puede incluir:

  • Actualizaciones solo de paquetes: para casos de uso en los que la versión del SO no cambia entre versiones de Edge.

  • Migración completa del SO: para casos de uso en los que la versión del SO cambia entre versiones de Edge.

La actualización se ejecuta uno a uno, empezando primero por los nodos del plano de control. Solo si finaliza la actualización del nodo del plano de control, comenzarán a actualizarse los nodos trabajadores.

Nota
Nota

El controlador de actualización configura los planes SUC del SO para realizar un vaciado de los nodos del clúster si este tiene más de un nodo del tipo especificado.

Para clústeres en los que los nodos del plano de control son más de uno y solo hay un nodo trabajador, se realizará un vaciado solo para los nodos del plano de control y viceversa.

Para obtener información sobre cómo desactivar por completo los vaciados de nodos, consulte la sección UpgradePlan (Sección 21.6.1, “UpgradePlan”).

21.5.2 Actualización de versión de Kubernetes

Para actualizar la distribución de Kubernetes de un clúster, el controlador de actualización crea planes SUC (Capítulo 20, Controlador de actualización del sistema) que tienen la siguiente plantilla de nomenclatura:

  • Para planes SUC relacionados con actualizaciones de versión de Kubernetes de nodos del plano de control: control-plane-<k8s-version>-<suffix>.

  • Para planes SUC relacionados con actualizaciones de versión de Kubernetes de nodos trabajadores: workers-<k8s-version>-<suffix>.

Basándose en estos planes, SUC procede a crear cargas de trabajo en cada nodo del clúster que realizan la actualización de versión de Kubernetes propiamente dicha.

La actualización de versión de Kubernetes se realizará uno a uno, empezando primero por los nodos del plano de control. Solo si finaliza la actualización de versión del nodo del plano de control, comenzarán a actualizarse los nodos trabajadores.

Nota
Nota

El controlador de actualización configura los planes SUC de Kubernetes para realizar un vaciado de los nodos del clúster si este tiene más de un nodo del tipo especificado.

Para clústeres en los que los nodos del plano de control son más de uno y solo hay un nodo trabajador, se realizará un vaciado solo para los nodos del plano de control y viceversa.

Para obtener información sobre cómo desactivar por completo los vaciados de nodos, consulte Sección 21.6.1, “UpgradePlan”.

21.5.3 Actualizaciones de componentes adicionales

Actualmente, todos los componentes adicionales se instalan mediante gráficos de Helm. Para obtener una lista completa de los componentes de una versión específica, consulte las Notas de la versión (Capítulo 75, Notas de la versión).

Para los gráficos de Helm desplegados a través de EIB (Capítulo 12, Edge Image Builder), el controlador de actualización actualiza el HelmChart CR existente de cada componente.

Para los gráficos de Helm desplegados fuera de EIB, el controlador de actualización crea un recurso HelmChart para cada componente.

Tras la creación/actualización del recurso HelmChart, el controlador de actualización depende del helm-controller para detectar este cambio y proceder con la actualización real del componente.

Los gráficos se actualizarán secuencialmente según su orden en el ReleaseManifest. También se pueden pasar valores adicionales a través del UpgradePlan. Si la versión de un gráfico permanece sin cambios en la nueva versión de SUSE Telco Cloud, no se actualizará. Para obtener más información acerca de esto, consulte Sección 21.6.1, “UpgradePlan”.

21.6 Extensiones de la API de Kubernetes

Extensiones de la API de Kubernetes introducidas por el controlador de actualización.

21.6.1 UpgradePlan

El Controlador de actualización introduce un nuevo recurso personalizado de Kubernetes llamado UpgradePlan.

El UpgradePlan sirve como mecanismo de instrucciones para el Controlador de actualización y admite las siguientes configuraciones:

  • releaseVersion - Versión de lanzamiento de Edge a la que se debe actualizar el clúster. La versión de lanzamiento debe seguir el versionado semántico y debe obtenerse de las Notas de la versión (Capítulo 75, Notas de la versión).

  • disableDrain - Opcional; indica al controlador de actualización si debe desactivar los drenajes de nodos. Útil cuando se tienen cargas de trabajo con presupuestos de interrupción.

    • Ejemplo para la desactivación del drenaje de nodos del plano de control:

      spec:
        disableDrain:
          controlPlane: true
    • Ejemplo para la desactivación del drenaje de nodos del plano de control y de nodos trabajadores:

      spec:
        disableDrain:
          controlPlane: true
          worker: true
  • helm - Opcional; especifica valores adicionales para los componentes instalados mediante Helm.

    Aviso
    Aviso

    Solo se recomienda utilizar este campo para valores que sean críticos para las actualizaciones. Las actualizaciones estándar de valores de gráficos deben realizarse después de que los gráficos respectivos se hayan actualizado a la siguiente versión.

    • Ejemplo:

      spec:
        helm:
        - chart: foo
          values:
            bar: baz

21.6.2 ReleaseManifest

El Upgrade Controller introduce un nuevo recurso personalizado de Kubernetes llamado ReleaseManifest.

El recurso ReleaseManifest es creado por el Upgrade Controller y contiene datos de componentes para una versión de lanzamiento de Edge específica. Esto significa que cada actualización de la versión de lanzamiento de Edge estará representada por un recurso ReleaseManifest diferente.

Aviso
Aviso

El Release Manifest siempre debe ser creado por el Upgrade Controller.

No es aconsejable crear o editar manualmente los recursos ReleaseManifest. Los usuarios que decidan hacerlo deben hacerlo bajo su propio riesgo.

Los datos de los componentes que incluye el Release Manifest incluyen, entre otros:

  • Datos del sistema operativo: versión, arquitecturas compatibles, datos de actualización adicionales, etc.

  • Datos de distribución de Kubernetes: versiones compatibles de RKE2/K3s

  • Datos de componentes adicionales: datos de los gráficos de Helm de SUSE (ubicación, versión, nombre, etc.)

Para ver un ejemplo de cómo puede ser un Release Manifest, consulte la documentación sentido ascendente. Tenga en cuenta que esto es solo un ejemplo y no pretende ser creado como un recurso ReleaseManifest válido.

21.7 Seguimiento del proceso de actualización

Esta sección sirve como medio para realizar el seguimiento y depurar el proceso de actualización que el Upgrade Controller inicia una vez que el usuario crea un UpgradePlan recurso.

21.7.1 General

La información general sobre el estado del proceso de actualización puede verse en las condiciones de estado del Upgrade Plan.

El estado del recurso Upgrade Plan puede verse de la siguiente manera:

kubectl get upgradeplan <upgradeplan_name> -n upgrade-controller-system -o yaml
Ejemplo 21.1: Ejemplo de Upgrade Plan en ejecución:
apiVersion: lifecycle.suse.com/v1alpha1
kind: UpgradePlan
metadata:
  name: upgrade-plan-mgmt
  namespace: upgrade-controller-system
spec:
  releaseVersion: 3.6
status:
  conditions:
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Control plane nodes are being upgraded
    reason: InProgress
    status: "False"
    type: OSUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Kubernetes upgrade is not yet started
    reason: Pending
    status: Unknown
    type: KubernetesUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Rancher upgrade is not yet started
    reason: Pending
    status: Unknown
    type: RancherUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Longhorn upgrade is not yet started
    reason: Pending
    status: Unknown
    type: LonghornUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: MetalLB upgrade is not yet started
    reason: Pending
    status: Unknown
    type: MetalLBUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: CDI upgrade is not yet started
    reason: Pending
    status: Unknown
    type: CDIUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: KubeVirt upgrade is not yet started
    reason: Pending
    status: Unknown
    type: KubeVirtUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: NeuVector upgrade is not yet started
    reason: Pending
    status: Unknown
    type: NeuVectorUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: EndpointCopierOperator upgrade is not yet started
    reason: Pending
    status: Unknown
    type: EndpointCopierOperatorUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Elemental upgrade is not yet started
    reason: Pending
    status: Unknown
    type: ElementalUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: SRIOV upgrade is not yet started
    reason: Pending
    status: Unknown
    type: SRIOVUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Metal3 upgrade is not yet started
    reason: Pending
    status: Unknown
    type: Metal3Upgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: RancherTurtles upgrade is not yet started
    reason: Pending
    status: Unknown
    type: RancherTurtlesUpgraded
  observedGeneration: 1
  sucNameSuffix: 90315a2b6d

Aquí se puede ver cada componente para el que el Upgrade Controller intentará programar una actualización. Cada condición sigue la siguiente plantilla:

  • lastTransitionTime - la última vez que esta condición de componente ha cambiado de un estado a otro.

  • message - mensaje que indica el estado de actualización actual de la condición del componente específico.

  • reason - el estado de actualización actual de la condición del componente específico. Posibles reasons incluyen:

    • Succeeded - la actualización del componente específico se ha realizado correctamente.

    • Failed - la actualización del componente específico ha fallado.

    • InProgress - la actualización del componente específico está en curso.

    • Pending - la actualización del componente específico aún no está programada.

    • Skipped - el componente específico no se encuentra en el clúster, por lo que se omitirá su actualización.

    • Error - el componente específico ha encontrado un error transitorio.

  • status - estado de la condición actual type, uno de True, False, Unknown.

  • type - indicador del componente actualizado actualmente.

El controlador de actualización crea planes SUC para condiciones de componente de tipo OSUpgraded y KubernetesUpgraded. Para realizar un seguimiento adicional de los planes SUC creados para estos componentes, consulte Sección 20.3, “Monitorización de los planes del controlador de actualización del sistema”.

Todos los demás tipos de condiciones de componente pueden seguirse consultando los recursos creados para ellos por el helm-controller. Para obtener más información, consulte Sección 21.7.2, “Controlador de Helm”.

Un plan de actualización programado por el controlador de actualización puede marcarse como successful una vez que:

  1. No hay condiciones de componente Pending o InProgress.

  2. La propiedad lastSuccessfulReleaseVersion apunta al releaseVersion que se especifica en la configuración del plan de actualización. Esta propiedad se añade al estado del plan de actualización por parte del controlador de actualización una vez que el proceso de actualización se realiza correctamente.

Ejemplo 21.2: Ejemplo de UpgradePlan correcto:
apiVersion: lifecycle.suse.com/v1alpha1
kind: UpgradePlan
metadata:
  name: upgrade-plan-mgmt
  namespace: upgrade-controller-system
spec:
  releaseVersion: 3.6
status:
  conditions:
  - lastTransitionTime: "2024-10-01T06:26:48Z"
    message: All cluster nodes are upgraded
    reason: Succeeded
    status: "True"
    type: OSUpgraded
  - lastTransitionTime: "2024-10-01T06:26:59Z"
    message: All cluster nodes are upgraded
    reason: Succeeded
    status: "True"
    type: KubernetesUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart rancher upgrade succeeded
    reason: Succeeded
    status: "True"
    type: RancherUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart longhorn is not installed
    reason: Skipped
    status: "False"
    type: LonghornUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Specified version of chart metallb is already installed
    reason: Skipped
    status: "False"
    type: MetalLBUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart cdi is not installed
    reason: Skipped
    status: "False"
    type: CDIUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart kubevirt is not installed
    reason: Skipped
    status: "False"
    type: KubeVirtUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart neuvector-crd is not installed
    reason: Skipped
    status: "False"
    type: NeuVectorUpgraded
  - lastTransitionTime: "2024-10-01T06:27:14Z"
    message: Specified version of chart endpoint-copier-operator is already installed
    reason: Skipped
    status: "False"
    type: EndpointCopierOperatorUpgraded
  - lastTransitionTime: "2024-10-01T06:27:14Z"
    message: Chart elemental-operator upgrade succeeded
    reason: Succeeded
    status: "True"
    type: ElementalUpgraded
  - lastTransitionTime: "2024-10-01T06:27:15Z"
    message: Chart sriov-crd is not installed
    reason: Skipped
    status: "False"
    type: SRIOVUpgraded
  - lastTransitionTime: "2024-10-01T06:27:19Z"
    message: Chart metal3 is not installed
    reason: Skipped
    status: "False"
    type: Metal3Upgraded
  - lastTransitionTime: "2024-10-01T06:27:27Z"
    message: Chart rancher-turtles is not installed
    reason: Skipped
    status: "False"
    type: RancherTurtlesUpgraded
  lastSuccessfulReleaseVersion: 3.6
  observedGeneration: 1
  sucNameSuffix: 90315a2b6d

21.7.2 Controlador de Helm

Esta sección trata sobre cómo realizar el seguimiento de los recursos creados por el helm-controller.

Nota
Nota

Los pasos siguientes asumen que kubectl se ha configurado para conectarse al clúster donde se ha desplegado el Upgrade Controller.

  1. Localice el recurso HelmChart para el componente específico:

    kubectl get helmcharts -n kube-system
  2. Utilizando el nombre del recurso HelmChart, localice el Pod de actualización que fue creado por el helm-controller:

    kubectl get pods -l helmcharts.helm.cattle.io/chart=<helmchart_name> -n kube-system
    
    # Example for Rancher
    kubectl get pods -l helmcharts.helm.cattle.io/chart=rancher -n kube-system
    NAME                         READY   STATUS      RESTARTS   AGE
    helm-install-rancher-tv9wn   0/1     Completed   0          16m
  3. Vea los registros del pod específico del componente:

    kubectl logs <pod_name> -n kube-system

21.8 Limitaciones conocidas

  • El Upgrade Controller espera que cualquier gráfico de Helm SUSE Telco Cloud adicional que se implemente a través de EIB (Capítulo 12, Edge Image Builder) tenga su HelmChart CR implementado en el espacio de nombres kube-system. Para hacer esto, configure la propiedad installationNamespace en su archivo de definición de EIB. Para obtener más información, consulte la documentación en sentido ascendente.

  • Actualmente, el Upgrade Controller no tiene forma de determinar la versión de lanzamiento de Edge que se está ejecutando en el clúster de gestión. Asegúrese de proporcionar una versión de lanzamiento de Edge que sea superior a la versión de lanzamiento de Edge que se está ejecutando actualmente en el clúster.

  • Actualmente, el Upgrade Controller solo admite actualizaciones en entornos no aislados. Las actualizaciones en entornos aislados aún no son posibles.

Parte IV Requisitos y suposiciones

  • 22 Hardware
  • Los requisitos de hardware para SUSE Telco Cloud son los siguientes:

  • 23 Red
  • Como referencia para la arquitectura de red, el siguiente diagrama muestra una arquitectura de red típica para un entorno de telecomunicaciones:

  • 24 Requisitos de puerto
  • Para funcionar correctamente, un despliegue de SUSE Telco Cloud requiere que varios puertos sean accesibles en los nodos del clúster de gestión y en los nodos del clúster de Kubernetes en sentido descendente.

  • 25 Servicios (DHCP, DNS, etc.)
  • Podrían requerirse algunos servicios externos como DHCP, DNS, etc., dependiendo del tipo de entorno donde se desplieguen:

  • 26 Deshabilitación de servicios de systemd
  • Para cargas de trabajo de telecomunicaciones, es importante deshabilitar o configurar correctamente algunos de los servicios que se ejecutan en los nodos para evitar cualquier impacto en el rendimiento de la carga de trabajo que se ejecuta en los nodos (latencia).

22 Hardware

Los requisitos de hardware para SUSE Telco Cloud son los siguientes:

  • Clúster de gestión: El clúster de gestión contiene componentes como SUSE Linux Micro, RKE2, SUSE Rancher Prime, Metal3, y se utiliza para gestionar varios clústeres en sentido descendente. Dependiendo del número de clústeres en sentido descendente que se vayan a gestionar, los requisitos de hardware para el servidor podrían variar.

    • Los requisitos mínimos para el servidor (VM o bare-metal) son:

      • RAM: 8 GB mínimo (recomendamos al menos 16 GB)

      • CPU: 2 mínimo (recomendamos al menos 4 CPU)

  • Clústeres en sentido descendente: Los clústeres en sentido descendente son los clústeres desplegados para ejecutar cargas de trabajo de telecomunicaciones. Se necesitan requisitos específicos para habilitar ciertas capacidades de telecomunicaciones como SR-IOV, CPU Performance Optimization, etc.

    • SR-IOV: para conectar VF (funciones virtuales) en modo de encaminamiento a CNF/VNF, la NIC debe ser compatible con SR-IOV y VT-d/AMD-Vi debe estar habilitado en el BIOS.

    • Procesadores: Para ejecutar cargas de trabajo de telecomunicaciones específicas, el modelo de procesador debe adaptarse para habilitar la mayoría de las funciones disponibles en esta tabla (Parte VI, “Configuración de las funciones Telco”) de referencia.

    • Requisitos de firmware para la instalación con medios virtuales:

      Hardware de servidorModelo de BMCEntorno de gestión

      Hardware de Dell

      15.ª generación

      iDRAC9

      Hardware de Supermicro

      01.00.25

      Supermicro SMC - redfish

      Hardware de HPE

      1.50

      iLO6

23 Red

Como referencia para la arquitectura de red, el siguiente diagrama muestra una arquitectura de red típica para un entorno de telecomunicaciones:

product atip requirements1

La arquitectura de red se basa en los siguientes componentes:

  • Red de gestión: Esta red se utiliza para la gestión de los nodos de clúster en sentido descendente. Se utiliza para la gestión fuera de banda. Normalmente, esta red también está conectada a un conmutador de gestión independiente, pero puede conectarse al mismo conmutador de servicio mediante VLAN para aislar el tráfico.

  • Red de plano de control: Esta red se utiliza para la comunicación entre los nodos de clúster descendentes y los servicios que se ejecutan en ellos. Esta red también se utiliza para la comunicación entre los nodos y los servicios externos, como los servidores DHCP o DNS. En algunos casos, para entornos conectados, el conmutador/enrutador puede gestionar el tráfico a través de Internet.

  • Otras redes: En algunos casos, los nodos podrían estar conectados a otras redes para fines específicos.

Nota
Nota

Para utilizar el flujo de trabajo de aprovisionamiento de red dirigido, el clúster de gestión debe tener conectividad de red con el controlador de gestión de placa base (BMC) del servidor de clúster descendente para que la preparación y el aprovisionamiento del host puedan automatizarse.

24 Requisitos de puerto

Para funcionar correctamente, un despliegue de SUSE Telco Cloud requiere que varios puertos sean accesibles en los nodos del clúster de gestión y en los nodos del clúster de Kubernetes en sentido descendente.

Nota
Nota

La lista exacta depende de los componentes opcionales desplegados y de las opciones de despliegue seleccionadas (p. ej., el complemento CNI).

24.1 Nodos de gestión

La siguiente tabla enumera los puertos abiertos en los nodos que ejecutan el clúster de gestión:

Nota
Nota

Para los puertos relacionados con el complemento CNI, véase Requisitos de puerto específicos de CNI (Sección 24.3, “Requisitos de puerto específicos de CNI”).

Tabla 24.1: Reglas de red de entrada para nodos de gestión
ProtocoloPuertoFuenteDescripción

TCP

22

Cualquier origen que requiera acceso SSH

Acceso SSH a los nodos del clúster de gestión

TCP

80

Equilibrador de carga/proxy que realiza la terminación TLS externa

Interfaz de usuario/API de Rancher cuando se utiliza la terminación TLS externa

TCP

443

Cualquier origen que requiera acceso TLS a la interfaz de usuario/API de Rancher

Agente de Rancher, interfaz de usuario/API de Rancher

TCP

2379

Nodos de servidor de RKE2 (clúster de gestión)

etcd Puerto de cliente

TCP

2380

Nodos de servidor de RKE2 (clúster de gestión)

etcd Puerto de par

TCP

6180

Cualquier BMC(1) al que Metal3/ironic haya indicado previamente que extraiga una imagen de disco RAM de IPA(2) de este puerto expuesto (sin TLS)

Ironic Servidor web httpd sin TLS que sirve imágenes ISO de IPA(2) para el arranque basado en medios virtuales

En caso de que este puerto esté habilitado, el funcionalmente equivalente pero habilitado para TLS (véase más abajo) no se abre

TCP

6185

Cualquier BMC(1) al que Metal3/ironic haya indicado previamente que extraiga una imagen de disco RAM de IPA(2) de este puerto expuesto (TLS)

Ironic Servidor web habilitado para TLS que sirve imágenes ISO de IPA(2) para el arranque basado en medios virtuales

En caso de que este puerto esté habilitado, el funcionalmente equivalente pero sin TLS (véase más arriba) no se abre

TCP

6385

Cualquier imagen de disco RAM de Metal3/ironic IPA(1) desplegada y ejecutándose en una instancia BareMetalHost "inscrita"

API de Ironic

TCP

6443

Cualquier nodo del clúster de gestión; cualquier cliente de Kubernetes externo (al clúster de gestión)

API de Kubernetes

TCP

6545

Cualquier nodo del clúster de gestión

Extraer artefactos de un registro compatible con OCI (Hauler)

TCP

9345

Nodos de servidor y agente de RKE2 (clúster de gestión)

API del supervisor de RKE2 para el registro de nodos (puerto abierto en todos los nodos de servidor de RKE2)

TCP

10250

Cualquier nodo del clúster de gestión

kubelet métricas

TCP/UDP/SCTP

30000-32767

Cualquier fuente externa (al clúster de gestión) que acceda a un servicio expuesto en la red principal a través de un spec.type: NodePort o spec.type: LoadBalancer objeto de API de servicio

Rango de puertos NodePort disponible

(1) BMC: Controlador de gestión de placa base
(2) IPA: Ironic Python Agent

24.2 Nodos de sentido descendente

En SUSE Telco Cloud, antes de que cualquier servidor en sentido descendente pase a formar parte de un clúster de Kubernetes en sentido descendente en ejecución (o ejecute por sí mismo un clúster de Kubernetes en sentido descendente de nodo único), es necesario que pase por algunos de los estados de aprovisionamiento de BaremetalHost.

  • El controlador de gestión de placa base (BMC) de un servidor en sentido descendente recién declarado debe ser accesible a través de la red fuera de banda. Se dan instrucciones al BMC (desde el servicio ironic que se ejecuta en el clúster de gestión) sobre los pasos iniciales a seguir:

    1. Extraer y cargar la imagen de ramdisk de IPA indicada en el BMC ofrecido virtual media.

    2. Encienda el servidor.

Se espera que los siguientes puertos estén expuestos desde el BMC (podrían diferir dependiendo del hardware exacto):

Tabla 24.2: Reglas de red de entrada para controladores de gestión de placa base (BMC)
ProtocoloPuertoFuenteDescripción

TCP

80

Conductor de Ironic (desde el clúster de gestión)

Acceso a la API de Redfish (HTTP)

TCP

443

Conductor de Ironic (desde el clúster de gestión)

Acceso a la API de Redfish (HTTPS)

  • Una vez que la imagen de ramdisk IPA cargada en el BMC virtual media se utiliza para arrancar la imagen del servidor descendente, comienza la fase de inspección del hardware. La siguiente tabla enumera los puertos expuestos por una imagen de ramdisk IPA en ejecución:

Tabla 24.3: Reglas de red de entrada para nodos descendentes - Metal3/Ironic Fase de aprovisionamiento
ProtocoloPuertoFuenteDescripción

TCP

22

Cualquier origen que requiera acceso SSH a la imagen de ramdisk IPA

Acceso SSH a un nodo de clúster descendente que está siendo inspeccionado

TCP

9999

Conductor de Ironic (desde el clúster de gestión)

Comandos de Ironic hacia la imagen de ramdisk en ejecución

  • Una vez que el host baremetal esté correctamente aprovisionado y se haya unido a un clúster de Kubernetes en sentido descendente, expone los siguientes puertos:

Nota
Nota

Para los puertos relacionados con el complemento CNI, véase Requisitos de puerto específicos de CNI (Sección 24.3, “Requisitos de puerto específicos de CNI”).

Tabla 24.4: Reglas de red de entrada para nodos descendentes
ProtocoloPuertoFuenteDescripción

TCP

22

Cualquier origen que requiera acceso SSH

Acceso SSH a nodos de clúster descendentes

TCP

80

Equilibrador de carga/proxy que realiza la terminación TLS externa

Interfaz de usuario/API de Rancher cuando se utiliza la terminación TLS externa

TCP

443

Cualquier origen que requiera acceso TLS a la interfaz de usuario/API de Rancher

Agente de Rancher, interfaz de usuario/API de Rancher

TCP

2379

Nodos de servidor de RKE2 (clúster descendente)

etcd Puerto de cliente

TCP

2380

Nodos de servidor de RKE2 (clúster descendente)

etcd Puerto de par

TCP

6443

Cualquier nodo de clúster descendente; cualquier cliente de Kubernetes externo (al clúster descendente).

API de Kubernetes

TCP

9345

Nodos de servidor y agente de RKE2 (clúster descendente)

API del supervisor de RKE2 para el registro de nodos (puerto abierto en todos los nodos de servidor de RKE2)

TCP

10250

Cualquier nodo de clúster descendente

kubelet métricas

TCP

10255

Cualquier nodo de clúster descendente

kubelet acceso de sólo lectura

TCP/UDP/SCTP

30000-32767

Cualquier fuente externa (al clúster descendente) que acceda a un servicio expuesto en la red primaria a través de un spec.type: NodePort o spec.type: LoadBalancer objeto de API de servicio

Rango de puertos NodePort disponible

24.3 Requisitos de puerto específicos de CNI

Cada variante de CNI compatible viene con su propio conjunto de requisitos de puerto. Para obtener más detalles, consulte Reglas de red de entrada específicas de CNI en la documentación de RKE2.

Cuando cilium se establece como el complemento CNI predeterminado/primario, el siguiente puerto TCP se expone adicionalmente cuando la carga de trabajo cilium-operator está configurada para exponer métricas fuera del clúster de Kubernetes en el que está desplegada. Esto garantiza que una instancia de servidor Prometheus externa que se ejecute fuera de ese clúster de Kubernetes aún pueda recopilar estas métricas.

Nota
Nota

Esta es la opción predeterminada al desplegar cilium a través del gráfico de Helm rke2-cilium.

Tabla 24.5: Reglas de red de entrada para nodos de gestión/sentido descendente: exposición de métricas externas desde cilium-operator habilitada
ProtocoloPuertoFuenteDescripción

TCP

9963

Colector de métricas externo (al clúster de Kubernetes)

exposición de métricas de cilium-operator

25 Servicios (DHCP, DNS, etc.)

Podrían requerirse algunos servicios externos como DHCP, DNS, etc., dependiendo del tipo de entorno donde se desplieguen:

  • Entorno conectado: En este caso, los nodos estarán conectados a Internet (mediante protocolos de enrutamiento L3) y los servicios externos serán proporcionados por el cliente.

  • Entorno desconectado / entorno aislado: En este caso, los nodos no tendrán conectividad IP a Internet y se requerirán servicios adicionales para replicar localmente el contenido necesario para el flujo de trabajo de aprovisionamiento de red dirigido.

  • Servidor de archivos: Se utiliza un servidor de archivos para almacenar las imágenes del SO que se aprovisionarán en los nodos del clúster en sentido descendente durante el flujo de trabajo de aprovisionamiento de red dirigido. El gráfico de Helm Metal3 puede desplegar un servidor multimedia para almacenar las imágenes del SO; consulte la siguiente sección (Nota), pero también es posible utilizar un servidor web local existente.

26 Deshabilitación de servicios de systemd

Para cargas de trabajo de telecomunicaciones, es importante deshabilitar o configurar correctamente algunos de los servicios que se ejecutan en los nodos para evitar cualquier impacto en el rendimiento de la carga de trabajo que se ejecuta en los nodos (latencia).

  • rebootmgr es un servicio que permite configurar una estrategia de reinicio cuando el sistema tiene actualizaciones pendientes. Para cargas de trabajo de telecomunicaciones, es realmente importante deshabilitar o configurar correctamente el servicio rebootmgr para evitar el reinicio de los nodos en caso de actualizaciones programadas por el sistema, a fin de evitar cualquier impacto en los servicios que se ejecutan en los nodos.

Nota
Nota

Para obtener más información sobre rebootmgr, consulte el repositorio de GitHub de rebootmgr.

Verifique la estrategia que se está utilizando ejecutando:

cat /etc/rebootmgr.conf
[rebootmgr]
window-start=03:30
window-duration=1h30m
strategy=best-effort
lock-group=default

y puede deshabilitarla ejecutando:

sed -i 's/strategy=best-effort/strategy=off/g' /etc/rebootmgr.conf

o utilizando el comando rebootmgrctl:

rebootmgrctl strategy off
Nota
Nota

Esta configuración para establecer la estrategia rebootmgr se puede automatizar utilizando el flujo de trabajo de aprovisionamiento de red dirigido. Para obtener más información, consulte la documentación de aprovisionamiento automatizado (Parte VII, “Aprovisionamiento de red dirigido totalmente automatizado”).

  • transactional-update es un servicio que permite actualizaciones automáticas controladas por el sistema. Para cargas de trabajo de telecomunicaciones, es importante deshabilitar las actualizaciones automáticas para evitar cualquier impacto en los servicios que se ejecutan en los nodos.

Para deshabilitar las actualizaciones automáticas, puede ejecutar:

systemctl --now disable transactional-update.timer
systemctl --now disable transactional-update-cleanup.timer
  • fstrim es un servicio que permite recortar los sistemas de archivos automáticamente cada semana. Para cargas de trabajo de telecomunicaciones, es importante deshabilitar el recorte automático para evitar cualquier impacto en los servicios que se ejecutan en los nodos.

Para deshabilitar el recorte automático, puede ejecutar:

systemctl --now disable fstrim.timer

Parte V Configuración del clúster de gestión

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

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

  • 29 Preparación de la imagen para entornos conectados
  • Edge Image Builder se utiliza para crear la imagen para el clúster de gestión; en este documento cubrimos la configuración mínima necesaria para configurar el clúster de gestión.

  • 30 Preparación de imágenes para entornos aislados
  • Esta sección describe cómo preparar la imagen para entornos aislados mostrando solo las diferencias respecto a las secciones anteriores. Se requieren los siguientes cambios en la sección anterior (Preparación de imágenes para entornos conectados (Capítulo 29, Preparación de la imagen para entornos c…

  • 31 Creación de imágenes
  • Una vez preparada la estructura de directorios siguiendo las secciones anteriores (tanto para escenarios conectados como para entornos aislados), ejecute el siguiente comando para construir la imagen:

  • 32 Aprovisionar el clúster de gestión
  • La imagen anterior contiene todos los componentes explicados anteriormente y puede utilizarse para aprovisionar el clúster de gestión mediante una máquina virtual o un servidor sin sistema operativo (utilizando la función de medios virtuales).

  • 33 Consideraciones y configuración de doble pila
  • Los ejemplos mostrados en las secciones anteriores proporcionan orientación y ejemplos sobre cómo configurar un clúster de gestión IPv4 de pila única. Dicho clúster de gestión es independiente del estado operativo de los clústeres descendentes, que pueden configurarse individualmente para operar en …

27 Introducción

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

  • SUSE Linux Micro como SO. Dependiendo del caso de uso, algunas configuraciones como la red, el almacenamiento, los usuarios y los argumentos del kernel pueden personalizarse.

  • RKE2 como clúster de Kubernetes. Dependiendo del caso de uso, puede configurarse para utilizar complementos de CNI específicos, como Multus, Cilium, Calico, etc.

  • Rancher como plataforma de gestión para administrar el ciclo de vida de los clústeres.

  • Metal3 como componente para gestionar el ciclo de vida de los nodos de equipo sin sistema operativo.

  • CAPI como componente para gestionar el ciclo de vida de los clústeres de Kubernetes (clústeres en sentido descendente). El RKE2 CAPI Provider se utiliza para gestionar el ciclo de vida de los clústeres RKE2.

Con todos los componentes mencionados anteriormente, el clúster de gestión puede administrar el ciclo de vida de los clústeres en sentido descendente, utilizando un enfoque declarativo para gestionar la infraestructura y las aplicaciones.

Nota
Nota

Para obtener más información acerca de SUSE Linux Micro, consulte: SUSE Linux Micro (Capítulo 10, SUSE Linux Micro)

Para obtener más información acerca de RKE2, consulte: RKE2 (Capítulo 14, RKE2)

Para obtener más información acerca de Rancher, consulte: Rancher (Capítulo 6, Rancher)

Para obtener más información acerca de Metal3, consulte: Metal3 (Capítulo 11, Metal3)

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

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

product atip mgmtcluster1

Los siguientes son los pasos principales para configurar el clúster de gestión utilizando un enfoque declarativo:

  1. Preparación de la imagen para entornos conectados (Capítulo 29, Preparación de la imagen para entornos conectados): El primer paso es preparar los manifiestos y archivos con todas las configuraciones necesarias que se utilizarán en entornos conectados.

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

    • Archivo de definición del clúster de gestión (Sección 29.2, “Archivo de definición del clúster de gestión”): El archivo mgmt-cluster.yaml es el archivo de definición principal para el 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 va a crear utilizando la imagen base.

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

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

    • Carpeta personalizada (Sección 29.3, “Carpeta personalizada”): La carpeta custom contiene los archivos de configuración y los scripts 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 scripts que utilizará el clúster de gestión.

    • Kubernetes folder (Sección 29.4, “Kubernetes folder”): 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 29.5, “Carpeta de redes”): 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 (Capítulo 30, Preparación de imágenes para entornos aislados): El paso consiste en mostrar las diferencias para preparar los manifiestos y archivos que se utilizarán en un entorno aislado.

    • Modificaciones en el archivo de definición (Sección 30.1, “Modificaciones en el archivo de definición”): El archivo mgmt-cluster.yaml debe modificarse para incluir la sección embeddedArtifactRegistry con el campo images establecido en todas las imágenes de contenedor que se incluirán en la imagen de salida de EIB.

    • Modificaciones en la carpeta personalizada (Sección 30.2, “Modificaciones en la carpeta custom”): La carpeta custom debe modificarse para incluir los recursos necesarios para ejecutar el clúster de gestión en un entorno aislado.

      • Script de registro: El script custom/scripts/99-register.sh debe eliminarse cuando utilice un entorno aislado.

  3. Creación de imagen (Capítulo 31, Creación de imágenes): Este paso cubre la creación de la imagen utilizando la herramienta Edge Image Builder (tanto para escenarios conectados como para entornos aislados). Compruebe los requisitos previos (Capítulo 12, Edge Image Builder) para ejecutar la herramienta Edge Image Builder en su sistema.

  4. Aprovisionamiento del clúster de gestión (Capítulo 32, Aprovisionar el clúster de gestión): Este paso cubre el aprovisionamiento del clúster de gestión utilizando la imagen creada en el paso anterior (tanto para escenarios conectados como para entornos aislados). Este paso se puede realizar utilizando un portátil, servidor, VM o cualquier otro sistema AMD64/Intel 64 con un puerto USB.

Nota
Nota

Para obtener más información sobre Edge Image Builder, consulte Edge Image Builder (Capítulo 12, Edge Image Builder) y Edge Image Builder Quick Start (Capítulo 5, Clústeres independientes con Edge Image Builder).

29 Preparación de la imagen para entornos conectados

Edge Image Builder se utiliza para crear la imagen para el clúster de gestión; en este documento cubrimos 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 contenedor, como Podman o Rancher Desktop. Para esta guía, asumimos que podman está disponible.

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

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

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

  • metal3VIP para la dirección VIP de Metal3.

29.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
├── os-files
│ └── var
│   └── lib
│     └── rancher
│       └── rke2
│         └── server
│           └── manifests
│             └── rke2-ingress-config.yaml
├── kubernetes
│ ├── manifests
│ │ ├── neuvector-namespace.yaml
│ │ ├── ingress-l2-adv.yaml
│ │ └── ingress-ippool.yaml
│ ├── helm
│ │ └── values
│ │     ├── rancher.yaml
│ │     ├── neuvector.yaml
│ │     ├── longhorn.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.2-Base-SelfInstall-GM.install.iso debe descargarse desde el SUSE Customer Center o la página de descargas de SUSE, y debe ubicarse en el directorio 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 puede encontrar en la misma ubicación donde se descargó la imagen.

Se puede encontrar un ejemplo de la estructura de directorios en el SUSE Telco Cloudrepositorio de GitHub bajo el directorio "telco-examples".

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

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

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-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
    - open-iscsi
    sccRegistrationCode: $SCC_REGISTRATION_CODE
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: cert-manager
        repositoryName: jetstack
        version: 1.20.1
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: suse-storage
        releaseName: longhorn
        version: 1.11.2
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: longhorn.yaml
      - name: metallb
        version: 306.0.2+up0.15.3
        targetNamespace: metallb-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
      - name: metal3
        version: 306.0.29+up0.15.0
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: rancher-turtles-providers
        version: 306.0.7+up0.26.2
        repositoryName: suse-edge-charts
        targetNamespace: cattle-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.14.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
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $\{APPS.RANCHER.IO_USERNAME\}
          password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
  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 en el 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.2-Base-SelfInstall-GM.install.iso
  outputImageName: eib-mgmt-cluster-image.iso

donde baseImage es la imagen original que descargó del SUSE Customer Center 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 del 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 compilación y puede obtenerse en el SUSE Customer Center. La contraseña cifrada puede generarse utilizando el comando openssl de la siguiente manera:

openssl passwd -6 MyPassword!123

Esto genera algo similar a:

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

kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: cert-manager
        repositoryName: jetstack
        version: 1.20.1
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: suse-storage
        releaseName: longhorn
        version: 1.11.2
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: longhorn.yaml
      - name: metal3
        version: 306.0.29+up0.15.0
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: metallb
        version: 306.0.2+up0.15.3
        targetNamespace: metallb-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
      - name: rancher-turtles-providers
        version: 306.0.7+up0.26.2
        repositoryName: suse-edge-charts
        targetNamespace: cattle-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.14.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
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $\{APPS.RANCHER.IO_USERNAME\}
          password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
    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 gráficos de Helm que se instalarán, los repositorios que se utilizarán y la configuración de la versión para todos ellos.

La sección network contiene la configuración de la red, como apiHost y apiVIP que utilizará el componente RKE2. La apiVIP debe ser una dirección IP que no se utilice en la red y no debe formar parte del grupo DHCP (en caso de que utilicemos DHCP). Además, cuando utilizamos la apiVIP en un clúster de varios nodos, se utiliza para acceder al servidor de la API de Kubernetes. La 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 puede ampliarse 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.

  • Opcionalmente, utilice el campo initializer para especificar el host de inicio; de lo contrario, será el primer nodo de la lista.

  • Los nombres de los nodos deben ser los mismos que los nombres de host definidos en la Carpeta de red (Sección 29.5, “Carpeta de redes”) cuando se requiera configuración de red.

29.3 Carpeta personalizada

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 scripts que utilizará el clúster de gestión.

La carpeta custom/files contiene los siguientes archivos:

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

    #!/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 utilizará (no se necesitan modificaciones). En futuras versiones, este script será reemplazado para utilizar en su lugar Rancher Turtles para facilitarlo.

    #!/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 -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
    
    # Clean up the lock cm
    
    ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE}
    • rancher.sh: contiene la configuración del componente Rancher que se utilizará (no se necesitan modificaciones).

      #!/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 para ejecutar los scripts durante el primer arranque (no se necesitan modificaciones).

      [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:

  • Script 99-alias.sh: contiene el alias que utilizará el clúster de gestión para cargar el archivo kubeconfig en el primer arranque (no se necesitan modificaciones).

    #!/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
  • Script 99-mgmt-setup.sh: contiene la configuración para copiar los scripts durante el primer arranque (no se necesitan modificaciones).

    #!/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
  • Script 99-register.sh: contiene la configuración para registrar el sistema utilizando el código de registro de SCC. Se deben configurar correctamente ${SCC_ACCOUNT_EMAIL} y ${SCC_REGISTRATION_CODE} 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}"

29.4 Kubernetes folder

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: El complemento CNI instalado por defecto es Cilium, por lo que no necesita crear esta carpeta ni este archivo para configurarlo. En caso de que necesite personalizar el complemento CNI, puede utilizar el archivo server.yaml en la carpeta kubernetes/config. Contiene la información siguiente:

    cni:
    - multus
    - cilium
    ingress-controller: traefik
    write-kubeconfig-mode: '0644'
    selinux: true
    system-default-registry: registry.rancher.com
Nota
Nota

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

Aviso
Aviso

El proveedor de ingress Traefik integrado en RKE2/K3s es el único controlador de ingress compatible en la versión SUSE Telco Cloud 3.6, siendo todavía posible ejecutar temporalmente Ingress-NGINX junto con Traefik para admitir escenarios complejos de migración de ingress, pero solo después de que los clústeres de gestión SUSE Telco Cloud y/o los clústeres en sentido descendente se hayan actualizado a la versión 3.6 y durante el tiempo necesario para realizar dicha migración. Dado que Traefik aún no es el controlador de ingress predeterminado en RKE2 (lo será a partir de RKE2 v1.36 en adelante), debe "solicitarse" explícitamente desde el archivo de configuración del servidor RKE2, lo que resulta en la necesidad de incluir el archivo kubernetes/config/server.yaml en todas las imágenes ISO de autoinstalación de EIB generadas para aprovisionar los nodos de los clústeres de gestión SUSE Telco Cloud 3.6.

La guía de RKE2 Migración de Ingress NGINX a Traefik proporciona detalles sobre las rutas de migración de ingress disponibles una vez que el controlador de ingress Traefik reemplace al descontinuado Ingress-NGINX.

La carpeta os-files/var/lib/rancher/rke2/server/manifests contiene el siguiente archivo:

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

    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
        providers:
          kubernetesIngressNginx:  # this provider allows traefik to "understand" most of the ingress-nginx annotations
            enabled: true
            ingressClass: "rke2-ingress-nginx-migration"
            controllerClass: "rke2.​cattle.​io/ingress-nginx-migration"
Nota
Nota

El HelmChartConfig debe incluirse mediante os-files en el directorio /var/lib/rancher/rke2/server/manifests, no mediante kubernetes/manifests como se describe en versiones anteriores.

La carpeta kubernetes/manifests contiene los siguientes archivos:

  • neuvector-namespace.yaml: contiene la configuración para crear el espacio de nombres NeuVector (no se necesitan modificaciones).

    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 se necesitan modificaciones).

    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 objeto IPAddressPool de MetalLB para el componente rke2-traefik. El ${INGRESS_VIP} debe establecerse correctamente para definir la dirección IP expuesta reservada para ser utilizada para acceder al servicio (interno) rke2-traefik.

    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-traefik]}

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

  • rancher.yaml: contiene la configuración para crear el componente Rancher. El ${INGRESS_VIP} debe establecerse 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:
        systemDefaultRegistry: "registry.rancher.com"
  • neuvector.yaml: contiene la configuración para crear el componente NeuVector (no se necesitan modificaciones).

    controller:
      replicas: 1
      ranchersso:
        enabled: true
    manager:
      enabled: false
    cve:
      scanner:
        enabled: false
        replicas: 1
    k3s:
      enabled: true
    crdwebhook:
      enabled: false
    registry: "registry.rancher.com"
    global:
      cattle:
        systemDefaultRegistry: "registry.rancher.com"
  • longhorn.yaml: contiene la configuración para crear el componente Longhorn. Para asegurarse de que las imágenes de contenedor necesarias se descarguen durante el arranque, añada sus credenciales de Rancher Application Collection.

    privateRegistry:
      createSecret: true
      registryUrl: dp.apps.rancher.io
      registryUser: $\{APPS.RANCHER.IO_USERNAME\}
      registryPasswd: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
      registrySecret: rancher-app-collection
  • metal3.yaml: contiene la configuración para crear el componente Metal3. El ${METAL3_VIP} debe establecerse correctamente para definir la dirección IP que utilizará el componente Metal3.

    global:
      ironicIP: ${METAL3_VIP}
      enable_vmedia_tls: false
      predictableNicNames: "true"
      # trustedCAs: tls-ca-bundle  # Optional: Uncomment and set to ConfigMap name for additional trusted CAs
    metal3-ironic:
      ipa:
        useHauler: false
      persistence:
        ironic:
          size: "5Gi"
    Importante
    Importante

    El parámetro del chart de Helm metal3-ironic.ipa.useHauler debe establecerse en true (valor booleano) en entornos aislados; esto indica a Metal3 que recupere la imagen de contenedor ironic-python-agent (IPA) del registro de artefactos integrado en lugar de intentar descargarla de internet. Esta imagen de contenedor IPA debe incluirse adicionalmente en la lista embeddedArtifactRegistry.images en el archivo de definición de imagen EIB para entornos aislados (Sección 30.1, “Modificaciones en el archivo de definición”).

Nota
Nota

El servidor multimedia es una característica opcional incluida en Metal3 (por defecto está desactivado). Para utilizar la característica Metal3, debe configurarla en el manifiesto anterior. Para utilizar el servidor multimedia Metal3, especifique la siguiente variable:

  • añada enable_metal3_media_server a true para habilitar la característica de servidor multimedia en la sección global.

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

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

Se puede utilizar un servidor multimedia externo para almacenar las imágenes y, en caso de que desee utilizarlo con TLS, deberá proporcionar el paquete de CA de confianza para Metal3.

Prepare el paquete de CA:

En primer lugar, prepare su archivo de paquete de CA que contenga todos los certificados necesarios para Metal3. Esto incluye el/los certificado(s) CA de su servidor multimedia externo.

+ Opcional - Paquete CA del sistema: Si Metal3 también necesita confiar en CA públicas (por ejemplo, al acceder a recursos HTTPS externos), puede incluir el paquete CA del sistema. Extráigalo de una imagen de contenedor y concaténelo con sus certificados personalizados:

+

# Extract system CAs from a container image
podman run --rm registry.suse.com/bci/bci-base:latest cat /etc/ssl/certs/ca-certificates.crt > system-cas.pem

# Concatenate system CAs with your custom CA
cat system-cas.pem your-custom-ca.crt > ca-bundle.pem

+ O, si solo necesita su CA personalizada:

+

cp your-custom-ca.crt ca-bundle.pem

+

Si incluye el paquete CA del sistema, usted es responsable de mantenerlo actualizado. Las CA del sistema en las imágenes de contenedor pueden quedar obsoletas a medida que los certificados caducan o son revocados. Actualice periódicamente el paquete volviéndolo a extraer de una imagen de contenedor actualizada.

Creación del ConfigMap:

Puede crear el ConfigMap de dos formas:

  1. Uso de un archivo de manifiesto (recomendado para EIB): Cree el archivo kubernetes/manifests/metal3-cacert-configmap.yaml e incluya el contenido del paquete CA en línea. Debe sangrar correctamente cada línea del certificado con 4 espacios:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: metal3-system
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: tls-ca-bundle
      namespace: metal3-system
    data:
      ca-bundle.pem: |
        -----BEGIN CERTIFICATE-----
        MIIDXTCCAkWgAwIBAgIJAKJ... (your certificate content here)
        ...
        -----END CERTIFICATE-----
        -----BEGIN CERTIFICATE-----
        MIIEkjCCA3qgAwIBAgIQCgF... (additional certificates if any)
        ...
        -----END CERTIFICATE-----

    Para rellenar este archivo automáticamente desde su ca-bundle.pem, puede usar:

    cat > kubernetes/manifests/metal3-cacert-configmap.yaml <<EOF
    apiVersion: v1
    kind: Namespace
    metadata:
      name: metal3-system
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: tls-ca-bundle
      namespace: metal3-system
    data:
      ca-bundle.pem: |
    $(sed 's/^/    /' ca-bundle.pem)
    EOF
  2. Uso directo de kubectl (para despliegue manual): Si no utiliza EIB y desea crear el ConfigMap directamente en el clúster:

    kubectl -n metal3-system create configmap tls-ca-bundle --from-file=ca-bundle.pem=./ca-bundle.pem
    • Establezca el valor global.trustedCAs en el archivo metal3.yaml para hacer referencia al nombre del ConfigMap:

      global:
        trustedCAs: tls-ca-bundle
  • certmanager.yaml: contiene la configuración para crear el componente Cert-Manager (no se necesitan modificaciones).

    installCRDs: true

29.5 Carpeta de redes

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 (escenario sin DHCP), puede utilizar el archivo mgmt-cluster-node1.yaml en la carpeta network. Contiene la información siguiente:

  • ${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 utilizar la siguiente configuración (la dirección MAC debe establecerse 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 en el 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 para el clúster de gestión.

30 Preparación de imágenes para entornos aislados

Esta sección describe cómo preparar la imagen para entornos aislados mostrando solo las diferencias respecto a las secciones anteriores. Se requieren los siguientes cambios en la sección anterior (Preparación de imágenes para entornos conectados (Capítulo 29, Preparación de la imagen para entornos conectados)) para preparar la imagen para entornos aislados:

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

  • El script custom/scripts/99-register.sh debe eliminarse cuando se utilice un entorno aislado.

Para incluir el SUSE Private Registry en el clúster de gestión para futuras ampliaciones en sentido descendente, también se requieren los siguientes cambios:

  • El archivo mgmt-cluster.yaml debe modificarse para incluir la sección helm chart, así como los artefactos integrados con las nuevas imágenes para incluirlas en la imagen de salida EIB.

  • Las carpetas kubernetes/values y kubernetes/manifests deben incluir archivos de manifiesto adicionales para configurar correctamente el SUSE Private Registry en el clúster de gestión.

Nota
Nota

Necesitará ciertas credenciales, que pueden obtenerse siguiendo la documentación oficial de SUSE Private Registry.

30.1 Modificaciones en el archivo de definición

El archivo mgmt-cluster.yaml debe modificarse para incluir la sección embeddedArtifactRegistry. En esta sección, 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

El siguiente archivo de ejemplo mgmt-cluster.yaml incluye tanto la sección embeddedArtifactRegistry como la funcionalidad de SUSE Private Registry. Asegúrese de que las imágenes enumeradas contengan las versiones de los componentes que necesita.

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-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.35.4+rke2r1
  helm:
    charts:
      - name: private-registry-helm
        createNamespace: true
        installationNamespace: kube-system
        repositoryName: privateregistry
        targetNamespace: suse-private-registry
        valuesFile: privateregistry.yaml
        version: 1.1.1
      - name: cert-manager
        repositoryName: jetstack
        version: 1.20.1
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: longhorn
        version: 1.11.2
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: longhorn.yaml
      - name: metallb
        version: 306.0.2+up0.15.3
        targetNamespace: metallb-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
      - name: metal3
        version: 306.0.29+up0.15.0
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: rancher-turtles-providers
        version: 306.0.7+up0.26.2
        repositoryName: suse-edge-charts
        targetNamespace: cattle-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.14.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
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $\{APPS.RANCHER.IO_USERNAME\}
          password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
      - name: privateregistry
        authentication:
          username: ${PRIVATE_REGISTRY_USERNAME}
          password: ${PRIVATE_REGISTRY_PASSWORD}
        plainHTTP: false
        skipTLSVerify: false
        url: oci://registry.suse.com/private-registry
    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
embeddedArtifactRegistry:
  registries:
    - uri: dp.apps.rancher.io
      authentication:
        username: $\{APPS.RANCHER.IO_USERNAME\}
        password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
    - uri: registry.suse.com
      authentication:
        username: ${PRIVATE_REGISTRY_USERNAME}
        password: ${PRIVATE_REGISTRY_PASSWORD}
  images:
    - name: registry.suse.com/private-registry/harbor-core:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-jobservice:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-portal:1.1.1-1.20
    - name: registry.suse.com/private-registry/harbor-registry:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-registryctl:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-trivy-adapter:1.1.1-1.24
    - name: registry.rancher.com/rancher/hardened-cluster-autoscaler:v1.10.3-build20260414
    - name: registry.rancher.com/rancher/hardened-cni-plugins:v1.9.1-build20260415
    - name: registry.rancher.com/rancher/hardened-coredns:v1.14.2-build20260416
    - name: registry.rancher.com/rancher/hardened-k8s-metrics-server:v0.8.1-build20260413
    - name: registry.rancher.com/rancher/hardened-multus-cni:v4.2.4-build20260310
    - name: registry.rancher.com/rancher/hardened-traefik:v3.6.13-build20260416
    - name: registry.rancher.com/rancher/klipper-helm:v0.9.17-build20260422
    - name: registry.rancher.com/rancher/mirrored-cilium-cilium:v1.19.3
    - name: registry.rancher.com/rancher/mirrored-cilium-operator-generic:v1.19.3
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-attacher:4.11.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-provisioner:5.3.0-14.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-resizer:2.1.0-6.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-snapshotter:8.5.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-livenessprobe:2.18.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-node-driver-registrar:2.16.0-13.2
    - name: dp.apps.rancher.io/containers/longhorn-backing-image-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-engine:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-instance-manager:1.11.2-4.3
    - name: dp.apps.rancher.io/containers/longhorn-manager:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-share-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-ui:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/rancher-support-bundle-kit:0.0.84-9.4
    - name: registry.rancher.com/rancher/mirrored-sig-storage-snapshot-controller:v8.2.0
    - name: registry.rancher.com/rancher/neuvector-compliance-config:1.0.12
    - name: registry.rancher.com/rancher/neuvector-controller:5.5.2
    - name: registry.rancher.com/rancher/neuvector-enforcer:5.5.2
    - name: registry.rancher.com/rancher/nginx-ingress-controller:v1.14.5-hardened2
    - name: registry.rancher.com/rancher/cluster-api-addon-provider-fleet:v0.14.1
    - name: registry.rancher.com/rancher/fleet-agent:v0.15.2
    - name: registry.rancher.com/rancher/fleet:v0.15.2
    - name: registry.rancher.com/rancher/rancher-webhook:v0.10.6
    - name: registry.rancher.com/rancher/turtles:v0.26.2
    - name: registry.rancher.com/rancher/rancher:v2.14.2
    - name: registry.rancher.com/rancher/shell:v0.1.24
    - name: registry.rancher.com/rancher/system-upgrade-controller:v0.19.1
    - name: registry.rancher.com/rancher/cluster-api-controller:v1.12.7
    - name: registry.suse.com/rancher/cluster-api-provider-metal3:v1.12.3
    - name: registry.rancher.com/rancher/cluster-api-provider-rke2-bootstrap:v0.24.4
    - name: registry.rancher.com/rancher/cluster-api-provider-rke2-controlplane:v0.24.4
    - name: registry.rancher.com/rancher/ip-address-manager:v1.12.3
    - name: registry.rancher.com/rancher/kubectl:v1.35.2
    - name: registry.rancher.com/rancher/scc-operator:v0.4.1
    - name: registry.rancher.com/rancher/kubectl:v1.33.1
    - name: registry.suse.com/edge/3.6/ironic-python-agent:3.0.9

30.2 Modificaciones en la carpeta custom

  • El script custom/scripts/99-register.sh debe eliminarse cuando se utilice un entorno aislado. Como puede ver en la estructura de directorios, el script 99-register.sh no está incluido en la carpeta custom/scripts.

30.3 Modificaciones en la carpeta kubernetes

  • Actualice el archivo kubernetes/helm/values/metal3.yaml para establecer el parámetro del gráfico de Helm metal3-ironic.ipa.useHauler en true (valor booleano).

    global:
      ironicIP: ${METAL3_VIP}
      enable_vmedia_tls: false
      predictableNicNames: "true"
      # trustedCAs: tls-ca-bundle  # Optional: Uncomment and set to ConfigMap name for additional trusted CAs
    metal3-ironic:
      ipa:
        useHauler: true
      persistence:
        ironic:
          size: "5Gi"
  • Actualice el archivo kubernetes/helm/values/rancher.yaml para modificar el parámetro hostname. En entornos aislados, los servicios de resolución DNS externos como sslip.io no son accesibles. dispone de dos opciones:

    1. Opción 1: Utilizar DNS interno (recomendado): Configure su servidor DNS interno para resolver el nombre de host de Rancher y actualice el archivo en consecuencia:

      hostname: rancher.yourdomain.internal
      bootstrapPassword: "foobar"
      replicas: 1
      global:
        cattle:
          systemDefaultRegistry: "registry.rancher.com"
    2. Opción 2: Utilizar inyección en /etc/hosts: Si no dispone de un servidor DNS interno, puede inyectar una entrada estática /etc/hosts a través de EIB. Cree un archivo en eib/os-files/etc/hosts dentro de su estructura de directorios de EIB con un contenido como:

      # Static DNS resolution for Rancher in air-gapped environment
      ${INGRESS_VIP} rancher-${INGRESS_VIP}.sslip.io

      A continuación, actualice el archivo rancher.yaml para utilizar este nombre de host:

      hostname: rancher-${INGRESS_VIP}.sslip.io
      bootstrapPassword: "foobar"
      replicas: 1
      global:
        cattle:
          systemDefaultRegistry: "registry.rancher.com"
      Importante
      Importante

      Al utilizar la Opción 2, recuerde que el archivo /etc/hosts deberá estar presente en cualquier sistema que necesite acceder a la interfaz de usuario de Rancher, no solo en los nodos del clúster de gestión.

  • Debe modificar el ${MGMT_CLUSTER_REGISTRY_IP} con una IP estática reservada para SUSE Private Registry en los siguientes archivos:

    1. kubernetes/manifests/metallb-registry.yaml

      apiVersion: metallb.io/v1beta1
      kind: L2Advertisement
      metadata:
        name: private-registry
        namespace: metallb-system
      spec:
        ipAddressPools:
        - private-registry-pool
      ---
      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        name: private-registry-pool
        namespace: metallb-system
      spec:
        addresses:
        - ${MGMT_CLUSTER_REGISTRY_IP}/32
        serviceAllocation:
          namespaces:
          - suse-private-registry
    2. kubernetes/helm/values/privateregistry.yaml

      core:
        secretName: suse-registry-tls
      expose:
        tls:
          certSource: secret
          enabled: true
          secret:
            secretName: suse-registry-tls
        type: loadBalancer
      externalURL: https://${MGMT_CLUSTER_REGISTRY_IP}
      persistence:
        persistentVolumeClaim:
          registry:
            size: 20Gi
  • El kubernetes/manifests/suse-private-registry-creds.yaml debe crearse con el siguiente contenido:

apiVersion: v1
kind: Secret
metadata:
  name: suse-registry
  namespace: suse-private-registry
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ${DOCKER_CONFIG_JSON_BASE64}
---
apiVersion: v1
kind: Secret
metadata:
    name: suse-registry-tls
    namespace: suse-private-registry
type: kubernetes.io/tls
data:
    tls.crt: ${TLS_CRT_BASE64}
    tls.key: ${TLS_KEY_BASE64}

Debe modificar el ${DOCKER_CONFIG_JSON_BASE64}, ${TLS_CRT_BASE64} y ${TLS_KEY_BASE64}. Para configurar correctamente el json de configuración de docker (base64), puede hacer lo siguiente:

# ${DOCKER_CONFIG_JSON_BASE64} CONTENT
echo -n '{"auths":{"<MGMT_CLUSTER_REGISTRY_IP>":{"username":"<USERNAME>","password":"<PASSWORD>","auth":"<AUTH>"}}}' | base64 -w 0

donde la IP es la misma que la del ${MGMT_CLUSTER_REGISTRY_IP} configurado anteriormente, y los valores de <USERNAME> y <PASSWORD> pueden obtenerse de la documentación oficial de SUSE Private Registry; el valor de <AUTH> establecido en el campo auth es la codificación base64 de la concatenación de <USERNAME>:<PASSWORD>.

Para establecer el contenido de los campos tls.crt y tls.key en el manifiesto Secret de suse-registry-tls anterior, puede generar su propio certificado autofirmado TLS y la clave privada relacionada ejecutando los siguientes comandos:

# Generate a self-signed certificate and key
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes

# Convert them to base64 for the suse-private-registry-creds.yaml file
cat cert.pem | base64 -w 0
cat key.pem | base64 -w 0

31 Creación de imágenes

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

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

32 Aprovisionar el clúster de gestión

La imagen anterior contiene todos los componentes explicados anteriormente y puede utilizarse para aprovisionar el clúster de gestión mediante una máquina virtual o un servidor sin sistema operativo (utilizando la función de medios virtuales).

33 Consideraciones y configuración de doble pila

Los ejemplos mostrados en las secciones anteriores proporcionan orientación y ejemplos sobre cómo configurar un clúster de gestión IPv4 de pila única. Dicho clúster de gestión es independiente del estado operativo de los clústeres descendentes, que pueden configurarse individualmente para operar en una configuración de pila única IPv4/IPv6 o de doble pila, una vez desplegados. Sin embargo, la forma en que se configura el clúster de gestión tiene un impacto directo en los protocolos de comunicación que pueden utilizarse durante la fase de aprovisionamiento, donde tanto las comunicaciones en banda como fuera de banda deben producirse de acuerdo con los protocolos admitidos por el clúster de gestión y el host descendente. En caso de que se espere que algunos o todos los BMCs y/o nodos de clúster descendentes utilicen IPv6, se requiere entonces una configuración de doble pila para el clúster de gestión.

Nota
Nota

Los clústeres de gestión IPv6 de pila única aún no son compatibles.

Para lograr la funcionalidad de doble pila, se debe proporcionar a Kubernetes CIDR tanto IPv4 como IPv6 para POD y Servicios. Sin embargo, otros componentes también requieren un ajuste específico antes de crear la imagen del clúster de gestión con EIB. Los servicios de aprovisionamiento Metal3 (Ironic) pueden configurarse de diferentes maneras, dependiendo de su infraestructura o requisitos:

  • Los servicios Ironic pueden configurarse para escuchar en todas las interfaces del sistema en lugar de en una única dirección IP, por lo que, siempre que el host o los hosts del clúster de gestión tengan direcciones IPv4 e IPv6 asignadas a la interfaz pertinente, cualquiera de ellas puede utilizarse potencialmente durante el aprovisionamiento. Tenga en cuenta que, en este momento, solo se puede seleccionar una de estas direcciones para la generación de la URL (para su consumo por otros servicios, p. ej., el Baremetal Operator, BMCs, etc.); como consecuencia, para habilitar las comunicaciones IPv6 con los BMCs, se puede indicar al Baremetal Operator que exponga y transmita una URL IPv6 al tratar con definiciones de BMH que incluyan una dirección IPv6. En otras palabras, cuando un BMC se identifica como compatible con IPv6, el aprovisionamiento se realizará solo a través de IPv6, y a través de IPv4 en todos los demás casos.

  • Se puede utilizar un único nombre de host, que resuelva tanto a IPv4 como a IPv6, mediante Metal3 para permitir que Ironic utilice esas direcciones para la vinculación y la creación de la URL. Este enfoque permite una configuración sencilla y un comportamiento flexible (tanto IPv4 como IPv6 siguen siendo viables en cada paso del aprovisionamiento), pero requiere una infraestructura con servidores DNS, asignaciones de IP y registros preexistentes ya implementados.

En ambos casos, Kubernetes necesitará saber qué CIDR utilizar tanto para IPv4 como para IPv6, por lo que puede añadir las siguientes líneas a su kubernetes/config/server.yaml en el directorio EIB, asegurándose de listar IPv4 primero:

service-cidr: 10.96.0.0/12,fd12:4567:789c::/112
cluster-cidr: 193.168.0.0/18,fd12:4567:789b::/48

Algunos contenedores aprovechan la red del host, así que modifique la configuración de red para el/los host(s), bajo el directorio network, para habilitar la conectividad IPv6:

routes:
  config:
  - destination: 0.0.0.0/0
    next-hop-address: ${MGMT_GATEWAY_V4}
    next-hop-interface: eth0
  - destination: ::/0
    next-hop-address: ${MGMT_GATEWAY_V6}
    next-hop-interface: eth0
dns-resolver:
  config:
    server:
    - ${MGMT_DNS}
    - 8.8.8.8
    - 2001:4860:4860::8888
interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: ${MGMT_MAC}
  ipv4:
    address:
    - ip: ${MGMT_CLUSTER_IP_V4}
      prefix-length: 24
    dhcp: false
    enabled: true
  ipv6:
    address:
    - ip: ${MGMT_CLUSTER_IP_V6}
      prefix-length: 128
    dhcp: false
    autoconf: false
    enabled: true

Sustituya los marcadores de posición por las direcciones IP del gateway, el servidor DNS adicional (si es necesario), la dirección MAC de la interfaz de red y las direcciones IP del clúster de gestión. Si se prefiere la autoconfiguración de direcciones, consulte el siguiente extracto y, simplemente, configure la variable ${MGMT_MAC}:

interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: ${MGMT_MAC}
  ipv4:
    enabled: true
    dhcp: true
  ipv6:
    enabled: false
    dhcp: true
    autoconf: true

A continuación, defina los archivos restantes para una configuración de un solo nodo, comenzando por la primera opción, creando kubernetes/helm/values/metal3.yaml como:

global:
  ironicIP: ${MGMT_CLUSTER_IP_V4}
  enable_vmedia_tls: false
  # trustedCAs: tls-ca-bundle  # Optional: Uncomment and set to ConfigMap name for trusted CA bundle
metal3-ironic:
  global:
    predictableNicNames: true
  listenOnAll: true
  persistence:
    ironic:
      size: "5Gi"
  service:
    type: NodePort
metal3-baremetal-operator:
  baremetaloperator:
    externalHttpIPv6: ${MGMT_CLUSTER_IP_V6}

y kubernetes/helm/values/rancher.yaml como:

hostname: rancher-${MGMT_CLUSTER_IP_V4}.sslip.io
bootstrapPassword: "foobar"
replicas: 1
global:
  cattle:
    systemDefaultRegistry: "registry.rancher.com"

donde ${MGMT_CLUSTER_IP_V4} y ${MGMT_CLUSTER_IP_V6} son las direcciones IP asignadas previamente al host.

Alternativamente, para usar el nombre de host en lugar de las direcciones IP, modifique kubernetes/helm/values/metal3.yaml a:

global:
  provisioningHostname: `${MGMT_CLUSTER_HOSTNAME}`
  enable_vmedia_tls: false
  # trustedCAs: tls-ca-bundle  # Optional: Uncomment and set to ConfigMap name for trusted CA bundle
metal3-ironic:
  global:
    predictableNicNames: true
  persistence:
    ironic:
      size: "5Gi"
  service:
    type: NodePort

Y modifique kubernetes/helm/values/rancher.yaml a:

hostname: rancher-${MGMT_CLUSTER_HOSTNAME}.sslip.io
bootstrapPassword: "foobar"
replicas: 1
global:
  cattle:
    systemDefaultRegistry: "registry.rancher.com"

Donde ${MGMT_CLUSTER_HOSTNAME} debe ser un nombre de dominio completo que resuelva a las direcciones IP de su host.

Para obtener más información, visite SUSE Telco Cloud el repositorio de GitHub bajo la carpeta "dual-stack", donde se puede encontrar una estructura de directorio de ejemplo.

Parte VI Configuración de las funciones Telco

Esta sección documenta y explica la configuración de funciones específicas de Telco en clústeres desplegados mediante SUSE Telco Cloud.

Se utiliza el método de despliegue de aprovisionamiento de red dirigida, tal como se describe en la sección Automated Provisioning (Parte VII, “Aprovisionamiento de red dirigido totalmente automatizado”).

Esta sección abarca los siguientes temas:

  • 34 Imagen del núcleo de Linux para tiempo real
  • La imagen del núcleo de Linux en tiempo real no es necesariamente mejor que un núcleo de Linux estándar. Es un núcleo de Linux diferente ajustado para un caso de uso específico. El núcleo de Linux en tiempo real está ajustado para una menor latencia a costa del rendimiento. El núcleo de Linux en tie…

  • 35 Argumentos del núcleo de Linux para baja latencia y alto rendimiento.
  • Configurar los argumentos adecuados del núcleo de Linux es esencial para optimizar el rendimiento, lograr una baja latencia y garantizar el despliegue exitoso del clúster para cargas de trabajo de telecomunicaciones. Aunque algunos parámetros están diseñados específicamente para permitir que el núcl…

  • 36 Fijación de CPU en el host
  • La fijación de CPU, también conocida como afinidad de procesador, es la técnica de vincular un proceso o hilo a un núcleo de CPU específico, evitando que el planificador del sistema operativo lo mueva. Al asegurar que un proceso siempre se ejecute en el mismo núcleo, se beneficia de un acceso más rá…

  • 37 Fijación de CPU en Kubernetes
  • Habilitad la fijación de CPU en vuestro clúster RKE2 editando el archivo de configuración de RKE2. Añadid los siguientes argumentos de kubelet en el archivo /etc/rancher/rke2/config.yaml. Aseguraos de especificar los núcleos de CPU de mantenimiento en los argumentos kubelet-reserved y system-reserve…

  • 38 Configuración de CNI
  • Cilium es el complemento CNI predeterminado para SUSE Telco Cloud. Para habilitar Cilium en el clúster RKE2 como complemento predeterminado, se requiere la siguiente configuración en el archivo /etc/rancher/rke2/config.yaml:

  • 39 SR-IOV
  • SR-IOV (Single Root I/O Virtualization) permite que un único dispositivo físico, como un adaptador de red, separe sus recursos entre múltiples PCIe funciones de hardware. Esto permite el acceso directo a los recursos para diversas aplicaciones.

  • 40 DPDK
  • DPDK (Data Plane Development Kit) es un conjunto de bibliotecas y controladores para el procesamiento rápido de paquetes. Se utiliza para acelerar las cargas de trabajo de procesamiento de paquetes que se ejecutan en una amplia variedad de arquitecturas de CPU. El DPDK incluye bibliotecas de plano d…

  • 41 Aceleración vRAN (Intel ACC100/VRB1/VRB2)
  • A medida que los proveedores de servicios de comunicaciones pasan de las redes 4G a las 5G, muchos están adoptando arquitecturas de red de acceso por radio virtualizada (vRAN) para obtener una mayor capacidad de canal y un despliegue más sencillo de servicios y aplicaciones basados en el borde. Las …

  • 42 Páginas enormes
  • Cuando un proceso utiliza RAM, el CPU lo marca como utilizado por dicho proceso. Para mayor eficiencia, el CPU asigna RAM en bloques; 4K bytes es el valor predeterminado en muchas plataformas. Esos bloques se denominan páginas. Las páginas pueden intercambiarse a disco, etc.

  • 43 Planificación consciente de NUMA
  • El acceso no uniforme a memoria o la arquitectura de memoria no uniforme (NUMA) es un diseño de memoria física utilizado en la arquitectura de SMP (multiprocesadores), donde el tiempo de acceso a la memoria depende de la ubicación de la memoria en relación con un procesador. Bajo NUMA, un procesador…

  • 44 Metal LB
  • MetalLB es una implementación de equilibrador de carga para clústeres de Kubernetes en equipo sin sistema operativo, que utiliza protocolos de enrutamiento estándar como L2 y BGP como protocolos de anuncio. Es un equilibrador de carga de red que se puede utilizar para exponer servicios en un clúster…

  • 45 Configuración de registro privado
  • Containerd se puede configurar para conectarse a registros privados y utilizarlos para extraer imágenes privadas en cada nodo.

  • 46 Protocolo de tiempo de precisión
  • El Protocolo de tiempo de precisión (PTP) es un protocolo de red desarrollado por el Instituto de Ingenieros Eléctricos y Electrónicos (IEEE) para permitir la sincronización horaria de submicrosegundos en una red informática. Desde su creación y desde hace ya un par de décadas, el PTP se ha utilizad…

  • 47 SCTP - Protocolo de control de transmisión de flujo
  • De Stream Control Transmission Protocol - Wikipedia

34 Imagen del núcleo de Linux para tiempo real

La imagen del núcleo de Linux en tiempo real no es necesariamente mejor que un núcleo de Linux estándar. Es un núcleo de Linux diferente ajustado para un caso de uso específico. El núcleo de Linux en tiempo real está ajustado para una menor latencia a costa del rendimiento. El núcleo de Linux en tiempo real no se recomienda para un uso de propósito general, pero en nuestro caso, es el núcleo recomendado para cargas de trabajo de telecomunicaciones donde la latencia es un factor clave.

Existen cuatro características principales:

  • Ejecución determinista:

    Obtenga una mayor previsibilidad: garantice que los procesos comerciales críticos se completen a tiempo en cada ocasión y ofrezca un servicio de alta calidad, incluso bajo cargas de sistema elevadas. Al proteger los recursos clave del sistema para procesos de alta prioridad, puede garantizar una mayor previsibilidad para las aplicaciones sensibles al tiempo.

  • Bajo jitter:

    El bajo jitter, basado en la tecnología altamente determinista, ayuda a mantener las aplicaciones sincronizadas con el mundo real. Esto ayuda a los servicios que necesitan cálculos continuos y repetidos.

  • Herencia de prioridad:

    La herencia de prioridad se refiere a la capacidad de un proceso de baja prioridad para adquirir una prioridad mayor cuando un proceso de mayor prioridad requiere que este finalice antes de poder completar su tarea. SUSE Linux Enterprise Real Time resuelve estos problemas de inversión de prioridad para procesos de misión crítica.

  • Interrupciones de hilos:

    Los procesos que se ejecutan en modo de interrupción en un sistema operativo de propósito general no pueden ser interrumpidos. Con SUSE Linux Enterprise Real Time, estas interrupciones han sido encapsuladas por hilos del núcleo de Linux, que son interrumpibles y permiten que las interrupciones de hardware y software sean interrumpidas por procesos de mayor prioridad definidos por el usuario.

    En nuestro caso, si ha instalado una imagen de tiempo real como SUSE Linux Micro RT, ya está instalado el núcleo de Linux en tiempo real. Desde el SUSE Customer Center, puede descargar la imagen del núcleo de Linux en tiempo real.

    Nota
    Nota

    Para obtener más información sobre el núcleo de Linux en tiempo real, visite SUSE Real Time.

35 Argumentos del núcleo de Linux para baja latencia y alto rendimiento.

Configurar los argumentos adecuados del núcleo de Linux es esencial para optimizar el rendimiento, lograr una baja latencia y garantizar el despliegue exitoso del clúster para cargas de trabajo de telecomunicaciones. Aunque algunos parámetros están diseñados específicamente para permitir que el núcleo de Linux en tiempo real funcione de manera óptima, esta sección se aplica tanto a las configuraciones del núcleo en tiempo real como a las predeterminadas. Además, ciertos argumentos son obligatorios para que el método de aprovisionamiento de red dirigida despliegue correctamente los nodos de clúster en sentido descendente.

  • Elimine kthread_cpus cuando utilice el núcleo de Linux en tiempo real de SUSE. Este parámetro controla en qué CPU se crean los hilos del núcleo de Linux. También controla qué CPU se permiten para el PID 1 y para cargar módulos del núcleo de Linux (el asistente de espacio de usuario kmod). Este parámetro no se reconoce y no tiene ningún efecto.

  • Aísle los núcleos de CPU utilizando isolcpus, nohz_full, rcu_nocbs y irqaffinity. Para obtener una lista completa de las técnicas de fijación de CPU, consulte el capítulo CPU Pinning on Host (Capítulo 36, Fijación de CPU en el host).

  • Añada los indicadores domain,nohz,managed_irq al argumento del núcleo de Linux isolcpus. Sin ningún indicador, isolcpus equivale a especificar solo el indicador domain. Esto aísla las CPU especificadas de la programación, incluidas las tareas del núcleo de Linux. El indicador nohz detiene el tick del planificador en las CPU especificadas (si solo hay una tarea ejecutable en una CPU), y el indicador managed_irq evita el enrutamiento de interrupciones externas (de dispositivo) gestionadas en las CPU especificadas. Tenga en cuenta que las líneas IRQ de los dispositivos NVMe están totalmente gestionadas por el núcleo de Linux y, como consecuencia, se enrutarán a los núcleos no aislados (de mantenimiento). Por ejemplo, la línea de comandos proporcionada al final de esta sección dará como resultado que solo se asignen cuatro colas (más una cola de administración/control) en el sistema:

    for I in $(grep nvme0 /proc/interrupts | cut -d ':' -f1); do cat /proc/irq/${I}/effective_affinity_list; done | column
    39      0       19      20      39

    Este comportamiento evita cualquier interrupción causada por la E/S de disco en cualquier aplicación sensible al tiempo que se ejecute en los núcleos aislados, pero podría requerir atención y un diseño cuidadoso para las cargas de trabajo centradas en el almacenamiento.

  • Ajuste los ticks (interrupciones periódicas del temporizador del núcleo de Linux):

    • skew_tick=1: los ticks a veces pueden ocurrir simultáneamente. En lugar de que todas las CPU reciban su tick de temporizador en el mismo momento exacto, skew_tick=1 hace que ocurran en momentos ligeramente desplazados. Esto ayuda a reducir la inestabilidad del sistema, lo que resulta en tiempos de respuesta de interrupción más consistentes y bajos (un requisito esencial para aplicaciones sensibles a la latencia).

    • nohz=on: detiene el tick periódico del temporizador en las CPUs inactivas.

    • nohz_full=<cpu-cores>: Detiene el tick periódico del temporizador en las CPUs especificadas que están dedicadas a aplicaciones en tiempo real.

  • Deshabilite la gestión de Machine Check Exception (MCE) especificando mce=off. Las MCE son errores de hardware detectados por el procesador y deshabilitarlas puede evitar registros ruidosos.

  • Añada nowatchdog para deshabilitar el watchdog de soft-lockup, que se implementa como un temporizador que se ejecuta en el contexto de interrupción de hardware del temporizador. Cuando expira (es decir, se detecta un bloqueo suave), imprimirá una advertencia (en el contexto de interrupción de hardware), ejecutando cualquier objetivo de latencia. Incluso si nunca expira, entra en la lista de temporizadores, aumentando ligeramente la sobrecarga de cada interrupción de temporizador. Esta opción también deshabilita el watchdog NMI, por lo que las NMI no pueden interferir.

  • nmi_watchdog=0 deshabilita el watchdog NMI (Non-Maskable Interrupt). Esto puede omitirse cuando se utiliza nowatchdog.

  • RCU (Read-Copy-Update) es un mecanismo del núcleo de Linux que permite el acceso concurrente y sin bloqueos para muchos lectores a datos compartidos. Una retrollamada RCU, una función activada tras un «período de gracia», garantiza que todos los lectores anteriores hayan terminado para que los datos antiguos puedan recuperarse de forma segura. Ajustamos RCU, especialmente para cargas de trabajo sensibles, para descargar estas retrollamadas de las CPU dedicadas (ancladas), evitando que las operaciones del núcleo de Linux interfieran con tareas críticas y sensibles al tiempo.

    • Especifique las CPU ancladas en rcu_nocbs para que las retrollamadas RCU no se ejecuten en ellas. Esto ayuda a reducir el jitter y la latencia para las cargas de trabajo en tiempo real.

    • rcu_nocb_poll hace que las CPUs sin retrollamadas «sondeen» regularmente para ver si se requiere la gestión de retrollamadas. Esto puede reducir la sobrecarga de interrupciones.

    • rcupdate.rcu_cpu_stall_suppress=1 suprime las advertencias de bloqueo de CPU RCU, que a veces pueden ser falsos positivos en sistemas en tiempo real con mucha carga.

    • rcupdate.rcu_expedited=1 acelera el período de gracia para las operaciones RCU, haciendo que las secciones críticas del lado de lectura sean más receptivas.

    • rcupdate.rcu_normal_after_boot=1 Cuando se utiliza con rcu_expedited, permite que RCU vuelva a la operación normal (no acelerada) después del arranque del sistema.

    • rcupdate.rcu_task_stall_timeout=0 deshabilita el detector de bloqueo de tareas RCU, evitando posibles advertencias o detenciones del sistema por tareas RCU de larga duración.

    • rcutree.kthread_prio=99 establece la prioridad del hilo del kernel de retrollamada RCU a la más alta posible (99), asegurando que se programe y gestione las retrollamadas RCU rápidamente, cuando sea necesario.

  • Añadid ignition.platform.id=openstack para que Metal3 y Cluster API puedan aprovisionar/desaprovisionar el clúster correctamente. Esto es utilizado por el agente Python de Metal3, que proviene de Openstack Ironic.

  • Activad Denominación predecible de interfaces de red mediante net.ifnames=1. A partir de SUSE Linux Micro 6.2, esto está activado por defecto y no se requiere una configuración explícita. Para versiones anteriores a la 6.2, esto debe establecerse explícitamente como un argumento del kernel. Esto se alinea con la configuración predictableNicNames en el gráfico de Helm de Metal3 del clúster de gestión, que es necesaria para que el aprovisionamiento de red dirigida funcione correctamente. La denominación coherente de las interfaces también es fundamental cuando se utiliza SR-IOV.

  • Eliminad intel_pstate=passive. Esta opción configura intel_pstate para que funcione con gobernadores cpufreq genéricos, pero para que esto funcione, desactiva como efecto secundario los estados P gestionados por hardware (HWP). Para reducir la latencia del hardware, no se recomienda esta opción para cargas de trabajo en tiempo real.

  • Sustituya intel_idle.max_cstate=0 processor.max_cstate=1 por idle=poll. Para evitar las transiciones de estado C, se utiliza la opción idle=poll para desactivar dichas transiciones y mantener la CPU en el estado C más alto. La opción intel_idle.max_cstate=0 desactiva intel_idle, por lo que se utiliza acpi_idle, y acpi_idle.max_cstate=1 establece entonces el estado C máximo para acpi_idle. En arquitecturas AMD64/Intel 64, el primer estado C ACPI es siempre POLL, pero utiliza una función poll_idle(), que puede introducir una pequeña latencia al leer el reloj periódicamente y reiniciar el bucle principal en do_idle() tras un tiempo de espera (esto también implica borrar y establecer el indicador de tarea TIF_POLL). Por el contrario, idle=poll se ejecuta en un bucle continuo, en espera activa de que se reprograme una tarea. Esto minimiza la latencia de salida del estado de inactividad, pero a costa de mantener la CPU funcionando a máxima velocidad en el hilo de inactividad.

  • Desactivad C1E en la BIOS. Esta opción es importante para desactivar el estado C1E en la BIOS y evitar que la CPU entre en el estado C1E cuando está inactiva. El estado C1E es un estado de bajo consumo que puede introducir latencia cuando la CPU está inactiva.

El resto de esta documentación cubre parámetros adicionales, incluyendo páginas enormes (huge pages) e IOMMU.

Esto proporciona un ejemplo de argumentos del kernel para un servidor Intel de 32 núcleos, incluyendo los ajustes mencionados anteriormente:

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll

Aquí tenéis otro ejemplo de configuración para un servidor AMD de 64 núcleos. De los 128 procesadores lógicos (0-127), los primeros 8 núcleos (0-7) se designan para tareas de mantenimiento, mientras que los 120 núcleos restantes (8-127) se fijan para las aplicaciones:

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=575291cf-74e8-42cf-8f2c-408a20dc00b8 skew_tick=1 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 amd_iommu=on iommu=pt irqaffinity=0-7 isolcpus=domain,nohz,managed_irq,8-127 nohz_full=8-127 rcu_nocbs=8-127 mce=off nohz=on nowatchdog nmi_watchdog=0 nosoftlockup quiet rcu_nocb_poll rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll

36 Fijación de CPU en el host

La fijación de CPU, también conocida como afinidad de procesador, es la técnica de vincular un proceso o hilo a un núcleo de CPU específico, evitando que el planificador del sistema operativo lo mueva. Al asegurar que un proceso siempre se ejecute en el mismo núcleo, se beneficia de un acceso más rápido a los datos que permanecen en la memoria caché de ese núcleo. Esta práctica es común en entornos de informática de alto rendimiento porque mejora drásticamente el rendimiento y reduce la sobrecarga.

36.1 Aislamiento de CPU mediante TuneD

tuned es una herramienta de ajuste del sistema que supervisa las condiciones del sistema para optimizar el rendimiento utilizando varios perfiles predefinidos. Una característica clave es su capacidad para aislar núcleos de CPU para cargas de trabajo específicas, como aplicaciones en tiempo real. Esto evita que el sistema operativo utilice estos núcleos y aumente potencialmente la latencia.

Para habilitar y configurar esta función, lo primero es crear un perfil para los núcleos de CPU que queremos aislar. En este ejemplo, de entre 64 núcleos, dedicamos 60 núcleos (1-30,33-62) a las aplicaciones y los 4 núcleos restantes se utilizan para tareas de mantenimiento. Tened en cuenta que el diseño de las CPU aisladas depende en gran medida de las aplicaciones en tiempo real.

$ echo "export tuned_params" >> /etc/grub.d/00_tuned

$ echo "isolated_cores=1-30,33-62" >> /etc/tuned/cpu-partitioning-variables.conf

$ tuned-adm profile cpu-partitioning
Tuned (re)started, changes applied.

36.2 Aislamiento de CPU mediante argumentos del kernel

A continuación, debemos modificar la opción de GRUB para aislar los núcleos de CPU y otros parámetros importantes para el uso de la CPU. Las siguientes opciones son importantes para personalizarlas con vuestras especificaciones de hardware actuales:

parametervalordescription

isolcpus

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

Aislad los núcleos 1-30 y 33-62. domain indica que estas CPU forman parte del dominio de aislamiento. nohz habilita el funcionamiento sin tick en estas CPU aisladas cuando están inactivas, para reducir las interrupciones. managed_irq aísla las CPU fijadas para que no sean objetivo de las IRQ. Esto contempla irqaffinity=0-7, que ya dirige la mayoría de las IRQ a los núcleos de mantenimiento.

skew_tick

1

Esta opción permite al kernel sesgar las interrupciones del temporizador a través de las CPU aisladas.

nohz

on

Cuando está habilitado, la interrupción periódica del temporizador del kernel (el 'tick') se detendrá en cualquier núcleo de CPU que esté inactivo. Esto beneficia principalmente a las CPU de mantenimiento (0,31,32,63). Esto ahorra energía y reduce los despertares innecesarios en esos núcleos de propósito general.

nohz_full

1-30,33-62

Para los núcleos aislados, esto detiene el tick y lo hace incluso cuando la CPU está ejecutando una única tarea activa. Significa que hace que la CPU funcione en modo sin tick completo (o 'dyntick'). El kernel solo enviará interrupciones de temporizador cuando sean realmente necesarias.

rcu_nocbs

1-30,33-62

Esta opción descarga el procesamiento de retrollamadas RCU de núcleos de CPU especificados.

rcu_nocb_poll

 

Cuando esta opción está establecida, las CPU sin retrollamadas RCU realizarán un sondeo periódico para ver si se requiere el manejo de retrollamadas, en lugar de ser despertadas explícitamente por otras CPU. Esto puede reducir la sobrecarga de interrupciones.

irqaffinity

0,31,32,63

Esta opción permite al kernel ejecutar las interrupciones en los núcleos de mantenimiento.

inactivo

poll

Esto minimiza la latencia de salida del estado de inactividad, pero a costa de mantener la CPU funcionando a máxima velocidad en el hilo de inactividad.

nmi_watchdog

0

Esta opción deshabilita solo el watchdog NMI. Esto puede omitirse cuando nowatchdog está establecido.

nowatchdog

 

Esta opción deshabilita el watchdog de soft-lockup, que se implementa como un temporizador que se ejecuta en el contexto de interrupción de hardware del temporizador.

Los siguientes comandos modifican la configuración de GRUB y aplican los cambios mencionados anteriormente para que estén presentes en el próximo arranque:

Editad el archivo /etc/default/grub con los parámetros anteriores y el archivo quedará así:

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

Actualizad la configuración de GRUB:

$ transactional-update grub.cfg
$ reboot

Para validar que los parámetros se aplican después del reinicio, se puede utilizar el siguiente comando para comprobar la línea de comandos del kernel:

$ cat /proc/cmdline

Existe otro script que se puede utilizar para ajustar la configuración de la CPU, que básicamente realiza los siguientes pasos:

  • Estableced el gobernador de CPU en performance.

  • Desactivad la migración del temporizador a las CPU aisladas.

  • Migrad los hilos kdaemon a las CPU de mantenimiento.

  • Ajustad la latencia de las CPU aisladas al valor más bajo posible.

  • Retrasad las actualizaciones de vmstat a 300 segundos.

El script está disponible en el repositorio de ejemplos de SUSE Telco Cloud.

37 Fijación de CPU en Kubernetes

37.1 Versiones de RKE2 < v1.32

Habilitad la fijación de CPU en vuestro clúster RKE2 editando el archivo de configuración de RKE2. Añadid los siguientes argumentos de kubelet en el archivo /etc/rancher/rke2/config.yaml. Aseguraos de especificar los núcleos de CPU de mantenimiento en los argumentos kubelet-reserved y system-reserved:

kubelet-arg:
- "cpu-manager-policy=static"
- "cpu-manager-policy-options=full-pcpus-only=true"
- "cpu-manager-reconcile-period=0s"
- "kubelet-reserved=cpu=0,31,32,63"
- "system-reserved=cpu=0,31,32,63"

37.2 Versiones de RKE2 >= v1.32

Si vuestra versión de RKE2 es v1.32 o superior, no se pueden utilizar argumentos de línea de comandos para configurar kubelet, siguiendo la práctica de Kubernetes upstream. Para configurar la fijación de CPU, es necesario crear un archivo de configuración de kubelet. Consultad la documentación de RKE2.

Cread un nuevo archivo de configuración de kubelet como 01-cpu-pinning.conf y colocadlo en el directorio /var/lib/rancher/rke2/agent/etc/kubelet.conf.d/:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cpuManagerPolicy: static
reservedSystemCPUs: 0,31,32,63
topologyManagerPolicy: single-numa-node

Para que los cambios de configuración surtan efecto, es necesario reiniciar el servicio RKE2 correspondiente (servidor o agente). Esta acción interrumpirá brevemente el servicio RKE2 en el host. Ejecute solo uno de los siguientes comandos, dependiendo del tipo de nodo:

# If the node is RKE2 agent
systemctl restart rke2-agent
# Else if the node is RKE2 server
systemctl restart rke2-server

37.3 Desplegar cargas de trabajo aprovechando CPUs con afinidad

Existen tres formas de utilizar la función mediante la Static Policy definida en kubelet, dependiendo de las solicitudes y límites que defina en su carga de trabajo:

  1. Clase de QoS BestEffort: Si no define ninguna solicitud o límite para CPU, el pod se programa en la primera CPU disponible en el sistema.

    Un ejemplo de uso de la clase de QoS BestEffort podría ser:

    spec:
      containers:
      - name: nginx
        image: nginx
  2. Clase de QoS Burstable: Si define una solicitud de CPU que no es igual a los límites, o si no hay ninguna solicitud de CPU.

    Ejemplos de uso de la clase de QoS Burstable podrían ser:

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
          requests:
            memory: "100Mi"

    O bien

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
            cpu: "2"
          requests:
            memory: "100Mi"
            cpu: "1"
  3. Clase de QoS Guaranteed: Si define una solicitud de CPU que es igual a los límites.

    Un ejemplo de uso de la clase de QoS Guaranteed podría ser:

    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: "200Mi"
              cpu: "2"
            requests:
              memory: "200Mi"
              cpu: "2"

38 Configuración de CNI

38.1 Cilium

Cilium es el complemento CNI predeterminado para SUSE Telco Cloud. Para habilitar Cilium en el clúster RKE2 como complemento predeterminado, se requiere la siguiente configuración en el archivo /etc/rancher/rke2/config.yaml:

cni:
- cilium

Esto también se puede especificar con argumentos de línea de comandos, es decir, --cni=cilium en la línea del servidor en el archivo /etc/systemd/system/rke2-server.

Para utilizar la red SR-IOV descrita en Sección 39.2, “Opción 2 (Recomendada): Operador de red SR-IOV” junto con Cilium, despliegue el meta complemento multus. Asegúrese de que multus aparezca antes que otros CNI.

cni:
- multus
- cilium

38.2 Calico

Calico es otro complemento CNI para SUSE Telco Cloud para Telco. Para habilitar Calico en el clúster RKE2 como complemento predeterminado, se requiere la siguiente configuración en el archivo /etc/rancher/rke2/config.yaml:

cni:
- calico

Esto también se puede especificar con argumentos de línea de comandos, es decir, --cni=calico en la línea del servidor en el archivo /etc/systemd/system/rke2-server.

Para utilizar la red SR-IOV descrita en Sección 39.2, “Opción 2 (Recomendada): Operador de red SR-IOV” junto con Calico, despliegue el meta complemento multus. Asegúrese de que multus aparezca antes que otros CNI.

cni:
- multus
- calico
Nota
Nota

Para obtener más información sobre los complementos CNI, consulte Network Options.

38.3 Bond CNI

En términos generales, la vinculación proporciona un método para agregar múltiples interfaces de red en una única interfaz lógica vinculada. Esto se utiliza habitualmente para aumentar la disponibilidad del servicio mediante la introducción de rutas de red redundantes, pero también puede utilizarse para incrementar el ancho de banda con ciertos modos de vinculación. Los siguientes complementos CNI son compatibles con el complemento Bond CNI en combinación con multus:

  • MACVLAN

  • Dispositivo host

  • SR-IOV

38.3.1 Bond CNI con MACVLAN

Para utilizar el complemento Bond CNI con MACVLAN se necesitan dos interfaces libres en el contenedor. El siguiente ejemplo utiliza 'enp8s0' y 'enp9s0'. Empezad creando definiciones de conexión de red para ellos:

NetworkAttachmentDefinition enp8s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp8s0-conf
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "macvlan",
          "capabilities": { "ips": true },
          "master": "enp8s0",
          "mode": "bridge",
          "ipam": {}
        }, {
          "capabilities": { "mac": true },
          "type": "tuning"
        }
      ]
    }'

NetworkAttachmentDefinition enp9s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp9s0-conf
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "macvlan",
          "capabilities": { "ips": true },
          "master": "enp9s0",
          "mode": "bridge",
          "ipam": {}
        }, {
          "capabilities": { "mac": true },
          "type": "tuning"
        }
      ]
    }'

Después de esto, añadid una definición de conexión de red para el propio bond.

NetworkAttachmentDefinition bond

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: bond-net1
spec:
  config: '{
  "type": "bond",
  "cniVersion": "0.3.1",
  "name": "bond-net1",
  "mode": "active-backup",
  "failOverMac": 1,
  "linksInContainer": true,
  "miimon": "100",
  "mtu": 1500,
  "links": [
     {"name": "net1"},
     {"name": "net2"}
  ],
  "ipam": {
    "type": "static",
    "addresses": [
      {
        "address": "192.168.200.100/24",
        "gateway": "192.168.200.1"
      }
    ],
    "subnet": "192.168.200.0/24",
    "routes": [{
      "dst": "0.0.0.0/0"
    }]
  }
}'

La asignación de la dirección IP aquí es estática y define la dirección del enlace como '192.168.200.100' en una red /24, con una puerta de enlace que reside en la primera dirección disponible de la red. En la conexión de red del enlace también definimos el tipo de enlace que queremos. En este caso es active-backup.

Para usar este enlace, el pod necesita conocer todas las interfaces. Un ejemplo de definición de pod podría ser así:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  annotations:
        k8s.v1.cni.cncf.io/networks: '[
{"name": "enp8s0-conf",
"interface": "net1"
},
{"name": "enp9s0-conf",
"interface": "net2"
},
{"name": "bond-net1",
"interface": "bond0"
}]'
spec:
  restartPolicy: Never
  containers:
  - name: bond-test
    image: alpine:latest
    command:
      - /bin/sh
      - "-c"
      - "sleep 60m"
    imagePullPolicy: IfNotPresent

Observad cómo la anotación hace referencia a todas las redes y cómo define el mapeo entre las interfaces 'enp8s0 → net1' y 'enp9s0→net2'.

38.3.2 Bond CNI con dispositivo host

Para usar el complemento Bond CNI con dispositivo host, se necesitan dos interfaces libres en el host. Estas interfaces se asignan entonces al contenedor. El siguiente ejemplo utiliza 'enp8s0' y 'enp9s0'. Empezad creando definiciones de conexión de red para ellos:

NetworkAttachmentDefinition enp8s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp8s0-hostdev
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "host-device",
          "name": "host0",
          "device": "enp8s0",
          "ipam": {}
        }]
    }'

NetworkAttachmentDefinition enp9s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp9s0-hostdev
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "host-device",
          "name": "host0",
          "device": "enp9s0",
          "ipam": {}
        }]
    }'

Después de esto, añadid la definición de conexión de red para el propio enlace. Esto es similar al caso de uso de MACVLAN.

NetworkAttachmentDefinition bond

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: bond-net1
spec:
  config: '{
  "type": "bond",
  "cniVersion": "0.3.1",
  "name": "bond-net1",
  "mode": "active-backup",
  "failOverMac": 1,
  "linksInContainer": true,
  "miimon": "100",
  "mtu": 1500,
  "links": [
     {"name": "net1"},
     {"name": "net2"}
  ],
  "ipam": {
    "type": "static",
    "addresses": [
      {
        "address": "192.168.200.100/24",
        "gateway": "192.168.200.1"
      }
    ],
    "subnet": "192.168.200.0/24",
    "routes": [{
      "dst": "0.0.0.0/0"
    }]
  }
}'

La asignación de la dirección IP aquí es estática y define la dirección del enlace como '192.168.200.100' en una red /24, con una puerta de enlace que reside en la primera dirección disponible de la red. En la conexión de red del enlace, definid el tipo de enlace. En este caso es active-backup.

Para usar este enlace, el pod necesita conocer todas las interfaces. Un ejemplo de definición de pod para un enlace con dispositivos host podría ser así:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  annotations:
        k8s.v1.cni.cncf.io/networks: '[
{"name": "enp8s0-hostdev",
"interface": "net1"
},
{"name": "enp9s0-hostdev",
"interface": "net2"
},
{"name": "bond-net1",
"interface": "bond0"
}]'
spec:
  restartPolicy: Never
  containers:
  - name: bond-test
    image: alpine:latest
    command:
      - /bin/sh
      - "-c"
      - "sleep 60m"
    imagePullPolicy: IfNotPresent

38.3.3 Bond CNI con SR-IOV

Usar el Bond CNI con SR-IOV es bastante sencillo. Para más detalles sobre cómo configurar SR-IOV, consultad Capítulo 39, SR-IOV. Como se describe allí, tenéis que crear SriovNetworkNodePolicies que defina resourceNames, así como el número de funciones virtuales y similares. Los resourceNames están siendo utilizados por el SriovNetwork que se usa como interfaces en la definición del pod. La definición de enlace es exactamente la misma que para los casos de MACVLAN y dispositivo host.

Nota
Nota

El CNI de enlace con SR-IOV solo es aplicable a funciones virtuales (VF) SR-IOV que utilizan el controlador del kernel. Las VF con controlador de espacio de usuario, como las utilizadas en cargas de trabajo DPDK, no pueden enlazarse con el CNI de enlace.

39 SR-IOV

SR-IOV (Single Root I/O Virtualization) permite que un único dispositivo físico, como un adaptador de red, separe sus recursos entre múltiples PCIe funciones de hardware. Esto permite el acceso directo a los recursos para diversas aplicaciones.

Proporcionamos dos métodos distintos para desplegar SR-IOV en su clúster:

En casos excepcionales en los que necesite ambas soluciones (usar el Operador de red para dispositivos de red y el Plugin de dispositivo para aceleradores vRAN), debe desplegarlas en espacios de nombres de Kubernetes separados. Esta separación es esencial para evitar conflictos entre ambos despliegues.

39.1 Opción 1: Daemonset y configMap del Plugin de dispositivo de red SR-IOV

El Plugin de dispositivo de red SR-IOV descubre y anuncia recursos de red, como funciones físicas (PF) PCI y sus funciones virtuales (VF), en un host de Kubernetes.

  • Prepare el mapa de configuración para el plugin de dispositivo

Necesitamos crear un mapa de configuración que defina los grupos de recursos SR-IOV. Ejecute el comando lspci para recuperar la información:

$ lspci | grep -i acc
07:00.0 Processing accelerators: Intel Corporation Device 57c2
07:00.1 Processing accelerators: Intel Corporation Device 57c3
07:00.2 Processing accelerators: Intel Corporation Device 57c3
07:00.3 Processing accelerators: Intel Corporation Device 57c3
07:00.4 Processing accelerators: Intel Corporation Device 57c3
07:00.5 Processing accelerators: Intel Corporation Device 57c3
07:00.6 Processing accelerators: Intel Corporation Device 57c3
07:00.7 Processing accelerators: Intel Corporation Device 57c3
07:01.0 Processing accelerators: Intel Corporation Device 57c3
07:01.1 Processing accelerators: Intel Corporation Device 57c3
07:01.2 Processing accelerators: Intel Corporation Device 57c3
07:01.3 Processing accelerators: Intel Corporation Device 57c3
07:01.4 Processing accelerators: Intel Corporation Device 57c3
07:01.5 Processing accelerators: Intel Corporation Device 57c3
07:01.6 Processing accelerators: Intel Corporation Device 57c3
07:01.7 Processing accelerators: Intel Corporation Device 57c3
07:02.0 Processing accelerators: Intel Corporation Device 57c3
0a:00.0 Processing accelerators: Intel Corporation Device 57c2

$ lspci | grep -i net
19:00.0 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.1 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.2 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.3 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
51:00.0 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02)
51:00.1 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02)
51:01.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)

El Plugin de dispositivo SR-IOV utiliza un configMap que contiene un archivo JSON para definir qué recursos de hardware debe exponer Kubernetes. Esta configuración se basa en dos conceptos fundamentales: selectors (para el descubrimiento de hardware) y resources (para la exposición en Kubernetes).

Un resource es la entidad con nombre que consumen los pods (p. ej., rancher.io/intel_fec_5g). Los recursos pueden definirse como uno de los dos tipos siguientes:

  • accelerator: Se utiliza para tarjetas aceleradoras vRAN (como ACC100/vRAN Boost).

  • netdevice: Se utiliza para interfaces de red estándar (NIC).

Define los dispositivos de destino utilizando selectors para filtrar el hardware en el nodo:

  • vendors: 8086 (Intel)

  • devices: 57c3 (FEC VF), 1889 (NIC VF)

  • drivers: vfio-pci

  • pfNames: p2p1 (nombre de la interfaz física)

Para tarjetas de red, también puede seleccionar un subconjunto de Funciones Virtuales (VF) a partir de una Función Física:

  • pfNames: ["eth1#1,2,3,4,5,6"] o bien [eth1#1-6]

Para permitir que los pods soliciten los dispositivos, cada recurso debe tener un nombre, que se compone de un prefijo y un nombre:

  • resourceName: pci_sriov_net_bh_dpdk

  • resourcePrefix: rancher.io

Los pods solicitarían entonces el nombre de recurso combinado: rancher.io/pci_sriov_net_bh_dpdk.

Nota
Nota

Este documento no enumera todos los selectores posibles. Los diferentes tipos de recursos utilizan diferentes conjuntos de selectores. Para obtener detalles completos, consulte el repositorio del plugin de dispositivos de red SR-IOV.

El ConfigMap siguiente es un ejemplo que crea tres recursos: uno para la tarjeta aceleradora vRAN (FEC) y dos para dos puertos NIC diferentes.

Para la tarjeta FEC, primero debe obtener el ID del dispositivo y el token VFIO. Siga las instrucciones del capítulo Capítulo 41, Aceleración vRAN (Intel ACC100/VRB1/VRB2) para conocer los requisitos previos.

apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": [
            {
                "resourcePrefix": "rancher.io",
                "resourceName": "intel_fec_5g",
                "deviceType": "accelerator",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["57c3"]
                },
                "additionalInfo": {
                      "*": {
                        "VFIO_TOKEN": "00112233-4455-6677-8899-aabbccddeeff"
                      }
                  }
            },
            {
                "resourcePrefix": "rancher.io",
                "resourceName": "intel_sriov_odu",
                "deviceType": "netdevice",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p1"]
                }
            },
            {
                "resourcePrefix": "rancher.io",
                "resourceName": "intel_sriov_oru",
                "deviceType": "netdevice",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p2"]
                }
            }
        ]
    }
  • Prepare el archivo daemonset para desplegar el complemento de dispositivo.

El complemento de dispositivo admite varias arquitecturas (arm, amd, ppc64le), por lo que se puede utilizar el mismo archivo para diferentes arquitecturas desplegando varios daemonset para cada arquitectura.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sriov-device-plugin
  namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-sriov-device-plugin-amd64
  namespace: kube-system
  labels:
    tier: node
    app: sriovdp
spec:
  selector:
    matchLabels:
      name: sriov-device-plugin
  template:
    metadata:
      labels:
        name: sriov-device-plugin
        tier: node
        app: sriovdp
    spec:
      hostNetwork: true
      nodeSelector:
        kubernetes.io/arch: amd64
      tolerations:
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      serviceAccountName: sriov-device-plugin
      containers:
      - name: kube-sriovdp
        image: registry.suse.com/rancher/hardened-sriov-network-device-plugin:v3.9.0-build20250425
        imagePullPolicy: IfNotPresent
        args:
        - --log-dir=sriovdp
        - --log-level=10
        securityContext:
          privileged: true
        resources:
          requests:
            cpu: "250m"
            memory: "40Mi"
          limits:
            cpu: 1
            memory: "200Mi"
        volumeMounts:
        - name: devicesock
          mountPath: /var/lib/kubelet/
          readOnly: false
        - name: log
          mountPath: /var/log
        - name: config-volume
          mountPath: /etc/pcidp
        - name: device-info
          mountPath: /var/run/k8s.cni.cncf.io/devinfo/dp
      volumes:
        - name: devicesock
          hostPath:
            path: /var/lib/kubelet/
        - name: log
          hostPath:
            path: /var/log
        - name: device-info
          hostPath:
            path: /var/run/k8s.cni.cncf.io/devinfo/dp
            type: DirectoryOrCreate
        - name: config-volume
          configMap:
            name: sriovdp-config
            items:
            - key: config.json
              path: config.json
  • Tras aplicar el configMap y el daemonset, el complemento de dispositivo se desplegará y las interfaces serán detectadas y estarán disponibles para los pods.

    $ kubectl get pods -n kube-system | grep sriov
    kube-system  kube-sriov-device-plugin-amd64-twjfl  1/1  Running  0  2m
  • Verifique en todos los nodos si las interfaces fueron detectadas y quedaron disponibles para los pods:

    $ kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, allocatable: .status.allocatable}'
    {
      "name": "node1.suse.edge.com",
      "allocatable": {
          "cpu": "64",
          "ephemeral-storage": "256196109726",
          "hugepages-1Gi": "40Gi",
          "hugepages-2Mi": "0",
          "rancher.io/intel_fec_5g": "16",
          "rancher.io/intel_sriov_odu": "4",
          "rancher.io/intel_sriov_oru": "4",
          "memory": "221396384Ki",
          "pods": "110"
      }
    }
  • El resourceName para el acelerador FEC es rancher.io/intel_fec_5g y hay 16 VFs disponibles para su uso.

  • El resourceName para las tarjetas NIC es rancher.io/intel_sriov_odu y rancher.io/intel_sriov_oru. Cada recurso proporciona 4 VFs.

Importante
Importante

Si no se detecta ninguna interfaz como recurso asignable en los nodos de Kubernetes, es esencial resolver este problema. Una causa común es una especificación de configMap mal formada, así que mejor revisad el configMap y sus selectores.

39.2 Opción 2 (Recomendada): Operador de red SR-IOV

  • Obtened Helm si no está presente:

$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
  • Instalad el Operador de red SR-IOV en el espacio de nombres sriov-network-operator:

helm install sriov-crd oci://registry.suse.com/edge/charts/sriov-crd -n sriov-network-operator
helm install sriov-network-operator oci://registry.suse.com/edge/charts/sriov-network-operator -n sriov-network-operator
  • Comprobad los CRD y pods desplegados:

$ kubectl get crd
$ kubectl -n sriov-network-operator get pods
  • Comprobad si la etiqueta SR-IOV se ha aplicado a los nodos.

Con todos los recursos en ejecución, la etiqueta aparece automáticamente en vuestro nodo:

$ kubectl get nodes -oyaml | grep feature.node.kubernetes.io/network-sriov.capable

feature.node.kubernetes.io/network-sriov.capable: "true"
  • Revisad el daemonset para ver los nuevos sriov-network-config-daemon y sriov-rancher-nfd-worker como activos y listos:

$ kubectl get daemonset -n sriov-network-operator
NAMESPACE             NAME                            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                                           AGE
sriov-network-operator   sriov-network-config-daemon     1         1         1       1            1           feature.node.kubernetes.io/network-sriov.capable=true   45m
sriov-network-operator   sriov-rancher-nfd-worker        1         1         1       1            1           <none>                                                  45m

En unos minutos, los nodos serán detectados y configurados completamente con SR-IOV capacidades. La actualización a veces puede tardar hasta 10 minutos:

$ kubectl get sriovnetworknodestates -A
NAMESPACE             NAME     AGE
sriov-network-operator   xr11-2   83s
  • Comprobad si se detectaron las interfaces.

Las interfaces descubiertas deberían ser la dirección PCI del dispositivo de red. Comprobad esta información con el comando lspci en el host.

$ kubectl get sriovnetworknodestates -n sriov-network-operator -oyaml
apiVersion: v1
items:
- apiVersion: sriovnetwork.openshift.io/v1
  kind: SriovNetworkNodeState
  metadata:
    creationTimestamp: "2023-06-07T09:52:37Z"
    generation: 1
    name: xr11-2
    namespace: sriov-network-operator
    ownerReferences:
    - apiVersion: sriovnetwork.openshift.io/v1
      blockOwnerDeletion: true
      controller: true
      kind: SriovNetworkNodePolicy
      name: default
      uid: 80b72499-e26b-4072-a75c-f9a6218ec357
    resourceVersion: "356603"
    uid: e1f1654b-92b3-44d9-9f87-2571792cc1ad
  spec:
    dpConfigVersion: "356507"
  status:
    interfaces:
    - deviceID: "1592"
      driver: ice
      eSwitchMode: legacy
      linkType: ETH
      mac: 40:a6:b7:9b:35:f0
      mtu: 1500
      name: p2p1
      pciAddress: "0000:51:00.0"
      totalvfs: 128
      vendor: "8086"
    - deviceID: "1592"
      driver: ice
      eSwitchMode: legacy
      linkType: ETH
      mac: 40:a6:b7:9b:35:f1
      mtu: 1500
      name: p2p2
      pciAddress: "0000:51:00.1"
      totalvfs: 128
      vendor: "8086"
    syncStatus: Succeeded
kind: List
metadata:
  resourceVersion: ""
Nota
Nota

Si vuestra interfaz no se detecta aquí, aseguraos de que esté presente en el siguiente config map:

$ kubectl get cm supported-nic-ids -oyaml -n sriov-network-operator

Si vuestro dispositivo no aparece en la lista, editad el config map añadiendo los valores correctos para que sea descubierto. A continuación, reiniciad los pods sriov-network-config-daemon en cada nodo para que la actualización surta efecto.

  • Cread el SriovNetworkNodePolicy para configurar el VFs

Esta política crea el recurso intelnicsDpdk para el consumo de pods. También vincula el controlador vfio-pci al dispositivo PCI proporcionado y crea 8 VFs con un tamaño de MTU de 1500:

Nota
Nota

El campo resourceName no debe contener caracteres especiales y debe ser único en todo el clúster. El ejemplo utiliza el deviceType: vfio-pci porque DPDK se utiliza en combinación con SR-IOV. Si no utilizáis DPDK, configurad deviceType: netdevice (valor predeterminado).

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: policy-dpdk
  namespace: sriov-network-operator
spec:
  nodeSelector:
    feature.node.kubernetes.io/network-sriov.capable: "true"
  resourceName: intelnicsDpdk
  deviceType: vfio-pci
  numVfs: 8
  mtu: 1500
  nicSelector:
    deviceID: "1592"
    vendor: "8086"
    rootDevices:
    - 0000:51:00.0
  • Validad las configuraciones en todos los nodos:

Con el resourcePrefix rancher.io predefinido, debería detectarse un recurso rancher.io/intelnicsDpdk con 8 VFs.

$ kubectl get nodes -o jsonpath='{"items": [ { "name": @.metadata.name, "allocatable": @.status.allocatable } ]}' | jq
{
  "name": "node1.suse.edge.com",
  "allocatable": {
      "cpu": "64",
      "ephemeral-storage": "256196109726",
      "hugepages-1Gi": "60Gi",
      "hugepages-2Mi": "0",
      "rancher.io/intel_fec_5g": "16",
      "memory": "200424836Ki",
      "pods": "110",
      "rancher.io/intelnicsDpdk": "8"
  }
}
  • (Opcional) Cread el sriovnetwork

Este paso es opcional y solo es necesario para definiciones de red personalizadas. Especificad el resourceName para vincularlo a la política de nodo creada anteriormente.

Si se establece el networkNamespace, la red se expone a los pods en ese espacio de nombres. De lo contrario, la red pasa a estar disponible en el espacio de nombres de instalación del operador de red.

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: network-dpdk
  namespace: sriov-network-operator        # where SRIOV Operator is installed
spec:
  ipam: |
    {
      "type": "host-local",
      "subnet": "192.168.0.0/24",
      "rangeStart": "192.168.0.20",
      "rangeEnd": "192.168.0.60",
      "routes": [{
        "dst": "0.0.0.0/0"
      }],
      "gateway": "192.168.0.1"
    }
  vlan: 500
  resourceName: intelnicsDpdk
  networkNamespace: default         # where workloads are deployed
  • Si la actualización se realiza correctamente, se crea una NetworkAttachmentDefinition (NAD) en el clúster de destino.

$ kubectl get net-attach-def -A -oyaml

apiVersion: v1
items:
- apiVersion: k8s.cni.cncf.io/v1
  kind: NetworkAttachmentDefinition
  metadata:
    annotations:
      k8s.v1.cni.cncf.io/resourceName: rancher.io/intelnicsDpdk
    creationTimestamp: "2023-06-08T11:22:27Z"
    generation: 1
    name: network-dpdk
    namespace: default
    resourceVersion: "13124"
    uid: df7c89f5-177c-4f30-ae72-7aef3294fb15
  spec:
    config: '{ "cniVersion":"0.4.0", "name":"network-dpdk","type":"sriov","vlan":500,"vlanQoS":0,"ipam":{"type":"host-local","subnet":"192.168.0.0/24","rangeStart":"192.168.0.10","rangeEnd":"192.168.0.60","routes":[{"dst":"0.0.0.0/0"}],"gateway":"192.168.0.1"}
      }'
kind: List
metadata:
  resourceVersion: ""

Los pods de carga de trabajo podrían usar el resourceName rancher.io/intelnicsDpdk para utilizar las VFs de la interfaz de red.

40 DPDK

DPDK (Data Plane Development Kit) es un conjunto de bibliotecas y controladores para el procesamiento rápido de paquetes. Se utiliza para acelerar las cargas de trabajo de procesamiento de paquetes que se ejecutan en una amplia variedad de arquitecturas de CPU. El DPDK incluye bibliotecas de plano de datos y controladores de tarjeta de interfaz de red (NIC) optimizados para lo siguiente:

  1. Un gestor de colas implementa colas sin bloqueo.

  2. Un gestor de búferes preasigna búferes de tamaño fijo.

  3. Un gestor de memoria asigna grupos de objetos en la memoria y utiliza un anillo para almacenar objetos libres; garantiza que los objetos se distribuyan equitativamente en todos los DRAM canales.

  4. Los controladores en modo sondeo (PMD) están diseñados para funcionar sin notificaciones asíncronas, lo que reduce la sobrecarga.

  5. Un marco de paquetes como un conjunto de bibliotecas que sirven de ayuda para desarrollar el procesamiento de paquetes.

Los siguientes pasos mostrarán cómo habilitar DPDK y cómo crear VFs a partir de NICs para que sean utilizados por las interfaces DPDK:

  • Instale el paquete DPDK:

$ transactional-update pkg install dpdk dpdk-tools libdpdk-25
$ reboot
  • Parámetros del kernel:

Para utilizar DPDK, utiliza algunos controladores para habilitar ciertos parámetros en el núcleo de Linux:

parametervalordescription

iommu

pt

Esta opción permite el uso del controlador vfio para las interfaces DPDK.

intel_iommu or amd_iommu

on

Esta opción permite el uso de vfio para VFs.

Para habilitar los parámetros, añádelos al archivo /etc/default/grub:

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

Actualiza la configuración de GRUB y reinicia el sistema para aplicar los cambios:

$ transactional-update grub.cfg
$ reboot
  • Carga el módulo del núcleo de Linux vfio-pci y habilita SR-IOV en las NIC. El primer argumento indica el controlador vfio-pci para admitir SR-IOV, y el segundo argumento evita que el dispositivo PCI entre en un estado de bajo consumo cuando está inactivo:

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • Cread algunas funciones virtuales (VFs) a partir de NICs.

Para crear para VFs, por ejemplo, para dos NICs diferentes, se requieren los siguientes comandos:

$ echo 4 > /sys/bus/pci/devices/0000:51:00.0/sriov_numvfs
$ echo 4 > /sys/bus/pci/devices/0000:51:00.1/sriov_numvfs
  • Vinculad las nuevas VFs con el controlador vfio-pci:

$ dpdk-devbind.py -b vfio-pci 0000:51:01.0 0000:51:01.1 0000:51:01.2 0000:51:01.3 \
                              0000:51:11.0 0000:51:11.1 0000:51:11.2 0000:51:11.3
  • Revisad que la configuración se haya aplicado correctamente:

$ dpdk-devbind.py -s

Network devices using DPDK-compatible driver
============================================
0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:11.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:21.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:31.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio

Network devices using kernel driver
===================================
0000:19:00.0 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em1 drv=bnxt_en unused=igb_uio,vfio-pci *Active*
0000:19:00.1 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em2 drv=bnxt_en unused=igb_uio,vfio-pci
0000:19:00.2 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em3 drv=bnxt_en unused=igb_uio,vfio-pci
0000:19:00.3 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em4 drv=bnxt_en unused=igb_uio,vfio-pci
0000:51:00.0 'Ethernet Controller E810-C for QSFP 1592' if=eth13 drv=ice unused=igb_uio,vfio-pci
0000:51:00.1 'Ethernet Controller E810-C for QSFP 1592' if=rename8 drv=ice unused=igb_uio,vfio-pci

41 Aceleración vRAN (Intel ACC100/VRB1/VRB2)

A medida que los proveedores de servicios de comunicaciones pasan de las redes 4G a las 5G, muchos están adoptando arquitecturas de red de acceso por radio virtualizada (vRAN) para obtener una mayor capacidad de canal y un despliegue más sencillo de servicios y aplicaciones basados en el borde. Las soluciones vRAN están idealmente situadas para ofrecer servicios de baja latencia con la flexibilidad de aumentar o disminuir la capacidad en función del volumen de tráfico en tiempo real y la demanda en la red.

Una de las cargas de trabajo 4G y 5G que requiere más computación es la capa 1 de RAN (L1) FEC, que resuelve los errores de transmisión de datos en canales de comunicación poco fiables o ruidosos. La tecnología FEC detecta y corrige un número limitado de errores en datos 4G o 5G, eliminando la necesidad de retransmisión. Dado que la transacción de aceleración FEC no contiene información sobre el estado de la celda, puede virtualizarse fácilmente, lo que permite obtener ventajas de agrupación y una migración sencilla de celdas.

Históricamente, Intel proporcionaba la tarjeta aceleradora vRAN ACC100 para ejecutar rápidamente algoritmos FEC de Layer 1, liberando potencia de procesamiento del host para la CPU principal. Desde entonces, Intel ha integrado esta tecnología directamente en las CPU más recientes, empezando por Sapphire Rapids, bajo el nombre Intel vRAN Boost (VRB). Intel vRAN Boost actúa como un acelerador de descarga en la propia CPU, eliminando la necesidad de una tarjeta de hardware independiente. Esta sección detalla la configuración de SUSE Telco Cloud para que las cargas de trabajo aprovechen ACC100 o Intel vRAN Boost.

41.1 Parámetros del kernel

Para habilitar la vRAN aceleración, debemos habilitar los siguientes parámetros del kernel (si aún no están presentes):

parametervalordescription

iommu

pt

Esta opción permite el uso de vfio para las interfaces DPDK.

intel_iommu or amd_iommu

on

Esta opción permite el uso de vfio para las VFs.

Modificad el archivo GRUB /etc/default/grub para añadirlos a la línea de comandos del kernel:

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

Actualizad la configuración de GRUB y reiniciad el sistema para aplicar los cambios:

$ transactional-update grub.cfg
$ reboot

Para verificar que los parámetros se han aplicado tras el reinicio, comprobad la línea de comandos:

$ cat /proc/cmdline

41.2 Configuración de SR-IOV en aceleradores FEC

  • Cargad el módulo del núcleo de Linux vfio-pci para habilitar la aceleración vRAN. El primer argumento indica el módulo vfio-pci para admitir SR-IOV, y el segundo argumento evita que el dispositivo PCI entre en un estado de bajo consumo cuando está inactivo.

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • Obtened la dirección del dispositivo PCI del acelerador FEC:

$ lspci -DPPnn | grep -i acc
0000:07:00.0 Processing accelerators [1200]: Intel Corporation Device [8086:57c2]
0000:0a:00.0 Processing accelerators [1200]: Intel Corporation Device [8086:57c2]
  • Vinculad la interfaz física (PF) con el controlador vfio-pci:

$ dpdk-devbind.py -b vfio-pci 0000:07:00.0
  • Cread las funciones virtuales (VFs) a partir de la interfaz física (PF).

Comprobad la capacidad máxima VF de la tarjeta aceleradora. A continuación, configurad la tarjeta para exponer el número deseado de VFs, sin exceder el número máximo. En este ejemplo, configuramos la tarjeta para su capacidad total de 16 VFs:

$ cat /sys/bus/pci/devices/0000:07:00.0/sriov_totalvfs
64
$ echo 16 > /sys/bus/pci/devices/0000:07:00.0/sriov_numvfs
  • Configurad la tarjeta aceleradora y sus funciones virtuales con un perfil 4G o 5G, seleccionando el tipo de dispositivo vRAN Boost correcto según la generación exacta del procesador Intel: VRB1 (anteriormente conocido como ACC200) si es Sapphire Rapids Edge Enhanced (SPR-EE), VRB2 para Granite Rapids-D (GNR-D). Se debe proporcionar un VF token único (UUID) (la carga de trabajo consumirá este VF token para utilizar las capacidades de aceleración FEC de la tarjeta).

Aviso
Aviso

Obsolescencia desde pf-bb-config: la nueva versión de RPM que admite el tipo de dispositivo VRB2 ahora instala los archivos de ejemplo de configuración en la ubicación /usr/share/pf-bb-config/examples; la vía antigua /opt/pf-bb-config/ sigue siendo compatible, pero se eliminará en futuras versiones. Por favor, actualizad vuestros scripts y documentación para reflejar la nueva vía (como se ha hecho en el ejemplo siguiente).

$ pf_bb_config VRB2 -c /usr/share/pf-bb-config/examples/vrb2/vrb2_config_vf_5g.cfg -f /usr/share/pf-bb-config/examples/vrb2/srs_fft_windows_coefficient.bin -v 00112233-4455-6677-8899-aabbccddeeff -p 0000:07:00.0
== pf_bb_config Version 25.11 ==
VRB2 PF [0000:07:00.0] configuration complete!
Log file = /var/log/pf_bb_cfg_0000:07:00.0.log
  • Verificad las nuevas VFs creadas a partir de la PF de FEC. Observad que las VFs obtuvieron el ID de dispositivo 0d5d. Esta información es necesaria en el siguiente paso para exponer las VFs como recurso de Kubernetes:

$ # dpdk-devbind.py -s | grep -A18 Baseband
Baseband devices using DPDK-compatible driver
=============================================
0000:07:00.0 'Device 57c2' numa_node=0 drv=vfio-pci unused=
0000:07:00.1 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.2 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.3 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.4 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.5 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.6 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.7 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.0 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.1 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.2 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.3 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.4 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.5 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.6 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.7 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:02.0 'Device 57c3' numa_node=0 drv=vfio-pci unused=
--
Other Baseband devices
======================
0000:0a:00.0 'Device 57c2' numa_node=0 unused=vfio-pci

Other Crypto devices
====================
0000:01:00.0 '420xx Series QAT 4946' numa_node=0 unused=vfio-pci
0000:03:00.0 'Device 2714' numa_node=0 unused=vfio-pci

DMA devices using kernel driver
===============================
0000:00:01.0 'Device 11fb' numa_node=0 drv=idxd unused=vfio-pci

Other Eventdev devices
======================
0000:03:00.0 'Device 2714' numa_node=0 unused=vfio-pci

No 'Mempool' devices detected
=============================

41.3 Configuración de Kubernetes para la aceleración FEC

El paso final consiste en exponer las VFs a Kubernetes con la ayuda del plugin de dispositivo SR-IOV. Cread un ConfigMap utilizando el ID de dispositivo de las VF obtenido en el paso anterior e instalad el plugin de dispositivo SR-IOV. Una vez que los nodos de Kubernetes muestren las VF de FEC como recursos Allocatable, el clúster estará listo para que las cargas de trabajo aprovechen la aceleración FEC.

Seguid los pasos de la Opción 1 en el capítulo Capítulo 39, SR-IOV. El operador de red SRIOV no es aplicable al acelerador FEC, por lo que la Opción 2 no es aplicable.

42 Páginas enormes

Cuando un proceso utiliza RAM, el CPU lo marca como utilizado por dicho proceso. Para mayor eficiencia, el CPU asigna RAM en bloques; 4K bytes es el valor predeterminado en muchas plataformas. Esos bloques se denominan páginas. Las páginas pueden intercambiarse a disco, etc.

Dado que el espacio de direcciones del proceso es virtual, el CPU y el sistema operativo deben recordar qué páginas pertenecen a qué proceso y dónde se almacena cada página. Cuanto mayor sea el número de páginas, más larga será la búsqueda del mapeo de memoria. Cuando un proceso utiliza 1 GB de memoria, eso supone 262144 entradas que buscar (1 GB / 4 K). Si una entrada de la tabla de páginas consume 8 bytes, eso supone 2 MB (262144 * 8) que buscar.

La mayoría de las arquitecturas CPU actuales admiten páginas mayores que las predeterminadas, lo que da al CPU/OS menos entradas que buscar.

  • Parámetros del kernel

Para habilitar las páginas enormes, debéis añadir los siguientes parámetros del kernel. En este ejemplo, configuramos 40 páginas de 1G, aunque el tamaño de las páginas enormes y el número exacto deben adaptarse a los requisitos de memoria de vuestra aplicación:

parametervalordescription

hugepagesz

1 G

Esta opción permite establecer el tamaño de las páginas enormes en 1 G

hugepages

40

Este es el número de páginas enormes definido anteriormente

default_hugepagesz

1 G

Este es el valor predeterminado para obtener las páginas enormes

Modificad el archivo GRUB /etc/default/grub para añadir estos parámetros en GRUB_CMDLINE_LINUX:

default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0

Actualizad la configuración de GRUB y reiniciad el sistema para aplicar los cambios:

$ transactional-update grub.cfg
$ reboot

Para validar que los parámetros se aplican tras el reinicio, podéis comprobar la línea de comandos:

$ cat /proc/cmdline
  • Uso de páginas enormes

Para usar las páginas enormes, debemos montarlas:

$ mkdir -p /hugepages
$ mount -t hugetlbfs nodev /hugepages

Desplegad una carga de trabajo de Kubernetes, creando los recursos y los volúmenes:

...
 resources:
   requests:
     memory: "24Gi"
     hugepages-1Gi: 16Gi
     intel.com/intel_sriov_oru: '4'
   limits:
     memory: "24Gi"
     hugepages-1Gi: 16Gi
     intel.com/intel_sriov_oru: '4'
...
...
volumeMounts:
  - name: hugepage
    mountPath: /hugepages
...
volumes:
  - name: hugepage
    emptyDir:
      medium: HugePages
...

43 Planificación consciente de NUMA

El acceso no uniforme a memoria o la arquitectura de memoria no uniforme (NUMA) es un diseño de memoria física utilizado en la arquitectura de SMP (multiprocesadores), donde el tiempo de acceso a la memoria depende de la ubicación de la memoria en relación con un procesador. Bajo NUMA, un procesador puede acceder a su propia memoria local más rápido que a la memoria no local, es decir, a la memoria local de otro procesador o a la memoria compartida entre procesadores.

43.1 Identificación de nodos NUMA

Para identificar los nodos NUMA, utilice el siguiente comando en su sistema:

$ lscpu | grep NUMA
NUMA node(s):                       1
NUMA node0 CPU(s):                  0-63
Nota
Nota

Para este ejemplo, solo tenemos un nodo NUMA que muestra 64 CPUs.

NUMA debe estar habilitado en BIOS. Si dmesg no tiene registros de la inicialización NUMA durante el arranque, es posible que los mensajes relacionados con NUMA en el búfer de anillo del kernel se hayan sobrescrito.

44 Metal LB

MetalLB es una implementación de equilibrador de carga para clústeres de Kubernetes en equipo sin sistema operativo, que utiliza protocolos de enrutamiento estándar como L2 y BGP como protocolos de anuncio. Es un equilibrador de carga de red que se puede utilizar para exponer servicios en un clúster de Kubernetes al mundo exterior debido a la necesidad de utilizar servicios de Kubernetes de tipo LoadBalancer con equipo sin sistema operativo.

Para habilitar MetalLB en el clúster RKE2, se requieren los siguientes pasos:

  • Instale MetalLB utilizando el siguiente comando:

$ kubectl apply <<EOF -f
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: metallb
  namespace: kube-system
spec:
  chart: oci://registry.suse.com/edge/charts/metallb
  targetNamespace: metallb-system
  version: 306.0.2+up0.15.3
  createNamespace: true
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: endpoint-copier-operator
  namespace: kube-system
spec:
  chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
  targetNamespace: endpoint-copier-operator
  version: 306.0.1+up0.3.0
  createNamespace: true
EOF
  • Cree la configuración de IpAddressPool y L2advertisement:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: kubernetes-vip-ip-pool
  namespace: metallb-system
spec:
  addresses:
    - 10.168.200.98/32
  serviceAllocation:
    priority: 100
    namespaces:
      - default
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ip-pool-l2-adv
  namespace: metallb-system
spec:
  ipAddressPools:
    - kubernetes-vip-ip-pool
  • Cree el servicio de punto final para exponer VIP:

apiVersion: v1
kind: Service
metadata:
  name: kubernetes-vip
  namespace: default
spec:
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: rke2-api
    port: 9345
    protocol: TCP
    targetPort: 9345
  - name: k8s-api
    port: 6443
    protocol: TCP
    targetPort: 6443
  sessionAffinity: None
  type: LoadBalancer
  • Compruebe que VIP se ha creado y que los pods de MetalLB se están ejecutando:

$ kubectl get svc -n default
$ kubectl get pods -n default

45 Configuración de registro privado

Containerd se puede configurar para conectarse a registros privados y utilizarlos para extraer imágenes privadas en cada nodo.

Al iniciarse, RKE2 comprueba si existe un archivo registries.yaml en /etc/rancher/rke2/ e indica a containerd que utilice los registros definidos en el archivo. Si deseáis utilizar un registro privado, cread este archivo como root en cada nodo que vaya a utilizar el registro.

Para añadir el registro privado, cread el archivo /etc/rancher/rke2/registries.yaml con el siguiente contenido:

mirrors:
  docker.io:
    endpoint:
      - "https://registry.example.com:5000"
configs:
  "registry.example.com:5000":
    auth:
      username: xxxxxx # this is the registry username
      password: xxxxxx # this is the registry password
    tls:
      cert_file:            # path to the cert file used to authenticate to the registry
      key_file:             # path to the key file for the certificate used to authenticate to the registry
      ca_file:              # path to the ca file used to verify the registry's certificate
      insecure_skip_verify: # may be set to true to skip verifying the registry's certificate

o sin autenticación:

mirrors:
  docker.io:
    endpoint:
      - "https://registry.example.com:5000"
configs:
  "registry.example.com:5000":
    tls:
      cert_file:            # path to the cert file used to authenticate to the registry
      key_file:             # path to the key file for the certificate used to authenticate to the registry
      ca_file:              # path to the ca file used to verify the registry's certificate
      insecure_skip_verify: # may be set to true to skip verifying the registry's certificate

Para que los cambios en el registro surtan efecto, debéis configurar este archivo antes de iniciar RKE2 en el nodo o reiniciar RKE2 en cada nodo configurado.

Nota
Nota

Para obtener más información al respecto, consultad la configuración del registro containerd en rke2.

46 Protocolo de tiempo de precisión

El Protocolo de tiempo de precisión (PTP) es un protocolo de red desarrollado por el Instituto de Ingenieros Eléctricos y Electrónicos (IEEE) para permitir la sincronización horaria de submicrosegundos en una red informática. Desde su creación y desde hace ya un par de décadas, el PTP se ha utilizado en muchas industrias. Recientemente ha experimentado una creciente adopción en las redes de telecomunicaciones como un elemento vital para las redes 5G. Aunque es un protocolo relativamente sencillo, su configuración puede cambiar significativamente dependiendo de la aplicación. Por este motivo, se han definido y estandarizado múltiples perfiles.

En esta sección, solo se tratarán los perfiles específicos de telecomunicaciones. En consecuencia, se asumirá la capacidad de marcado de tiempo y un reloj de hardware PTP (PHC) en la NIC. Hoy en día, todos los adaptadores de red de grado de telecomunicaciones vienen con soporte PTP en hardware, pero podéis verificar dichas capacidades con el siguiente comando:

# ethtool -T p1p1
Time stamping parameters for p1p1:
Capabilities:
        hardware-transmit
        software-transmit
        hardware-receive
        software-receive
        software-system-clock
        hardware-raw-clock
PTP Hardware Clock: 0
Hardware Transmit Timestamp Modes:
        off
        on
Hardware Receive Filter Modes:
        none
        all

Sustituid p1p1 por el nombre de la interfaz que se utilizará para PTP.

Las siguientes secciones proporcionarán orientación sobre cómo instalar y configurar PTP específicamente en SUSE Telco Cloud, pero se espera familiaridad con los conceptos básicos de PTP. Para obtener una breve descripción general de PTP y la implementación incluida en SUSE Telco Cloud, consulte la documentación del Protocolo de tiempo de precisión de SLES.

46.1 Instalad los componentes de software PTP

En SUSE Telco Cloud, la implementación de PTP la proporciona el paquete linuxptp, que incluye dos componentes:

  • ptp4l: un daemon que controla el PHC en la NIC y ejecuta el protocolo PTP

  • phc2sys: un daemon que mantiene el reloj del sistema sincronizado con el PHC sincronizado por PTP en la NIC

Ambos daemon son necesarios para que la sincronización del sistema funcione correctamente y deben configurarse correctamente según la configuración de su sistema. Esto se trata en Sección 46.2, “Configuración de PTP para despliegues de telecomunicaciones”.

La forma más fácil y mejor de integrar PTP en su clúster en sentido descendente es añadir el paquete linuxptp bajo packageList en el archivo de definición de Edge Image Builder (EIB). De esta forma, el software del plano de control PTP se instalará automáticamente durante el aprovisionamiento del clúster. Consulte la documentación de EIB (Sección 5.3.6, “Configuración de paquetes RPM”) para obtener más información sobre la instalación de paquetes.

A continuación, encontrará un manifiesto de EIB de muestra con linuxptp:

apiVersion: 1.3
image:
  imageType: RAW
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-Base-RT-GM.raw
  outputImageName: eibimage-slmicrort-telco.raw
operatingSystem:
  time:
    timezone: America/New_York
  kernelArgs:
    - ignition.platform.id=openstack
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
    enable:
      - ptp4l
      - phc2sys
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
  packages:
    packageList:
      - jq            # Non Telco specific - category: testing/utils
      - dpdk          # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: runtime
      - dpdk-tools    # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: testing/utils
      - libdpdk-25    # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: runtime
      - pf-bb-config  # TelCo RAN (gNB: DU) - category: config.
      - open-iscsi    # Non Telco specific (required by SUSE Storage/Longhorn) - category: runtime
      - tuned         # Non Telco specific (linux tuning) - category: config.
      - cpupower      # Non Telco specific (linux tuning - CPU power related settings) - category: config.
      - rt-tests      # Non Telco specific (RT scheduler-latency testing) - category: testing/utils
      - linuxptp      # TelCo RAN; time sync (gNB: DU) - category: runtime
      - synce4l       # TelCo RAN; time sync (gNN: DU) - category: runtime
      - pciutils      # Non Telco specific (provides "lspci" command) - category: testing/utils
      - numactl       # Non Telco specific (provides "numatcl" command) - category: testing/utils
    sccRegistrationCode: $SCC_REGISTRATION_CODE
Nota
Nota

El paquete linuxptp incluido en SUSE Telco Cloud no habilita ptp4l y phc2sys por defecto. Si sus archivos de configuración específicos del sistema se despliegan en el momento del aprovisionamiento (véase Sección 46.3, “Integración de Cluster API”), deberían estar habilitados. Hágalo añadiéndolos a la sección systemd del manifiesto, como en el ejemplo anterior.

Siga el proceso habitual para construir la imagen tal y como se describe en la Documentación de EIB (Sección 5.4, “Compilación de la imagen”) y utilícela para desplegar su clúster. Si es nuevo en EIB, empiece por Capítulo 12, Edge Image Builder en su lugar.

46.2 Configuración de PTP para despliegues de telecomunicaciones

Muchas aplicaciones de telecomunicaciones requieren una sincronización estricta de fase y tiempo con poca desviación, lo que dio lugar a la definición de dos perfiles orientados a telecomunicaciones: ITU-T G.8275.1 e ITU-T G.8275.2. Ambos tienen una alta tasa de mensajes de sincronización y otros rasgos distintivos, como el uso de un algoritmo de mejor reloj maestro (BMCA) alternativo. Dicho comportamiento exige ajustes específicos en el archivo de configuración consumido por ptp4l, proporcionados en las siguientes secciones como referencia.

Nota
Nota
  • Ambas secciones solo cubren el caso de un reloj ordinario en la configuración de receptor de tiempo.

  • Cualquier perfil de este tipo debe utilizarse en una infraestructura PTP bien planificada.

  • Su red PTP específica puede requerir ajustes adicionales de la configuración; asegúrese de revisar y adaptar los ejemplos proporcionados si es necesario.

46.2.1 Perfil PTP ITU-T G.8275.1

El perfil G.8275.1 tiene las siguientes especificaciones:

  • Se ejecuta directamente sobre Ethernet y requiere compatibilidad total con la red (los nodos/conmutadores adyacentes deben ser compatibles con PTP).

  • El ajuste de dominio predeterminado es 24.

  • La comparación de conjuntos de datos se basa en el algoritmo G.8275.x y sus valores localPriority después de priority2.

Copie el siguiente contenido en un archivo llamado /etc/ptp4l-G.8275.1.conf:

# Telecom G.8275.1 example configuration
[global]
domainNumber                    24
priority2            255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout        3
serverOnly                      0
ptp_dst_mac                     01:80:C2:00:00:0E
network_transport               L2

Una vez creado el archivo, debe hacerse referencia a él en /etc/sysconfig/ptp4l para que el demonio se inicie correctamente. Esto puede hacerse cambiando la línea OPTIONS= por:

OPTIONS="-f /etc/ptp4l-G.8275.1.conf -i $IFNAME --message_tag ptp-8275.1"

Más concretamente:

  • -f requiere el nombre de archivo de configuración que se va a utilizar; /etc/ptp4l-G.8275.1.conf en este caso

  • -i requiere el nombre de la interfaz que se va a utilizar, sustituya $IFNAME por un nombre de interfaz real.

  • --message_tag permite identificar mejor la salida de ptp4l en los registros del sistema y es opcional.

Una vez completados los pasos anteriores, el daemon ptp4l debe iniciarse (o reiniciarse):

# systemctl restart ptp4l

Compruebe el estado de la sincronización observando los registros con:

# journalctl -e -u ptp4l

46.2.2 Perfil PTP ITU-T G.8275.2

El perfil G.8275.2 tiene las siguientes especificaciones:

  • Se ejecuta sobre IP y no requiere compatibilidad total con la red (es posible que los nodos/conmutadores adyacentes no sean compatibles con PTP).

  • El ajuste de dominio predeterminado es 44.

  • La comparación de conjuntos de datos se basa en el algoritmo G.8275.x y sus valores localPriority después de priority2.

Copie el siguiente contenido en un archivo llamado /etc/ptp4l-G.8275.2.conf:

# Telecom G.8275.2 example configuration
[global]
domainNumber                    44
priority2            255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             0
serverOnly                      0
hybrid_e2e                      1
inhibit_multicast_service       1
unicast_listen                  1
unicast_req_duration            60
logSyncInterval                 -5
logMinDelayReqInterval          -4
announceReceiptTimeout        2
#
# Customize the following for slave operation:
#
[unicast_master_table]
table_id                        1
logQueryInterval                2
UDPv4                           $PEER_IP_ADDRESS
[$IFNAME]
unicast_master_table            1

Asegúrese de sustituir los siguientes marcadores de posición:

  • $PEER_IP_ADDRESS - la dirección IP del siguiente nodo PTP con el que comunicarse, como el reloj maestro o de contorno que proporcionará la sincronización.

  • $IFNAME - indica a ptp4l qué interfaz utilizar para PTP.

Una vez creado el archivo, debe hacerse referencia a él, junto con el nombre de la interfaz que se utilizará para PTP, en /etc/sysconfig/ptp4l para que el demonio se inicie correctamente. Esto puede hacerse cambiando la línea OPTIONS= por:

OPTIONS="-f /etc/ptp4l-G.8275.2.conf --message_tag ptp-8275.2"

Más concretamente:

  • -f requiere el nombre de archivo de configuración que se va a utilizar. En este caso, es /etc/ptp4l-G.8275.2.conf.

  • --message_tag permite identificar mejor la salida de ptp4l en los registros del sistema y es opcional.

Una vez completados los pasos anteriores, el daemon ptp4l debe iniciarse (o reiniciarse):

# systemctl restart ptp4l

Compruebe el estado de la sincronización observando los registros con:

# journalctl -e -u ptp4l

46.2.3 Configuración PTP de un Boundary Clock

Las secciones anteriores trataban la configuración de un Ordinary Clock, pero los despliegues de telecomunicaciones pueden requerir que el nodo actúe como un Boundary Clock. En tal escenario, la hora de referencia debe propagarse desde un Grand Master a uno o más Time Receivers en sentido descendente, lo que requiere una NIC con dos o más puertos. En este caso, un puerto asumirá el rol de Time Receiver, es decir, controlará las actualizaciones del PTP Hardware Clock (PHC) en la NIC, mientras que los restantes funcionarán como Time Transmitters. Una única instancia de ptp4l es suficiente para una única NIC multipuerto, pero debe proporcionarse cada interfaz de núcleo de Linux implicada en la distribución de la hora, como parte de su configuración. Por ejemplo, actualice el archivo /etc/sysconfig/ptp4l para incluir cuatro puertos; simplemente sustituya las variables por los nombres reales de las interfaces o ajústelo según sea necesario:

OPTIONS="-f /etc/ptp4l-G.8275.1.conf --message_tag ptp-8275.1 -i $IFNAME1 -i $IFNAME2 -i $IFNAME3 -i $IFNAME4"
Nota
Nota

No es necesario establecer clock_type en BC, ya que se sobreentenderá automáticamente si se proporciona más de un puerto.

Una vez hecho esto, el daemon ptp4l puede (re)iniciarse con:

# systemctl restart ptp4l

Sin una configuración de puerto específica, ptp4l ejecutará el BMCA para determinar a través de qué puerto se puede alcanzar el GM. Si se prefiere una configuración estática, añada una sección para cada puerto con el rol prescrito en el archivo de configuración. Por ejemplo:

# Telecom G.8275.1 example configuration
[global]
domainNumber                    24
priority2                       255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout          3
ptp_dst_mac                     01:80:C2:00:00:0E
network_transport               L2

[$IFNAME1]
# Time Receiver by default

[$IFNAME2]
serverOnly                      1

[$IFNAME3]
serverOnly                      1

[$IFNAME4]
serverOnly                      1

No obstante, asegúrese de determinar la conexión correcta con el GM antes de iniciar el daemon.

46.2.4 Sincronización del reloj del sistema desde PTP

Es importante tener en cuenta que PTP funciona sincronizando los relojes de hardware locales de las NIC. Esto no alinea automáticamente el reloj del sistema con el GM, ya que el reloj del sistema se deriva de un reloj de hardware diferente. Para mantener el reloj del sistema sincronizado con PTP, debe ejecutarse phc2sys. Se recomienda completar totalmente la configuración de ptp4l antes de pasar a phc2sys. phc2sys no requiere un archivo de configuración por defecto y sus parámetros de ejecución pueden controlarse únicamente a través de la variable OPTIONS= presente en /etc/sysconfig/ptp4l, de forma similar a ptp4l:

OPTIONS="-s $IFNAME -w"

Donde $IFNAME es el nombre de la interfaz ya configurada en ptp4l que se utilizará como fuente para el reloj del sistema. Esto se utiliza para identificar el PHC de origen.

Sin embargo, si se utiliza un perfil PTP o un número de dominio específico, es posible que phc2sys requiera que se le proporcione un archivo de configuración de acuerdo con el proporcionado a ptp4l. En la mayoría de los casos, también se puede reutilizar directamente con phc2sys:

OPTIONS="-f /etc/ptp4l-G.8275.1.conf -s $IFNAME -w"

46.3 Integración de Cluster API

Siempre que un clúster se despliegue a través de un clúster de gestión y aprovisionamiento de red dirigido, tanto el archivo de configuración como las dos variables de configuración en /etc/sysconfig pueden desplegarse en el host en el momento del aprovisionamiento. A continuación se muestra un extracto de una definición de clúster, centrado en un objeto RKE2ControlPlane modificado que despliega el mismo archivo de configuración G.8275.1 en todos los hosts:

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  registrationMethod: "control-plane-endpoint"
  serverConfig:
    cni: canal
  agentConfig:
    format: ignition
    cisProfile: cis
    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
        storage:
          files:
            - path: /etc/ptp4l-G.8275.1.conf
              overwrite: true
              contents:
                inline: |
                  # Telecom G.8275.1 example configuration
                  [global]
                  domainNumber                    24
                  priority2                       255
                  dataset_comparison              G.8275.x
                  G.8275.portDS.localPriority     128
                  G.8275.defaultDS.localPriority  128
                  maxStepsRemoved                 255
                  logAnnounceInterval             -3
                  logSyncInterval                 -4
                  logMinDelayReqInterval          -4
                  announceReceiptTimeout          3
                  serverOnly                      0
                  ptp_dst_mac                     01:80:C2:00:00:0E
                  network_transport               L2
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /etc/sysconfig/ptp4l
              overwrite: true
              contents:
                inline: |
                  ## Path:           Network/LinuxPTP
                  ## Description:    Precision Time Protocol (PTP): ptp4l settings
                  ## Type:           string
                  ## Default:        "-i eth0 -f /etc/ptp4l.conf"
                  ## ServiceRestart: ptp4l
                  #
                  # Arguments when starting ptp4l(8).
                  #
                  OPTIONS="-f /etc/ptp4l-G.8275.1.conf -i $IFNAME --message_tag ptp-8275.1"
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /etc/sysconfig/phc2sys
              overwrite: true
              contents:
                inline: |
                  ## Path:           Network/LinuxPTP
                  ## Description:    Precision Time Protocol (PTP): phc2sys settings
                  ## Type:           string
                  ## Default:        "-s eth0 -w"
                  ## ServiceRestart: phc2sys
                  #
                  # Arguments when starting phc2sys(8).
                  #
                  OPTIONS="-s $IFNAME -w"
              mode: 0644
              user:
                name: root
              group:
                name: root
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

Además de otras variables, la definición anterior debe completarse con el nombre de la interfaz y con los demás objetos de Cluster API, tal como se describe en Parte VII, “Aprovisionamiento de red dirigido totalmente automatizado”.

Nota
Nota
  • Este enfoque solo es conveniente si el hardware del clúster es uniforme y se necesita la misma configuración en todos los hosts, incluido el nombre de la interfaz.

  • Existen enfoques alternativos que se tratarán en futuras versiones.

En este punto, sus hosts deberían tener una pila PTP operativa y en ejecución, y comenzarán a negociar su función PTP.

46.4 PTP en plataformas Intel Granite Rapids-D

SUSE Telco Cloud admite una temporización precisa en una variedad de plataformas diferentes, incluidos los últimos diseños basados en Intel Granite Rapids-D (GNR-D). Estos nuevos servidores suelen incluir un controlador Ethernet de alta velocidad integrado y una o más tarjetas adicionales con un controlador Ethernet para puertos adicionales. A diferencia de las generaciones de plataformas anteriores, también están equipados con un DPLL dedicado que permite el enrutamiento de las señales de temporización a través del sistema y las diferentes NIC, y ya no requiere cableado externo. Por tanto, el despliegue general se simplifica, pero se requieren pasos y componentes de software específicos, como la configuración del DPLL y de la señal interna durante el arranque.

Antes de realizar los pasos de configuración, descargad e instalad el controlador de núcleo de Linux más reciente para los Intel 800 Series Network Devices desde el sitio web de Intel. Seleccionad el archivo zip que contiene los "ice_RPM_Files" y descomprimid el archivo, luego instalad el ice-kmp-default-*sles16sp0.x86_64.rpm RPM que contiene, por ejemplo, el archivo ice-kmp-default-2.4.5_k6.12.0_160000.5-1.sles16sp0.x86_64.rpm:

# transactional-update pkg install ice-kmp-default-2.4.5_k6.12.0_160000.5-1.sles16sp0.x86_64.rpm

Reiniciad el servidor para que el cambio sea persistente y efectivo.

Nota
Nota
  • Se utilizará un sistema Dell PowerEdge XR8720t como sistema de referencia a lo largo de los ejemplos; las interfaces del núcleo de Linux y la configuración de puertos podrían ser diferentes en otro servidor GNR-D.

  • Se asume un despliegue de telecomunicaciones y el perfil G.8275.1 utilizado a lo largo de las siguientes secciones para PTP.

46.4.1 Reloj de frontera PTP

Esta sección describe el proceso de configuración de un Reloj de frontera (BC) en un sistema GNR-D, donde un puerto en la NIC integrada recibe las marcas de tiempo PTP de un GM y todos los puertos restantes en el sistema actúan como transmisores de tiempo hacia otros nodos de red.

Nota
Nota

La configuración descrita aquí es completamente estática. Si el GM deja de estar disponible, la sincronización en sentido descendente dependerá exclusivamente de las capacidades de mantenimiento de tiempo (holdover) del host; no se realizará ningún cambio automático a una fuente de referencia de tiempo diferente.

Para habilitar el comportamiento de BC, ejecutad los siguientes pasos en el mismo orden cada vez que se inicie el sistema:

  1. Verificad que los dispositivos PTP esperados que controlan los PHC estén presentes:

    # ls -l /sys/class/ptp/
    total 0
    lrwxrwxrwx. 1 root root 0 Apr 27 20:21 ptp1 -> ../../devices/pci0000:12/0000:12:04.0/0000:13:00.0/ptp/ptp1
    lrwxrwxrwx. 1 root root 0 Apr 27 20:21 ptp2 -> ../../devices/pci0000:6b/0000:6b:02.0/0000:6c:00.0/ptp/ptp2
    lrwxrwxrwx. 1 root root 0 Apr 27 20:21 ptp3 -> ../../devices/pci0000:6b/0000:6b:06.0/0000:6e:00.0/ptp/ptp3
    Nota
    Nota

    Ajustad los comandos subsiguientes de acuerdo con los nombres reales encontrados en el sistema que se está configurando.

  2. Identificad el controlador integrado, ya que requerirá una configuración específica:

    La salida anterior debería indicar el dispositivo al que están vinculados a través de la dirección PCI y podéis utilizar lspci para buscar el tipo de dispositivo:

    # lspci -s 0000:13:00.0
    13:00.0 Ethernet controller: Intel Corporation Ethernet Connection E825-C for SFP (rev 04)
    # lspci -s 0000:6c:00.0
    6c:00.0 Ethernet controller: Intel Corporation Ethernet Controller E830-CC for SFP
    # lspci -s 0000:6e:00.0
    6e:00.0 Ethernet controller: Intel Corporation Ethernet Controller E830-CC for SFP

    Este servidor específico está equipado con un controlador integrado Intel E825-C y dos tarjetas complementarias E830-CC.

    Alternativamente, podéis encontrar más información sobre el controlador buscando el primer puerto de red del controlador que expone ese PHC:

    # ls -l /sys/class/ptp/ptp0/device/net/
    total 0
    drwxr-xr-x. 5 root root 0 Apr 30 15:16 em5
    # ethtool -i em5
    driver: ice
    version: 2.4.5
    firmware-version: 4.03 0x80007f91 1.3881.0
    expansion-rom-version:
    bus-info: 0000:13:00.0
    [...]

    Tened en cuenta que em5 es el primer puerto del controlador Ethernet integrado en este sistema.

  3. Configurad las señales entre el PHC en el controlador Ethernet integrado y el DPLL de temporización del sistema:

    1. Dejad que el DPLL controle el reloj Ethernet en el controlador integrado:

      # echo 4 1 > /sys/class/net/em5/device/tspll_cfg
    2. Habilitad un pulso cada inicio de segundo (Pulse Per Second, PPS) desde el PHC al DPLL a través del pin SDP2 (señal de 1 kHz):

      # echo 2 1 > /sys/class/ptp/ptp1/pins/SDP2
      # echo 1 0 0 0 1000000 > /sys/class/ptp/ptp1/period
    3. Opcionalmente, el pin SPD0 (señal de 1 Hz) también puede habilitarse:

      # echo 2 2 > /sys/class/ptp/ptp1/pins/SDP0
      # echo 2 0 0 1 0 > /sys/class/ptp/ptp1/period
    4. Habilitad la señal de 1 PPS para que se propague desde el DPLL del sistema de temporización a las tarjetas adicionales:

      # echo 1 1 > /sys/class/ptp/ptp2/pins/SDP1
      # echo 1 1 > /sys/class/ptp/ptp3/pins/SDP1
  4. Ejecutad ts2phc para mantener los PHC de las tarjetas adicionales sincronizados con la misma marca de tiempo del PHC /dev/ptp1:

    # ts2phc -f ts2phc-aic-all.cfg -s /dev/ptp1

    Consultad Sección 46.4.2.3, “ts2phc archivo de configuración para tarjetas complementarias” para ver el contenido de ts2phc-aic-all.cfg.

  5. Ejecutad una instancia de ptp4l para el controlador integrado (/dev/ptp1):

    # ptp4l -f ptp4l-G.8275.1-nac.conf

    Consultad Sección 46.4.2.1, “Archivo de configuración de ptp4l para el controlador integrado (/dev/ptp1)” para ver el contenido de ptp4l-G.8275.1-nac.conf.

  6. Ejecutad una instancia de ptp4l para cada tarjeta complementaria (/dev/ptp3 y/o /dev/ptp2):

    # ptp4l -f ptp4l-G.8275.1-aic1.conf
    # ptp4l -f ptp4l-G.8275.1-aic2.conf

    Consultad Sección 46.4.2.2, “ptp4l archivo de configuración para tarjetas complementarias (/dev/ptp2 o /dev/ptp3)” para conocer el contenido de los archivos de configuración.

    Nota
    Nota

    Para evitar conflictos y permitir el siguiente paso, cada una de estas instancias debe utilizar sockets de control y de solo lectura diferentes.

  7. Sincronizad los parámetros y valores de tiempo de ejecución PTP de las instancias de AICs ptp4l con pmc:

    Se espera que un BC reenvíe no solo la hora de un GM al que está conectado, sino también parámetros auxiliares, como su clase de reloj y nivel de precisión. Esto ocurre automáticamente dentro de un grupo de interfaces gestionadas por la misma instancia de ptp4l, pero no entre diferentes instancias de ptp4l, que gestionan diferentes PHC y puertos.

    Una vez que el sistema esté sincronizado con un GM, consultad la instancia de ptp4l en el controlador integrado y estableced los valores en las instancias de ptp4l restantes mediante comandos pmc. Por ejemplo:

    # pmc -f /etc/ptp4l-G.8275.1-nac-bmca.conf -u -b 0 'GET PARENT_DATA_SET' | grep gm
                    gm.ClockClass                         8
                    gm.ClockAccuracy                      0xfe
                    gm.OffsetScaledLogVariance            0xffff
    # pmc -f /etc/ptp4l-G.8275.1-nac-bmca.conf -u -b 0 'GET TIME_PROPERTIES_DATA_SET' | grep -v PROPERTIES
                    currentUtcOffset      37
                    leap61                0
                    leap59                0
                    currentUtcOffsetValid 0
                    ptpTimescale          1
                    timeTraceable         0
                    frequencyTraceable    0
                    timeSource            0xa0
    pmc -f /etc/ptp4l-G.8275.1-aic1-static.conf -u -b 0 'SET GRANDMASTER_SETTINGS_NP
                    clockClass              8
                    clockAccuracy           0xfe
                    offsetScaledLogVariance 0xffff
                    currentUtcOffset        37
                    leap61                  0
                    leap59                  0
                    currentUtcOffsetValid   0
                    ptpTimescale            1
                    timeTraceable           0
                    frequencyTraceable      0
                    timeSource              0xa0

    Consultad Sección 46.4.2.4, “Script de reenvío de parámetros GM” para automatizar este proceso y evitar pasos manuales.

  8. Opcionalmente, ejecutad phc2sys para obtener la hora del sistema a partir de la sincronización PTP:

    # phc2sys -f /etc/ptp4l-G.8275.1-nac.conf -s /dev/ptp1 -c CLOCK_REALTIME -w

    El archivo de entrada es el mismo archivo de configuración utilizado para ptp4l y el controlador integrado. Consultad Sección 46.2.4, “Sincronización del reloj del sistema desde PTP” para permitir que systemd gestione su ejecución.

46.4.2 Archivos de configuración

Esta sección proporciona archivos de configuración y scripts de ejemplo que pueden utilizarse junto con los pasos anteriores para configurar rápidamente un BC funcional en GNR-D. Los archivos de configuración de ptp4l contienen todos los ajustes necesarios, sin necesidad de indicadores de ejecución externos adicionales, y se basan todos en el perfil de telecomunicaciones G.8275.1. Se proporcionan más detalles sobre cada archivo en sus respectivas secciones.

46.4.2.1 Archivo de configuración de ptp4l para el controlador integrado (/dev/ptp1)

[global]
domainNumber                    24
priority2                       255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout          3
ptp_dst_mac                     01:1b:19:00:00:00
network_transport               L2
summary_interval                3
message_tag                     "ptp4l-nac"
uds_address                     /var/run/ptp4l-nac
uds_ro_address                  /var/run/ptp4lro-nac

[em1]

[em2]

[em3]

[em4]

La configuración anterior aprovecha el BMCA para determinar el papel del puerto, asumiendo que hay un GM disponible a través de uno de ellos. Si se necesita un control más estricto, añadid el indicador serverOnly bajo cada definición de interfaz. Para obtener más detalles, consultad Sección 46.2.3, “Configuración PTP de un Boundary Clock” o la configuración de las tarjetas complementarias a continuación como ejemplo. Por motivos de brevedad, solo se enumeran cuatro interfaces. Debéis ajustarlas según vuestros requisitos.

46.4.2.2 ptp4l archivo de configuración para tarjetas complementarias (/dev/ptp2 o /dev/ptp3)

# Telecom G.8275.1 example configuration
[global]
domainNumber                    24
priority2                       255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     250
G.8275.defaultDS.localPriority  250
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout          3
ptp_dst_mac                     01:1b:19:00:00:00
network_transport               L2
summary_interval                3
message_tag                     "ptp4l-iac1"
uds_address                     /var/run/ptp4l-aic1
uds_ro_address                  /var/run/ptp4lro-aic1

[p1p1]
serverOnly                      1

[p1p2]
serverOnly                      1

[p1p3]
serverOnly                      1

[p1p4]
serverOnly                      1

Por motivos de brevedad, solo se enumeran cuatro interfaces. Debéis realizar los ajustes según vuestros requisitos. Todas las interfaces se han configurado estáticamente con el rol TimeTransmitter.

46.4.2.3 ts2phc archivo de configuración para tarjetas complementarias

[global]
use_syslog              0
verbose                 1
logging_level           7
ts2phc.pulsewidth       100000000

[p1p1]
ts2phc.channel          1
ts2phc.extts_polarity   rising
ts2phc.pin_index        1

[p2p1]
ts2phc.channel          1
ts2phc.extts_polarity   rising
ts2phc.pin_index        1

Esta configuración cubre la sincronización de dos tarjetas complementarias (referenciadas por su primer puerto, p1p1 y p2p1) a través del SDP1 en cada controlador.

46.4.2.4 Script de reenvío de parámetros GM

El script siguiente puede utilizarse para reenviar los valores y parámetros del GM a los Time Receivers en puertos gestionados por instancias de ptp4l distintas de aquella en la que reside el GM. No olvidéis editar la sección Input variables para ajustar los nombres de archivo y ejecutarlo una vez que el sistema esté sincronizado con un GM.

#!/bin/bash

set -euo pipefail

################## Variables de entrada ##################
VERBOSE=1

CONFIG_FILE_NAC=/etc/ptp4l-G.8275.1-nac-bmca.conf
CONFIG_FILES_AICS=(/etc/ptp4l-G.8275.1-aic1-static.conf /etc/ptp4l-G.8275.1-aic2-static.conf)

#####################################################


# Comprobad que el sistema está sincronizado con un GM
GM_PRESENT=$(pmc -f ${CONFIG_FILE_NAC} -u -b 0 'GET TIME_STATUS_NP' | awk '/gmPresent/ {print $2}')

if [ \"${GM_PRESENT}\" != \"true\" ]; then
    echo \"No hay ningún GM presente, saliendo...\"
    exit 1
fi

# Obtened los valores del Grand Master "sentido ascendente"

PDS_GM_VALUES=$(pmc -f ${CONFIG_FILE_NAC} -u -b 0 'GET PARENT_DATA_SET' | awk 'BEGIN {ORS=" "} /gm./ {print $2}')
TPDS_GM_VALUES=$(pmc -f ${CONFIG_FILE_NAC} -u -b 0 'GET TIME_PROPERTIES_DATA_SET' | awk 'BEGIN {ORS=" "} NR>2 {print $2}')

if [ -z \"$PDS_GM_VALUES\" ]; then
    echo \"No se han recuperado valores de PARENT_DATA_SET\"
    exit 2
elif [ -z \"$TPDS_GM_VALUES\" ]; then
    echo \"No se han recuperado valores de TIME_PROPERTIES_DATA_SET\"
    exit 2
fi

# Desempaquetad de PARENT_DATA_SET
leer CLOCK_CLASS CLOCK_ACCURACY VARIANCE <<< $PDS_GM_VALUES

# Desempaquetad de TIME_PROPERTIES_DATA_SET
leer UTC_OFFSET LEAP_61 LEAP_59 UTC_OFFSET_VALID PTP_TIMESCALE T_TRACEABLE F_TRACEABLE T_SOURCE <<< $TPDS_GM_VALUES

if [ \"$VERBOSE\" -eq 1 ]; then\n    echo \"Leer de PARENT_DATA_SET: clockClass=${CLOCK_CLASS} clockAccuracy=${CLOCK_ACCURACY} offsetScaledLogVariance=${VARIANCE}\"\n    echo \"Leer de TIME_PROPERTIES_DATA_SET: currentUtcOffset=${UTC_OFFSET} leap61=${LEAP_61} leap59=${LEAP_59}\" \\\n         \"currentUtcOffsetValid=${UTC_OFFSET_VALID} ptpTimescale=${PTP_TIMESCALE} timeTraceable=${T_TRACEABLE}\" \\\n         \"frequencyTraceable=${F_TRACEABLE} timeSource=${T_SOURCE}\"\nfi


# Reenviad estos valores a los receptores de tiempo "sentido descendente" actualizando las instancias de ptp4l

for FILE in \"${CONFIG_FILES_AICS[@]}\"; do\n    if [ \"$VERBOSE\" -eq 1 ]; then\n        echo \"Actualizando GRANDMASTER_SETTINGS_NP (${FILE})\"\n    fi

    pmc -f ${FILE} -u -b 0 'SET GRANDMASTER_SETTINGS_NP
       clockClass              '${CLOCK_CLASS}'
       clockAccuracy           '${CLOCK_ACCURACY}'
       offsetScaledLogVariance '${VARIANCE}'
       currentUtcOffset        '${UTC_OFFSET}'
       leap61                  '${LEAP_61}'
       leap59                  '${LEAP_59}'
       currentUtcOffsetValid   '${UTC_OFFSET_VALID}'
       ptpTimescale            '${PTP_TIMESCALE}'
       timeTraceable           '${T_TRACEABLE}'
       frequencyTraceable      '${F_TRACEABLE}'
       timeSource              '${T_SOURCE}'' &> /dev/null

    if [ $? -ne 0 ]; then +
        echo "Falló al actualizar ${FILE}" +
    fi +
done
Nota
Nota

El script debe ejecutarse cada vez que cambie el GM.

47 SCTP - Protocolo de control de transmisión de flujo

De Stream Control Transmission Protocol - Wikipedia

El Stream Control Transmission Protocol (SCTP) es un protocolo de comunicaciones de redes informáticas en la capa de transporte del conjunto de protocolos de Internet. Originalmente destinado al transporte de mensajes del Sistema de Señalización 7 (SS7) en telecomunicaciones, el protocolo proporciona la característica orientada a mensajes del Protocolo de Datagramas de Usuario (UDP) mientras garantiza un transporte fiable y en secuencia de mensajes con control de congestión como el Protocolo de Control de Transmisión (TCP). A diferencia de UDP y TCP, el protocolo admite multihoming y rutas redundantes para aumentar la resiliencia y la fiabilidad.

SCTP está estandarizado por el Internet Engineering Task Force (IETF) en el RFC 9260. La implementación de referencia de SCTP se lanzó como parte de la versión 7 de FreeBSD y desde entonces ha sido ampliamente portada a otras plataformas.

En las especificaciones 3GPP 4G (LTE), SCTP (Stream Control Transmission Protocol) actúa como el transporte fundamental de Capa 4 para los mensajes de señalización del plano de control a través del Evolved Packet Core (EPC), incluida la conexión de señalización con el dominio de la Radio Access Network (RAN). Las especificaciones 3GPP 5G han eliminado en su lugar la necesidad de SCTP dentro de la Red Central mediante la introducción de la Service Based Architecture (SBA), que reemplaza todas las interfaces de señalización basadas en Diameter-over-SCTP por HTTP/2. Sin embargo, todavía es necesario dentro del dominio RAN 5G:

  • en las interfaces de señalización a través de los elementos de red que componen una instancia de gNodeB "desagregada" (interfaz F1-C entre DU y CU-CP e interfaz E1 entre CU-CP y CU-UP).

  • en la interfaz Xn-C que conecta instancias de gNodeB para fines de señalización.

  • en el punto de referencia N2 (también conocido como NG-C) utilizado para conectar instancias de gNodeB (dominio RAN) con instancias de AMF (dominio de red central) para fines de señalización.

Debe entonces habilitar el módulo del kernel sctp (lksctp) en los nodos del clúster en sentido descendente que alojan las cargas de trabajo de telecomunicaciones compatibles con SCTP que lo aprovechan:

  • Para cargar manualmente el módulo del kernel sctp en un nodo Linux:

$ sudo modprobe sctp
  • Para automatizar la carga del módulo del kernel sctp en cada arranque del nodo, cree un archivo llamado sctp.conf en el directorio /etc/modules-load.d/ que contenga simplemente la cadena sctp (es decir, el nombre del módulo del kernel que la unidad systemd-modules-load.service debería cargar en el arranque).

$ echo "sctp" > /etc/modules-load.d/sctp.conf
$ reboot

La forma más fácil y mejor de asegurar que el módulo del kernel sctp se cargue en cada arranque del nodo es añadir ese archivo /etc/modules-load.d/sctp.conf a la imagen sin procesar creada por Edge Image Builder (EIB) utilizada para aprovisionar los nodos en sentido descendente; consulte la documentación de EIB (Sección 5.3.5, “Añadir archivos de sistema operativo”) para obtener más información sobre cómo hacerlo.

Parte VII Aprovisionamiento de red dirigido totalmente automatizado

48 Introducción

Este capítulo describe cómo aprovisionar clústeres descendentes utilizando el aprovisionamiento de red dirigido, el método de aprovisionamiento admitido para SUSE Telco Cloud. A diferencia del aprovisionamiento basado en imágenes, este flujo de trabajo mantiene la imagen del SO genérica y dirige toda la configuración específica del clúster desde el clúster de gestión, lo que permite despliegues coherentes y totalmente automatizados a escala en sitios distribuidos.

El aprovisionamiento de red dirigido es un flujo de trabajo totalmente automatizado y sin intervención (zero-touch) gestionado por el clúster de gestión. Cada host bare-metal se preinscribe primero en Metal3 desde el clúster de gestión registrando sus credenciales de BMC y los detalles del hardware. Una vez que el host está instalado en el rack, conectado a las redes necesarias y encendido, el clúster de gestión toma el control: aprovisiona el SO utilizando una imagen base generada por EIB a través de la interfaz de gestión fuera de banda (out-of-band) y despliega la pila completa de Kubernetes con todos los perfiles de telecomunicaciones aplicados, sin ninguna intervención manual adicional.

El clúster de gestión automatiza el despliegue de los siguientes componentes en cada nodo del clúster descendente:

  • SUSE Linux Micro (Capítulo 10, SUSE Linux Micro) (o SUSE Linux Micro RT para el kernel de tiempo real) como sistema operativo. Las redes, el almacenamiento, los usuarios y los argumentos del kernel se pueden personalizar según el caso de uso.

  • RKE2 (Capítulo 14, RKE2) como distribución de Kubernetes. El complemento CNI predeterminado es Cilium. Se pueden utilizar otras combinaciones de CNI, como Cilium+Multus, dependiendo del caso de uso.

  • (Opcional) SUSE Storage (Capítulo 15, SUSE Storage)

  • (Opcional) SUSE Security (Capítulo 16, SUSE Security)

  • (Opcional) MetalLB como equilibrador de carga para clústeres de varios nodos de alta disponibilidad.

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

Nota
Nota

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

49 Preparar la imagen del clúster descendente para escenarios conectados

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

Gran parte de la configuración a través de Edge Image Builder es posible, pero en esta guía cubrimos las configuraciones mínimas necesarias para configurar el clúster descendente.

49.1 Requisitos previos para escenarios conectados

Nota
Nota

Es necesario utilizar un host de compilación con la misma arquitectura que las imágenes que se están compilando. En otras palabras, para compilar una imagen aarch64, es necesario utilizar un host de compilación aarch64, y viceversa para x86-64 (las compilaciones cruzadas no son compatibles en este momento).

49.2 Configuración de imagen para escenarios conectados

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

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

  • La carpeta de la imagen base contendrá la imagen raw de salida generada siguiendo la guía Capítulo 64, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi con el perfil Base (o Base-RT para el kernel de tiempo real), y ésta debe copiarse o moverse a la carpeta base-images.

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

  • El directorio custom/scripts contiene scripts que se ejecutarán en el primer arranque:

    1. El script 01-fix-growfs.sh es necesario para redimensionar la partición raíz del SO durante el despliegue

    2. El script 02-performance.sh es opcional y puede utilizarse para configurar el sistema para el ajuste del rendimiento.

    3. El script 03-sriov.sh es opcional y puede utilizarse para configurar el sistema para SR-IOV.

  • La carpeta network es opcional; consulte Sección 49.2.6, “Script adicional para la configuración de red avanzada” para obtener más detalles.

  • La carpeta os-files contiene los archivos de configuración necesarios para cargar, en cada arranque del nodo, los módulos del kernel sctp y vfio-pci con las opciones requeridas.

├── downstream-cluster-config.yaml
├── base-images
│   └── SL-Micro.x86_64-6.2-Base-GM.raw
├── custom
│   ├── files
│   │   ├── performance-settings.sh
│   │   └── sriov-auto-filler.sh
│   └── scripts
│       ├── 01-fix-growfs.sh
│       ├── 02-performance.sh
│       └── 03-sriov.sh
├── network
│   └── configure-network.sh
└── os-files
    └── etc
        ├── modprobe.d
        │   └── vfio-pci-options.conf
        └── modules-load.d
            ├── sctp.conf
            └── vfio-pci.conf

49.2.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: eibimage-output-telco.raw
operatingSystem:
  kernelArgs:
    - ignition.platform.id=openstack
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
  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 requerido.

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

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

Nota
Nota

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

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

Para versiones de SUSE Linux Micro anteriores a la 6.2, net.ifnames=1 debe establecerse explícitamente como argumento del kernel para habilitar Predictable Network Interface Naming. Esto se aplica de forma predeterminada a partir de la versión 6.2 y no se requiere una configuración explícita. Esto se alinea con la configuración predictableNicNames en el gráfico de Helm de Metal3 del clúster de gestión, que es necesaria para que el aprovisionamiento de red dirigido funcione correctamente. La nomenclatura coherente de las interfaces también es fundamental cuando se utiliza SR-IOV.

49.2.2 Script Growfs

Actualmente, se requiere un script personalizado (custom/scripts/01-fix-growfs.sh) para ampliar el sistema de archivos de modo que coincida con el tamaño del disco en el primer arranque tras el aprovisionamiento. El script 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 /

49.2.3 Script de rendimiento

El siguiente script opcional (custom/scripts/02-performance.sh) puede utilizarse para configurar el sistema para el ajuste del rendimiento:

#!/bin/bash

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

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

El contenido de custom/files/performance-settings.sh es un script que puede utilizarse para configurar el sistema para el ajuste del rendimiento y puede descargarse desde el siguiente enlace.

49.2.4 Script de SR-IOV

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

#!/bin/bash

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

El contenido de custom/files/sriov-auto-filler.sh es un script que puede utilizarse para configurar el sistema para SR-IOV y puede descargarse desde el siguiente enlace.

Nota
Nota

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

49.2.5 Configuración adicional para cargas de trabajo de Telco

Para habilitar funciones de Telco como dpdk, sr-iov o FEC, pueden ser necesarios paquetes adicionales como se muestra en el siguiente ejemplo.

apiVersion: 1.3
image:
  imageType: raw
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-Base-GM.raw
  outputImageName: eibimage-output-telco.raw
operatingSystem:
  kernelArgs:
    - ignition.platform.id=openstack
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
      sshKeys:
      - $user1Key1
      createHomeDir: true
  packages:
    packageList:
      - jq            # Non Telco specific - category: testing/utils
      - dpdk          # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: runtime
      - dpdk-tools    # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: testing/utils
      - libdpdk-25    # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: runtime
      - pf-bb-config  # TelCo RAN (gNB: DU) - category: config.
      - open-iscsi    # Non Telco specific (required by SUSE Storage/Longhorn) - category: runtime
      - tuned         # Non Telco specific (linux tuning) - category: config.
      - cpupower      # Non Telco specific (linux tuning - CPU power related settings) - category: config.
      - rt-tests      # Non Telco specific (RT scheduler-latency testing) - category: testing/utils
      - linuxptp      # TelCo RAN; time sync (gNB: DU) - category: runtime
      - synce4l       # TelCo RAN; time sync (gNN: DU) - category: runtime
      - pciutils      # Non Telco specific (provides "lspci" command) - category: testing/utils
      - numactl       # Non Telco specific (provides "numactl" command) - category: testing/utils
    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 los paquetes mínimos que se utilizarán para los perfiles de Telco.

Nota
Nota

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

49.2.6 Script adicional para la configuración de red avanzada

Si necesita configurar IP estáticas o escenarios de red más avanzados como se describe en Capítulo 53, Configuración de red avanzada, es necesaria la siguiente configuración adicional.

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 de configuración de NM.

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

49.2.7 Módulos de kernel necesarios para Telco

Para asegurar que los módulos de kernel necesarios para las cargas de trabajo de telecomunicaciones se carguen en cada arranque del nodo, debe añadir los siguientes archivos de configuración a la carpeta EIB os-files:

49.2.7.1 sctp.conf

Para colocar en la ruta os-files/etc/modules-load.d/, indicando al systemd-modules-load.service que cargue el módulo del kernel sctp en el arranque del nodo.

$ cat os-files/etc/modules-load.d/sctp.conf
# Request "systemd-modules-load.service" to load sctp module at boot time
sctp

49.2.7.2 vfio-pci.conf

Para colocar en la ruta os-files/etc/modules-load.d/, indicando al systemd-modules-load.service que cargue el módulo del kernel vfio-pci en el arranque del nodo.

$ cat os-files/etc/modules-load.d/vfio-pci.conf
# Request "systemd-modules-load.service" to load vfio-pci module at boot time
# NOTE: The (SRIOV & DPDK related) required load-module options settings are defined in related "/etc/modprobe.d/vfio-pci-options.conf" file
vfio_pci

49.2.7.3 vfio-pci-options.conf

Para colocar en la ruta os-files/etc/modprobe.d/, estableciendo los parámetros necesarios del módulo del kernel vfio-pci que se aplicarán cuando se cargue el módulo del kernel.

$ cat os-files/etc/modprobe.d/vfio-pci-options.conf
# Enable SR-IOV and disable idle D3 state for vfio-pci driver
options vfio_pci enable_sriov=1 disable_idle_d3=1

49.3 Creación de imágenes

Una vez preparada la estructura de directorios siguiendo las secciones anteriores, ejecute 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 ISO de salida llamado eibimage-output-telco.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 del servidor multimedia habilitado mediante la Documentación del Clúster de Gestión (Nota) o algún otro servidor accesible localmente. En los ejemplos siguientes, nos referimos a este servidor como imagecache.local:8080

50 Preparar la imagen del clúster descendente para escenarios de entorno aislado

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

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

50.1 Requisitos previos para escenarios de entorno aislado

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

  • La imagen base se compilará utilizando la siguiente guía Capítulo 64, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi con el perfil Base (o Base-RT para el kernel de tiempo real). El proceso es el mismo para ambas arquitecturas (x86-64 y aarch64).

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

Nota
Nota

Es necesario utilizar un host de compilación con la misma arquitectura que las imágenes que se están compilando. En otras palabras, para compilar una imagen aarch64, es necesario utilizar un host de compilación aarch64, y viceversa para x86-64 (las compilaciones cruzadas no son compatibles en este momento).

50.2 Configuración de la imagen para escenarios de entorno aislado

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-airgap-config.yaml es el archivo de definición de imagen, véase Capítulo 5, Clústeres independientes con Edge Image Builder para más detalles.

  • La carpeta de la imagen base contendrá la imagen raw de salida generada siguiendo la guía Capítulo 64, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi con el perfil Base (o Base-RT para el kernel de tiempo real) debe copiarse/moverse a la carpeta base-images.

  • La carpeta network es opcional; consulte Sección 49.2.6, “Script adicional para la configuración de red avanzada” para obtener más detalles.

  • El directorio custom/scripts contiene scripts que se ejecutarán en el primer arranque:

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

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

    3. El script 03-performance.sh es opcional y puede utilizarse para configurar el sistema para el ajuste del rendimiento.

    4. El script 04-sriov.sh es opcional y puede utilizarse para configurar el sistema para SR-IOV.

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

  • La carpeta os-files contiene los archivos de configuración necesarios para cargar, en cada arranque del nodo, los módulos del kernel sctp y vfio-pci con las opciones requeridas.

├── downstream-cluster-airgap-config.yaml
├── base-images
│   └── SL-Micro.x86_64-6.2-Base-GM.raw
├── custom
│   ├── files
│   │   ├── install.sh
│   │   ├── rke2-images-cilium.linux-amd64.tar.zst
│   │   ├── rke2-images-core.linux-amd64.tar.zst
│   │   ├── rke2-images-multus.linux-amd64.tar.zst
│   │   ├── rke2-images.linux-amd64.tar.zst
│   │   ├── rke2-images-traefik.linux-amd64.tar.zst
│   │   ├── rke2.linux-amd64.tar.zst
│   │   ├── sha256sum-amd64.txt
│   │   ├── performance-settings.sh
│   │   └── sriov-auto-filler.sh
│   └── scripts
│       ├── 01-fix-growfs.sh
│       ├── 02-airgap.sh
│       ├── 03-performance.sh
│       └── 04-sriov.sh
├── network
│   └── configure-network.sh
└── os-files
    └── etc
        ├── modprobe.d
        │   └── vfio-pci-options.conf
        └── modules-load.d
            ├── sctp.conf
            └── vfio-pci.conf

50.2.1 Archivo de definición de imagen del clúster en sentido descendente

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

50.2.2 Script Growfs

Actualmente, se requiere un script personalizado (custom/scripts/01-fix-growfs.sh) para ampliar el sistema de archivos de modo que coincida con el tamaño del disco en el primer arranque tras el aprovisionamiento. El script 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 /

50.2.3 Script para entorno aislado

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

#!/bin/bash

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

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

50.2.4 Script de rendimiento

El siguiente script opcional (custom/scripts/03-performance.sh) puede utilizarse para configurar el sistema para el ajuste del rendimiento:

#!/bin/bash

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

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

El contenido de custom/files/performance-settings.sh es un script que puede utilizarse para configurar el sistema para el ajuste del rendimiento y puede descargarse desde el siguiente enlace.

50.2.5 Script de SR-IOV

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

#!/bin/bash

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

El contenido de custom/files/sriov-auto-filler.sh es un script que puede utilizarse para configurar el sistema para SR-IOV y puede descargarse desde el siguiente enlace.

50.2.6 Módulos de kernel necesarios para Telco

Tal como se describe para el escenario sin entorno aislado en la sección (Sección 49.2.7, “Módulos de kernel necesarios para Telco”).

50.2.7 Preparación de los artefactos para entorno aislado

Se requieren los siguientes pasos para preparar los artefactos de entorno aislado utilizando la imagen del contenedor de la versión, con el fin de poblar un registro con los artefactos de la versión específica. Gestiona la generación del archivo tar de RKE2, la duplicación OCI de charts de Helm y la duplicación de imágenes de contenedor en un solo comando: no se necesitan scripts adicionales.

  1. Si su registro privado requiere autenticación, cree un archivo de autenticación de registro con las credenciales codificadas en base64:

    $ echo -n "$(echo -n 'myusername' | base64 -w 0):$(echo -n 'mypassword' | base64 -w 0)" > registry-auth.txt
  2. Si utiliza un repositorio de charts de Rancher Apps (necesario para los charts de Longhorn y los obtenidos de Rancher), cree un archivo de autenticación de Rancher Apps:

    $ echo -n "$(echo -n 'myusername@apps.rancher.io' | base64 -w 0):$(echo -n 'mypassword' | base64 -w 0)" > rancher-apps-auth.txt
  3. (Opcional) Si desea replicar los artefactos de SUSE Private Registry (charts/imágenes de Harbor), cree un archivo de autenticación de SUSE Private Registry utilizando su SCC mirroring credentials recuperado siguiendo la documentación de SUSE Private Registry:

    $ echo -n "$(echo -n 'SUSE_REGISTRY_USERNAME' | base64 -w 0):$(echo -n 'SUSE_REGISTRY_PASSWORD' | base64 -w 0)" > suse-private-registry-auth.txt
  4. Ejecute el comando mirror utilizando la imagen de contenedor de la versión para poblar su registro privado con todos los artefactos necesarios para una versión específica (imágenes de RKE2, imágenes OCI de charts de Helm e imágenes de contenedor). Coloque cualquier archivo de autenticación y certificados en el directorio actual para que sean accesibles dentro del contenedor a través del bind mount -v ./:/opt:z.

    Sin SUSE Private Registry (se omitirán los charts/imágenes de Harbor):

    $ podman run --rm \
      -v ./:/opt:z \
      registry.suse.com/edge/3.6/release-manifest:3.6 \
      mirror \
      -o /opt/output \
      -a /opt/registry-auth.txt \
      -c /opt/cert.pem \
      -r ${REGISTRY_IP}:5000 \
      --rancher-apps-authfile /opt/rancher-apps-auth.txt \
      --debug

    donde ${REGISTRY_IP} es la dirección IP de la instancia del registro que se va a poblar.

    Con SUSE Private Registry:

    $ podman run --rm \
      -v ./:/opt:z \
      registry.suse.com/edge/3.6/release-manifest:3.6 \
      mirror \
      -o /opt/output \
      -a /opt/registry-auth.txt \
      -c /opt/cert.pem \
      -r ${MGMT_CLUSTER_REGISTRY_IP}:5000 \
      --rancher-apps-authfile /opt/rancher-apps-auth.txt \
      --suse-private-registry-authfile /opt/suse-private-registry-auth.txt \
      --debug

    donde ${MGMT_CLUSTER_REGISTRY_IP} es la dirección IP estática reservada asignada a la instancia de SUSE Private Registry desplegada en el clúster de gestión, como se describe en la sección (Sección 30.3, “Modificaciones en la carpeta kubernetes”) anterior.

  5. Copie los artefactos de RKE2 generados desde el directorio de salida (/opt/output`en el ejemplo) al directorio `custom/files para que sean consumidos por EIB para los clústeres en sentido descendente durante el proceso de construcción:

    $ cp output/rke2-images*.tar.zst custom/files/
    $ cp output/rke2.linux-amd64.tar.gz custom/files/
    $ cp output/sha256sum-amd64.txt custom/files/
Nota
Nota

La imagen del contenedor de la versión ya incluye /release_manifest.yaml y /release_images.yaml internamente, por lo que no es necesario proporcionar archivos de manifiesto adicionales. Para obtener una referencia completa de los flags y un uso avanzado, consulte la documentación de seactl.

50.3 Creación de imágenes para escenarios de entorno aislado

Una vez preparado el directorio siguiendo las secciones anteriores, ejecute 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-airgap-config.yaml

Esto crea el archivo de imagen ISO de salida llamado eibimage-output-telco.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 la Documentación del Clúster de Gestión (Nota) o algún otro servidor accesible localmente. En los ejemplos siguientes, nos referimos a este servidor como imagecache.local:8080.

51 Aprovisionamiento de clústeres en sentido descendente con aprovisionamiento de red dirigida (nodo único)

Esta sección describe el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster en sentido descendente de nodo único mediante el aprovisionamiento de red dirigida. Esta es la forma más sencilla de automatizar el aprovisionamiento de un clúster en sentido descendente.

Requisitos

Flujo de trabajo

El siguiente diagrama muestra el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente de nodo único mediante aprovisionamiento de red dirigido:

atip automated singlenode1

Existen dos pasos diferentes para automatizar el aprovisionamiento de un clúster descendente de nodo único mediante aprovisionamiento de red dirigido:

  1. Inscriba el host de equipo sin sistema operativo para que esté disponible para el proceso de aprovisionamiento.

  2. Aprovisione el host de equipo sin sistema operativo para instalar y configurar el sistema operativo y el clúster de Kubernetes.

Inscribir el host de equipo sin sistema operativo

El primer paso es inscribir el nuevo host de equipo sin sistema operativo en el clúster de gestión para que esté disponible para ser aprovisionado. Para ello, se debe crear el siguiente archivo (bmh-example.yaml) en el clúster de gestión, para especificar las credenciales BMC que se utilizarán y el objeto BaremetalHost que se va a inscribir:

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

Donde:

  • ${BMC_USERNAME} — El nombre de usuario para el BMC del nuevo host de equipo sin sistema operativo.

  • ${BMC_PASSWORD} — La contraseña para el BMC del nuevo host de equipo sin sistema operativo.

  • ${BMC_MAC} — La dirección MAC del nuevo host de equipo sin sistema operativo que se va a utilizar.

  • ${BMC_ADDRESS} — El URL para el host de equipo sin sistema operativo BMC (por ejemplo, redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/). Para obtener más información sobre las diferentes opciones disponibles según su proveedor de hardware, consulte el siguiente enlace.

Nota
Nota
  • La arquitectura debe ser x86_64 o aarch64, dependiendo de la arquitectura del host de equipo sin sistema operativo que se va a inscribir.

  • Si no se ha especificado ninguna configuración de red para el host, ya sea en el momento de la creación de la imagen o a través de la definición BareMetalHost, se utilizará un mecanismo de autoconfiguración (DHCP, DHCPv6, SLAAC). Para obtener más detalles o configuraciones complejas, consulte el Capítulo 53, Configuración de red avanzada.

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

$ kubectl apply -f bmh-example.yaml

El nuevo objeto de host de equipo sin sistema operativo se inscribirá, cambiando su estado de registro a inspección y disponible. Los cambios se pueden comprobar utilizando el siguiente comando:

$ kubectl get bmh
Nota
Nota

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

Paso de aprovisionamiento

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

Nota
Nota

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

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

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: single-node-cluster
  namespace: default
  labels:
    cluster-api.cattle.io/rancher-auto-import: "true"
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
        - fd00:bad:cafe::/48
    services:
      cidrBlocks:
        - 10.96.0.0/12
        - fd00:bad:bad:cafe::/112
  controlPlaneRef:
    apiGroup: controlplane.cluster.x-k8s.io
    kind: RKE2ControlPlane
    name: single-node-cluster
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3Cluster
    name: single-node-cluster
Nota
Nota
  • Son posibles tanto las implementaciones de pila única como de pila dual; elimine los CIDR de IPv6 de la definición anterior para un clúster solo de IPv4.

  • Las implementaciones de IPv6 de pila única están en fase de vista previa técnica y aún no cuentan con soporte oficial.

  • 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.

El objeto Metal3Cluster especifica el punto de conexión del plano de control (reemplazando el ${DOWNSTREAM_CONTROL_PLANE_IPV4}) que se va a configurar y el noCloudProvider porque se utiliza un equipo sin sistema operativo.

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

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

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

El objeto Metal3MachineTemplate especifica la siguiente información:

  • El dataTemplate que se va a utilizar como referencia para la plantilla.

  • El hostSelector que se debe utilizar coincidiendo con la etiqueta creada durante el proceso de inscripción.

  • El image que se debe utilizar como referencia a la imagen generada utilizando EIB en la sección (Capítulo 49, Preparar la imagen del clúster descendente para escenarios conectados) anterior, y el checksum y checksumType que se deben utilizar para validar la imagen.

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

El objeto Metal3DataTemplate especifica el metaData para el clúster descendente.

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

Una vez creado el archivo uniendo los bloques anteriores, se debe ejecutar el siguiente comando en el clúster de gestión para comenzar a aprovisionar el nuevo host de equipo sin sistema operativo:

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

52 Aprovisionamiento de clúster descendente con aprovisionamiento de red dirigido (multinodo)

Esta sección describe el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente multinodo utilizando aprovisionamiento de red dirigida y MetalLB como estrategia de equilibrador de carga. Esta es la forma más sencilla de automatizar el aprovisionamiento de un clúster descendente. El siguiente diagrama muestra el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente multinodo utilizando aprovisionamiento de red dirigida y MetalLB.

Requisitos

Flujo de trabajo

El siguiente diagrama muestra el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente multinodo utilizando aprovisionamiento de red dirigida:

atip automate multinode1
  1. Inscribid los tres hosts de equipo sin sistema operativo para que estén disponibles para el proceso de aprovisionamiento.

  2. Aprovisionad los tres hosts de equipo sin sistema operativo para instalar y configurar el sistema operativo y el clúster de Kubernetes utilizando MetalLB.

Inscribid los hosts de equipo sin sistema operativo

El primer paso es inscribir los tres hosts de equipo sin sistema operativo en el clúster de gestión para que estén disponibles para ser aprovisionados. Para ello, debéis crear los siguientes archivos (bmh-example-node1.yaml, bmh-example-node2.yaml y bmh-example-node3.yaml) en el clúster de gestión, para especificar las credenciales de BMC que se utilizarán y el objeto BaremetalHost que se inscribirá en el clúster de gestión.

Nota
Nota
  • Solo debéis reemplazar los valores entre $\{…​\} por los valores reales.

  • Os guiaremos a través del proceso para un solo host. Los mismos pasos se aplican a los otros dos nodos.

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

Dónde:

  • ${BMC_NODE1_USERNAME} — El nombre de usuario para la BMC del primer host bare-metal.

  • ${BMC_NODE1_PASSWORD} — La contraseña para la BMC del primer host bare-metal.

  • ${BMC_NODE1_MAC} — La dirección MAC del primer host bare-metal que se debe utilizar.

  • ${BMC_NODE1_ADDRESS} — La URL para el BMC del primer host bare-metal (por ejemplo, redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/). La parte del host de la URL puede ser una dirección IP (v4 o v6) o un nombre de dominio, donde la infraestructura existente lo permita. Para obtener más información sobre las diferentes opciones disponibles según su proveedor de hardware, consulte el siguiente enlace.

Nota
Nota
  • Si no se ha especificado ninguna configuración de red para el host, ya sea en el momento de la creación de la imagen o a través de la definición BareMetalHost, se utilizará un mecanismo de autoconfiguración (DHCP, DHCPv6, SLAAC). Para obtener más detalles o configuraciones complejas, consulte el Capítulo 53, Configuración de red avanzada.

  • Los clústeres IPv6 de pila única están en estado de vista previa técnica y aún no son compatibles oficialmente.

  • La arquitectura debe ser x86_64 o aarch64, dependiendo de la arquitectura de los hosts de equipo sin sistema operativo que se van a inscribir.

  • Todos los servidores modernos vienen con un BMC capaz de manejar pila dual; sin embargo, la compatibilidad con IPv6 (y posiblemente la opción de usar nombres de host para la capacidad VirtualMedia) debe verificarse antes de su uso en producción en un entorno de pila dual.

Una vez creado el archivo, se debe ejecutar el siguiente comando en el clúster de gestión para comenzar a inscribir los equipos sin sistema operativo en el clúster de gestión:

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

Los nuevos objetos de equipo sin sistema operativo se inscriben, cambiando su estado de registro a inspección y disponible. Los cambios se pueden comprobar utilizando el siguiente comando:

$ kubectl get bmh -o wide
Nota
Nota

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

Paso de aprovisionamiento

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

Nota
Nota
  • Solo se deben reemplazar los valores entre $\{…​\} con los valores reales.

  • La dirección VIP es una dirección IP reservada que no está asignada a ningún nodo y se utiliza para configurar el equilibrador de carga. En un clúster de pila dual, se pueden especificar tanto una IPv4 como una IPv6, pero en los siguientes ejemplos se dará prioridad a la dirección IPv4.

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

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: multinode-cluster
  namespace: default
  labels:
    cluster-api.cattle.io/rancher-auto-import: "true"
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
        - fd00:1234:4321::/48
    services:
      cidrBlocks:
        - 10.96.0.0/12
        - fd00:5678:8765:4321::/112
  controlPlaneRef:
    apiGroup: controlplane.cluster.x-k8s.io
    kind: RKE2ControlPlane
    name: multinode-cluster
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3Cluster
    name: multinode-cluster
Nota
Nota
  • Son posibles tanto despliegues de pila única como de pila dual; elimine los CIDR IPv6 y las direcciones VIP IPv6 (en las secciones siguientes) para un clúster solo IPv4.

  • 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.

El objeto Metal3Cluster especifica el punto final del plano de control que utiliza la dirección VIP ya reservada (reemplazando el ${EDGE_VIP_ADDRESS_IPV4}) para ser configurado y el noCloudProvider porque se utilizan los tres nodos de equipo sin sistema operativo.

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

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

  • Una anotación de exclusión del equilibrador de carga que informa a los equilibradores de carga externos como MetalLB de que un nodo va a ser vaciado durante las operaciones de ciclo de vida, como la actualización de versión de los clústeres en sentido descendente. Para obtener información, consulte: Sección 59.1, “Exclusión del equilibrador de carga”

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

  • El modo de anuncio que debe utilizar el equilibrador de carga (address utiliza la implementación L2), así como la dirección que se va a utilizar (reemplazando el ${EDGE_VIP_ADDRESS} con la dirección VIP).

  • El serverConfig con el complemento CNI que se va a utilizar (en este caso, Cilium), y la(s) dirección(es) y nombre(s) VIP adicionales que se incluirán en tlsSan.

  • El bloque agentConfig contiene el Ignition formato que se debe utilizar y el additionalUserData que se debe utilizar para configurar el RKE2 nodo con información como:

    • El servicio systemd denominado rke2-preinstall.service para reemplazar automáticamente el BAREMETALHOST_UUID y el node-name durante el proceso de aprovisionamiento utilizando la información de Ironic además de añadir la etiqueta metal3.io/uuid a los objetos Node con el UUID BareMetalHost.

    • El servicio systemd denominado rke2-traefik-deployment.service para establecer la opción de configuración server de RKE2 ingress-controller en el archivo /etc/rancher/rke2/config.yaml a traefik.

    • El bloque storage que contiene los gráficos de Helm que se deben utilizar para instalar el MetalLB y el endpoint-copier-operator.

    • El archivo de recurso personalizado metalLB con el IPaddressPool y el L2Advertisement que se deben utilizar (reemplazando ${EDGE_VIP_ADDRESS_IPV4} con la dirección VIP).

    • El archivo endpoint-svc.yaml que se debe utilizar para configurar el servicio kubernetes-vip que utilizará el MetalLB para gestionar la dirección VIP.

  • El último bloque de información contiene la versión de Kubernetes que se debe utilizar. El ${RKE2_VERSION} es la versión de RKE2 que se debe utilizar reemplazando este valor (por ejemplo, v1.35.4+rke2r1).

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

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

El objeto Metal3MachineTemplate especifica la siguiente información:

  • El dataTemplate que se va a utilizar como referencia para la plantilla.

  • El hostSelector que se debe utilizar coincidiendo con la etiqueta creada durante el proceso de inscripción.

  • El image que se debe utilizar como referencia a la imagen generada mediante EIB en la sección (Capítulo 49, Preparar la imagen del clúster descendente para escenarios conectados) anterior, y checksum y checksumType que se deben utilizar para validar la imagen.

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

El objeto Metal3DataTemplate especifica el metaData para el clúster en sentido descendente.

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

Los siguientes archivos yaml son un ejemplo de configuración para los nodos trabajadores.

A MachineDeployment:

apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineDeployment
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: multinode-cluster
    nodepool: nodepool-0
  name: multinode-cluster-workers
  namespace: default
spec:
  clusterName: multinode-cluster
  replicas: 3
  selector:
    matchLabels:
      cluster.x-k8s.io/cluster-name: multinode-cluster
      nodepool: nodepool-0
  template:
    metadata:
      labels:
        cluster.x-k8s.io/cluster-name: multinode-cluster
        nodepool: nodepool-0
    spec:
      bootstrap:
        configRef:
          apiGroup: bootstrap.cluster.x-k8s.io
          kind: RKE2ConfigTemplate
          name: multinode-cluster-workers
      clusterName: multinode-cluster
      infrastructureRef:
        apiGroup: infrastructure.cluster.x-k8s.io
        kind: Metal3MachineTemplate
        name: multinode-cluster-workers
      deletion:
        nodeDrainTimeoutSeconds: 0
      version: ${RKE2_VERSION}

El objeto RKE2ConfigTemplate especifica la plantilla de configuración que se debe utilizar para los nodos trabajadores de clústeres multinodo.

apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: RKE2ConfigTemplate
metadata:
  name: multinode-cluster-workers
  namespace: default
spec:
  template:
    spec:
      agentConfig:
        format: ignition
        kubelet:
          extraArgs:
          - provider-id=metal3://BAREMETALHOST_UUID
        nodeName: "Node-multinode-cluster-worker"
        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

El objeto Metal3MachineTemplate contiene referencias a dataTemplate, hostSelector y image para los nodos trabajadores:

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

El objeto Metal3DataTemplate especifica la metaData para el clúster descendente para los nodos trabajadores:

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

Una vez creado el archivo uniendo los bloques anteriores, ejecute el siguiente comando en el clúster de gestión para comenzar a aprovisionar los tres nuevos hosts como equipos sin sistema operativo:

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

53 Configuración de red avanzada

El flujo de trabajo de aprovisionamiento de red dirigida permite configuraciones de red específicas en clústeres en sentido descendente, como IP estáticas, bonding, VLAN, IPv6, etc.

Las siguientes secciones describen los pasos adicionales necesarios para habilitar el aprovisionamiento de clústeres en sentido descendente mediante la configuración de red avanzada.

Requisitos

Configuración

Antes de continuar, consulte una de las siguientes secciones para obtener orientación sobre los pasos necesarios para inscribir y aprovisionar el/los host(s):

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

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

Como podéis ver, el ejemplo muestra la configuración para habilitar la interfaz con IPs estáticas, así como la configuración para habilitar la VLAN utilizando la interfaz base, una vez que se sustituyan las siguientes variables por los valores reales, de acuerdo con vuestra infraestructura:

  • ${CONTROLPLANE_INTERFACE} — La interfaz del plano de control que se utilizará para el clúster en sentido descendente (por ejemplo, eth0). Al incluir identifier: mac-address, el nombre se inspecciona automáticamente mediante la dirección MAC, por lo que se puede utilizar cualquier nombre de interfaz.

  • ${CONTROLPLANE_IP} — La dirección IP que se utilizará como punto final para el clúster en sentido descendente (debe coincidir con el punto final de kubeapi-server).

  • ${CONTROLPLANE_PREFIX} — El CIDR que se utilizará para el clúster en sentido descendente (por ejemplo, 24 si deseáis /24 o 255.255.255.0).

  • ${CONTROLPLANE_GATEWAY} — La puerta de enlace que se utilizará para el clúster en sentido descendente (por ejemplo, 192.168.100.1).

  • ${CONTROLPLANE_MAC} — La dirección MAC que se utilizará para la interfaz del plano de control (por ejemplo, 00:0c:29:3e:3e:3e).

  • ${DNS_SERVER} — El DNS que se utilizará para el clúster en sentido descendente (por ejemplo, 192.168.100.2).

  • ${VLAN_ID} — El ID de VLAN que se utilizará para el clúster en sentido descendente (por ejemplo, 100).

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

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

Al igual que en el ejemplo anterior, sustituid las siguientes variables por los valores reales, de acuerdo con vuestra infraestructura:

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

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

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

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

  • ${CONTROLPLANE_GATEWAY_V4} - la dirección IPv4 de la puerta de enlace para el tráfico que coincide con la ruta predeterminada

  • ${CONTROLPLANE_GATEWAY_V6} - la dirección IPv6 de la puerta de enlace para el tráfico que coincide con la ruta predeterminada

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

  • ${DNS_SERVER_V4} y/o ${DNS_SERVER_V6} - la(s) dirección(es) IP del/de los servidor(es) DNS que se utilizará(n), que puede(n) especificarse como una o varias entradas. Se admiten tanto direcciones IPv4 como IPv6

Nota
Nota
  • Puede consultar el repositorio de ejemplos de SUSE Telco Cloud para ver ejemplos más complejos, incluidas configuraciones solo IPv6 y de pila dual.

  • Las implementaciones de IPv6 de pila única están en fase de vista previa técnica y aún no cuentan con soporte oficial.

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

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

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

  • La arquitectura debe ser x86_64 o aarch64, dependiendo de la arquitectura del equipo sin sistema operativo que se va a inscribir.

54 Funcionalidades de telecomunicaciones (DPDK, SR-IOV, aislamiento de CPU, páginas enormes, NUMA, etc.)

El flujo de trabajo de aprovisionamiento de red dirigido permite automatizar las funcionalidades de telecomunicaciones que se utilizarán en los clústeres descendentes para ejecutar cargas de trabajo de telecomunicaciones sobre esos servidores.

Requisitos

Configuración

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

Las funcionalidades de telecomunicaciones cubiertas en esta sección son las siguientes:

  • DPDK y creación de VFs

  • SR-IOV y asignación de VFs para ser utilizadas por las cargas de trabajo

  • Aislamiento de CPU y ajuste de rendimiento

  • Configuración de páginas enormes

  • Ajuste de parámetros del kernel

Nota
Nota

Para obtener más información sobre las funcionalidades de Telco, consultad Parte VI, “Configuración de las funciones Telco”.

Los cambios necesarios para habilitar las funcionalidades de Telco mostradas anteriormente se encuentran todos dentro del bloque RKE2ControlPlane en el archivo de aprovisionamiento capi-provisioning-example.yaml. El resto de la información dentro del archivo capi-provisioning-example.yaml es la misma que la información proporcionada en la sección de aprovisionamiento (Capítulo 51, Aprovisionamiento de clústeres en sentido descendente con aprovisionamiento de red dirigida (nodo único)).

Para aclarar el proceso, los cambios necesarios en ese bloque (RKE2ControlPlane) para habilitar las funcionalidades de Telco son los siguientes:

  • El archivo de ignición /var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml que se va a utilizar para definir las interfaces, los controladores y el número de VFs que se van a crear y exponer a las cargas de trabajo.

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

      • ${RESOURCE_NAME1} — El nombre del recurso que se va a utilizar para la primera interfaz PF (por ejemplo, sriov-resource-du1). Se añade al prefijo rancher.io para utilizarlo como etiqueta que emplearán las cargas de trabajo (por ejemplo, rancher.io/sriov-resource-du1).

      • ${SRIOV-NIC-NAME1} — El nombre de la primera interfaz PF que se va a utilizar (por ejemplo, eth0).

      • ${PF_NAME1} — El nombre de la primera función física PF que se va a utilizar. Generad filtros más complejos utilizando esto (por ejemplo, eth0#2-5).

      • ${DRIVER_NAME1} — El nombre del controlador que se va a utilizar para la primera interfaz VF (por ejemplo, vfio-pci).

      • ${NUM_VFS1} — El número de VFs que se van a crear para la primera interfaz PF (por ejemplo, 8).

  • El /var/sriov-auto-filler.sh que se va a utilizar como traductor entre el mapa de configuración de alto nivel sriov-custom-auto-config y el sriovnetworknodepolicy que contiene la información de hardware de bajo nivel. Este script se ha creado para abstraer al usuario de la complejidad de conocer de antemano la información del hardware. No se requieren cambios en este archivo, pero debe estar presente si necesitamos habilitar sr-iov y crear VFs.

  • Los argumentos del kernel que se van a utilizar para habilitar las siguientes funciones:

Parámetro

Valor

Descripción

isolcpus

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

Aislád los núcleos 1-30 y 33-62.

skew_tick

1

Permite al kernel sesgar las interrupciones del temporizador a través de las CPU aisladas.

nohz

on

Permite al kernel ejecutar el tick del temporizador en una única CPU cuando el sistema está inactivo.

nohz_full

1-30,33-62

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

rcu_nocbs

1-30,33-62

Permite al kernel ejecutar las devoluciones de llamada RCU en una única CPU cuando el sistema está inactivo.

irqaffinity

0,31,32,63

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

inactivo

poll

Minimiza la latencia de salida del estado inactivo.

iommu

pt

Permite utilizar vfio para las interfaces DPDK.

intel_iommu

on

Habilita el uso de vfio para VFs.

hugepagesz

1 G

Permite establecer el tamaño de las páginas enormes a 1 G.

hugepages

40

Número de páginas enormes definidas anteriormente.

default_hugepagesz

1 G

Valor predeterminado para habilitar páginas enormes.

nowatchdog

 

Deshabilita el watchdog.

nmi_watchdog

0

Deshabilita el watchdog NMI.

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

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

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

    • performance-settings.service para habilitar el ajuste de rendimiento de la CPU.

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

  • El ${RKE2_VERSION} es la versión de RKE2 que se debe utilizar reemplazando este valor (por ejemplo, v1.35.4+rke2r1).

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

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

Una vez creado el archivo uniendo los bloques anteriores, se debe ejecutar el siguiente comando en el clúster de gestión para comenzar a aprovisionar el nuevo clúster descendente utilizando las funcionalidades de Telco:

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

55 Registro privado

Es posible configurar un registro privado como réplica para las imágenes utilizadas por las cargas de trabajo.

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

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

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

Nota
Nota

tls.crt, tls.key, ca.crt, username y password deben estar codificados en formato base64 antes de utilizarse en el secreto.

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

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

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

56 Aprovisionamiento de clúster descendente en entornos aislados

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

56.1 Requisitos para entornos aislados

  1. La imagen raw generada mediante EIB debe incluir las imágenes de contenedor específicas (OCI de helm-chart e imágenes de contenedor) necesarias para ejecutar el clúster descendente en un entorno aislado. Para obtener más información, consultad esta sección (Capítulo 50, Preparar la imagen del clúster descendente para escenarios de entorno aislado).

  2. En caso de utilizar SR-IOV o cualquier otra carga de trabajo personalizada, las imágenes necesarias para ejecutar las cargas de trabajo deben estar precargadas en vuestro registro privado siguiendo la sección de precarga del registro privado (Sección 50.2.7, “Preparación de los artefactos para entorno aislado”).

56.2 Inscribid los equipos sin sistema operativo en entornos aislados.

El proceso para inscribir los equipos sin sistema operativo en el clúster de gestión es el mismo que el descrito en la sección anterior (Capítulo 51, Aprovisionamiento de clústeres en sentido descendente con aprovisionamiento de red dirigida (nodo único)).

56.3 Aprovisionad el clúster descendente en entornos aislados.

Existen algunos cambios importantes necesarios para aprovisionar el clúster descendente en entornos aislados:

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

  2. La configuración del registro privado debe incluirse en el bloque RKE2ControlPlane del archivo capi-provisioning-airgap-example.yaml siguiendo la sección de registro privado (Capítulo 55, Registro privado).

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

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

  • Referencias de secretos del registro privado

  • Definición de Helm-Chart utilizando el registro privado en lugar de las imágenes OCI públicas.

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

Parte VIII Operaciones del día 2

Esta sección explica cómo los administradores pueden gestionar diferentes tareas de operaciones del «día dos», tanto en la gestión como en los clústeres en sentido descendente.

  • 57 Migración edge 3.6
  • Esta sección explica cómo migrar sus clústeres management y downstream de SUSE Telco Cloud 3.5 a SUSE Telco Cloud 3.6.0.

  • 58 Clúster de gestión
  • Actualmente, existen dos formas de realizar operaciones de «Día 2» en su clúster management:

  • 59 Acciones del ciclo de vida
  • Esta sección cubre las acciones de gestión del ciclo de vida para clústeres desplegados a través de SUSE Telco Cloud.

57 Migración edge 3.6

Esta sección explica cómo migrar sus clústeres management y downstream de SUSE Telco Cloud 3.5 a SUSE Telco Cloud 3.6.0.

Importante
Importante

Realice siempre las migraciones de clúster desde la latest Z-stream release de SUSE Telco Cloud 3.5.

Migre siempre a la SUSE Telco Cloud 3.6.0 release. Para actualizaciones posteriores a la migración, consulte las management (Capítulo 58, Clúster de gestión) secciones.

La siguiente tabla enumera los diferentes tipos de clústeres y los métodos para actualizarlos:

Tabla 57.1: Clústeres y métodos para actualizar clústeres en sentido descendente
Tipo de clústerMétodo

Clústeres aprovisionados por EIB

Consulte el Sección 57.1.3, “Fleet” para obtener más información.

Clústeres aprovisionados por Metal3

Consulte Actualizaciones de clúster descendente (Sección 59.3, “Actualizaciones de clústeres descendentes”) para obtener más detalles.

57.1 Clúster de gestión

Esta sección cubre los temas siguientes:

Sección 57.1.1, “Requisitos previos” - pasos previos necesarios antes de comenzar la migración.

Sección 57.1.2, “Upgrade Controller” - cómo realizar una migración de clúster management utilizando Capítulo 21, Controlador de actualización.

Sección 57.1.3, “Fleet” - cómo realizar una migración de clúster management utilizando Capítulo 9, Fleet.

57.1.1 Requisitos previos

57.1.1.1 Actualice los CRD del Bare Metal Operator

Nota
Nota

Se aplica solo a los clústeres de gestión de CAPI/Metal3 que requieren una actualización del gráfico Capítulo 11, Metal3.

El gráfico de Helm Metal3 incluye los CRD de Bare Metal Operator (BMO) aprovechando el directorio CRD de Helm.

Sin embargo, este enfoque tiene ciertas limitaciones, en particular la imposibilidad de actualizar los CRD en este directorio mediante Helm. Para obtener más información, consulte la documentación de Helm.

Como resultado, antes de actualizar Metal3 a una versión compatible con SUSE Telco Cloud 3.6.0, los usuarios deben actualizar manualmente los CRD de BMO subyacentes.

En una máquina con Helm instalado y kubectl configurado para apuntar a su clúster management:

  1. Aplique manualmente los CRD de BMO:

    helm show crds oci://registry.suse.com/edge/charts/metal3 --version 306.0.29+up0.15.0 | kubectl apply -f -

57.1.1.2 Migrar la configuración del certificado de CA de Metal3

Nota
Nota

Se aplica solo a las implementaciones de Metal3 que utilizan CA de confianza adicionales para servidores de medios externos con TLS.

El gráfico de Helm de Metal3 ha cambiado la forma en que se configuran los certificados de CA de confianza. Anteriormente, las CA adicionales se proporcionaban a través de un Secret (tls-ca-additional) con el indicador booleano additionalTrustedCAs. La nueva versión utiliza un ConfigMap que contiene el paquete de CA completo al que hace referencia el valor global.trustedCAs.

Si ha configurado CA de confianza adicionales para Metal3, debe migrar del enfoque basado en Secret al enfoque basado en ConfigMap:

  1. Cree un ConfigMap que contenga su paquete de CA a partir del Secret existente:

    Extraiga los certificados del Secret antiguo:

    kubectl get secret tls-ca-additional -n metal3-system -o jsonpath='{.data}' | \
      jq -r 'to_entries[] | .value' | base64 -d > ca-bundle.pem

    Opcional: incluya el paquete de CA del sistema: Si el despliegue de Metal3 también necesita confiar en CA públicas (por ejemplo, al acceder a recursos externos a través de HTTPS), debe incluir el paquete de CA del sistema además de sus CA personalizadas. Extraiga el paquete de CA del sistema de una imagen de contenedor y antepóngalo a sus CA personalizadas:

    # Extract system CAs from a container image (using podman or docker)
    podman run --rm registry.suse.com/bci/bci-base:latest cat /etc/ssl/certs/ca-certificates.crt > system-cas.pem
    
    # Combine system CAs with your custom CAs
    cat system-cas.pem ca-bundle.pem > combined-ca-bundle.pem
    mv combined-ca-bundle.pem ca-bundle.pem
    Importante
    Importante

    Si incluye el paquete de CA del sistema, es su responsabilidad mantenerlo actualizado. Los certificados de CA del sistema en la imagen de contenedor pueden quedar obsoletos con el tiempo a medida que los certificados de CA caducan o son revocados. Debe actualizar periódicamente el paquete de CA del sistema volviéndolo a extraer de una imagen de contenedor actualizada.

    Cree el ConfigMap con el paquete de CA final:

    kubectl create configmap tls-ca-bundle -n metal3-system --from-file=ca-bundle.pem=ca-bundle.pem
  2. Actualice los valores de Helm de Metal3 para utilizar la nueva referencia de ConfigMap:

    Cambie de:

    global:
      additionalTrustedCAs: true

    A:

    global:
      trustedCAs: tls-ca-bundle
  3. Tras actualizar el gráfico de Helm de Metal3 con la nueva configuración, puede eliminar el Secret antiguo:

    kubectl delete secret tls-ca-additional -n metal3-system

57.1.2 Upgrade Controller

Importante
Importante

Upgrade Controller actualmente solo admite migraciones de versiones de SUSE Telco Cloud para clústeres de gestión no en entorno aislado.

Los siguientes temas se tratan como parte de esta sección:

Sección 57.1.2.1, “Requisitos previos”: requisitos previos específicos para Upgrade Controller.

Sección 57.1.2.2, “Pasos de migración”: pasos para migrar un clúster management a una nueva versión de SUSE Telco Cloud utilizando Upgrade Controller.

57.1.2.1 Requisitos previos

57.1.2.1.1 SUSE Telco Cloud 3.6 Upgrade Controller

Antes de utilizar Upgrade Controller, debe asegurarse primero de que está ejecutando una versión capaz de migrar a la versión de SUSE Telco Cloud deseada.

Para realizar esta operación:

  1. Si ya tiene Upgrade Controller desplegado desde una versión de SUSE Telco Cloud anterior, actualice su gráfico:

    helm upgrade upgrade-controller -n upgrade-controller-system oci://registry.suse.com/edge/charts/upgrade-controller --version 306.0.4+up0.1.3
  2. Si no tiene Upgrade Controller desplegado, siga Sección 21.3, “Instalación del Controlador de actualización”.

57.1.2.2 Pasos de migración

Realizar una migración de clúster management con Upgrade Controller es fundamentalmente similar a ejecutar una actualización.

La única diferencia es que su UpgradePlan debe especificar la versión de lanzamiento 3.6.0:

apiVersion: lifecycle.suse.com/v1alpha1
kind: UpgradePlan
metadata:
  name: upgrade-plan-mgmt
  # Change to the namespace of your Upgrade Controller
  namespace: CHANGE_ME
spec:
  releaseVersion: 3.6.0

Para obtener información sobre cómo utilizar el UpgradePlan anterior para realizar una migración, consulte el proceso de actualización del Upgrade Controller (Sección 58.1, “Upgrade Controller”).

57.1.3 Fleet

Nota
Nota

Siempre que sea posible, utilice Sección 57.1.2, “Upgrade Controller” para la migración.

Consulte esta sección solo para casos de uso no cubiertos por Upgrade Controller.

Realizar una migración de clúster management con Fleet es fundamentalmente similar a ejecutar una actualización.

Las diferencias clave son que:

  1. Las flotas deben utilizarse desde la versión release-3.6.0 del repositorio suse-edge/fleet-examples.

  2. Los gráficos programados para una actualización deben actualizarse a versiones compatibles con la versión SUSE Telco Cloud 3.6.0. Para obtener una lista de los componentes SUSE Telco Cloud 3.6.0, consulte Sección 75.4, “Versión 3.6.0”.

Importante
Importante

Para garantizar una migración SUSE Telco Cloud 3.6.0 correcta, es importante que los usuarios cumplan los puntos indicados anteriormente.

57.2 Clústeres descendentes

Sección 57.2.1, “Fleet” - cómo realizar una migración de clúster downstream utilizando Capítulo 9, Fleet.

57.2.1 Fleet

Realizar una migración de clúster downstream con Fleet es fundamentalmente similar a ejecutar una actualización.

Las diferencias clave son que:

  1. Las flotas deben utilizarse desde la versión release-3.6.0 del repositorio suse-edge/fleet-examples.

  2. Los gráficos programados para una actualización deben actualizarse a versiones compatibles con la versión SUSE Telco Cloud 3.6.0. Para obtener una lista de los componentes SUSE Telco Cloud 3.6.0, consulte Sección 75.4, “Versión 3.6.0”.

Importante
Importante

Para garantizar una migración SUSE Telco Cloud 3.6.0 correcta, es importante que los usuarios cumplan los puntos indicados anteriormente.

58 Clúster de gestión

Actualmente, existen dos formas de realizar operaciones de «Día 2» en su clúster management:

58.1 Upgrade Controller

Importante
Importante

El Upgrade Controller actualmente solo admite operaciones Day 2 para clústeres de gestión sin entorno aislado.

Esta sección cubre cómo realizar las diversas operaciones de Day 2 relacionadas con la actualización de su clúster management de una versión de plataforma SUSE Telco Cloud a otra.

Las operaciones de Day 2 están automatizadas por el Upgrade Controller (Capítulo 21, Controlador de actualización) e incluyen:

58.1.1 Requisitos previos

Antes de actualizar su clúster management, se deben cumplir los siguientes requisitos previos:

  1. SCC registered nodes - asegúrese de que el SO de los nodos de su clúster esté registrado con una clave de suscripción que admita la versión del SO especificada en la SUSE Telco Cloud release (Capítulo 75, Notas de la versión) a la que pretende actualizar.

  2. Upgrade Controller - asegúrese de que el Upgrade Controller se haya desplegado en su clúster management. Para conocer los pasos de instalación, consulte Sección 21.3, “Instalación del Controlador de actualización”.

58.1.2 Actualización

  1. Determine la versión de SUSE Telco Cloud release (Capítulo 75, Notas de la versión) a la que desea actualizar su clúster management.

  2. En el clúster management, despliegue un UpgradePlan que especifique la release version deseada. El UpgradePlan debe desplegarse en el espacio de nombres del Upgrade Controller.

    kubectl apply -n <upgrade_controller_namespace> -f - <<EOF
    apiVersion: lifecycle.suse.com/v1alpha1
    kind: UpgradePlan
    metadata:
      name: upgrade-plan-mgmt
    spec:
      # Version retrieved from release notes
      releaseVersion: 3.X.Y
    EOF
    Nota
    Nota

    Puede haber casos de uso en los que desee realizar configuraciones adicionales sobre el UpgradePlan. Para todas las configuraciones posibles, consulte Sección 21.6.1, “UpgradePlan”.

  3. El despliegue del UpgradePlan en el espacio de nombres Upgrade Controller’s iniciará el upgrade process.

    Nota
    Nota

    Para obtener más información sobre el upgrade process real, consulte Sección 21.5, “¿Cómo funciona el Controlador de actualización?”.

    Para obtener información sobre cómo realizar el seguimiento del upgrade process, consulte Sección 21.7, “Seguimiento del proceso de actualización”.

58.1.3 Pasos posteriores a la actualización

Las actualizaciones de SUSE Telco Cloud desde la última versión z-stream de 3.5 a 3.6.0 pueden requerir algunos pasos manuales finales que deben realizarse después de que el Upgrade Controller haya completado el proceso de actualización. Estos están relacionados con la sustitución de Ingress-NGINX por Traefik como el único controlador de entrada admitido en SUSE Telco Cloud a partir de la versión 3.6.

Nota
Nota

El proveedor de entrada Traefik integrado en RKE2/K3s es el único controlador de entrada admitido en la versión SUSE Telco Cloud 3.6, siendo todavía posible ejecutar temporalmente Ingress-NGINX junto con Traefik para admitir escenarios complejos de migración de entrada, pero solo después de que los clústeres de gestión y/o sentido descendente SUSE Telco Cloud se hayan actualizado a la versión 3.6 y durante el tiempo necesario para realizar dicha migración.

La guía de RKE2 Migración de Ingress NGINX a Traefik proporciona detalles sobre las rutas de migración de entrada disponibles una vez que el controlador de entrada Traefik sustituya al Ingress-NGINX discontinuado.

En caso de que el clúster de gestión recién actualizado no estuviera ejecutando el controlador de entrada Traefik (sino el predeterminado Ingress-NGINX) antes de iniciar la actualización, ahora es necesario desplegar manualmente Traefik.

Primero vamos a asegurarnos de que la instancia de ingress-NGINX implementada esté configurada correctamente (por ejemplo, para evitar colisiones innecesarias de hostPort entre los pods de los dos controladores de entrada):

kubectl apply -f - <<- EOF
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-ingress-nginx
  namespace: kube-system
spec:
  valuesContent: |-
    controller:
      hostPort:
        enabled: false  # not needed when exposing through a type:LoadBalancer service
      config:
        use-forwarded-headers: "true"
        enable-real-ip: "true"
      publishService:
        enabled: true
      service:
        enabled: true
        type: LoadBalancer
        externalTrafficPolicy: Local
EOF

Ahora podemos proceder con el despliegue de Traefik, mediante la instalación de los gráficos de Helm rke2-traefik-crd y rke2-traefik.

Nota
Nota

Despliegue estos gráficos de Helm a través de manifiestos HelmChart, como se muestra a continuación, para asegurar que Upgrade Controller se encargue también de actualizar estos gráficos de Helm en futuras actualizaciones del clúster de gestión.

kubectl apply -f - <<- EOF
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: rke2-traefik-crd
  namespace: kube-system
spec:
  chart: rke2-traefik-crd
  version: {rke2-traefik-crd Helm chart version}
  repo: https://rke2-charts.rancher.io
  bootstrap: false
  failurePolicy: reinstall
  backOffLimit: 20
  targetNamespace: kube-system
  set:
    global.cattle.systemDefaultRegistry: registry.rancher.com
    global.rke2DataDir: /var/lib/rancher/rke2
    global.systemDefaultRegistry: registry.rancher.com
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: rke2-traefik
  namespace: kube-system
spec:
  chart: rke2-traefik
  version: {rke2-traefik Helm chart version}
  repo: https://rke2-charts.rancher.io
  bootstrap: false
  failurePolicy: reinstall
  backOffLimit: 20
  targetNamespace: kube-system
  set:
    global.cattle.systemDefaultRegistry: registry.rancher.com
    global.rke2DataDir: /var/lib/rancher/rke2
    global.systemDefaultRegistry: registry.rancher.com
  valuesContent: |-
    ingressClass:
      isDefaultClass: false  # if traefik deployed alongside ingress-nginx
    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
    providers:
      kubernetesIngressNginx:  # this provider allows traefik to "understand" most of the ingress-nginx annotations
        enabled: true
        ingressClass: "rke2-ingress-nginx-migration"
        controllerClass: "rke2.​cattle.​io/ingress-nginx-migration"
EOF

El {rke2-traefik-crd Helm chart version} y el {rke2-traefik-crd Helm chart version} son los dictados por la versión de RKE2/k3s a la que hemos actualizado.

En el último paso, creamos finalmente los objetos necesarios de MetalLB para exponer el servicio Traefik a través de un servicio de tipo LoadBalancer:

kubectl apply -f - <<- EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ingress-ippool-traefik
  namespace: metallb-system
spec:
  addresses:
  - {EXTERNAL_IP_FOR_TRAEFIK_SERVICE}/32
  serviceAllocation:
    priority: 100
    serviceSelectors:
    - matchExpressions:
      - {key: app.kubernetes.io/name, operator: In, values: [rke2-traefik]}
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ingress-l2-adv-traefik
  namespace: metallb-system
spec:
  ipAddressPools:
  - ingress-ippool-traefik
EOF

Ahora tanto Traefik como Ingress-NGINX se ejecutan simultáneamente, lo que le permite realizar de forma segura la migración necesaria de sus ingresses de uno a otro.

Importante
Importante

Una vez que todos los ingresses se hayan migrado y ya no necesite Ingress-NGINX, asegúrese de desinstalarlo y limpiar todos los recursos relacionados para evitar cualquier consumo innecesario de recursos en su clúster.

58.2 Fleet

Esta sección ofrece información sobre cómo realizar operaciones de «Día 2» utilizando el componente Fleet (Capítulo 9, Fleet).

Los siguientes temas se tratan como parte de esta sección:

  1. Sección 58.2.1, “Componentes” - componentes predeterminados utilizados para todas las operaciones de «Día 2».

  2. Sección 58.2.2, “Determinad vuestro caso de uso” - proporciona una visión general de los recursos personalizados de Fleet que se utilizarán y su idoneidad para diferentes casos de uso de operaciones de «Día 2».

  3. Sección 58.2.3, “Flujo de trabajo de Día 2” - proporciona una guía de flujo de trabajo para ejecutar operaciones de «Día 2» con Fleet.

  4. Sección 58.2.4, “Actualización del SO” - describe cómo realizar actualizaciones del SO utilizando Fleet.

  5. Sección 58.2.5, “Actualización de la versión de Kubernetes” - describe cómo realizar actualizaciones de la versión de Kubernetes utilizando Fleet.

  6. Sección 58.2.6, “Actualización de Helm chart” - describe cómo realizar actualizaciones de Helm charts utilizando Fleet.

58.2.1 Componentes

A continuación, podéis encontrar una descripción de los componentes predeterminados que deben configurarse en vuestro clúster management para que podáis realizar con éxito operaciones de «Día 2» utilizando Fleet.

58.2.1.1 Rancher

Opcional; responsable de gestionar downstream clusters y desplegar System Upgrade Controller en vuestro management cluster.

Para obtener más información, consulte el Capítulo 6, Rancher.

58.2.1.2 System Upgrade Controller (SUC)

System Upgrade Controller es responsable de ejecutar tareas en nodos especificados basándose en los datos de configuración proporcionados a través de un recurso personalizado, llamado Plan.

SUC se utiliza activamente para actualizar el sistema operativo y la distribución de Kubernetes.

Para obtener más información sobre el componente SUC y cómo encaja en la pila Edge, consultad Capítulo 20, Controlador de actualización del sistema.

58.2.2 Determinad vuestro caso de uso

Fleet utiliza dos tipos de recursos personalizados para permitir la gestión de recursos de Kubernetes y Helm.

A continuación, podéis encontrar información sobre el propósito de estos recursos y los casos de uso para los que son más adecuados en el contexto de las operaciones de «Día 2».

58.2.2.1 GitRepo

Un GitRepo es un recurso de Fleet (Capítulo 9, Fleet) que representa un repositorio Git desde el cual Fleet puede crear Bundles. Cada Bundle se crea en función de las rutas de configuración definidas dentro del recurso GitRepo. Para obtener más información, consultad la documentación de GitRepo.

En el contexto de las operaciones de «Día 2», los recursos GitRepo se utilizan normalmente para desplegar SUC o SUC Plans en entornos no aislados que utilizan un enfoque de Fleet GitOps.

Alternativamente, los recursos GitRepo también pueden utilizarse para desplegar SUC o SUC Plans en entornos aislados, siempre que reflejéis la configuración de vuestro repositorio a través de un servidor git local.

58.2.2.2 Bundle

Bundles contienen recursos de Kubernetes sin procesar que se implementarán en el clúster de destino. Normalmente se crean a partir de un recurso GitRepo, pero existen casos de uso en los que se pueden desplegar manualmente. Para obtener más información, consultad la documentación de Bundle.

En el contexto de las operaciones de "Día 2", los recursos Bundle se utilizan normalmente para desplegar SUC o SUC Plans en entornos aislados que no utilizan ningún tipo de procedimiento de GitOps local (por ejemplo, un servidor git local).

Alternativamente, si vuestro caso de uso no permite un flujo de trabajo GitOps (por ejemplo, mediante un repositorio Git), los recursos Bundle también podrían utilizarse para desplegar SUC o SUC Plans en entornos no aislados.

58.2.3 Flujo de trabajo de Día 2

A continuación se muestra un flujo de trabajo de «Día 2» que debe seguirse al actualizar la versión de un clúster management a una versión específica de Edge.

  1. Actualización de versión del SO (Sección 58.2.4, “Actualización del SO”)

  2. Actualización de versión de Kubernetes (Sección 58.2.5, “Actualización de la versión de Kubernetes”)

  3. Actualización de versión de Helm charts (Sección 58.2.6, “Actualización de Helm chart”)

58.2.4 Actualización del SO

Esta sección describe cómo realizar una actualización del sistema operativo utilizando Capítulo 9, Fleet y Capítulo 20, Controlador de actualización del sistema.

Los siguientes temas se tratan como parte de esta sección:

  1. Sección 58.2.4.1, “Componentes” - componentes adicionales utilizados por el proceso de actualización.

  2. Sección 58.2.4.2, “Descripción general” - descripción general del proceso de actualización.

  3. Sección 58.2.4.3, “Requisitos” - requisitos del proceso de actualización.

  4. Sección 58.2.4.4, “Actualización del SO - Ampliación del plan SUC” - información sobre cómo desplegar SUC plans, responsable de activar el proceso de actualización.

58.2.4.1 Componentes

Esta sección cubre los componentes personalizados que utiliza el proceso OS upgrade sobre los componentes predeterminados (Sección 58.2.1, “Componentes”) de «Día 2».

58.2.4.1.1 systemd.service

La actualización del SO en un nodo específico se gestiona mediante un systemd.service.

Se crea un servicio diferente dependiendo del tipo de actualización que requiera el SO de una versión de Edge a otra:

  • Para las versiones de Edge que requieren la misma versión de SO (p. ej., 6.1), se creará el os-pkg-update.service. Utiliza transactional-update para realizar una actualización normal de paquetes.

  • Para las versiones de Edge que requieren una migración de versión de SO (p. ej., 6.1 → 6.2), se creará el os-migration.service. Utiliza transactional-update para realizar:

    1. Una actualización normal de paquetes que garantiza que todos los paquetes estén actualizados para mitigar cualquier fallo en la migración relacionado con versiones antiguas de paquetes.

    2. Una migración de SO utilizando el comando zypper migration.

Los servicios mencionados anteriormente se envían a cada nodo a través de un SUC plan que debe estar ubicado en el clúster management que necesita una actualización del SO.

58.2.4.2 Descripción general

La actualización del sistema operativo para los nodos del clúster management se realiza utilizando Fleet y el System Upgrade Controller (SUC).

Fleet se utiliza para desplegar y gestionar SUC plans en el clúster deseado.

Nota
Nota

SUC plans son recursos personalizados que describen los pasos que SUC debe seguir para que se ejecute una tarea específica en un conjunto de nodos. Para ver un ejemplo de cómo es un SUC plan, consultad el repositorio upstream.

Los OS SUC plans se envían a cada clúster desplegando un recurso GitRepo o Bundle en un espacio de trabajo de Fleet específico. Fleet recupera el GitRepo/Bundle desplegado y despliega su contenido (el OS SUC plans) en el clúster o clústeres deseados.

Nota
Nota

Los recursos GitRepo/Bundle siempre se despliegan en el management cluster. Si utilizar un recurso GitRepo o Bundle depende de vuestro caso de uso, consultad Sección 58.2.2, “Determinad vuestro caso de uso” para obtener más información.

OS SUC plans describe el siguiente flujo de trabajo:

  1. Acordonad siempre los nodos antes de las actualizaciones del SO.

  2. Actualizad siempre los nodos control-plane antes que los nodos worker.

  3. Actualizad siempre el clúster uno a uno.

Una vez que los OS SUC plans se hayan desplegado, el flujo de trabajo tiene este aspecto:

  1. SUC reconcilia los OS SUC plans desplegados y crea un Kubernetes Job en cada nodo.

  2. El Kubernetes Job crea un systemd.service (Sección 58.2.4.1.1, “systemd.service”) para la actualización de paquetes o la migración del SO.

  3. El systemd.service creado activa el proceso de actualización del SO en el nodo específico.

    Importante
    Importante

    Una vez que finalice el proceso de actualización del SO, el nodo correspondiente se rebooted para aplicar las actualizaciones en el sistema.

A continuación podéis encontrar un diagrama de la descripción anterior:

fleet day2 management os upgrade

58.2.4.3 Requisitos

General:

  1. Máquina registrada en SCC - Todos los management nodos del clúster deben estar registrados en https://scc.suse.com/, lo cual es necesario para que el systemd.service correspondiente pueda conectarse correctamente al repositorio RPM deseado.

    Importante
    Importante

    Para las versiones Edge que requieran una migración de la versión del SO (p. ej., 6.1 → 6.2), aseguraos de que vuestra clave SCC admita la migración a la nueva versión.

  2. Aseguraos de que las tolerancias del plan SUC coincidan con las tolerancias de los nodos - Si los nodos de vuestro clúster de Kubernetes tienen taints personalizados, aseguraos de añadir tolerancias para esas taints en los planes SUC. Por defecto, los planes SUC solo tienen tolerancias para los nodos del plano de control. Las tolerancias por defecto incluyen:

    • CriticalAddonsOnly=true:NoExecute

    • node-role.kubernetes.io/control-plane:NoSchedule

    • node-role.kubernetes.io/etcd:NoExecute

      Nota
      Nota

      Cualquier tolerancia adicional debe añadirse bajo la sección .spec.tolerations de cada plan. Los planes SUC relacionados con la actualización del SO se pueden encontrar en el repositorio suse-edge/fleet-examples bajo fleets/day2/system-upgrade-controller-plans/os-upgrade. Aseguraos de utilizar los planes de una etiqueta de versión de repositorio válida.

      Un ejemplo de cómo definir tolerancias personalizadas para el plan SUC de plano de control sería el siguiente:

      apiVersion: upgrade.cattle.io/v1
      kind: Plan
      metadata:
        name: os-upgrade-control-plane
      spec:
        ...
        tolerations:
        # default tolerations
        - key: "CriticalAddonsOnly"
          operator: "Equal"
          value: "true"
          effect: "NoExecute"
        - key: "node-role.kubernetes.io/control-plane"
          operator: "Equal"
          effect: "NoSchedule"
        - key: "node-role.kubernetes.io/etcd"
          operator: "Equal"
          effect: "NoExecute"
        # custom toleration
        - key: "foo"
          operator: "Equal"
          value: "bar"
          effect: "NoSchedule"
      ...

Entorno aislado:

  1. Duplicar repositorios RPM de SUSE - Los repositorios RPM del SO deben estar duplicados localmente para que el systemd.service pueda tener acceso a ellos. Esto se puede lograr utilizando RMT o SUMA.

58.2.4.4 Actualización del SO - Ampliación del plan SUC

Importante
Importante

Para los entornos actualizados previamente mediante este procedimiento, los usuarios deben asegurarse de que se complete uno de los siguientes pasos:

  • Remove any previously deployed SUC Plans related to older Edge release versions from the management cluster - se puede realizar eliminando el clúster deseado de la GitRepo/Bundle configuración de destino existente, o eliminando el recurso GitRepo/Bundle por completo.

  • Reuse the existing GitRepo/Bundle resource - se puede realizar apuntando la revisión del recurso a una nueva etiqueta que contenga las flotas correctas para la suse-edge/fleet-examples release deseada.

Esto se hace para evitar conflictos entre SUC Plans para versiones de release de Edge anteriores.

Si los usuarios intentan actualizar mientras existen SUC Plans en el clúster management, verán el siguiente error de fleet:

Not installed: Unable to continue with install: Plan <plan_name> in namespace <plan_namespace> exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error..

Como se menciona en Sección 58.2.4.2, “Descripción general”, las actualizaciones del SO se realizan enviando SUC plans al clúster deseado a través de una de las siguientes formas:

Para determinar qué recurso debéis utilizar, consultad Sección 58.2.2, “Determinad vuestro caso de uso”.

Para casos de uso en los que deseéis desplegar el OS SUC plans desde una herramienta GitOps de terceros, consultad Sección 58.2.4.4.3, “Despliegue del plan SUC: flujo de trabajo GitOps de terceros”

58.2.4.4.1 Ampliación del plan SUC - Recurso GitRepo

Un recurso GitRepo, que envía el OS SUC plans necesario, puede desplegarse de una de las siguientes formas:

  1. A través del Rancher UI - Sección 58.2.4.4.1.1, “Creación de GitRepo - Interfaz de usuario de Rancher” (cuando Rancher esté disponible).

  2. Mediante desplegar manualmente (Sección 58.2.4.4.1.2, “Creación de GitRepo - manual”) el recurso en vuestro management cluster.

Una vez desplegado, para supervisar el proceso de actualización del SO de los nodos de vuestro clúster de destino, consultad Sección 20.3, “Monitorización de los planes del controlador de actualización del sistema”.

58.2.4.4.1.1 Creación de GitRepo - Interfaz de usuario de Rancher

Para crear un recurso GitRepo a través de la interfaz de usuario de Rancher, seguid su documentación oficial.

El equipo de Edge mantiene un fleet listo para usar. Dependiendo de vuestro entorno, este fleet podría utilizarse directamente o como plantilla.

Importante
Importante

Utilizad siempre este fleet a partir de una etiqueta de release de Edge válida.

Para casos de uso en los que no sea necesario incluir cambios personalizados en el SUC plans que distribuye el fleet, referenciad directamente el fleet os-upgrade desde el repositorio suse-edge/fleet-examples.

En los casos en los que se necesiten cambios personalizados (por ejemplo, para añadir tolerancias personalizadas), referenciad el fleet os-upgrade desde un repositorio independiente, lo que os permite añadir los cambios a los planes SUC según sea necesario.

Podéis ver un ejemplo de cómo se puede configurar un GitRepo para utilizar el fleet del repositorio suse-edge/fleet-examples aquí.

58.2.4.4.1.2 Creación de GitRepo - manual
  1. Extraed el recurso GitRepo:

    curl -o os-upgrade-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/gitrepos/day2/os-upgrade-gitrepo.yaml
  2. Edita la configuración de GitRepo:

    • Elimina la sección spec.targets: solo es necesaria para los clústeres en sentido descendente.

      # Example using sed
      sed -i.bak '/^  targets:/,$d' os-upgrade-gitrepo.yaml && rm -f os-upgrade-gitrepo.yaml.bak
      
      # Example using yq (v4+)
      yq eval 'del(.spec.targets)' -i os-upgrade-gitrepo.yaml
    • Apunta el espacio de nombres del GitRepo al espacio de nombres fleet-local: se hace para desplegar el recurso en el clúster de gestión.

      # Example using sed
      sed -i.bak 's/namespace: fleet-default/namespace: fleet-local/' os-upgrade-gitrepo.yaml && rm -f os-upgrade-gitrepo.yaml.bak
      
      # Example using yq (v4+)
      yq eval '.metadata.namespace = "fleet-local"' -i os-upgrade-gitrepo.yaml
  3. Aplica el recurso GitRepo en tu management cluster:

    kubectl apply -f os-upgrade-gitrepo.yaml
  4. Visualiza el recurso GitRepo creado bajo el espacio de nombres fleet-local:

    kubectl get gitrepo os-upgrade -n fleet-local
    
    # Example output
    NAME            REPO                                              COMMIT         BUNDLEDEPLOYMENTS-READY   STATUS
    os-upgrade      https://github.com/suse-edge/fleet-examples.git   release-3.6.1  0/0
58.2.4.4.2 Despliegue del plan SUC - Recurso Bundle

Un recurso Bundle, que incluye los OS SUC Plans necesarios, puede desplegarse de una de las siguientes maneras:

  1. A través del Rancher UI - Sección 58.2.4.4.2.1, “Creación de Bundle - Interfaz de usuario de Rancher” (cuando Rancher esté disponible).

  2. Mediante el despliegue manual (Sección 58.2.4.4.2.2, “Creación de bundle - manual”) del recurso en tu management cluster.

Una vez desplegado, para supervisar el proceso de actualización del SO de los nodos de tu clúster de destino, consulta Sección 20.3, “Monitorización de los planes del controlador de actualización del sistema”.

58.2.4.4.2.1 Creación de Bundle - Interfaz de usuario de Rancher

El equipo de Edge mantiene un bundle listo para usar que puede utilizarse en los pasos siguientes.

Importante
Importante

Utiliza siempre este bundle a partir de una etiqueta de release de Edge válida.

Para crear un bundle a través de la interfaz de usuario de Rancher:

  1. En la esquina superior izquierda, haz clic en ☰ → Continuous Delivery

  2. Ve a Avanzado > Bundles

  3. Selecciona Crear a partir de YAML

  4. Desde aquí puedes crear el Bundle de una de las siguientes maneras:

    Nota
    Nota

    Puede haber casos de uso en los que necesites incluir cambios personalizados en el SUC plans que incorpora el bundle (por ejemplo, para añadir tolerancias personalizadas). Asegúrate de incluir esos cambios en el bundle que se generará mediante los pasos siguientes.

    1. Copiando manualmente el contenido del bundle desde suse-edge/fleet-examples a la página Crear a partir de YAML.

    2. Clonando el repositorio suse-edge/fleet-examples desde la etiqueta de release deseada y seleccionando la opción Leer desde archivo en la página Crear a partir de YAML. Desde ahí, navega a la ubicación del bundle (bundles/day2/system-upgrade-controller-plans/os-upgrade) y selecciona el archivo del bundle. Esto rellenará automáticamente la página Crear a partir de YAML con el contenido del bundle.

  5. Edita el bundle en la interfaz de usuario de Rancher:

    • Cambia el espacio de nombres del Bundle para que apunte al espacio de nombres fleet-local.

      # Example
      kind: Bundle
      apiVersion: fleet.cattle.io/v1alpha1
      metadata:
        name: os-upgrade
        namespace: fleet-local
      ...
    • Cambia los clústeres target del Bundle para que apunten a tu clúster local (gestión):

      spec:
        targets:
        - clusterName: local
      Nota
      Nota

      Existen algunos casos de uso en los que tu clúster local podría tener un nombre diferente.

      Para recuperar el nombre de tu clúster local, ejecuta el comando siguiente:

      kubectl get clusters.fleet.cattle.io -n fleet-local
  6. Selecciona Crear

58.2.4.4.2.2 Creación de bundle - manual
  1. Obtén el recurso Bundle:

    curl -o os-upgrade-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/bundles/day2/system-upgrade-controller-plans/os-upgrade/os-upgrade-bundle.yaml
  2. Editad la configuración del Bundle:

    • Cambia los clústeres target del Bundle para que apunten a tu clúster local (gestión):

      spec:
        targets:
        - clusterName: local
      Nota
      Nota

      Existen algunos casos de uso en los que tu clúster local podría tener un nombre diferente.

      Para recuperar el nombre de tu clúster local, ejecuta el comando siguiente:

      kubectl get clusters.fleet.cattle.io -n fleet-local
    • Cambia el espacio de nombres del Bundle para que apunte al espacio de nombres fleet-local.

      # Example
      kind: Bundle
      apiVersion: fleet.cattle.io/v1alpha1
      metadata:
        name: os-upgrade
        namespace: fleet-local
      ...
  3. Aplica el recurso Bundle a tu management cluster:

    kubectl apply -f os-upgrade-bundle.yaml
  4. Visualiza el recurso Bundle creado en el espacio de nombres fleet-local:

    kubectl get bundles -n fleet-local
58.2.4.4.3 Despliegue del plan SUC: flujo de trabajo GitOps de terceros

Puede haber casos de uso en los que desees incorporar el OS SUC plans a tu propio flujo de trabajo GitOps de terceros (p. ej., Flux).

Para obtener los recursos de actualización del SO que necesitas, primero determina la etiqueta de release de Edge del repositorio suse-edge/fleet-examples que desees utilizar.

Después de eso, los recursos se pueden encontrar en fleets/day2/system-upgrade-controller-plans/os-upgrade, donde:

  • plan-control-plane.yaml es un recurso de plan SUC para nodos de control-plane.

  • plan-worker.yaml es un recurso de plan SUC para nodos worker.

  • secret.yaml es un Secret que contiene el script upgrade.sh, el cual es responsable de crear el systemd.service (Sección 58.2.4.1.1, “systemd.service”).

  • config-map.yaml es un ConfigMap que contiene la configuración que consume el script upgrade.sh.

Importante
Importante

Estos recursos Plan son interpretados por el System Upgrade Controller y deben desplegarse en cada clúster descendente que desees actualizar. Para obtener información sobre el despliegue de SUC, consulta Sección 20.2, “Instalación del controlador de actualización del sistema”.

Para comprender mejor cómo puede utilizar tu flujo de trabajo GitOps para desplegar los SUC Plans para la actualización del SO, puede resultar útil echar un vistazo a visión general (Sección 58.2.4.2, “Descripción general”).

58.2.5 Actualización de la versión de Kubernetes

Esta sección describe cómo realizar una actualización de Kubernetes utilizando Capítulo 9, Fleet y Capítulo 20, Controlador de actualización del sistema.

Los siguientes temas se tratan como parte de esta sección:

  1. Sección 58.2.5.1, “Componentes” - componentes adicionales utilizados por el proceso de actualización.

  2. Sección 58.2.5.2, “Descripción general” - visión general del proceso de actualización.

  3. Sección 58.2.5.3, “Requisitos” - requisitos del proceso de actualización.

  4. Sección 58.2.5.4, “Actualización de K8s - Ampliación del plan SUC” - información sobre cómo desplegar SUC plans, responsable de activar el proceso de actualización.

58.2.5.1 Componentes

Esta sección cubre los componentes personalizados que utiliza el proceso K8s upgrade sobre los componentes (Sección 58.2.1, “Componentes”) predeterminados del "Día 2".

58.2.5.1.1 rke2-upgrade

Imagen de contenedor responsable de actualizar la versión de RKE2 de un nodo específico.

Distribuida a través de un Pod creado por SUC basado en un Plan SUC. El Plan debe estar ubicado en cada clúster que necesite una actualización de RKE2.

Para obtener más información sobre cómo la imagen rke2-upgrade realiza la actualización, consultad la documentación de sentido ascendente.

58.2.5.1.2 k3s-upgrade

Imagen de contenedor responsable de actualizar la versión de K3s de un nodo específico.

Distribuida a través de un Pod creado por SUC basado en un Plan SUC. El Plan debe estar ubicado en cada clúster que necesite una actualización de K3s.

Para obtener más información sobre cómo la imagen k3s-upgrade realiza la actualización, consultad la documentación de sentido ascendente.

58.2.5.2 Descripción general

La actualización de la distribución de Kubernetes para los nodos del clúster management se realiza utilizando Fleet y System Upgrade Controller (SUC).

Fleet se utiliza para desplegar y gestionar SUC plans en el clúster deseado.

Nota
Nota

SUC plans son recursos personalizados que describen los pasos que SUC debe seguir para que se ejecute una tarea específica en un conjunto de nodos. Para ver un ejemplo de cómo es un SUC plan, consultad el repositorio de sentido ascendente.

Los K8s SUC plans se distribuyen en cada clúster desplegando un recurso GitRepo o Bundle en un espacio de trabajo de Fleet específico. Fleet recupera el GitRepo/Bundle desplegado y despliega su contenido (el K8s SUC plans) en el clúster o clústeres deseados.

Nota
Nota

Los recursos GitRepo/Bundle se despliegan siempre en el management cluster. El uso de un recurso GitRepo o Bundle depende de su caso de uso; consulte Sección 58.2.2, “Determinad vuestro caso de uso” para obtener más información.

K8s SUC plans describen el siguiente flujo de trabajo:

  1. Acordonad siempre los nodos antes de actualizar la versión de K8s.

  2. Actualizad siempre los nodos control-plane antes que los nodos worker.

  3. Actualizad siempre los nodos control-plane de uno en uno y los nodos worker de dos en dos.

Una vez desplegados los K8s SUC plans, el flujo de trabajo es el siguiente:

  1. SUC reconcilia el K8s SUC plans desplegado y crea un Kubernetes Job en cada nodo.

  2. Dependiendo de la distribución de Kubernetes, el Job creará un Pod que ejecute la imagen de contenedor rke2-upgrade (Sección 58.2.5.1.1, “rke2-upgrade”) o k3s-upgrade (Sección 58.2.5.1.2, “k3s-upgrade”).

  3. El Pod creado seguirá el siguiente flujo de trabajo:

    1. Reemplazad el binario rke2/k3s existente en el nodo por el de la imagen rke2-upgrade/k3s-upgrade.

    2. Matad el proceso rke2/k3s en ejecución.

  4. Matar el proceso rke2/k3s provoca un reinicio, lo que lanza un nuevo proceso que ejecuta el binario actualizado, dando lugar a una versión de distribución de Kubernetes actualizada.

A continuación podéis encontrar un diagrama de la descripción anterior:

fleet day2 management k8s upgrade

58.2.5.3 Requisitos

  1. Haced una copia de seguridad de vuestra distribución de Kubernetes:

    1. Para clústeres RKE2, consultad la documentación de copia de seguridad y restauración de RKE2.

    2. Para clústeres K3s, consultad la documentación de copia de seguridad y restauración de K3s.

  2. Aseguraos de que las tolerancias del Plan SUC coincidan con las tolerancias del nodo - Si los nodos de vuestro clúster de Kubernetes tienen taints personalizados, aseguraos de añadir tolerancias para esas taints en los Planes SUC. Por defecto, los Planes SUC solo tienen tolerancias para los nodos del plano de control. Las tolerancias predeterminadas incluyen:

    • CriticalAddonsOnly=true:NoExecute

    • node-role.kubernetes.io/control-plane:NoSchedule

    • node-role.kubernetes.io/etcd:NoExecute

      Nota
      Nota

      Cualquier tolerancia adicional debe añadirse en la sección .spec.tolerations de cada Plan. Los Planes SUC relacionados con la actualización de versión de Kubernetes se pueden encontrar en el repositorio suse-edge/fleet-examples en:

      • Para RKE2 - fleets/day2/system-upgrade-controller-plans/rke2-upgrade

      • Para K3s - fleets/day2/system-upgrade-controller-plans/k3s-upgrade

      Aseguraos de utilizar los Planes de una etiqueta de versión de repositorio válida.

      Un ejemplo de cómo definir tolerancias personalizadas para el Plan SUC del plano de control de RKE2 tendría este aspecto:

      apiVersion: upgrade.cattle.io/v1
      kind: Plan
      metadata:
        name: rke2-upgrade-control-plane
      spec:
        ...
        tolerations:
        # default tolerations
        - key: "CriticalAddonsOnly"
          operator: "Equal"
          value: "true"
          effect: "NoExecute"
        - key: "node-role.kubernetes.io/control-plane"
          operator: "Equal"
          effect: "NoSchedule"
        - key: "node-role.kubernetes.io/etcd"
          operator: "Equal"
          effect: "NoExecute"
        # custom toleration
        - key: "foo"
          operator: "Equal"
          value: "bar"
          effect: "NoSchedule"
      ...

58.2.5.4 Actualización de K8s - Ampliación del plan SUC

Importante
Importante

Para entornos actualizados previamente mediante este procedimiento, los usuarios deben asegurarse de que se completa uno de los siguientes pasos:

  • Remove any previously deployed SUC Plans related to older Edge release versions from the management cluster - se puede hacer eliminando el clúster deseado de la GitRepo/Bundle configuración de destino existente, o eliminando el recurso GitRepo/Bundle por completo.

  • Reuse the existing GitRepo/Bundle resource - se puede hacer apuntando la revisión del recurso a una nueva etiqueta que contenga las flotas correctas para la suse-edge/fleet-examples versión deseada.

Esto se hace para evitar conflictos entre SUC Plans para versiones de lanzamiento de Edge más antiguas.

Si los usuarios intentan actualizar mientras existen SUC Plans en el clúster management, verán el siguiente error de flota:

Not installed: Unable to continue with install: Plan <plan_name> in namespace <plan_namespace> exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error..

Como se menciona en Sección 58.2.5.2, “Descripción general”, las actualizaciones de Kubernetes se realizan enviando SUC plans al clúster deseado a través de una de las siguientes formas:

Para determinar qué recurso debéis utilizar, consultad Sección 58.2.2, “Determinad vuestro caso de uso”.

Para casos de uso en los que deseéis desplegar el K8s SUC plans desde una herramienta GitOps de terceros, consultad Sección 58.2.5.4.3, “Ampliación del plan SUC: flujo de trabajo GitOps de terceros”

58.2.5.4.1 Ampliación del plan SUC - recurso GitRepo

Se puede desplegar un recurso GitRepo, que envía los K8s SUC plans necesarios, de una de las siguientes maneras:

  1. A través de Rancher UI - Sección 58.2.5.4.1.1, “Creación de GitRepo - Interfaz de usuario de Rancher” (cuando Rancher esté disponible).

  2. Mediante el despliegue manual (Sección 58.2.5.4.1.2, “Creación de GitRepo - manual”) del recurso en vuestro management cluster.

Una vez desplegado, para supervisar el proceso de actualización de Kubernetes de los nodos de vuestro clúster de destino, consultad Sección 20.3, “Monitorización de los planes del controlador de actualización del sistema”.

58.2.5.4.1.1 Creación de GitRepo - Interfaz de usuario de Rancher

Para crear un recurso GitRepo a través de la interfaz de usuario de Rancher, seguid su documentación oficial.

El equipo de Edge mantiene flotas listas para usar tanto para las distribuciones de Kubernetes rke2 como k3s. Dependiendo de vuestro entorno, esta flota podría utilizarse directamente o como plantilla.

Importante
Importante

Utilizad siempre estas flotas a partir de una etiqueta de versión de Edge válida.

Para casos de uso en los que no sea necesario incluir cambios personalizados en los SUC plans que envían estas flotas, los usuarios pueden referenciar directamente las flotas desde el repositorio suse-edge/fleet-examples.

En los casos en los que se necesiten cambios personalizados (p. ej., para añadir tolerancias personalizadas), los usuarios deben referenciar las flotas desde un repositorio independiente, lo que les permite añadir los cambios a los planes de SUC según sea necesario.

Ejemplos de configuración para un recurso GitRepo utilizando las flotas del repositorio suse-edge/fleet-examples:

58.2.5.4.1.2 Creación de GitRepo - manual
  1. Obtened el recurso GitRepo:

    • Para clústeres RKE2:

      curl -o rke2-upgrade-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/gitrepos/day2/rke2-upgrade-gitrepo.yaml
    • Para clústeres K3s:

      curl -o k3s-upgrade-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/gitrepos/day2/k3s-upgrade-gitrepo.yaml
  2. Editad la configuración del GitRepo:

    • Eliminad la sección spec.targets, solo es necesaria para los clústeres de sentido descendente.

      • Para RKE2:

        # Example using sed
        sed -i.bak '/^  targets:/,$d' rke2-upgrade-gitrepo.yaml && rm -f rke2-upgrade-gitrepo.yaml.bak
        
        # Example using yq (v4+)
        yq eval 'del(.spec.targets)' -i rke2-upgrade-gitrepo.yaml
      • Para K3s:

        # Example using sed
        sed -i.bak '/^  targets:/,$d' k3s-upgrade-gitrepo.yaml && rm -f k3s-upgrade-gitrepo.yaml.bak
        
        # Example using yq (v4+)
        yq eval 'del(.spec.targets)' -i k3s-upgrade-gitrepo.yaml
    • Apuntad el espacio de nombres del GitRepo al espacio de nombres fleet-local; esto se hace para desplegar el recurso en el clúster de gestión.

      • Para RKE2:

        # Example using sed
        sed -i.bak 's/namespace: fleet-default/namespace: fleet-local/' rke2-upgrade-gitrepo.yaml && rm -f rke2-upgrade-gitrepo.yaml.bak
        
        # Example using yq (v4+)
        yq eval '.metadata.namespace = "fleet-local"' -i rke2-upgrade-gitrepo.yaml
      • Para K3s:

        # Example using sed
        sed -i.bak 's/namespace: fleet-default/namespace: fleet-local/' k3s-upgrade-gitrepo.yaml && rm -f k3s-upgrade-gitrepo.yaml.bak
        
        # Example using yq (v4+)
        yq eval '.metadata.namespace = "fleet-local"' -i k3s-upgrade-gitrepo.yaml
  3. Aplicad los recursos GitRepo a vuestro management cluster:

    # RKE2
    kubectl apply -f rke2-upgrade-gitrepo.yaml
    
    # K3s
    kubectl apply -f k3s-upgrade-gitrepo.yaml
  4. Visualizad el recurso GitRepo creado en el espacio de nombres fleet-local:

    # RKE2
    kubectl get gitrepo rke2-upgrade -n fleet-local
    
    # K3s
    kubectl get gitrepo k3s-upgrade -n fleet-local
    
    # Example output
    NAME           REPO                                              COMMIT          BUNDLEDEPLOYMENTS-READY   STATUS
    k3s-upgrade    https://github.com/suse-edge/fleet-examples.git   fleet-local   0/0
    rke2-upgrade   https://github.com/suse-edge/fleet-examples.git   fleet-local   0/0
58.2.5.4.2 Ampliación del plan SUC - Recurso Bundle

Un recurso Bundle, que incluye los Kubernetes upgrade SUC Plans necesarios, puede desplegarse de una de las siguientes maneras:

  1. A través de Rancher UI - Sección 58.2.5.4.2.1, “Creación de Bundle - Interfaz de usuario de Rancher” (cuando Rancher esté disponible).

  2. Mediante el despliegue manual (Sección 58.2.5.4.2.2, “Creación de bundle - manual”) del recurso en vuestro management cluster.

Una vez desplegado, para supervisar el proceso de actualización de Kubernetes de los nodos de vuestro clúster de destino, consultad Sección 20.3, “Monitorización de los planes del controlador de actualización del sistema”.

58.2.5.4.2.1 Creación de Bundle - Interfaz de usuario de Rancher

El equipo de Edge mantiene bundles listos para usar tanto para las distribuciones de Kubernetes rke2 como k3s. Dependiendo de vuestro entorno, estos bundles podrían utilizarse directamente o como plantilla.

Importante
Importante

Utilizad siempre este bundle a partir de una etiqueta de release de Edge válida.

Para crear un bundle a través de la interfaz de usuario de Rancher:

  1. En la esquina superior izquierda, haced clic en ☰ → Entrega Continua

  2. Id a Advanced > Bundles

  3. Seleccionad Create from YAML

  4. Desde aquí podéis crear el Bundle de una de las siguientes maneras:

    Nota
    Nota

    Puede haber casos de uso en los que necesitéis incluir cambios personalizados en los SUC plans que el bundle incluye (p. ej., para añadir tolerancias personalizadas). Aseguraos de incluir esos cambios en el bundle que se generará mediante los siguientes pasos.

    1. Copiando manualmente el contenido del bundle para RKE2 o K3s desde suse-edge/fleet-examples a la página Create from YAML.

    2. Clonando el repositorio suse-edge/fleet-examples desde la release deseada y seleccionando la opción Read from File en la página Create from YAML. Desde allí, navegad hasta el bundle que necesitéis (bundles/day2/system-upgrade-controller-plans/rke2-upgrade/plan-bundle.yaml para RKE2 y bundles/day2/system-upgrade-controller-plans/k3s-upgrade/plan-bundle.yaml para K3s). Esto rellenará automáticamente la página Create from YAML con el contenido del bundle.

  5. Editad el Bundle en la interfaz de usuario de Rancher:

    • Cambiad el espacio de nombres del Bundle para que apunte al espacio de nombres fleet-local.

      # Example
      kind: Bundle
      apiVersion: fleet.cattle.io/v1alpha1
      metadata:
        name: rke2-upgrade
        namespace: fleet-local
      ...
    • Cambiad los clústeres target del Bundle para que apunten a vuestro clúster local (gestión):

      spec:
        targets:
        - clusterName: local
      Nota
      Nota

      Existen algunos casos de uso en los que vuestro clúster local podría tener un nombre diferente.

      Para recuperar el nombre de vuestro clúster local, ejecutad el siguiente comando:

      kubectl get clusters.fleet.cattle.io -n fleet-local
  6. Seleccionad Crear

58.2.5.4.2.2 Creación de bundle - manual
  1. Obtened los recursos del Bundle:

    • Para clústeres RKE2:

      curl -o rke2-plan-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/bundles/day2/system-upgrade-controller-plans/rke2-upgrade/plan-bundle.yaml
    • Para clústeres K3s:

      curl -o k3s-plan-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/bundles/day2/system-upgrade-controller-plans/k3s-upgrade/plan-bundle.yaml
  2. Editad la configuración del Bundle:

    • Cambiad los clústeres target del Bundle para que apunten a vuestro clúster local (gestión):

      spec:
        targets:
        - clusterName: local
      Nota
      Nota

      Existen algunos casos de uso en los que vuestro clúster local podría tener un nombre diferente.

      Para recuperar el nombre de vuestro clúster local, ejecutad el siguiente comando:

      kubectl get clusters.fleet.cattle.io -n fleet-local
    • Cambiad el espacio de nombres del Bundle para que apunte al espacio de nombres fleet-local.

      # Example
      kind: Bundle
      apiVersion: fleet.cattle.io/v1alpha1
      metadata:
        name: rke2-upgrade
        namespace: fleet-local
      ...
  3. Aplicad los recursos del Bundle a vuestro management cluster:

    # For RKE2
    kubectl apply -f rke2-plan-bundle.yaml
    
    # For K3s
    kubectl apply -f k3s-plan-bundle.yaml
  4. Visualizad el recurso Bundle creado en el espacio de nombres fleet-local:

    # For RKE2
    kubectl get bundles rke2-upgrade -n fleet-local
    
    # For K3s
    kubectl get bundles k3s-upgrade -n fleet-local
    
    # Example output
    NAME           BUNDLEDEPLOYMENTS-READY   STATUS
    k3s-upgrade    0/0
    rke2-upgrade   0/0
58.2.5.4.3 Ampliación del plan SUC: flujo de trabajo GitOps de terceros

Puede haber casos de uso en los que los usuarios deseen incorporar el Kubernetes upgrade SUC plans a su propio flujo de trabajo GitOps de terceros (p. ej., Flux).

Para obtener los recursos de actualización de K8s que necesitáis, determinad primero la etiqueta de release de Edge del repositorio suse-edge/fleet-examples que deseáis utilizar.

Después de eso, los recursos se pueden encontrar en:

  • Para una actualización de clúster RKE2:

    • Para nodos control-plane - fleets/day2/system-upgrade-controller-plans/rke2-upgrade/plan-control-plane.yaml

    • Para nodos worker - fleets/day2/system-upgrade-controller-plans/rke2-upgrade/plan-worker.yaml

  • Para una actualización de clúster K3s:

    • Para nodos control-plane - fleets/day2/system-upgrade-controller-plans/k3s-upgrade/plan-control-plane.yaml

    • Para nodos worker - fleets/day2/system-upgrade-controller-plans/k3s-upgrade/plan-worker.yaml

Importante
Importante

Estos recursos Plan son interpretados por el System Upgrade Controller y deben desplegarse en cada clúster de sentido descendente que deseéis actualizar. Para obtener información sobre la ampliación de SUC, consultad Sección 20.2, “Instalación del controlador de actualización del sistema”.

Para comprender mejor cómo podéis utilizar vuestro flujo de trabajo de GitOps para implementar los planes de SUC para la actualización de la versión de Kubernetes, puede resultar útil echar un vistazo a la descripción general (Sección 58.2.5.2, “Descripción general”) del procedimiento de actualización utilizando Fleet.

58.2.6 Actualización de Helm chart

Esta sección trata las siguientes partes:

  1. Sección 58.2.6.1, “Preparación para entornos aislados” - contiene información sobre cómo enviar gráficos e imágenes OCI relacionados con Edge a su registro privado.

  2. Sección 58.2.6.2, “Procedimiento de actualización” - contiene información sobre diferentes casos de uso de actualización de gráficos de Helm y su procedimiento de actualización.

58.2.6.1 Preparación para entornos aislados

58.2.6.1.1 Asegúrese de tener acceso a su Fleet de gráficos de Helm

Dependiendo de lo que admita su entorno, puede elegir una de las siguientes opciones:

  1. Aloje los recursos de Fleet de su gráfico en un servidor Git local al que pueda acceder su management cluster.

  2. Utilizad la CLI de Fleet para convertir un Helm chart en un Bundle que podáis usar directamente sin necesidad de alojarlo en otro sitio. La CLI de Fleet se puede obtener en su página de lanzamientos; para usuarios de Mac, existe una fleet-cli Homebrew Formulae.

58.2.6.1.2 Busque los activos necesarios para su versión de lanzamiento de Edge
  1. Vaya a la página de lanzamiento de «Día 2», busque el lanzamiento de Edge al que desea actualizar su gráfico y haga clic en Activos.

  2. Desde la sección «Activos», descargue los siguientes archivos:

    Archivo de lanzamiento

    Descripción

    edge-save-images.sh

    Extrae las imágenes especificadas en el archivo edge-release-images.txt y las empaqueta dentro de un archivo '.tar.gz'.

    edge-save-oci-artefacts.sh

    Extrae las imágenes de gráfico OCI relacionadas con la versión específica de Edge y las empaqueta dentro de un archivo '.tar.gz'.

    edge-load-images.sh

    Carga imágenes desde un archivo '.tar.gz', las vuelve a etiquetar y las envía a un registro privado.

    edge-load-oci-artefacts.sh

    Toma un directorio que contiene paquetes de gráfico OCI '.tgz' de Edge y los carga en un registro privado.

    edge-release-helm-oci-artefacts.txt

    Contiene una lista de imágenes de gráfico OCI relacionadas con una versión específica de Edge.

    edge-release-images.txt

    Contiene una lista de imágenes relacionadas con una versión específica de Edge.

58.2.6.1.3 Cread el archivo de imágenes de la versión de Edge

En una máquina con acceso a internet:

  1. Haced que edge-save-images.sh sea ejecutable:

    chmod +x edge-save-images.sh
  2. Generad el archivo de imagen:

    ./edge-save-images.sh --source-registry registry.suse.com
  3. Esto creará un archivo listo para cargar llamado edge-images.tar.gz.

    Nota
    Nota

    Si se especifica la opción -i|--images, el nombre del archivo puede variar.

  4. Copiad este archivo a vuestra máquina air-gapped:

    scp edge-images.tar.gz <user>@<machine_ip>:/path
58.2.6.1.4 Cread el archivo de imágenes de gráfico OCI de Edge

En una máquina con acceso a internet:

  1. Haced que edge-save-oci-artefacts.sh sea ejecutable:

    chmod +x edge-save-oci-artefacts.sh
  2. Generad el archivo de imagen de gráfico OCI:

    ./edge-save-oci-artefacts.sh --source-registry registry.suse.com
  3. Esto creará un archivo llamado oci-artefacts.tar.gz.

    Nota
    Nota

    Si se especifica la opción -a|--archive, el nombre del archivo puede variar.

  4. Copiad este archivo a vuestra máquina air-gapped:

    scp oci-artefacts.tar.gz <user>@<machine_ip>:/path
58.2.6.1.5 Cargad las imágenes de la versión de Edge en vuestra máquina en entorno aislado.

En vuestra máquina en entorno aislado:

  1. Iniciad sesión en vuestro registro privado (si es necesario):

    podman login <REGISTRY.YOURDOMAIN.COM:PORT>
  2. Haced que edge-load-images.sh sea ejecutable:

    chmod +x edge-load-images.sh
  3. Ejecutad el script, pasando el archivo edge-images.tar.gz que fue copiado anteriormente:

    ./edge-load-images.sh --source-registry registry.suse.com --registry <REGISTRY.YOURDOMAIN.COM:PORT> --images edge-images.tar.gz
    Nota
    Nota

    Esto cargará todas las imágenes desde edge-images.tar.gz, las volverá a etiquetar y las enviará al registro especificado en la opción --registry.

58.2.6.1.6 Cargad las imágenes del gráfico Edge OCI en vuestra máquina en entorno aislado.

En vuestra máquina en entorno aislado:

  1. Iniciad sesión en vuestro registro privado (si es necesario):

    podman login <REGISTRY.YOURDOMAIN.COM:PORT>
  2. Haced que edge-load-oci-artefacts.sh sea ejecutable:

    chmod +x edge-load-oci-artefacts.sh
  3. Desempaquetad el archivo oci-artefacts.tar.gz copiado:

    tar -xvf oci-artefacts.tar.gz
  4. Esto producirá un directorio con la plantilla de nomenclatura edge-release-oci-tgz-<date>

  5. Pasad este directorio al script edge-load-oci-artefacts.sh para cargar las imágenes del gráfico Edge OCI en vuestro registro privado:

    Nota
    Nota

    Este script asume que la CLI de helm ha sido preinstalada en vuestro entorno. Para obtener instrucciones sobre la instalación de Helm, consultad Instalación de Helm.

    ./edge-load-oci-artefacts.sh --archive-directory edge-release-oci-tgz-<date> --registry <REGISTRY.YOURDOMAIN.COM:PORT> --source-registry registry.suse.com
58.2.6.1.7 Configurad vuestro registro privado en vuestra distribución de Kubernetes

Para RKE2, consultad Configuración de registro privado.

Para K3s, consultad Configuración de registro privado.

58.2.6.2 Procedimiento de actualización

Esta sección se centra en los siguientes casos de uso del procedimiento de actualización de Helm:

Importante
Importante

Los gráficos de Helm desplegados manualmente no se pueden actualizar de forma fiable. Sugerimos volver a desplegar el gráfico de Helm utilizando el método Sección 58.2.6.2.1, “Tengo un nuevo clúster y me gustaría desplegar y gestionar un Helm chart de Edge”.

58.2.6.2.1 Tengo un nuevo clúster y me gustaría desplegar y gestionar un Helm chart de Edge

Esta sección cubre cómo:

58.2.6.2.1.1 Preparad los recursos de Fleet para vuestro Helm chart
  1. Adquirid los recursos de Fleet de vuestro Helm chart desde la etiqueta de lanzamiento de Edge que deseéis utilizar.

  2. Navegad hasta el Fleet de vuestro Helm chart (fleets/day2/chart-templates/<chart>)

  3. Si tenéis la intención de utilizar un flujo de trabajo GitOps, copiad el directorio Fleet del Helm chart al repositorio Git desde donde realizaréis GitOps.

  4. Opcionalmente, si el Helm chart requiere configuraciones en sus valores, editad la configuración .helm.values dentro del archivo fleet.yaml del directorio copiado.

  5. Opcionalmente, puede haber casos de uso en los que necesitéis añadir recursos adicionales a la flota de vuestro gráfico para que se adapte mejor a vuestro entorno. Para obtener información sobre cómo mejorar vuestro directorio de Fleet, consultad Contenido del repositorio Git.

Nota
Nota

En algunos casos, el tiempo de espera predeterminado que utiliza Fleet para las operaciones de Helm puede ser insuficiente, lo que da lugar al siguiente error:

failed pre-install: context deadline exceeded

En tales casos, añadid la propiedad timeoutSeconds bajo la configuración helm de vuestro archivo fleet.yaml.

Un ejemplo para el Helm chart longhorn sería así:

  • Estructura del repositorio Git del usuario:

    <user_repository_root>
    ├── longhorn
    │   └── fleet.yaml
    └── longhorn-crd
        └── fleet.yaml
  • Contenido de fleet.yaml poblado con datos de usuario Longhorn:

    defaultNamespace: longhorn-system
    
    helm:
      # timeoutSeconds: 10
      releaseName: "longhorn"
      chart: "longhorn"
      repo: "https://charts.rancher.io/"
      version: "1.11.2"
      takeOwnership: true
      # custom chart value overrides
      values:
        # Example for user provided custom values content
        defaultSettings:
          deletingConfirmationFlag: true
    
    # https://fleet.rancher.io/bundle-diffs
    diff:
      comparePatches:
      - apiVersion: apiextensions.k8s.io/v1
        kind: CustomResourceDefinition
        name: engineimages.longhorn.io
        operations:
        - {"op":"remove", "path":"/status/conditions"}
        - {"op":"remove", "path":"/status/storedVersions"}
        - {"op":"remove", "path":"/status/acceptedNames"}
      - apiVersion: apiextensions.k8s.io/v1
        kind: CustomResourceDefinition
        name: nodes.longhorn.io
        operations:
        - {"op":"remove", "path":"/status/conditions"}
        - {"op":"remove", "path":"/status/storedVersions"}
        - {"op":"remove", "path":"/status/acceptedNames"}
      - apiVersion: apiextensions.k8s.io/v1
        kind: CustomResourceDefinition
        name: volumes.longhorn.io
        operations:
        - {"op":"remove", "path":"/status/conditions"}
        - {"op":"remove", "path":"/status/storedVersions"}
        - {"op":"remove", "path":"/status/acceptedNames"}
    Nota
    Nota

    Estos son solo valores de ejemplo que se utilizan para ilustrar configuraciones personalizadas sobre el Helm chart longhorn. NO deben tratarse como directrices de despliegue para el Helm chart longhorn.

58.2.6.2.1.2 Desplegad la flota para vuestro Helm chart

Podéis desplegar la flota para vuestro Helm chart utilizando un GitRepo (Sección 58.2.6.2.1.2.1, “GitRepo”) o un Bundle (Sección 58.2.6.2.1.2.2, “Bundle”).

Nota
Nota

Al desplegar vuestra flota, si recibís un mensaje de Modified, aseguraos de añadir la entrada comparePatches correspondiente a la sección diff de la flota. Para más información, consultad Generación de diferencias para ignorar GitRepos modificados.

58.2.6.2.1.2.1 GitRepo

El recurso GitRepo de Fleet contiene información sobre cómo acceder a los recursos de flota de vuestro Helm chart y a qué clústeres debe aplicar dichos recursos.

El recurso GitRepo puede desplegarse a través de la interfaz de usuario de Rancher, o manualmente, desplegando el recurso en management cluster.

Ejemplo de recurso Longhorn GitRepo para despliegue manual:

apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
  name: longhorn-git-repo
  namespace: fleet-local
spec:
  # If using a tag
  # revision: user_repository_tag
  #
  # If using a branch
  # branch: user_repository_branch
  paths:
  # As seen in the 'Prepare your Fleet resources' example
  - longhorn
  - longhorn-crd
  repo: user_repository_url
58.2.6.2.1.2.2 Bundle

Los recursos Bundle contienen los recursos brutos de Kubernetes que deben ser desplegados por Fleet. Normalmente se recomienda utilizar el enfoque GitRepo, pero para casos de uso en los que el entorno sea aislado y no pueda admitir un servidor Git local, Bundles puede ayudaros a propagar vuestro Helm chart con Fleet a vuestros clústeres de destino.

Un Bundle puede desplegarse a través de la interfaz de usuario de Rancher (Continuous Delivery → Advanced → Bundles → Create from YAML) o desplegando manualmente el recurso Bundle en el espacio de nombres de Fleet correcto. Para obtener información sobre los espacios de nombres de Fleet, consulte la documentación original.

Se pueden crear Bundles para los Helm charts de Edge utilizando el enfoque Convertir un Helm chart en un Bundle de Fleet.

A continuación, podéis encontrar un ejemplo sobre cómo crear un recurso Bundle a partir de las plantillas de Fleet de los Helm charts longhorn y longhorn-crd, y desplegad manualmente este Bundle en vuestro management cluster.

Nota
Nota

Para ilustrar el flujo de trabajo, el siguiente ejemplo utiliza la estructura de directorio suse-edge/fleet-examples.

  1. Navegad hasta la plantilla de Fleet del Helm chart longhorn:

    cd fleets/day2/chart-templates/longhorn/longhorn
  2. Cread un archivo targets.yaml que indique a Fleet en qué clústeres debe desplegar el Helm chart:

    cat > targets.yaml <<EOF
    targets:
    # Match your local (management) cluster
    - clusterName: local
    EOF
    Nota
    Nota

    Existen algunos casos de uso en los que vuestro clúster local podría tener un nombre diferente.

    Para recuperar el nombre de su clúster local, ejecute el siguiente comando:

    kubectl get clusters.fleet.cattle.io -n fleet-local
  3. Convierta el recurso Fleet del gráfico de Helm Longhorn en un recurso Bundle utilizando la fleet-cli.

    Nota
    Nota

    La CLI de Fleet se puede obtener desde su página de lanzamientos Assets (fleet-linux-amd64).

    Para los usuarios de Mac, existe una fórmula de Homebrew para fleet-cli.

    fleet apply --compress --targets-file=targets.yaml -n fleet-local -o - longhorn-bundle > longhorn-bundle.yaml
  4. Navegue hasta la plantilla de Fleet del gráfico longhorn-crd:

    cd fleets/day2/chart-templates/longhorn/longhorn-crd
  5. Cree un archivo targets.yaml que indique a Fleet en qué clústeres debe desplegar el gráfico de Helm:

    cat > targets.yaml <<EOF
    targets:
    # Match your local (management) cluster
    - clusterName: local
    EOF
  6. Convierta el recurso Fleet del gráfico de Helm Longhorn CRD en un recurso Bundle utilizando la fleet-cli.

    fleet apply --compress --targets-file=targets.yaml -n fleet-local -o - longhorn-crd-bundle > longhorn-crd-bundle.yaml
  7. Despliegue los archivos longhorn-bundle.yaml y longhorn-crd-bundle.yaml en su management cluster:

    kubectl apply -f longhorn-crd-bundle.yaml
    kubectl apply -f longhorn-bundle.yaml

Seguir estos pasos garantizará que SUSE Storage se despliegue en todos los management clústeres especificados.

58.2.6.2.1.3 Gestionar el gráfico de Helm desplegado

Una vez desplegado con Fleet, para las actualizaciones del gráfico de Helm, consulte Sección 58.2.6.2.2, “Me gustaría actualizar un gráfico de Helm gestionado por Fleet”.

58.2.6.2.2 Me gustaría actualizar un gráfico de Helm gestionado por Fleet
  1. Determine la versión a la que necesita actualizar su gráfico para que sea compatible con la versión de Edge deseada. La versión del gráfico de Helm por versión de Edge se puede consultar en las notas de la versión (Capítulo 75, Notas de la versión).

  2. En su repositorio Git supervisado por Fleet, edite el archivo fleet.yaml del gráfico de Helm con la versión y el repositorio correctos de las notas de la versión (Capítulo 75, Notas de la versión).

  3. Tras confirmar y enviar los cambios a su repositorio, esto activará una actualización del gráfico de Helm deseado.

58.2.6.2.3 Me gustaría actualizar un gráfico de Helm desplegado a través de EIB.

Capítulo 12, Edge Image Builder despliega gráficos de Helm creando un recurso HelmChart y utilizando el helm-controller introducido por la función de integración de Helm de RKE2/K3s.

Para garantizar que un gráfico de Helm desplegado a través de EIB se actualice correctamente, los usuarios deben realizar una actualización sobre los recursos HelmChart respectivos.

A continuación, puede encontrar información sobre:

58.2.6.2.3.1 Descripción general

Los gráficos de Helm que se despliegan a través de EIB se actualizan mediante un fleet llamado eib-charts-upgrader.

Este fleet procesa datos proporcionados por el usuario para actualizar un conjunto específico de recursos HelmChart.

La actualización de estos recursos activa el helm-controller, que actualiza la versión de los gráficos de Helm asociados con los recursos HelmChart modificados.

Solo se espera que el usuario:

  1. Localmente, extraed los archivos comprimidos para cada gráfico de Helm que deba actualizarse.

  2. Pasad estos archivos al script generate-chart-upgrade-data.sh generate-chart-upgrade-data.sh, que incluirá los datos de estos archivos en la flota eib-charts-upgrader.

  3. Desplegad la flota eib-charts-upgrader en vuestro management cluster. Esto se realiza a través de un recurso GitRepo o Bundle.

Una vez desplegado, el eib-charts-upgrader, con la ayuda de Fleet, enviará sus recursos al clúster management deseado.

Estos recursos incluyen:

  1. Un conjunto de Secrets que contiene los datos del gráfico de Helm proporcionados por el usuario.

  2. Un Kubernetes Job que desplegará un Pod que montará los Secrets mencionados anteriormente y, basándose en ellos, parcheará los recursos de HelmChart correspondientes.

Como se mencionó anteriormente, esto activará el helm-controller que realizará la actualización real del gráfico de Helm.

A continuación podéis encontrar un diagrama de la descripción anterior:

fleet day2 management helm eib upgrade
58.2.6.2.3.2 Pasos de actualización
  1. Clonad el repositorio suse-edge/fleet-examples desde la etiqueta de la versión correcta.

  2. Cread un directorio en el que almacenaréis el/los archivo(s) comprimido(s) del gráfico de Helm descargado(s).

    mkdir archives
  3. Dentro del directorio de archivos comprimidos recién creado, descargad el/los archivo(s) comprimido(s) para el/los gráfico(s) de Helm que deseéis actualizar:

    cd archives
    helm pull [chart URL | repo/chartname]
    
    # Alternatively if you want to pull a specific version:
    # helm pull [chart URL | repo/chartname] --version 0.0.0
  4. Desde Assets de la etiqueta de versión deseada, descargad el script generate-chart-upgrade-data.sh.

  5. Ejecutad el script generate-chart-upgrade-data.sh:

    chmod +x ./generate-chart-upgrade-data.sh
    
    ./generate-chart-upgrade-data.sh --archive-dir /foo/bar/archives/ --fleet-path /foo/bar/fleet-examples/fleets/day2/eib-charts-upgrader

    Para cada archivo de gráfico en el directorio --archive-dir, el script genera un archivo Kubernetes Secret YAML que contiene los datos de actualización del gráfico y los almacena en el directorio base/secrets de la flota especificada por --fleet-path.

    El script generate-chart-upgrade-data.sh también aplica modificaciones adicionales a la flota para garantizar que los archivos Kubernetes Secret YAML generados sean utilizados correctamente por la carga de trabajo desplegada por la flota.

    Importante
    Importante

    Los usuarios no deben realizar cambios sobre lo que genera el script generate-chart-upgrade-data.sh.

Los pasos siguientes dependen del entorno en el que estéis ejecutando:

  1. Para un entorno que admita GitOps (por ejemplo, que no esté aislado o que esté aislado, pero permita el soporte de un servidor Git local):

    1. Copiad la flota fleets/day2/eib-charts-upgrader al repositorio que utilizaréis para GitOps.

      Nota
      Nota

      Aseguraos de que la flota incluya los cambios realizados por el script generate-chart-upgrade-data.sh.

    2. Configurad un recurso GitRepo que se utilizará para enviar todos los recursos de la flota eib-charts-upgrader.

      1. Para la configuración y el despliegue de GitRepo a través de la interfaz de usuario de Rancher, consultad Acceso a Fleet en la interfaz de usuario de Rancher.

      2. Para la configuración y el despliegue manual de GitRepo, consultad Creación de un despliegue.

  2. Para un entorno que no admita GitOps (por ejemplo, que sea un entorno aislado y no permita el uso de un servidor Git local):

    1. Descargad el binario fleet-cli desde la página rancher/fleet release (fleet-linux-amd64 para Linux). Para los usuarios de Mac, existe una fórmula de Homebrew que se puede utilizar: fleet-cli.

    2. Navegad a eib-charts-upgrader Fleet:

      cd /foo/bar/fleet-examples/fleets/day2/eib-charts-upgrader
    3. Cread un archivo targets.yaml que indique a Fleet dónde desplegar vuestros recursos:

      cat > targets.yaml <<EOF
      targets:
      # To map the local(management) cluster
      - clusterName: local
      EOF
      Nota
      Nota

      Existen algunos casos de uso en los que vuestro clúster local podría tener un nombre diferente.

      Para recuperar el nombre de vuestro clúster local, ejecutad el siguiente comando:

      kubectl get clusters.fleet.cattle.io -n fleet-local
    4. Utilizad fleet-cli para convertir Fleet en un recurso Bundle:

      fleet apply --compress --targets-file=targets.yaml -n fleet-local -o - eib-charts-upgrade > bundle.yaml

      Esto creará un Bundle (bundle.yaml) que contendrá todos los recursos con plantilla del Fleet eib-charts-upgrader.

      Para obtener más información sobre el comando fleet apply, consultad fleet apply.

      Para obtener más información sobre la conversión de Fleets a Bundles, consultad Convertir un gráfico de Helm en un Bundle.

    5. Desplegad Bundle. Esto se puede hacer de dos formas:

      1. A través de la interfaz de usuario de Rancher: navegad a Continuous Delivery → Advanced → Bundles → Create from YAML y pegad el contenido de bundle.yaml o haced clic en la opción Read from File y enviad el archivo directamente.

      2. Manualmente: desplegad el archivo bundle.yaml manualmente dentro de vuestro management cluster.

La ejecución de estos pasos dará como resultado un recurso GitRepo/Bundle desplegado correctamente. Fleet detectará el recurso y su contenido se desplegará en los clústeres de destino que hayáis especificado en los pasos anteriores. Para obtener una visión general del proceso, consultad Sección 58.2.6.2.3.1, “Descripción general”.

Para obtener información sobre cómo realizar el seguimiento del proceso de actualización, podéis consultar Sección 58.2.6.2.3.3, “Ejemplo”.

Importante
Importante

Una vez que se haya verificado correctamente la actualización del gráfico, eliminad el recurso Bundle/GitRepo.

Esto eliminará los recursos de actualización que ya no son necesarios de vuestro clúster management, asegurando que no se produzcan conflictos de versiones en el futuro.

58.2.6.2.3.3 Ejemplo
Nota
Nota

El siguiente ejemplo demuestra cómo actualizar un gráfico de Helm desplegado mediante EIB de una versión a otra en un clúster management. Tened en cuenta que las versiones utilizadas en este ejemplo no son recomendaciones. Para obtener recomendaciones de versiones específicas de una versión Edge, consultad las notas de la versión (Capítulo 75, Notas de la versión).

Caso práctico:

  • Un clúster management está ejecutando una versión anterior de Longhorn.

  • El clúster se ha desplegado a través de EIB, utilizando la siguiente definición de imagen snippet:

    kubernetes:
      helm:
        charts:
        - name: longhorn-crd
          repositoryName: rancher-charts
          targetNamespace: longhorn-system
          createNamespace: true
          version: 104.2.0+up1.7.1
          installationNamespace: kube-system
        - name: longhorn
          repositoryName: rancher-charts
          targetNamespace: longhorn-system
          createNamespace: true
          version: 104.2.0+up1.7.1
          installationNamespace: kube-system
        repositories:
        - name: rancher-charts
          url: https://charts.rancher.io/
    ...
  • SUSE Storage necesita ser actualizado a una versión que sea compatible con la versión 3.6 de Edge. Lo que significa que debe actualizarse a 1.11.2.

  • Se asume que el management cluster está en un entorno aislado, sin soporte para un servidor Git local y tiene una configuración de Rancher en funcionamiento.

Seguid los Pasos de actualización (Sección 58.2.6.2.3.2, “Pasos de actualización”):

  1. Clonad el repositorio suse-edge/fleet-example desde la etiqueta release-3.6.1.

    git clone -b release-3.6.1 https://github.com/suse-edge/fleet-examples.git
  2. Cread un directorio donde se almacenará el archivo de actualización de Longhorn.

    mkdir archives
  3. Descargad la versión del archivo del chart Longhorn deseada:

    # First add the Rancher Helm chart repository
    helm repo add rancher-charts https://charts.rancher.io/
    
    # Pull the Longhorn 1.11.2 chart archive
    helm pull oci://dp.apps.rancher.io/charts/suse-storage --version 1.11.2
  4. Fuera del directorio archives, descargad el script generate-chart-upgrade-data.sh desde la suse-edge/fleet-examples etiqueta de la versión.

  5. La configuración del directorio debería ser similar a:

    .
    ├── archives
    │   └── longhorn-1.11.2.tgz
    ├── fleet-examples
    ...
    │   ├── fleets
    │   │   ├── day2
    |   |   |   ├── ...
    │   │   │   ├── eib-charts-upgrader
    │   │   │   │   ├── base
    │   │   │   │   │   ├── job.yaml
    │   │   │   │   │   ├── kustomization.yaml
    │   │   │   │   │   ├── patches
    │   │   │   │   │   │   └── job-patch.yaml
    │   │   │   │   │   ├── rbac
    │   │   │   │   │   │   ├── cluster-role-binding.yaml
    │   │   │   │   │   │   ├── cluster-role.yaml
    │   │   │   │   │   │   ├── kustomization.yaml
    │   │   │   │   │   │   └── sa.yaml
    │   │   │   │   │   └── secrets
    │   │   │   │   │       ├── eib-charts-upgrader-script.yaml
    │   │   │   │   │       └── kustomization.yaml
    │   │   │   │   ├── fleet.yaml
    │   │   │   │   └── kustomization.yaml
    │   │   │   └── ...
    │   └── ...
    └── generate-chart-upgrade-data.sh
  6. Ejecutad el script generate-chart-upgrade-data.sh:

    # First make the script executable
    chmod +x ./generate-chart-upgrade-data.sh
    
    # Then execute the script
    ./generate-chart-upgrade-data.sh --archive-dir ./archives --fleet-path ./fleet-examples/fleets/day2/eib-charts-upgrader

    La estructura del directorio después de la ejecución del script debería ser similar a:

    .
    ├── archives
    │   └── longhorn-1.11.2.tgz
    ├── fleet-examples
    ...
    │   ├── fleets
    │   │   ├── day2
    │   │   │   ├── ...
    │   │   │   ├── eib-charts-upgrader
    │   │   │   │   ├── base
    │   │   │   │   │   ├── job.yaml
    │   │   │   │   │   ├── kustomization.yaml
    │   │   │   │   │   ├── patches
    │   │   │   │   │   │   └── job-patch.yaml
    │   │   │   │   │   ├── rbac
    │   │   │   │   │   │   ├── cluster-role-binding.yaml
    │   │   │   │   │   │   ├── cluster-role.yaml
    │   │   │   │   │   │   ├── kustomization.yaml
    │   │   │   │   │   │   └── sa.yaml
    │   │   │   │   │   └── secrets
    │   │   │   │   │       ├── eib-charts-upgrader-script.yaml
    │   │   │   │   │       ├── kustomization.yaml
    │   │   │   │   │       ├── longhorn-VERSION.yaml - secret created by the generate-chart-upgrade-data.sh script
    │   │   │   │   │       └── longhorn-crd-VERSION.yaml - secret created by the generate-chart-upgrade-data.sh script
    │   │   │   │   ├── fleet.yaml
    │   │   │   │   └── kustomization.yaml
    │   │   │   └── ...
    │   └── ...
    └── generate-chart-upgrade-data.sh

    Los archivos modificados en git deberían tener este aspecto:

    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
        modified:   fleets/day2/eib-charts-upgrader/base/patches/job-patch.yaml
        modified:   fleets/day2/eib-charts-upgrader/base/secrets/kustomization.yaml
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
        fleets/day2/eib-charts-upgrader/base/secrets/longhorn-VERSION.yaml
        fleets/day2/eib-charts-upgrader/base/secrets/longhorn-crd-VERSION.yaml
  7. Cread un Bundle para el Fleet eib-charts-upgrader:

    1. Primero, navegad hasta el Fleet:

      cd ./fleet-examples/fleets/day2/eib-charts-upgrader
    2. A continuación, cread un archivo targets.yaml:

      cat > targets.yaml <<EOF
      targets:
      - clusterName: local
      EOF
    3. Después, utilizad el binario fleet-cli para convertir el Fleet en un Bundle:

      fleet apply --compress --targets-file=targets.yaml -n fleet-local -o - eib-charts-upgrade > bundle.yaml
  8. Desplegad el Bundle a través de la interfaz de usuario de Rancher:

    day2 helm chart upgrade example 1
    Figura 58.1: Desplegad el Bundle a través de la interfaz de usuario de Rancher

    Desde aquí, seleccionad Leer desde archivo y buscad el archivo bundle.yaml en vuestro sistema.

    Esto rellenará automáticamente el Bundle dentro de la interfaz de usuario de Rancher.

    Seleccionad Crear.

  9. Tras un despliegue correcto, vuestro Bundle debería tener un aspecto similar a:

    day2 helm chart upgrade example 2
    Figura 58.2: Bundle desplegado correctamente

Tras el despliegue correcto del Bundle, para supervisar el proceso de actualización:

  1. Verificad los registros del Upgrade Pod:

    day2 helm chart upgrade example 3 management
  2. Ahora verificad los registros del Pod creado para la actualización por el helm-controller:

    1. El nombre del Pod seguirá la siguiente plantilla: helm-install-longhorn-<random-suffix>

    2. El Pod estará en el espacio de nombres donde se desplegó el recurso HelmChart. En nuestro caso, es kube-system.

      day2 helm chart upgrade example 4 management
      Figura 58.3: Registros de la actualización correcta del chart de Longhorn
  3. Verificad que la versión de HelmChart se ha actualizado navegando a la sección HelmCharts de Rancher (More Resources → HelmCharts). Seleccionad el espacio de nombres donde se desplegó el chart; para este ejemplo, sería kube-system.

  4. Finalmente, comprobad que los Pods de Longhorn se están ejecutando.

Tras realizar las validaciones anteriores, es seguro asumir que el chart de Helm de Longhorn se ha actualizado a la versión 1.11.2.

58.2.6.2.3.4 Actualización del chart de Helm mediante una herramienta GitOps de terceros

Puede haber casos de uso en los que los usuarios deseen utilizar este procedimiento de actualización con un flujo de trabajo GitOps distinto de Fleet (por ejemplo, Flux).

Para generar los recursos necesarios para el procedimiento de actualización, puede utilizar el script generate-chart-upgrade-data.sh para poblar el Fleet eib-charts-upgrader con los datos proporcionados por el usuario. Para obtener información sobre cómo hacerlo, consulte Sección 58.2.6.2.3.2, “Pasos de actualización”.

Una vez que tengáis la configuración completa, podéis utilizar kustomize para generar una solución funcional completa que podáis desplegar en vuestro clúster:

cd /foo/bar/fleets/day2/eib-charts-upgrader

kustomize build .

Si queréis incluir la solución en vuestro flujo de trabajo GitOps, podéis eliminar el archivo fleet.yaml y usar lo que queda como una configuración Kustomize válida. Simplemente, no olvidéis ejecutar primero el script generate-chart-upgrade-data.sh, para que pueda poblar la configuración Kustomize con los datos de los charts de Helm a los que queráis actualizar.

Para entender cómo se pretende utilizar este flujo de trabajo, consultad Sección 58.2.6.2.3.1, “Descripción general” y Sección 58.2.6.2.3.2, “Pasos de actualización”.

59 Acciones del ciclo de vida

Esta sección cubre las acciones de gestión del ciclo de vida para clústeres desplegados a través de SUSE Telco Cloud.

59.1 Exclusión del equilibrador de carga

Existen muchas acciones del ciclo de vida que requieren que los nodos sean vaciados. Durante el proceso de vaciado, todos los pods se moverán a otros nodos del clúster. Una vez finalizado el proceso de vaciado, el nodo no aloja ningún servicio y, por tanto, no debería recibir tráfico dirigido a él. Los equilibradores de carga, como MetalLB, pueden ser informados de esto aplicando una etiqueta al nodo:

node.kubernetes.io/exclude-from-external-load-balancers: "true"

Para obtener más detalles, consulte: Documentación de Kubernetes.

Para ver las etiquetas en todos vuestros nodos de un clúster, podéis ejecutar:

kubectl get nodes -o json | jq -r '.items[].metadata | .name, .labels'

En el caso de actualizaciones de clústeres descendentes, esto se puede automatizar añadiendo una anotación al RKE2ControlPlane en el clúster de gestión:

rke2.controlplane.cluster.x-k8s.io/load-balancer-exclusion="true"

Esto crea inmediatamente una anotación en todos los objetos de máquina del clúster de gestión para ese RKE2ControlPlane.

pre-drain.delete.hook.machine.cluster.x-k8s.io/rke2-lb-exclusion: ""

Con esta anotación en los objetos de máquina, cualquier nodo del clúster descendente que esté programado para ser vaciado recibirá la etiqueta de nodo mencionada anteriormente antes de que comience el proceso de vaciado. La etiqueta se eliminará del nodo una vez que esté disponible y listo de nuevo.

59.2 Actualizaciones del clúster de gestión

La actualización del clúster de gestión se describe en la documentación del Day 2 clúster de gestión (Capítulo 58, Clúster de gestión).

59.3 Actualizaciones de clústeres descendentes

La actualización de los clústeres descendentes implica actualizar varios componentes. Las siguientes secciones cubren el proceso de actualización para cada uno de los componentes.

Actualización del sistema operativo

Para este proceso, consultad la siguiente referencia (Capítulo 49, Preparar la imagen del clúster descendente para escenarios conectados) para crear la nueva imagen con una nueva versión del sistema operativo. Con esta nueva imagen generada por EIB, la siguiente fase de aprovisionamiento utiliza la nueva versión del sistema operativo proporcionada. En el siguiente paso, se utiliza la nueva imagen para actualizar los nodos.

Actualización del clúster RKE2

Los cambios necesarios para actualizar el clúster RKE2 mediante el flujo de trabajo automatizado son los siguientes:

  • Cambiad el bloque RKE2ControlPlane en el capi-provisioning-example.yaml que se muestra en la siguiente sección (Capítulo 51, Aprovisionamiento de clústeres en sentido descendente con aprovisionamiento de red dirigida (nodo único)):

    • Especificad la rolloutStrategy deseada.

    • Cambiad la versión del clúster RKE2 a la nueva versión sustituyendo ${RKE2_NEW_VERSION}.

    • Decida si se debe implementar un controlador de entrada en el clúster descendente:

      • [Opción 0]: No despleguéis ningún controlador de entrada

      • [Opción 1]: Desplegad solo Traefik

      • [Opción 2]: Desplegad tanto Ingress-NGINX como Traefik (para su uso en escenarios complejos de migración de entrada)

Nota
Nota

El proveedor de entrada Traefik integrado en RKE2/K3s es el único controlador de entrada admitido en la versión SUSE Telco Cloud 3.6, siendo todavía posible ejecutar temporalmente Ingress-NGINX junto con Traefik para admitir escenarios complejos de migración de entrada, pero solo después de que los clústeres de gestión y/o descendentes SUSE Telco Cloud se hayan actualizado a la versión 3.6 y durante el tiempo necesario para realizar dicha migración. Dado que Traefik aún no es el controlador de entrada predeterminado en RKE2 (lo será a partir de RKE2 v1.36), debe «solicitarse» explícitamente desde el archivo de configuración del servidor RKE2.

La guía de migración de Ingress NGINX a Traefik de RKE2 proporciona detalles sobre las rutas de migración de ingress disponibles una vez que el controlador de ingress Traefik sustituya al Ingress-NGINX discontinuado.

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  version: ${RKE2_NEW_VERSION}
  replicas: 1
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  serverConfig:
    cni: cilium
  #===========================================================================
  # Uncomment the following lines if selecting [Option 0]: Do not deploy
  # any ingress controller
  #===========================================================================
    #disableComponents:
    #  pluginComponents:
    #  - "rke2-ingress-nginx"
  #---------------------------------------------------------------------------
  rolloutStrategy:
    rollingUpdate:
      maxSurge: 0
  registrationMethod: "control-plane-endpoint"
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
          - name: rke2-preinstall.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-preinstall
              Wants=network-online.target
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
              ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              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-ingress-deployment.service unit
          - name: rke2-ingress-deployment.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-ingress-deployment
              Wants=rke2-preinstall.service
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              #===============================================================================================================================
              # Leave one (and only one) of the two following ExecStart lines uncommented, depending on the desired ingress-controller(s):
              #   [Option 1]: Deploy only "Traefik"
              #   [Option 2]: Deploy both "Ingress-NGINX" and "Traefik"
              #
              # Keep both commented ONLY in case of seleting [Option 0]: "Do not deploy any ingress controller"
              #===============================================================================================================================
              #ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"                       # [Option 1]
              ExecStart=/bin/sh -c "echo -e \"ingress-controller:\n- ingress-nginx\n- traefik\" >> /etc/rancher/rke2/config.yaml" # [Option 2]
              #-------------------------------------------------------------------------------------------------------------------------------
              [Install]
              WantedBy=multi-user.target
        storage:
          directories:
          - path: /var/lib/rancher/rke2/server/manifests
            overwrite: true
          files:
          #############################################################################
          # if [Option 2]: "Deploy both `Ingress-NGINX` and `Traefik`" is selected
          #############################################################################
          - path: /var/lib/rancher/rke2/server/manifests/rke2-ingress-nginx-config.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: helm.cattle.io/v1
                kind: HelmChartConfig
                metadata:
                  name: rke2-ingress-nginx
                  namespace: kube-system
                spec:
                  valuesContent: |-
                    controller:
                      hostPort:
                        enabled: false  # not needed when exposing through a type:LoadBalancer service
                      config:
                        use-forwarded-headers: "true"
                        enable-real-ip: "true"
                      publishService:
                        enabled: true
                      service:
                        enabled: true
                        type: LoadBalancer
                        externalTrafficPolicy: Local
            mode: 0644
            user:
              name: root
            group:
              name: root
          #############################################################################
          # if [Option 1]: "Deploy only `Traefik`" OR  [Option 2]: "Deploy both
          #`Ingress-NGINX` and `Traefik`" is selected
          #############################################################################
          - 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: false  # Assumes [Option 2]; set to true if [Option 1]: "only deploying `Traefik`"
                    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
                    providers:
                      kubernetesIngressNginx:  # this provider allows Traefik to "understand" most of the Ingress-NGINX annotations
                        enabled: true
                        ingressClass: "rke2-ingress-nginx-migration"
                        controllerClass: "rke2.​cattle.​io/ingress-nginx-migration"
            mode: 0644
            user:
              name: root
            group:
              name: root
    kubelet:
      extraArgs:
      - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: single-node-cluster-controlplane
  namespace: default
spec:
  nodeReuse: True
  template:
    spec:
      automatedCleaningMode: metadata
      dataTemplate:
        name: single-node-cluster-controlplane-template
      hostSelector:
        matchLabels:
          cluster-role: control-plane
      image:
        checksum: http://imagecache.local:8080/${NEW_IMAGE_GENERATED}.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/${NEW_IMAGE_GENERATED}.raw

Antes de aplicar el archivo capi-provisioning-example.yaml, siempre es una buena práctica informar a los equilibradores de carga externos (p. ej., MetalLB) de que los nodos se están vaciando para que no dirijan tráfico a los nodos en este estado. Como se menciona en la sección Sección 59.1, “Exclusión del equilibrador de carga”, podéis automatizar esto anotando el RKE2ControlPlane en el clúster de gestión. En este ejemplo, se anota un objeto RKE2ControlPlane llamado multinode-cluster:

kubectl annotate  RKE2ControlPlane/multinode-cluster  rke2.controlplane.cluster.x-k8s.io/load-balancer-exclusion="true"

Verificad que los objetos de máquina se hayan anotado:

pre-drain.delete.hook.machine.cluster.x-k8s.io/rke2-lb-exclusion: ""

Obtened las anotaciones de todos vuestros objetos de máquina:

kubectl get machines -o json | jq -r '.items[].metadata | .name, .annotations'
Nota
Nota

Sin estas anotaciones, los usuarios podrían experimentar tiempos de respuesta más largos en los servicios, ya que los equilibradores de carga no detectan los nodos vaciados.

Tras realizar estos cambios, el archivo capi-provisioning-example.yaml puede aplicarse al clúster mediante el siguiente comando:

kubectl apply -f capi-provisioning-example.yaml

Parte IX Guías de instrucciones

Guías de instrucciones y mejores prácticas

  • 60 MetalLB en K3s (usando el modo de capa 2)
  • MetalLB es una implementación de equilibrador de carga para clústeres de Kubernetes bare-metal que utiliza protocolos de enrutamiento estándar.

  • 61 MetalLB en K3s (usando el modo de capa 3)
  • MetalLB es una implementación de balanceador de la carga para clústeres de Kubernetes en equipo sin sistema operativo, que utiliza protocolos de enrutamiento estándar.

  • 62 MetalLB delante del servidor de API de Kubernetes
  • Esta guía demuestra el uso de un servicio MetalLB para exponer la API de RKE2/K3s externamente en un clúster de alta disponibilidad con tres nodos de plano de control. Para lograr esto, se creará manualmente un Servicio de Kubernetes de tipo LoadBalancer. A continuación, se creará automáticamente un…

  • 63 Despliegues en entorno aislado con Edge Image Builder
  • Esta guía mostrará cómo desplegar varios de los componentes de SUSE Telco Cloud completamente aislados en SUSE Linux Micro 6.2 utilizando Edge Image Builder(EIB) (Capítulo 12, Edge Image Builder). Con esto, podréis arrancar en una imagen personalizada y lista para arrancar (CRB) creada por EIB y ten…

  • 64 Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi
  • Esta sección explica cómo generar imágenes actualizadas de SUSE Linux Micro para ser utilizadas con Edge Image Builder, con Cluster API (CAPI) + Metal3, o para escribir la imagen de disco directamente en un dispositivo de bloque. Este proceso es útil en situaciones en las que se requiere incluir los…

  • 65 Uso de ClusterClass para desplegar clústeres en sentido descendente
  • El aprovisionamiento de clústeres de Kubernetes es una tarea compleja que exige una gran experiencia en la configuración de los componentes del clúster. A medida que las configuraciones se vuelven más complejas, o a medida que las demandas de los diferentes proveedores introducen numerosas definicio…

60 MetalLB en K3s (usando el modo de capa 2)

MetalLB es una implementación de equilibrador de carga para clústeres de Kubernetes bare-metal que utiliza protocolos de enrutamiento estándar.

En esta guía, demostramos cómo desplegar MetalLB en modo de capa 2 (L2).

60.1 Por qué usar MetalLB

MetalLB es una opción atractiva para el balance de la carga en clústeres de Kubernetes bare-metal por varias razones:

  1. Integración nativa con Kubernetes: MetalLB se integra perfectamente con Kubernetes, lo que facilita su despliegue y gestión mediante herramientas y prácticas habituales de Kubernetes.

  2. Compatibilidad con bare-metal: A diferencia de los equilibradores de carga basados en la nube, MetalLB está diseñado específicamente para despliegues in situ donde los equilibradores de carga tradicionales podrían no estar disponibles o no ser viables.

  3. Admite distintos protocolos: MetalLB admite tanto el modo de capa 2 como el modo BGP (Border Gateway Protocol), lo que proporciona flexibilidad para diferentes arquitecturas y requisitos de red.

  4. Alta disponibilidad: Al distribuir las responsabilidades de balance de la carga entre varios nodos, MetalLB garantiza alta disponibilidad y fiabilidad para sus servicios.

  5. Escalabilidad: MetalLB puede gestionar despliegues a gran escala, aumentando su escalabilidad junto con su clúster de Kubernetes para satisfacer la creciente demanda.

En el modo de capa 2, un nodo asume la responsabilidad de anunciar un servicio a la red local. Desde la perspectiva de la red, simplemente parece que esa máquina tiene varias direcciones IP asignadas a su interfaz de red.

La principal ventaja del modo de capa 2 es su universalidad: funciona en cualquier red Ethernet, sin necesidad de hardware especial, ni siquiera routers sofisticados.

60.2 MetalLB en K3s (usando L2)

En esta guía de inicio rápido, se utilizará el modo L2. Esto significa que no necesitamos ningún equipo de red especial, sino tres IP libres dentro del rango de la red.

60.3 Requisitos previos

  • Un clúster de K3s donde se va a desplegar MetalLB.

Aviso
Aviso

K3S viene con su propio equilibrador de carga para servicios llamado Klipper. Debes desactivarlo para ejecutar MetalLB. Para desactivar Klipper, K3s debe instalarse utilizando el indicador --disable=servicelb.

  • Helm

  • Tres direcciones IP libres dentro del rango de la red. En este ejemplo 192.168.122.10-192.168.122.12

Importante
Importante

Debes asegurarte de que estas direcciones IP no estén asignadas. En un entorno DHCP, estas direcciones no deben formar parte del grupo DHCP para evitar asignaciones dobles.

60.4 Distribución

Utilizaremos el chart de Helm de MetalLB publicado como parte de la solución SUSE Telco Cloud:

helm install \
  metallb oci://registry.suse.com/edge/charts/metallb \
  --namespace metallb-system \
  --create-namespace

while ! kubectl wait --for condition=ready -n metallb-system $(kubectl get\
 pods -n metallb-system -l app.kubernetes.io/component=controller -o name)\
 --timeout=10s; do
 sleep 2
done

60.5 Configuración

En este punto, la instalación se ha completado. Ahora es el momento de configurar utilizando nuestros valores de ejemplo:

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ip-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.122.10/32
  - 192.168.122.11/32
  - 192.168.122.12/32
EOF
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ip-pool-l2-adv
  namespace: metallb-system
spec:
  ipAddressPools:
  - ip-pool
EOF

Ahora, está listo para ser utilizado. Puedes personalizar muchas cosas para el modo L2, tales como:

Y mucho más para BGP.

60.5.1 Traefik y MetalLB

Traefik se despliega por defecto con K3s (se puede desactivar con --disable=traefik) y, por defecto, se expone como LoadBalancer (para utilizarse con Klipper). Sin embargo, como Klipper debe desactivarse, el servicio de Traefik para ingress sigue siendo de tipo LoadBalancer. Por tanto, en el momento de desplegar MetalLB, la primera IP se asignará automáticamente a Traefik Ingress.

# Before deploying MetalLB
kubectl get svc -n kube-system traefik
NAME      TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
traefik   LoadBalancer   10.43.44.113   <pending>     80:31093/TCP,443:32095/TCP   28s
# After deploying MetalLB
kubectl get svc -n kube-system traefik
NAME      TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
traefik   LoadBalancer   10.43.44.113   192.168.122.10   80:31093/TCP,443:32095/TCP   3m10s

Esto se aplicará más adelante (Sección 60.6.1, “Ingress con MetalLB”) en el proceso.

60.6 Uso

Vamos a crear un despliegue de ejemplo:

cat <<- EOF | kubectl apply -f -
---
apiVersion: v1
kind: Namespace
metadata:
  name: hello-kubernetes
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: hello-kubernetes
  namespace: hello-kubernetes
  labels:
    app.kubernetes.io/name: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes
  namespace: hello-kubernetes
  labels:
    app.kubernetes.io/name: hello-kubernetes
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: hello-kubernetes
  template:
    metadata:
      labels:
        app.kubernetes.io/name: hello-kubernetes
    spec:
      serviceAccountName: hello-kubernetes
      containers:
        - name: hello-kubernetes
          image: "paulbouwer/hello-kubernetes:1.10"
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          env:
          - name: HANDLER_PATH_PREFIX
            value: ""
          - name: RENDER_PATH_PREFIX
            value: ""
          - name: KUBERNETES_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: KUBERNETES_POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: KUBERNETES_NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: CONTAINER_IMAGE
            value: "paulbouwer/hello-kubernetes:1.10"
EOF

Y, finalmente, el servicio:

cat <<- EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes
  namespace: hello-kubernetes
  labels:
    app.kubernetes.io/name: hello-kubernetes
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: hello-kubernetes
EOF

Veámoslo en acción:

kubectl get svc -n hello-kubernetes
NAME               TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
hello-kubernetes   LoadBalancer   10.43.127.75   192.168.122.11   80:31461/TCP   8s

curl http://192.168.122.11
<!DOCTYPE html>
<html>
<head>
    <title>Hello Kubernetes!</title>
    <link rel="stylesheet" type="text/css" href="/css/main.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" >
</head>
<body>

  <div class="main">
    <img src="/images/kubernetes.png"/>
    <div class="content">
      <div id="message">
  Hello world!
</div>
<div id="info">
  <table>
    <tr>
      <th>namespace:</th>
      <td>hello-kubernetes</td>
    </tr>
    <tr>
      <th>pod:</th>
      <td>hello-kubernetes-7c8575c848-2c6ps</td>
    </tr>
    <tr>
      <th>node:</th>
      <td>allinone (Linux 5.14.21-150400.24.46-default)</td>
    </tr>
  </table>
</div>
<div id="footer">
  paulbouwer/hello-kubernetes:1.10 (linux/amd64)
</div>
    </div>
  </div>

</body>
</html>

60.6.1 Ingress con MetalLB

Como Traefik ya actúa como controlador de ingress, podemos exponer cualquier tráfico HTTP/HTTPS mediante un objeto Ingress como:

IP=$(kubectl get svc -n kube-system traefik -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
cat <<- EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-kubernetes-ingress
  namespace: hello-kubernetes
spec:
  rules:
  - host: hellok3s.${IP}.sslip.io
    http:
      paths:
        - path: "/"
          pathType: Prefix
          backend:
            service:
              name: hello-kubernetes
              port:
                name: http
EOF

Y después:

curl http://hellok3s.${IP}.sslip.io
<!DOCTYPE html>
<html>
<head>
    <title>Hello Kubernetes!</title>
    <link rel="stylesheet" type="text/css" href="/css/main.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" >
</head>
<body>

  <div class="main">
    <img src="/images/kubernetes.png"/>
    <div class="content">
      <div id="message">
  Hello world!
</div>
<div id="info">
  <table>
    <tr>
      <th>namespace:</th>
      <td>hello-kubernetes</td>
    </tr>
    <tr>
      <th>pod:</th>
      <td>hello-kubernetes-7c8575c848-fvqm2</td>
    </tr>
    <tr>
      <th>node:</th>
      <td>allinone (Linux 5.14.21-150400.24.46-default)</td>
    </tr>
  </table>
</div>
<div id="footer">
  paulbouwer/hello-kubernetes:1.10 (linux/amd64)
</div>
    </div>
  </div>

</body>
</html>

Verifica que MetalLB funciona correctamente:

% arping hellok3s.${IP}.sslip.io

ARPING 192.168.64.210
60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=0 time=1.169 msec
60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=1 time=2.992 msec
60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=2 time=2.884 msec

En el ejemplo anterior, el tráfico fluye de la siguiente manera:

  1. hellok3s.${IP}.sslip.io se resuelve en la IP real.

  2. A continuación, el tráfico es gestionado por el pod metallb-speaker.

  3. metallb-speaker redirige el tráfico al controlador traefik.

  4. Finalmente, Traefik reenvía la solicitud al servicio hello-kubernetes.

61 MetalLB en K3s (usando el modo de capa 3)

MetalLB es una implementación de balanceador de la carga para clústeres de Kubernetes en equipo sin sistema operativo, que utiliza protocolos de enrutamiento estándar.

En esta guía, demostramos cómo desplegar MetalLB en modo BGP de capa 3 (L3).

61.1 Por qué usar MetalLB

MetalLB es una opción atractiva para el balance de la carga en clústeres de Kubernetes en equipo sin sistema operativo por varias razones:

  1. Integración nativa con Kubernetes: MetalLB se integra perfectamente con Kubernetes, lo que facilita su implementación y gestión mediante herramientas y prácticas habituales de Kubernetes.

  2. Compatibilidad con equipo sin sistema operativo: A diferencia de los balanceadores de la carga basados en la nube, MetalLB está diseñado específicamente para ampliaciones in situ donde los balanceadores de la carga tradicionales podrían no estar disponibles o no ser viables.

  3. Admite distintos protocolos: MetalLB admite modos de capa 2 y de capa 3 BGP (Border Gateway Protocol), lo que proporciona flexibilidad para diferentes arquitecturas y requisitos de red.

  4. Alta disponibilidad: Al distribuir las responsabilidades de balance de la carga entre varios nodos, MetalLB garantiza alta disponibilidad y fiabilidad para tus servicios.

  5. Escalabilidad: MetalLB puede gestionar implementaciones a gran escala, escalándose junto con tu clúster de Kubernetes para satisfacer la creciente demanda.

En el modo de capa 2, un nodo asume la responsabilidad de anunciar un servicio a la red local. Desde la perspectiva de la red, simplemente parece que esa máquina tiene varias direcciones IP asignadas a su interfaz de red.

La principal ventaja del modo de capa 2 es su universalidad: funciona en cualquier red Ethernet, sin necesidad de hardware especial, ni siquiera routers sofisticados.

61.2 MetalLB en K3s (usando L3)

En este inicio rápido, se utiliza el modo L3. Esto significa que necesitamos tener router(s) vecino(s) con capacidades BGP dentro del rango de la red.

61.3 Requisitos previos

  • Un clúster de K3s donde se va a desplegar MetalLB.

  • Router(es) en la red que admitan el protocolo BGP.

  • Una dirección IP libre dentro del rango de la red para el servicio. En este ejemplo 192.168.10.100

Importante
Importante

Debéis aseguraros de que esta dirección IP no esté asignada. En un entorno DHCP, esta dirección no debe formar parte del grupo DHCP para evitar asignaciones dobles.

61.4 Configuración para anunciar direcciones IP de servicio

Por defecto, BGP anuncia una dirección IP de servicio a todos los pares que están configurados. Estos pares, que normalmente son routers, recibirán una ruta para cada dirección IP de servicio con una máscara de red de 32 bits. En este ejemplo utilizaremos un router basado en FRR que se encuentra en la misma red que nuestro clúster. A continuación, utilizaremos la capacidad BGP de MetalLB para anunciar un servicio a ese router basado en FRR.

61.5 Distribución

Utilizaremos el gráfico de Helm de MetalLB publicado como parte de la solución SUSE Telco Cloud:

helm install \
  metallb oci://registry.suse.com/edge/charts/metallb \
  --namespace metallb-system \
  --create-namespace

while ! kubectl wait --for condition=ready -n metallb-system $(kubectl get\
 pods -n metallb-system -l app.kubernetes.io/component=controller -o name)\
 --timeout=10s; do
 sleep 2
done

61.6 Configuración

  1. En este punto, la instalación está completa. Crear un IPAddressPool:

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: bgp-pool
  namespace: metallb-system
  labels:
    app: httpd
spec:
  addresses:
  - 192.168.10.100/32
  autoAssign: true
  avoidBuggyIPs: false
  serviceAllocation:
    namespaces:
    - metallb-system
    priority: 100
    serviceSelectors:
    - matchExpressions:
      - key: serviceType
        operator: In
        values:
        - httpd
EOF
  1. Configurar un BGPPeer.

Nota
Nota

El router FRR tiene el ASN 1000, mientras que nuestro BGPPeer tendrá el 1001. También podemos ver que el router FRR tiene una dirección IP que es 192.168.3.140.

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  namespace: metallb-system
  name: mypeertest
spec:
  peerAddress: 192.168.3.140
  peerASN: 1000
  myASN: 1001
  routerID: 4.4.4.4
EOF
  1. Crea BGPAdvertisement (L3):

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
  name: bgpadvertisement-test
  namespace: metallb-system
spec:
  ipAddressPools:
  - bgp-pool
EOF

61.7 Uso

  1. Crea una aplicación de ejemplo con un servicio. En este caso, la dirección IP del IPAddressPool es 192.168.10.100 para ese servicio.

cat <<- EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-deployment
  namespace: metallb-system
  labels:
    app: httpd
spec:
  replicas: 3
  selector:
    matchLabels:
      pod-label: httpd
  template:
    metadata:
      labels:
        pod-label: httpd
    spec:
      containers:
      - name: httpdcontainer
        image: image: docker.io/library/httpd:2.4
        ports:
          - containerPort: 80
            protocol: TCP
      restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  name: http-service
  namespace: metallb-system
  labels:
    serviceType: httpd
spec:
  selector:
    pod-label: httpd
  type: LoadBalancer
  ports:
  - protocol: TCP
    port: 8080
    name: 8080-tcp
    targetPort: 80
EOF
  1. Para verificarlo, iniciad sesión en el router FRR para poder ver las rutas creadas a partir del anuncio BGP.

42178089cba5# show ip bgp all

For address family: IPv4 Unicast
BGP table version is 3, local router ID is 2.2.2.2, vrf id 0
Default local pref 100, local AS 1000
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

   Network          Next Hop            Metric LocPrf Weight Path
* i172.16.0.0/24    1.1.1.1                  0    100      0 i
*>                  0.0.0.0                  0         32768 i
* i172.17.0.0/24    3.3.3.3                  0    100      0 i
*>                  0.0.0.0                  0         32768 i
*= 192.168.10.100/32
                    192.168.3.162                          0 1001 i
*=                  192.168.3.163                          0 1001 i
*>                  192.168.3.161                          0 1001 i

Displayed  3 routes and 7 total paths
kubectl get svc -n hello-kubernetes
NAME               TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
hello-kubernetes   LoadBalancer   10.43.127.75   192.168.122.11   80:31461/TCP   8s
  1. Si este router es el gateway predeterminado de vuestra red, podéis ejecutar el comando curl desde un equipo en esa red para verificar que pueden acceder a la aplicación de ejemplo httpd.

# curl http://192.168.10.100:8080
<html><body><h1>It works!</h1></body></html>
#

62 MetalLB delante del servidor de API de Kubernetes

Esta guía demuestra el uso de un servicio MetalLB para exponer la API de RKE2/K3s externamente en un clúster de alta disponibilidad con tres nodos de plano de control. Para lograr esto, se creará manualmente un Servicio de Kubernetes de tipo LoadBalancer. A continuación, se creará automáticamente un objeto EndpointSlices que mantiene las IP de todos los nodos del plano de control disponibles en el clúster. Para que los EndpointSlices se sincronicen continuamente con los eventos que ocurren en el clúster (añadir/eliminar un nodo o un nodo que se desconecta), se desplegará el Endpoint Copier Operator (Capítulo 18, Operador de Endpoint Copier). El operador supervisa los eventos que ocurren en los EndpointSlices kubernetes predeterminados y actualiza automáticamente el gestionado para mantenerlos sincronizados. Dado que el Servicio gestionado es de tipo LoadBalancer, MetalLB le asigna una ExternalIP estática. Esta ExternalIP se utilizará para comunicarse con el servidor de API.

62.1 Requisitos previos

  • Tres hosts sobre los que desplegar RKE2/K3s.

    • Aseguraos de que los hosts tengan nombres de host diferentes.

    • Para realizar pruebas, podrían ser máquinas virtuales

  • Al menos 2 IP disponibles en la red (una para el servicio expuesto del controlador de entrada Traefik y otra para el servicio gestionado).

  • Helm

62.2 Instalación de RKE2/K3s

Nota
Nota

Si no queréis utilizar un clúster nuevo, sino uno ya existente, saltad este paso y continuad con el siguiente.

Primero, debéis reservar una IP libre en la red que se utilizará más adelante para ExternalIP del Servicio gestionado.

Acceded por SSH al primer host e instalad la distribución deseada en modo clúster.

Para RKE2:

# As a root user, create the /etc/rancher/rke2/config.yaml config file with the following content:

mkdir -p /etc/rancher/rke2/
cat <<EOF > /etc/rancher/rke2/config.yaml
# An example of the config.yaml file for a server node:
write-kubeconfig-mode: "0644"
ingress-controller: traefik
tls-san:
  - "${VIP_SERVICE_IP}"
  - "https://${VIP_SERVICE_IP}.sslip.io"
EOF

# Install RKE2
curl -sfL https://get.rke2.io | INSTALL_RKE2_EXEC="server" sh -

# Enable and start the RKE2 service with the configuration specified in the config.yaml file
systemctl enable rke2-server.service
systemctl start rke2-server.service

# Fetch the cluster token to be used later:
RKE2_TOKEN=$(tr -d '\n' < /var/lib/rancher/rke2/server/node-token)

Para K3s:

# Export the free IP mentioned above
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --cluster-init \
 --disable=servicelb --write-kubeconfig-mode=644 --tls-san=${VIP_SERVICE_IP} \
 --tls-san=https://${VIP_SERVICE_IP}.sslip.io" K3S_TOKEN=foobar sh -
Nota
Nota

Aseguraos de que el flag --disable=servicelb se incluya en el comando k3s server.

Importante
Importante

A partir de ahora, debéis ejecutar los comandos en la máquina local.

Para acceder al servidor de la API desde el exterior, se utilizará la IP de la máquina virtual de RKE2/K3s.

# Replace <node-ip> with the actual IP of the machine
export NODE_IP=<node-ip>
export KUBE_DISTRIBUTION=<k3s/rke2>

scp ${NODE_IP}:/etc/rancher/${KUBE_DISTRIBUTION}/${KUBE_DISTRIBUTION}.yaml ~/.kube/config && sed \
 -i '' "s/127.0.0.1/${NODE_IP}/g" ~/.kube/config && chmod 600 ~/.kube/config

62.3 Configuración de un clúster existente

Nota
Nota

Este paso solo es válido si tenéis intención de utilizar un clúster de RKE2/K3s existente.

Para utilizar un clúster existente, debéis modificar los flags tls-san. Además, debéis desactivar el LB servicelb para K3s.

Para cambiar los flags de los servidores de RKE2 o K3s, debéis modificar el archivo /etc/systemd/system/rke2.service o /etc/systemd/system/k3s.service en todas las máquinas virtuales del clúster, dependiendo de la distribución.

Los flags deben insertarse en ExecStart. Por ejemplo:

Para RKE2:

# Replace the <vip-service-ip> with the actual ip
ExecStart=/usr/local/bin/rke2 \
    server \
        '--write-kubeconfig-mode=644' \
        '--tls-san=<vip-service-ip>' \
        '--tls-san=https://<vip-service-ip>.sslip.io' \

Para K3s:

# Replace the <vip-service-ip> with the actual ip
ExecStart=/usr/local/bin/k3s \
    server \
        '--cluster-init' \
        '--write-kubeconfig-mode=644' \
        '--disable=servicelb' \
        '--tls-san=<vip-service-ip>' \
        '--tls-san=https://<vip-service-ip>.sslip.io' \

A continuación, debéis ejecutar los siguientes comandos para cargar las nuevas configuraciones:

systemctl daemon-reload
systemctl restart ${KUBE_DISTRIBUTION}

62.4 Instalación de MetalLB

Para desplegar MetalLB, podéis utilizar la guía MetalLB on K3s (Capítulo 60, MetalLB en K3s (usando el modo de capa 2)).

NOTA: Aseguraos de que la dirección IP VIP_SERVICE_IP no se solape con la IPAddressPools existente en el clúster.

Cread un IpAddressPool y un L2Advertisement independientes que se utilizarán únicamente para el Servicio gestionado.

NOTA: El IPAddressPool que aparece a continuación se asignará a un Servicio de tipo LoadBalancer en el espacio de nombres default. Si existen múltiples LoadBalancer servicios allí, se pueden configurar ServiceSelectors adicionales para que coincidan explícitamente con este servicio VIP.

# Export the VIP_SERVICE_IP on the local machine
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: kubernetes-vip-ip-pool
  namespace: metallb-system
spec:
  addresses:
  - ${VIP_SERVICE_IP}/32
  serviceAllocation:
    priority: 100
    namespaces:
      - default
EOF
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: kubernetes-vip-l2-adv
  namespace: metallb-system
spec:
  ipAddressPools:
  - kubernetes-vip-ip-pool
EOF

62.5 Instalación del operador Endpoint Copier

helm install \
endpoint-copier-operator oci://registry.suse.com/edge/charts/endpoint-copier-operator \
--namespace endpoint-copier-operator \
--create-namespace

El comando anterior desplegará el Deployment del operador endpoint-copier-operator con dos réplicas. Uno será el líder y el otro asumirá el papel de líder si es necesario.

Ahora, el servicio kubernetes-vip debería estar desplegado, el cual será reconciliado por el operador y se crearán unos EndpointSlices con los puertos y la IP configurados.

Para RKE2:

cat <<-EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-vip
  namespace: default
spec:
  ports:
  - name: rke2-api
    port: 9345
    protocol: TCP
    targetPort: 9345
  - name: k8s-api
    port: 6443
    protocol: TCP
    targetPort: 6443
  type: LoadBalancer
EOF

Para K3s:

cat <<-EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-vip
  namespace: default
spec:
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: https
    port: 6443
    protocol: TCP
    targetPort: 6443
  sessionAffinity: None
  type: LoadBalancer
EOF

Verificad que el servicio kubernetes-vip tenga la dirección IP correcta:

kubectl get service kubernetes-vip -n default \
 -o=jsonpath='{.status.loadBalancer.ingress[0].ip}'

Aseguraos de que los recursos EndpointSlices kubernetes-vip-* y kubernetes en el espacio de nombres default apunten a las mismas IP.

kubectl get endpointslices | grep kubernetes

Si todo es correcto, lo último que queda es utilizar el VIP_SERVICE_IP en nuestro Kubeconfig.

sed -i '' "s/${NODE_IP}/${VIP_SERVICE_IP}/g" ~/.kube/config

A partir de ahora, todo el kubectl pasará a través del servicio kubernetes-vip.

62.6 Añadir nodos del plano de control

Para supervisar todo el proceso, se pueden abrir dos pestañas de terminal más.

Primera terminal:

watch kubectl get nodes

Segunda terminal:

watch kubectl get endpointslices

Ahora, ejecutad los comandos siguientes en el segundo y el tercer nodo.

Para RKE2:

# As a root user, create the /etc/rancher/rke2/config.yaml config file with the following content:

mkdir -p /etc/rancher/rke2/
cat <<EOF > /etc/rancher/rke2/config.yaml
# An example of the config.yaml file for an additional server node:
server: https://${VIP_SERVICE_IP}:9345
write-kubeconfig-mode: "0644"
ingress-controller: traefik
tls-san:
  - "${VIP_SERVICE_IP}"
  - "https://${VIP_SERVICE_IP}.sslip.io"
# The one from above
token: ${RKE2_TOKEN}
EOF

# Install RKE2
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="server" sh -

# Enable the RKE2 service with the configuration specified in the config.yaml file

systemctl enable --now rke2-server.service

# Fetch the cluster token to be used later:
RKE2_TOKEN=$(tr -d '\n' < /var/lib/rancher/rke2/server/node-token)

Para K3s:

# Export the VIP_SERVICE_IP in the VM
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
 --server https://${VIP_SERVICE_IP}:6443 --disable=servicelb \
 --write-kubeconfig-mode=644" K3S_TOKEN=foobar sh -

63 Despliegues en entorno aislado con Edge Image Builder

63.1 Introducción

Esta guía mostrará cómo desplegar varios de los componentes de SUSE Telco Cloud completamente aislados en SUSE Linux Micro 6.2 utilizando Edge Image Builder(EIB) (Capítulo 12, Edge Image Builder). Con esto, podréis arrancar en una imagen personalizada y lista para arrancar (CRB) creada por EIB y tener los componentes especificados desplegados en un clúster RKE2 o K3s sin conexión a Internet ni pasos manuales. Esta configuración es muy deseable para los clientes que desean preinstalar todos los artefactos necesarios para el despliegue en su imagen de SO, de modo que estén disponibles inmediatamente al arrancar.

Cubriremos una instalación en entorno aislado de:

Aviso
Aviso

EIB analizará y descargará previamente todas las imágenes referenciadas en los charts de Helm y los manifiestos de Kubernetes proporcionados. Sin embargo, algunos de ellos podrían intentar descargar imágenes de contenedor y crear recursos de Kubernetes basados en ellas durante el tiempo de ejecución. En estos casos tenemos que especificar manualmente las imágenes necesarias en el archivo de definición si queremos configurar un entorno completamente aislado.

63.2 Requisitos previos

Si estáis siguiendo esta guía, se asume que ya estáis familiarizados con EIB (Capítulo 12, Edge Image Builder). Si no es así, por favor, seguid la guía de inicio rápido (Capítulo 5, Clústeres independientes con Edge Image Builder) para comprender mejor los conceptos que se muestran en la práctica a continuación.

63.3 Configuración de red de Libvirt

Nota
Nota

Para realizar una demostración del despliegue en entorno aislado, esta guía se llevará a cabo utilizando una red libvirt simulada y aislada, y la siguiente configuración se adaptará a ello. Para vuestros propios despliegues, es posible que tengáis que modificar la configuración host1.local.yaml que se presentará en el siguiente paso.

Si queréis utilizar la misma configuración de red libvirt, seguid los pasos. De lo contrario, vaya a la Sección 63.4, “Configuración del directorio base”.

Vamos a crear una configuración de red aislada con un rango de direcciones IP 192.168.100.2/24 para DHCP:

cat << EOF > isolatednetwork.xml
<network>
  <name>isolatednetwork</name>
  <bridge name='virbr1' stp='on' delay='0'/>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.2' end='192.168.100.254'/>
    </dhcp>
  </ip>
</network>
EOF

Ahora, lo único que queda es crear la red e iniciarla:

virsh net-define isolatednetwork.xml
virsh net-start isolatednetwork

63.4 Configuración del directorio base

La configuración del directorio base es la misma en todos los componentes, por lo que la estableceremos aquí.

Primero crearemos los subdirectorios necesarios:

export CONFIG_DIR=$HOME/config
mkdir -p $CONFIG_DIR/base-images
mkdir -p $CONFIG_DIR/network
mkdir -p $CONFIG_DIR/kubernetes/helm/values

Aseguraos de añadir la imagen base que planeéis utilizar en el directorio base-images. Esta guía se centrará en la ISO de autoinstalación que encontraréis aquí.

Vamos a copiar la imagen descargada:

cp SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso $CONFIG_DIR/base-images/slemicro.iso
Nota
Nota

EIB nunca modificará la entrada de la imagen base.

Vamos a crear un archivo que contenga la configuración de red deseada:

cat << EOF > $CONFIG_DIR/network/host1.local.yaml
routes:
  config:
  - destination: 0.0.0.0/0
    metric: 100
    next-hop-address: 192.168.100.1
    next-hop-interface: eth0
    table-id: 254
  - destination: 192.168.100.0/24
    metric: 100
    next-hop-address: 192.168.122.1
    next-hop-interface: eth0
    table-id: 254
dns-resolver:
  config:
    server:
    - 192.168.100.1
    - 8.8.8.8
interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: 34:8A:B1:4B:16:E7
  ipv4:
    address:
    - ip: 192.168.100.50
      prefix-length: 24
    dhcp: false
    enabled: true
  ipv6:
    enabled: false
EOF

Esta configuración garantiza que lo siguiente esté presente en los sistemas aprovisionados (utilizando la dirección MAC especificada):

  • una interfaz Ethernet con una dirección IP estática

  • encaminamiento

  • DNS

  • Nombre de host (host1.local)

La estructura de archivos resultante debería tener ahora este aspecto:

├── kubernetes/
│   └── helm/
│       └── values/
├── base-images/
│   └── slemicro.iso
└── network/
    └── host1.local.yaml

63.5 Archivo de definición base

Edge Image Builder utiliza archivos de definición para modificar las imágenes de SUSE Linux Micro. Estos archivos contienen la mayoría de las opciones configurables. Muchas de estas opciones se repetirán en las distintas secciones de los componentes, por lo que las enumeraremos y explicaremos aquí.

Sugerencia
Sugerencia

La lista completa de opciones de personalización en el archivo de definición se puede encontrar en la documentación en sentido ascendente

Echaremos un vistazo a los siguientes campos que estarán presentes en todos los archivos de definición:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
embeddedArtifactRegistry:
  images:
    - ...

La sección image es obligatoria y especifica la imagen de entrada, su arquitectura y tipo, así como el nombre que recibirá la imagen de salida.

La sección operatingSystem es opcional y contiene la configuración para habilitar el inicio de sesión en los sistemas aprovisionados con el nombre de usuario/contraseña root/eib.

La sección kubernetes es opcional y define el tipo y la versión de Kubernetes. Vamos a utilizar la distribución RKE2. Utilizad kubernetes.version: v1.35.4+k3s1 si preferís K3s. A menos que se configure explícitamente mediante el campo kubernetes.nodes, todos los clústeres que iniciemos en esta guía serán de un solo nodo.

La sección embeddedArtifactRegistry incluirá todas las imágenes que solo se referencian y se descargan en tiempo de ejecución para el componente específico.

63.6 Instalación de Rancher

Nota
Nota

El despliegue de Rancher (Capítulo 6, Rancher) que se mostrará estará muy simplificado con fines de demostración. Para vuestros despliegues reales, pueden ser necesarios artefactos adicionales dependiendo de vuestra configuración.

Los activos de la versión Rancher 2.14.2 contienen un archivo rancher-images.txt que enumera todas las imágenes necesarias para una instalación en entorno aislado.

Hay más de 600 imágenes de contenedor en total, lo que significa que la imagen CRB resultante sería de aproximadamente 30 GB. Para nuestra instalación de Rancher, reduciremos esa lista a la configuración funcional más pequeña. A partir de ahí, podéis volver a añadir las imágenes que necesitéis para vuestros despliegues.

Crearemos el archivo de definición e incluiremos la lista de imágenes reducida:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
  manifests:
    urls:
    - https://github.com/cert-manager/cert-manager/releases/download/v1.15.3/cert-manager.crds.yaml
  helm:
    charts:
      - name: rancher
        version: 2.14.2
        repositoryName: rancher-prime
        valuesFile: rancher-values.yaml
        targetNamespace: cattle-system
        createNamespace: true
        installationNamespace: kube-system
      - name: cert-manager
        installationNamespace: kube-system
        createNamespace: true
        repositoryName: jetstack
        targetNamespace: cert-manager
        version: 1.20.1
    repositories:
      - name: jetstack
        url: https://charts.jetstack.io
      - name: rancher-prime
        url: https://charts.rancher.com/server-charts/prime
embeddedArtifactRegistry:
  images:
    - name: registry.rancher.com/rancher/backup-restore-operator:v10.0.2
    - name: registry.rancher.com/rancher/compliance-operator:v1.4.1
    - name: registry.rancher.com/rancher/fleet-agent:v0.15.2
    - name: registry.rancher.com/rancher/fleet:v0.15.2
    - name: registry.rancher.com/rancher/hardened-addon-resizer:1.8.23-build20260413
    - name: registry.rancher.com/rancher/hardened-calico:v3.31.5-build20260415
    - name: registry.rancher.com/rancher/hardened-cluster-autoscaler:v1.10.3-build20260414
    - name: registry.rancher.com/rancher/hardened-cni-plugins:v1.9.1-build20260415
    - name: registry.rancher.com/rancher/hardened-coredns:v1.14.2-build20260416
    - name: registry.rancher.com/rancher/hardened-dns-node-cache:1.26.8-build20260416
    - name: registry.rancher.com/rancher/hardened-etcd:v3.6.7-k3s1-build20260415
    - name: registry.rancher.com/rancher/hardened-flannel:v0.28.4-build20260415
    - name: registry.rancher.com/rancher/hardened-k8s-metrics-server:v0.8.1-build20260413
    - name: registry.rancher.com/rancher/hardened-kubernetes:v1.35.4-rke2r1-build20260416
    - name: registry.rancher.com/rancher/hardened-multus-cni:v4.2.4-build20260310
    - name: registry.rancher.com/rancher/hardened-multus-dynamic-networks-controller:v0.3.7-build20260310
    - name: registry.rancher.com/rancher/hardened-multus-thick:v4.2.4-build20260310
    - name: registry.rancher.com/rancher/hardened-traefik:v3.6.13-build20260416
    - name: registry.rancher.com/rancher/hardened-whereabouts:v0.9.3-build20260408
    - name: registry.rancher.com/rancher/k3s-upgrade:v1.35.4-k3s1
    - name: registry.rancher.com/rancher/klipper-helm:v0.9.17-build20260422
    - name: registry.rancher.com/rancher/klipper-lb:v0.4.16
    - name: registry.rancher.com/rancher/kubectl:v1.35.2
    - name: registry.rancher.com/rancher/kuberlr-kubectl:v7.0.3
    - name: registry.rancher.com/rancher/local-path-provisioner:v0.0.35
    - name: registry.rancher.com/rancher/machine:v0.15.0-rancher142
    - name: registry.rancher.com/rancher/nginx-ingress-controller:v1.14.5-hardened2
    - name: registry.rancher.com/rancher/prom-prometheus:v3.8.1
    - name: registry.rancher.com/rancher/prometheus-federator:v6.0.0
    - name: registry.rancher.com/rancher/pushprox:v0.1.10
    - name: registry.rancher.com/rancher/rancher-agent:v2.14.2
    - name: registry.rancher.com/rancher/rancher-csp-adapter:v9.0.0
    - name: registry.rancher.com/rancher/rancher-webhook:v0.10.6
    - name: registry.rancher.com/rancher/rancher:v2.14.2
    - name: registry.rancher.com/rancher/remotedialer-proxy:v0.7.2
    - name: registry.rancher.com/rancher/rke2-cloud-provider:v1.35.4-0.20260415195656-e51c0636351d-build20260415
    - name: registry.rancher.com/rancher/rke2-runtime:v1.35.4-rke2r1
    - name: registry.rancher.com/rancher/rke2-upgrade:v1.35.4-rke2r1
    - name: registry.rancher.com/rancher/scc-operator:v0.4.1
    - name: registry.rancher.com/rancher/security-scan:v0.9.1
    - name: registry.rancher.com/rancher/shell:v0.1.24
    - name: registry.rancher.com/rancher/supportability-review-app-frontend:v0.19.0
    - name: registry.rancher.com/rancher/supportability-review-internal:latest
    - name: registry.rancher.com/rancher/supportability-review-operator:v0.19.0
    - name: registry.rancher.com/rancher/supportability-review:latest
    - name: registry.rancher.com/rancher/system-agent-installer-k3s:v1.35.4-k3s1
    - name: registry.rancher.com/rancher/system-agent-installer-rke2:v1.35.4-rke2r1
    - name: registry.rancher.com/rancher/system-agent:v0.3.16-suc
    - name: registry.rancher.com/rancher/system-upgrade-controller:v0.19.1
    - name: registry.rancher.com/rancher/turtles:v0.26.2
    - name: registry.rancher.com/rancher/ui-plugin-catalog:4.15.0
    - name: registry.rancher.com/rancher/kubectl:v1.20.2
    - name: registry.rancher.com/rancher/mirrored-ingress-nginx-kube-webhook-certgen:v1.6.7

En comparación con la lista completa de más de 600 imágenes de contenedor, esta versión reducida solo contiene unas 60, lo que hace que la nueva imagen CRB sea de solo unos 7 GB.

También necesitamos crear un archivo de valores de Helm para Rancher:

cat << EOF > $CONFIG_DIR/kubernetes/helm/values/rancher-values.yaml
hostname: 192.168.100.50.sslip.io
replicas: 1
bootstrapPassword: "adminadminadmin"
systemDefaultRegistry: registry.rancher.com
useBundledSystemChart: true
EOF
Aviso
Aviso

Establecer systemDefaultRegistry en registry.rancher.com permite a Rancher buscar automáticamente imágenes en el registro de artefactos integrado que se inicia dentro de la imagen CRB al arrancar. Omitir este campo puede provocar que no se encuentren las imágenes de contenedor en el nodo.

Vamos a compilar la imagen:

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

La salida debería ser similar a la siguiente:

Downloading file: dl-manifest-1.yaml 100% |██████████████████████████████████████████████████████████████████████████████| (583/583 kB, 12 MB/s)
Pulling selected Helm charts... 100% |███████████████████████████████████████████████████████████████████████████████████████████| (2/2, 3 it/s)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Rpm .......................... [SKIPPED]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% |███████████████████████████████████████████████████████████████████████████| (56/56, 8 it/min)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Downloading file: rke2-images-core.linux-amd64.tar.zst 100% |███████████████████████████████████████████████████████████| (644/644 MB, 29 MB/s)
Downloading file: rke2-images-cilium.linux-amd64.tar.zst 100% |█████████████████████████████████████████████████████████| (400/400 MB, 29 MB/s)
Downloading file: rke2.linux-amd64.tar.gz 100% |███████████████████████████████████████████████████████████████████████████| (36/36 MB, 30 MB/s)
Downloading file: sha256sum-amd64.txt 100% |█████████████████████████████████████████████████████████████████████████████| (4.3/4.3 kB, 29 MB/s)
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

Una vez que se aprovisione un nodo que utilice la imagen compilada, podemos verificar la instalación de Rancher:

/var/lib/rancher/rke2/bin/kubectl get all -n cattle-system --kubeconfig /etc/rancher/rke2/rke2.yaml

El resultado debería ser similar al siguiente, mostrando que todo se ha desplegado correctamente:

NAME                                            READY   STATUS      RESTARTS   AGE
pod/helm-operation-6l6ld                        0/2     Completed   0          107s
pod/helm-operation-8tk2v                        0/2     Completed   0          2m2s
pod/helm-operation-blnrr                        0/2     Completed   0          2m49s
pod/helm-operation-hdcmt                        0/2     Completed   0          3m19s
pod/helm-operation-m74c7                        0/2     Completed   0          97s
pod/helm-operation-qzzr4                        0/2     Completed   0          2m30s
pod/helm-operation-s9jh5                        0/2     Completed   0          3m
pod/helm-operation-tq7ts                        0/2     Completed   0          2m41s
pod/rancher-99d599967-ftjkk                     1/1     Running     0          4m15s
pod/rancher-webhook-79798674c5-6w28t            1/1     Running     0          2m27s
pod/system-upgrade-controller-56696956b-trq5c   1/1     Running     0          104s

NAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/rancher           ClusterIP   10.43.255.80   <none>        80/TCP,443/TCP   4m15s
service/rancher-webhook   ClusterIP   10.43.7.238    <none>        443/TCP          2m27s

NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/rancher                     1/1     1            1           4m15s
deployment.apps/rancher-webhook             1/1     1            1           2m27s
deployment.apps/system-upgrade-controller   1/1     1            1           104s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/rancher-99d599967                     1         1         1       4m15s
replicaset.apps/rancher-webhook-79798674c5            1         1         1       2m27s
replicaset.apps/system-upgrade-controller-56696956b   1         1         1       104s

Y cuando vamos a https://192.168.100.50.sslip.io e iniciamos sesión con la contraseña adminadminadmin que establecimos anteriormente, nos recibe el panel de control de Rancher:

air gapped rancher

63.7 Instalación de SUSE Security

A diferencia de la instalación de Rancher, la instalación de SUSE Security no requiere ningún manejo especial en EIB. EIB aislará automáticamente cada imagen requerida por su componente subyacente NeuVector.

Crearemos el archivo de definición:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: neuvector-crd
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector-values.yaml
      - name: neuvector
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector-values.yaml
    repositories:
      - name: rancher-charts
        url: https://charts.rancher.io/

También crearemos un archivo de valores de Helm para NeuVector:

cat << EOF > $CONFIG_DIR/kubernetes/helm/values/neuvector-values.yaml
controller:
  replicas: 1
manager:
  enabled: false
cve:
  scanner:
    enabled: false
    replicas: 1
k3s:
  enabled: true
crdwebhook:
  enabled: false
EOF

Vamos a compilar la imagen:

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

La salida debería ser similar a la siguiente:

Pulling selected Helm charts... 100% |███████████████████████████████████████████████████████████████████████████████████████████| (2/2, 4 it/s)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Rpm .......................... [SKIPPED]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% |██████████████████████████████████████████████████████████████████████████████| (5/5, 13 it/min)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

Una vez que se aprovisione un nodo que utilice la imagen compilada, podemos verificar la instalación de SUSE Security:

/var/lib/rancher/rke2/bin/kubectl get all -n neuvector --kubeconfig /etc/rancher/rke2/rke2.yaml

El resultado debería ser similar al siguiente, mostrando que todo se ha desplegado correctamente:

NAME                                            READY   STATUS      RESTARTS   AGE
pod/neuvector-cert-upgrader-job-bxbnz           0/1     Completed   0          3m39s
pod/neuvector-controller-pod-7d854bfdc7-nhxjf   1/1     Running     0          3m44s
pod/neuvector-enforcer-pod-ct8jm                1/1     Running     0          3m44s

NAME                                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
service/neuvector-svc-admission-webhook   ClusterIP   10.43.234.241   <none>        443/TCP                         3m44s
service/neuvector-svc-controller          ClusterIP   None            <none>        18300/TCP,18301/TCP,18301/UDP   3m44s
service/neuvector-svc-crd-webhook         ClusterIP   10.43.50.190    <none>        443/TCP                         3m44s

NAME                                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/neuvector-enforcer-pod   1         1         1       1            1           <none>          3m44s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/neuvector-controller-pod   1/1     1            1           3m44s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/neuvector-controller-pod-7d854bfdc7   1         1         1       3m44s

NAME                                        SCHEDULE    TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/neuvector-cert-upgrader-pod   0 0 1 1 *   <none>     True      0        <none>          3m44s
cronjob.batch/neuvector-updater-pod         0 0 * * *   <none>     False     0        <none>          3m44s

NAME                                    STATUS     COMPLETIONS   DURATION   AGE
job.batch/neuvector-cert-upgrader-job   Complete   1/1           7s         3m39s

63.8 Instalación de SUSE Storage

La documentación oficial de Longhorn contiene un longhorn-images.txt archivo que enumera todas las imágenes necesarias para una instalación en entorno aislado. Incluiremos sus equivalentes reflejados desde el registro de contenedores de Rancher en nuestro archivo de definición. Vamos a crearlo:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
  packages:
    sccRegistrationCode: [reg-code]
    packageList:
      - open-iscsi
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: suse-storage
        releaseName: longhorn
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        version: 1.11.2
    repositories:
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
embeddedArtifactRegistry:
    registries:
      - uri: dp.apps.rancher.io
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-attacher:4.11.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-provisioner:5.3.0-14.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-resizer:2.1.0-6.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-snapshotter:8.5.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-livenessprobe:2.18.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-node-driver-registrar:2.16.0-13.2
    - name: dp.apps.rancher.io/containers/longhorn-backing-image-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-engine:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-instance-manager:1.11.2-4.3
    - name: dp.apps.rancher.io/containers/longhorn-manager:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-share-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-ui:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/rancher-support-bundle-kit:0.0.84-9.4
Nota
Nota

Observaréis que el archivo de definición enumera el paquete open-iscsi. Esto es necesario ya que Longhorn depende de un daemon iscsiadm que se ejecuta en los diferentes nodos para proporcionar volúmenes persistentes a Kubernetes.

Vamos a compilar la imagen:

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

La salida debería ser similar a la siguiente:

Setting up Podman API listener...
Pulling selected Helm charts... 100% |██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| (2/2, 3 it/s)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Resolving package dependencies...
Rpm .......................... [SUCCESS]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% |███████████████████████████████████████████████████████████████████████████████████████████████████████████| (15/15, 20956 it/s)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Downloading file: rke2-images-core.linux-amd64.tar.zst 100% (782/782 MB, 108 MB/s)
Downloading file: rke2-images-cilium.linux-amd64.tar.zst 100% (367/367 MB, 104 MB/s)
Downloading file: rke2.linux-amd64.tar.gz 100% (34/34 MB, 108 MB/s)
Downloading file: sha256sum-amd64.txt 100% (3.9/3.9 kB, 7.5 MB/s)
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

Una vez que se aprovisione un nodo que utilice la imagen compilada, podemos verificar la instalación de Longhorn:

/var/lib/rancher/rke2/bin/kubectl get all -n longhorn-system --kubeconfig /etc/rancher/rke2/rke2.yaml

El resultado debería ser similar al siguiente, mostrando que todo se ha desplegado correctamente:

NAME                                                    READY   STATUS    RESTARTS   AGE
pod/csi-attacher-787fd9c6c8-sf42d                       1/1     Running   0          2m28s
pod/csi-attacher-787fd9c6c8-tb82p                       1/1     Running   0          2m28s
pod/csi-attacher-787fd9c6c8-zhc6s                       1/1     Running   0          2m28s
pod/csi-provisioner-74486b95c6-b2v9s                    1/1     Running   0          2m28s
pod/csi-provisioner-74486b95c6-hwllt                    1/1     Running   0          2m28s
pod/csi-provisioner-74486b95c6-mlrpk                    1/1     Running   0          2m28s
pod/csi-resizer-859d4557fd-t54zk                        1/1     Running   0          2m28s
pod/csi-resizer-859d4557fd-vdt5d                        1/1     Running   0          2m28s
pod/csi-resizer-859d4557fd-x9kh4                        1/1     Running   0          2m28s
pod/csi-snapshotter-6f69c6c8cc-r62gr                    1/1     Running   0          2m28s
pod/csi-snapshotter-6f69c6c8cc-vrwjn                    1/1     Running   0          2m28s
pod/csi-snapshotter-6f69c6c8cc-z65nb                    1/1     Running   0          2m28s
pod/engine-image-ei-4623b511-9vhkb                      1/1     Running   0          3m13s
pod/instance-manager-6f95fd57d4a4cd0459e469d75a300552   1/1     Running   0          2m43s
pod/longhorn-csi-plugin-gx98x                           3/3     Running   0          2m28s
pod/longhorn-driver-deployer-55f9c88499-fbm6q           1/1     Running   0          3m28s
pod/longhorn-manager-dpdp7                              2/2     Running   0          3m28s
pod/longhorn-ui-59c85fcf94-gg5hq                        1/1     Running   0          3m28s
pod/longhorn-ui-59c85fcf94-s49jc                        1/1     Running   0          3m28s

NAME                                  TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/longhorn-admission-webhook    ClusterIP   10.43.77.89    <none>        9502/TCP   3m28s
service/longhorn-backend              ClusterIP   10.43.56.17    <none>        9500/TCP   3m28s
service/longhorn-conversion-webhook   ClusterIP   10.43.54.73    <none>        9501/TCP   3m28s
service/longhorn-frontend             ClusterIP   10.43.22.82    <none>        80/TCP     3m28s
service/longhorn-recovery-backend     ClusterIP   10.43.45.143   <none>        9503/TCP   3m28s

NAME                                      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/engine-image-ei-4623b511   1         1         1       1            1           <none>          3m13s
daemonset.apps/longhorn-csi-plugin        1         1         1       1            1           <none>          2m28s
daemonset.apps/longhorn-manager           1         1         1       1            1           <none>          3m28s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/csi-attacher               3/3     3            3           2m28s
deployment.apps/csi-provisioner            3/3     3            3           2m28s
deployment.apps/csi-resizer                3/3     3            3           2m28s
deployment.apps/csi-snapshotter            3/3     3            3           2m28s
deployment.apps/longhorn-driver-deployer   1/1     1            1           3m28s
deployment.apps/longhorn-ui                2/2     2            2           3m28s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/csi-attacher-787fd9c6c8               3         3         3       2m28s
replicaset.apps/csi-provisioner-74486b95c6            3         3         3       2m28s
replicaset.apps/csi-resizer-859d4557fd                3         3         3       2m28s
replicaset.apps/csi-snapshotter-6f69c6c8cc            3         3         3       2m28s
replicaset.apps/longhorn-driver-deployer-55f9c88499   1         1         1       3m28s
replicaset.apps/longhorn-ui-59c85fcf94                2         2         2       3m28s

63.9 Instalación de KubeVirt y CDI

Los charts de Helm tanto para KubeVirt como para CDI solo instalan sus respectivos operadores. Depende de los operadores desplegar el resto de los sistemas, lo que significa que tendremos que incluir todas las imágenes de contenedor necesarias en nuestro archivo de definición. Vamos a crearlo:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: kubevirt
        repositoryName: suse-edge
        version: 306.0.2+up0.7.0
        targetNamespace: kubevirt-system
        createNamespace: true
        installationNamespace: kube-system
      - name: cdi
        repositoryName: suse-edge
        version: 306.0.2+up0.7.0
        targetNamespace: cdi-system
        createNamespace: true
        installationNamespace: kube-system
    repositories:
      - name: suse-edge
        url: oci://registry.suse.com/edge/charts
embeddedArtifactRegistry:
  images:
    - name: registry.suse.com/suse/sles/15.7/cdi-apiserver:1.64.0-150700.9.6.1
    - name: registry.suse.com/suse/sles/15.7/cdi-controller:1.64.0-150700.9.6.1
    - name: registry.suse.com/suse/sles/15.7/cdi-operator:1.64.0-150700.9.6.1
    - name: registry.suse.com/suse/sles/15.7/cdi-uploadproxy:1.64.0-150700.9.6.1
    - name: registry.suse.com/suse/sles/15.7/virt-api:1.7.0-150700.3.16.2
    - name: registry.suse.com/suse/sles/15.7/virt-controller:1.7.0-150700.3.16.2
    - name: registry.suse.com/suse/sles/15.7/virt-handler:1.7.0-150700.3.16.2
    - name: registry.suse.com/suse/sles/15.7/virt-launcher:1.7.0-150700.3.16.2
    - name: registry.suse.com/suse/sles/15.7/virt-operator:1.7.0-150700.3.16.2

Vamos a compilar la imagen:

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

La salida debería ser similar a la siguiente:

Pulling selected Helm charts... 100% |███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| (2/2, 48 it/min)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Rpm .......................... [SKIPPED]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% |██████████████████████████████████████████████████████████████████████████████████████████████████████████| (15/15, 4 it/min)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

Una vez que se aprovisione un nodo que utilice la imagen compilada, podemos verificar la instalación tanto de KubeVirt como de CDI.

Verify KubeVirt:

/var/lib/rancher/rke2/bin/kubectl get all -n kubevirt-system --kubeconfig /etc/rancher/rke2/rke2.yaml

El resultado debería ser similar al siguiente, mostrando que todo se ha desplegado correctamente:

NAME                                  READY   STATUS    RESTARTS   AGE
pod/virt-api-59cb997648-mmt67         1/1     Running   0          2m34s
pod/virt-controller-69786b785-7cc96   1/1     Running   0          2m8s
pod/virt-controller-69786b785-wq2dz   1/1     Running   0          2m8s
pod/virt-handler-2l4dm                1/1     Running   0          2m8s
pod/virt-operator-7c444cff46-nps4l    1/1     Running   0          3m1s
pod/virt-operator-7c444cff46-r25xq    1/1     Running   0          3m1s

NAME                                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubevirt-operator-webhook     ClusterIP   10.43.167.109   <none>        443/TCP   2m36s
service/kubevirt-prometheus-metrics   ClusterIP   None            <none>        443/TCP   2m36s
service/virt-api                      ClusterIP   10.43.18.202    <none>        443/TCP   2m36s
service/virt-exportproxy              ClusterIP   10.43.142.188   <none>        443/TCP   2m36s

NAME                          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/virt-handler   1         1         1       1            1           kubernetes.io/os=linux   2m8s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/virt-api          1/1     1            1           2m34s
deployment.apps/virt-controller   2/2     2            2           2m8s
deployment.apps/virt-operator     2/2     2            2           3m1s

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/virt-api-59cb997648         1         1         1       2m34s
replicaset.apps/virt-controller-69786b785   2         2         2       2m8s
replicaset.apps/virt-operator-7c444cff46    2         2         2       3m1s

NAME                            AGE    PHASE
kubevirt.kubevirt.io/kubevirt   3m1s   Deployed

Verify CDI:

/var/lib/rancher/rke2/bin/kubectl get all -n cdi-system --kubeconfig /etc/rancher/rke2/rke2.yaml

El resultado debería ser similar al siguiente, mostrando que todo se ha desplegado correctamente:

NAME                                   READY   STATUS    RESTARTS   AGE
pod/cdi-apiserver-5598c9bf47-pqfxw     1/1     Running   0          3m44s
pod/cdi-deployment-7cbc5db7f8-g46z7    1/1     Running   0          3m44s
pod/cdi-operator-777c865745-2qcnj      1/1     Running   0          3m48s
pod/cdi-uploadproxy-646f4cd7f7-fzkv7   1/1     Running   0          3m44s

NAME                             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/cdi-api                  ClusterIP   10.43.2.224    <none>        443/TCP    3m44s
service/cdi-prometheus-metrics   ClusterIP   10.43.237.13   <none>        8080/TCP   3m44s
service/cdi-uploadproxy          ClusterIP   10.43.114.91   <none>        443/TCP    3m44s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cdi-apiserver     1/1     1            1           3m44s
deployment.apps/cdi-deployment    1/1     1            1           3m44s
deployment.apps/cdi-operator      1/1     1            1           3m48s
deployment.apps/cdi-uploadproxy   1/1     1            1           3m44s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/cdi-apiserver-5598c9bf47     1         1         1       3m44s
replicaset.apps/cdi-deployment-7cbc5db7f8    1         1         1       3m44s
replicaset.apps/cdi-operator-777c865745      1         1         1       3m48s
replicaset.apps/cdi-uploadproxy-646f4cd7f7   1         1         1       3m44s

63.10 Instalación de SUSE Private Registry

Para incluir SUSE Private Registry en una ampliación en entorno aislado, debemos actualizar el archivo de definición para incluir el chart de Helm requerido, así como los artefactos integrados para las nuevas imágenes.

Actualicemos el archivo de definición:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: metallb
        version: 306.0.2+up0.15.3
        targetNamespace: metallb-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
      - name: suse-storage
        releaseName: longhorn
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        version: 1.11.2
      - name: private-registry-helm
        createNamespace: true
        installationNamespace: kube-system
        repositoryName: privateregistry
        targetNamespace: suse-private-registry
        valuesFile: privateregistry.yaml
        version: 1.1.1
    repositories:
      - name: privateregistry
        authentication:
          username: ${PRIVATE_REGISTRY_USERNAME}
          password: ${PRIVATE_REGISTRY_PASSWORD}
        plainHTTP: false
        skipTLSVerify: false
        url: oci://registry.suse.com/private-registry
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
embeddedArtifactRegistry:
  registries:
    - uri: registry.suse.com
      authentication:
        username: ${PRIVATE_REGISTRY_USERNAME}
        password: ${PRIVATE_REGISTRY_PASSWORD}
    - uri: dp.apps.rancher.io
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
  images:
    - name: registry.suse.com/private-registry/harbor-core:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-jobservice:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-portal:1.1.1-1.20
    - name: registry.suse.com/private-registry/harbor-registry:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-registryctl:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-trivy-adapter:1.1.1-1.24
Nota
Nota

Necesitaréis ciertas credenciales, que pueden obtenerse siguiendo la documentación oficial de SUSE Private Registry. También deberéis modificar las variables ${PRIVATE_REGISTRY_USERNAME} y ${PRIVATE_REGISTRY_PASSWORD}. Aseguraos de enumerar las imágenes que contienen las versiones de los componentes que necesitáis.

Ahora necesitamos añadir los manifiestos de Kubernetes requeridos para configurar correctamente SUSE Private Registry.

Debe modificar el ${MGMT_CLUSTER_REGISTRY_IP} con una IP estática reservada para SUSE Private Registry en los siguientes archivos:

  1. kubernetes/manifests/metallb-registry.yaml

    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: private-registry
      namespace: metallb-system
    spec:
      ipAddressPools:
      - private-registry-pool
    ---
    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: private-registry-pool
      namespace: metallb-system
    spec:
      addresses:
      - ${MGMT_CLUSTER_REGISTRY_IP}/32
      serviceAllocation:
        namespaces:
        - suse-private-registry
  2. kubernetes/helm/values/privateregistry.yaml

    core:
      secretName: suse-registry-tls
    expose:
      tls:
        certSource: secret
        enabled: true
        secret:
          secretName: suse-registry-tls
      type: loadBalancer
    externalURL: https://${MGMT_CLUSTER_REGISTRY_IP}
    persistence:
      persistentVolumeClaim:
        registry:
          size: 20Gi

Finalmente, el kubernetes/manifests/suse-private-registry-creds.yaml debe crearse con el siguiente contenido:

apiVersion: v1
kind: Secret
metadata:
  name: suse-registry
  namespace: suse-private-registry
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ${DOCKER_CONFIG_JSON_BASE64}
---
apiVersion: v1
kind: Secret
metadata:
    name: suse-registry-tls
    namespace: suse-private-registry
type: kubernetes.io/tls
data:
    tls.crt: ${TLS_CRT_BASE64}
    tls.key: ${TLS_KEY_BASE64}

Para configurar correctamente el json de configuración de docker (base64) para ${DOCKER_CONFIG_JSON_BASE64}, ejecute:

# ${DOCKER_CONFIG_JSON_BASE64} CONTENT
echo -n '{"auths": {"<MGMT_CLUSTER_REGISTRY_IP>": {"username": "<USERNAME>", "password": "<PASSWORD>", "auth": "<AUTH>"}}}' | base64

Donde la IP es la misma que el ${MGMT_CLUSTER_REGISTRY_IP} configurado anteriormente, y el username, password y auth se pueden obtener de la documentación oficial de SUSE Private Registry.

Para generar el certificado TLS y la clave codificados en base64 (tls.crt y tls.key) para ${TLS_CRT_BASE64} y ${TLS_KEY_BASE64}, puede crear los suyos propios ejecutando:

# Generate a self-signed certificate and key
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes

# Convert them to base64 for the suse-private-registry-creds.yaml file
cat cert.pem | base64 -w 0
cat key.pem | base64 -w 0

Verifique SUSE Private Registry:

/var/lib/rancher/rke2/bin/kubectl get pods -n suse-private-registry --kubeconfig /etc/rancher/rke2/rke2.yaml

El resultado debería ser similar al siguiente, mostrando que todo se ha desplegado correctamente:

NAME                                                      READY   STATUS    RESTARTS   AGE
pod/private-registry-harbor-core-588fd4876f-8tqnv         1/1     Running   0          4m30s
pod/private-registry-harbor-database-0                    1/1     Running   0          4m30s
pod/private-registry-harbor-jobservice-7658f97fbc-4vq6n   1/1     Running   0          4m30s
pod/private-registry-harbor-portal-5455ccc4bc-jpmt5       1/1     Running   0          4m30s
pod/private-registry-harbor-redis-0                       1/1     Running   0          4m30s
pod/private-registry-harbor-registry-5648b9d89-wdswz      2/2     Running   0          4m30s
pod/private-registry-harbor-trivy-0                       1/1     Running   0          4m30s

63.11 Instalación de Metal3

Al implementar Metal3 en un entorno aislado (air-gapped) utilizando EIB y Hauler, se requiere una configuración especial para la imagen del Ironic Python Agent (IPA). La imagen IPA es utilizada por Metal3 para la inspección y el aprovisionamiento de equipos sin sistema operativo.

Nota
Nota

Para obtener más información sobre la instalación y configuración de Metal3, incluida la configuración de MetalLB, consulte Capítulo 4, Despliegues automatizados de BMC con Metal3.

Para incluir Metal3 en una ampliación en un entorno aislado, debe:

  1. Añada el gráfico de Helm de Metal3 a su archivo de definición

  2. Añada la imagen IPA al registro de artefactos integrado

  3. Cree un archivo de valores de Helm con useHauler: true

Añada lo siguiente a la sección kubernetes.helm.charts de su archivo de definición:

  helm:
    charts:
      - name: metal3
        version: 306.0.29+up0.15.0
        targetNamespace: metal3-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
        valuesFile: metal3-values.yaml

Añada la imagen IPA a la sección embeddedArtifactRegistry.images:

embeddedArtifactRegistry:
  images:
    - name: registry.suse.com/edge/3.6/ironic-python-agent:3.0.9

Cree un archivo de valores de Helm para Metal3:

cat << EOF > $CONFIG_DIR/kubernetes/helm/values/metal3-values.yaml
global:
  ironicIP: <STATIC_IRONIC_IP>
metal3-ironic:
  ipa:
    useHauler: true
EOF
Importante
Importante

El valor metal3-ironic.ipa.useHauler debe establecerse en true (valor booleano) al realizar la ampliación en entornos aislados utilizando EIB/Hauler. Esto indica a Metal3 que recupere la imagen IPA del registro de artefactos integrado en lugar de intentar descargarla de internet.

63.12 Solución de problemas

Si encuentra algún problema durante la creación de las imágenes o desea realizar más pruebas y depurar el proceso, consulte la documentación en sentido ascendente.

64 Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi

Esta sección explica cómo generar imágenes actualizadas de SUSE Linux Micro para ser utilizadas con Edge Image Builder, con Cluster API (CAPI) + Metal3, o para escribir la imagen de disco directamente en un dispositivo de bloque. Este proceso es útil en situaciones en las que se requiere incluir los últimos parches en las imágenes de arranque inicial del sistema (para minimizar la transferencia de parches tras la instalación), o para escenarios en los que se utiliza CAPI, donde se prefiere reinstalar el sistema operativo con una nueva imagen en lugar de actualizar los hosts in situ.

Este proceso utiliza Kiwi para ejecutar la creación de la imagen. SUSE Telco Cloud incluye una versión en contenedores que simplifica el proceso general con una utilidad auxiliar integrada, lo que permite especificar el perfil de destino requerido. El perfil define el tipo de imagen de salida requerida, con las más comunes enumeradas a continuación:

  • "Base" - Una imagen de disco de SUSE Linux Micro con un conjunto de paquetes reducido (incluye podman).

  • "Base-SelfInstall" - Una imagen SelfInstall basada en la "Base" anterior.

  • "Base-RT" - Igual que "Base" anterior, pero utilizando un kernel en tiempo real (rt) en su lugar.

  • "Base-RT-SelfInstall" - Una imagen SelfInstall basada en la "Base-RT" anterior

  • "Default" - Una imagen de disco de SUSE Linux Micro basada en la "Base" anterior, pero con algunas herramientas más, incluyendo la pila de virtualización, Cockpit y salt-minion.

  • "Default-SelfInstall" - Una imagen SelfInstall basada en la "Default" anterior

Consulte la documentación de SUSE Linux Micro 6.2 para obtener más detalles.

Nota
Nota

Este proceso funciona tanto para arquitecturas AMD64/Intel 64 como AArch64, pero es necesario utilizar un host de compilación con la misma arquitectura que las imágenes que se están creando. En otras palabras, para crear una imagen AArch64, es necesario utilizar un host de compilación AArch64, y viceversa para AMD64/Intel 64; las compilaciones cruzadas no son compatibles en este momento.

64.1 Requisitos previos

El generador de imágenes Kiwi requiere lo siguiente:

  • Un host de SUSE Linux Micro 6.2 (\"sistema de compilación\") con la misma arquitectura que la imagen que se está compilando.

  • El sistema de compilación debe estar ya registrado a través de SUSEConnect (el registro se utiliza para extraer los paquetes más recientes de los repositorios de SUSE)

  • Una conexión a internet que se pueda utilizar para obtener los paquetes necesarios. Si se conecta a través de un proxy, el host de compilación debe estar preconfigurado.

  • SELinux debe estar desactivado en el host de compilación (ya que el etiquetado de SELinux tiene lugar en el contenedor y puede entrar en conflicto con la directiva del host)

  • Al menos 10 GB de espacio libre en disco para alojar la imagen del contenedor, la raíz de compilación y la(s) imagen(es) de salida resultante(s)

64.2 Inicio

Debido a ciertas limitaciones, actualmente es necesario desactivar SELinux. Conéctese al host de compilación de imágenes de SUSE Linux Micro 6.2 y asegúrese de que SELinux esté desactivado:

# setenforce 0

Cree un directorio de salida para compartirlo con el contenedor de compilación de Kiwi y guardar las imágenes resultantes:

# mkdir ~/output

Descargue la última imagen del generador Kiwi desde el repositorio de SUSE:

# podman pull registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1
(...)

64.3 Compilación de la imagen predeterminada

Este es el comportamiento predeterminado del contenedor de imágenes Kiwi si no se proporcionan argumentos durante la ejecución de la imagen del contenedor. El siguiente comando ejecuta podman con dos directorios asignados al contenedor:

  • El directorio del repositorio de paquetes de SUSE Linux Micro /etc/zypp/repos.d del host subyacente.

  • El directorio de salida ~/output creado anteriormente.

El contenedor de imágenes Kiwi requiere ejecutar el script auxiliar build-image de la siguiente manera:

# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image
(...)
Nota
Nota

Se espera que, si ejecuta este script por primera vez, falle poco después de iniciarse con \"ERROR: La prueba inicial del dispositivo de bucle falló, vuelva a intentar la ejecución del contenedor.\", esto es un síntoma de que los dispositivos de bucle creados en el sistema host subyacente no son visibles inmediatamente dentro de la imagen del contenedor. Simplemente vuelva a ejecutar el comando y debería proceder sin problemas.

Tras unos minutos, las imágenes se pueden encontrar en el directorio de salida local:

(...)
INFO: Image build successful, generated images are available in the 'output' directory.

# ls -1 output/
SLE-Micro.x86_64-6.2.changes
SLE-Micro.x86_64-6.2.packages
SLE-Micro.x86_64-6.2.raw
SLE-Micro.x86_64-6.2.verified
build
kiwi.result
kiwi.result.json

64.4 Creación de imágenes con otros perfiles

Para crear diferentes perfiles de imagen, se utiliza la opción de comando \"-p\" en el script auxiliar de imagen de contenedor Kiwi. Por ejemplo, para crear la imagen ISO \"Default-SelfInstall\":

# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image -p Default-SelfInstall
(...)
Nota
Nota

Para evitar la pérdida de datos, Kiwi se negará a ejecutarse si hay imágenes en el directorio output. Es necesario eliminar el contenido del directorio de salida antes de continuar con rm -f output/*.

Alternativamente, para crear una imagen ISO SelfInstall con el kernel RealTime (\"kernel-rt\"):

# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image -p Base-RT-SelfInstall
(...)

64.5 Creación de imágenes con tamaños de sector grandes

Algunos hardware requieren una imagen con un tamaño de sector grande, es decir, 4096 bytes en lugar de los 512 bytes estándar. El generador Kiwi en contenedores admite la capacidad de generar imágenes con un tamaño de bloque grande especificando el parámetro "-b". Por ejemplo, para crear una imagen \"Default-SelfInstall\" con un tamaño de sector grande:

# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image -p Default-SelfInstall -b
(...)

64.6 Uso de un archivo de definición de imagen Kiwi personalizado

Para casos de uso avanzados, se puede utilizar un archivo de definición de imagen Kiwi personalizado (SL-Micro.kiwi) junto con los scripts posteriores a la compilación necesarios. Esto requiere anular las definiciones predeterminadas preempaquetadas por el equipo de SUSE Telco Cloud.

Cree un nuevo directorio y asígnelo a la imagen del contenedor donde el guion auxiliar está buscando (/micro-sdk/defs):

# mkdir ~/mydefs/
# cp /path/to/SL-Micro.kiwi ~/mydefs/
# cp /path/to/config.sh ~/mydefs/
# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output -v ~/mydefs/:/micro-sdk/defs/ \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image
(...)
Aviso
Aviso

Esto solo es necesario para casos de uso avanzados y puede causar problemas de soporte. Póngase en contacto con su representante de SUSE para obtener más consejos y orientación.

Para obtener los archivos de definición de imagen Kiwi predeterminados incluidos en el contenedor, se pueden utilizar los siguientes comandos:

$ podman create --name kiwi-builder registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1
$ podman cp kiwi-builder:/micro-sdk/defs/SL-Micro.kiwi .
$ podman cp kiwi-builder:/micro-sdk/defs/SL-Micro.kiwi.4096 .
$ podman rm kiwi-builder
$ ls ./SL-Micro.*
(...)

65 Uso de ClusterClass para desplegar clústeres en sentido descendente

65.1 Introducción

El aprovisionamiento de clústeres de Kubernetes es una tarea compleja que exige una gran experiencia en la configuración de los componentes del clúster. A medida que las configuraciones se vuelven más complejas, o a medida que las demandas de los diferentes proveedores introducen numerosas definiciones de recursos específicas del proveedor, la creación de clústeres puede resultar desalentadora. Afortunadamente, Kubernetes Cluster API (CAPI) ofrece un enfoque más elegante y declarativo que se ve mejorado aún más por ClusterClass. Esta funcionalidad introduce un modelo basado en plantillas, que os permite definir una clase de clúster reutilizable que encapsula la complejidad y promueve la coherencia.

65.2 ¿Qué es ClusterClass?

El proyecto CAPI introdujo la funcionalidad ClusterClass como un cambio de paradigma en la gestión del ciclo de vida de los clústeres de Kubernetes mediante la adopción de una metodología basada en plantillas para la instanciación de clústeres. En lugar de definir recursos de forma independiente para cada clúster, los usuarios definen una ClusterClass, que sirve como un plano completo y reutilizable. Esta representación abstracta encapsula el estado y la configuración deseados de un clúster de Kubernetes, lo que permite la creación rápida y coherente de múltiples clústeres que cumplen con las especificaciones definidas. Esta abstracción reduce la carga de configuración, lo que da lugar a manifiestos de ampliación más manejables. Esto significa que los componentes principales de un clúster de carga de trabajo se definen a nivel de clase, lo que permite a los usuarios utilizar estas plantillas como variantes de clúster de Kubernetes que pueden reutilizarse una o varias veces para el aprovisionamiento de clústeres. La implementación de ClusterClass aporta varias ventajas clave que abordan los desafíos inherentes de la gestión tradicional de CAPI a escala:

  • Reducción sustancial de la complejidad y de la verbosidad de YAML

  • Procesos de mantenimiento y actualización optimizados

  • Consistencia y estandarización mejoradas en todas las implementaciones

  • Capacidades mejoradas de escalabilidad y automatización

  • Gestión declarativa y control de versiones robusto

clusterclass v1beta2

65.3 Ejemplo del archivo de aprovisionamiento de CAPI actual

El despliegue de un clúster de Kubernetes que aprovecha Cluster API (CAPI) con los proveedores CAPRKE2 (plano de control e iniciar) y CAPM3 (infraestructura) requiere definir varios recursos personalizados. Estos recursos definen el estado deseado del clúster y su infraestructura subyacente, lo que permite a CAPI orquestar el ciclo de vida de aprovisionamiento y gestión. El fragmento de código a continuación ilustra los tipos de recursos que deben configurarse para instanciar un clúster de Kubernetes solo con nodos del plano de control:

  • Cluster: Este recurso encapsula configuraciones de alto nivel, incluida la topología de red que regirá la comunicación entre nodos y la detección de servicios. Además, establece vínculos esenciales con la especificación del plano de control y el recurso del proveedor de infraestructura designado, informando así a CAPI sobre la arquitectura de clúster deseada y la infraestructura subyacente sobre la que se aprovisionará.

  • Metal3Cluster: Este recurso define atributos a nivel de infraestructura exclusivos de Metal3, por ejemplo, el punto de conexión externo a través del cual será accesible el servidor de la API de Kubernetes.

  • RKE2ControlPlane: El recurso RKE2ControlPlane define las características y el comportamiento de los nodos del plano de control del clúster. Dentro de esta especificación, se configuran parámetros como el número deseado de réplicas del plano de control (crucial para garantizar la alta disponibilidad y la tolerancia a fallos), la versión específica de la distribución de Kubernetes (alineada con la versión de RKE2 elegida) y la estrategia para implementar actualizaciones en los componentes del plano de control. Además, este recurso dicta la interfaz de red (CNI) que se empleará dentro del clúster y facilita la inyección de configuraciones específicas del agente, a menudo aprovechando Ignition para un aprovisionamiento fluido y automatizado de los agentes de RKE2 en los nodos del plano de control.

  • Metal3MachineTemplate: Este recurso sirve como modelo para crear las instancias de computación individuales que forman los nodos del plano de control del clúster.

  • Metal3DataTemplate: Como complemento de Metal3MachineTemplate, el recurso Metal3DataTemplate permite especificar metadatos adicionales para las instancias de máquina recién aprovisionadas.

    apiVersion: cluster.x-k8s.io/v1beta2
    kind: Cluster
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
      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: emea-spa-cluster-3
      infrastructureRef:
        apiGroup: infrastructure.cluster.x-k8s.io
        kind: Metal3Cluster
        name: emea-spa-cluster-3
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3Cluster
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      controlPlaneEndpoint:
        host: 192.168.122.203
        port: 6443
      cloudProviderEnabled: false
    ---
    apiVersion: controlplane.cluster.x-k8s.io/v1beta2
    kind: RKE2ControlPlane
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      machineTemplate:
        spec:
          infrastructureRef:
            apiGroup: infrastructure.cluster.x-k8s.io
            kind: Metal3MachineTemplate
            name: emea-spa-cluster-3
      replicas: 1
      version: v1.35.4+rke2r1
      rolloutStrategy:
        type: "RollingUpdate"
        rollingUpdate:
          maxSurge: 1
      registrationMethod: "control-plane-endpoint"
      registrationAddress: 192.168.122.203
      serverConfig:
        cni: cilium
        cniMultusEnable: true
        tlsSan:
          - 192.168.122.203
          - https://192.168.122.203.sslip.io
      agentConfig:
        format: ignition
        additionalUserData:
          config: |
            variant: fcos
            version: 1.4.0
            storage:
              files:
                - path: /var/lib/rancher/rke2/server/manifests/endpoint-copier-operator.yaml
                  overwrite: true
                  contents:
                    inline: |
                      apiVersion: helm.cattle.io/v1
                      kind: HelmChart
                      metadata:
                        name: endpoint-copier-operator
                        namespace: kube-system
                      spec:
                        chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
                        targetNamespace: endpoint-copier-operator
                        version: 306.0.1+up0.3.0
                        createNamespace: true
                - path: /var/lib/rancher/rke2/server/manifests/metallb.yaml
                  overwrite: true
                  contents:
                    inline: |
                      apiVersion: helm.cattle.io/v1
                      kind: HelmChart
                      metadata:
                        name: metallb
                        namespace: kube-system
                      spec:
                        chart: oci://registry.suse.com/edge/charts/metallb
                        targetNamespace: metallb-system
                        version: 306.0.2+up0.15.3
                        createNamespace: true
                - path: /var/lib/rancher/rke2/server/manifests/metallb-cr.yaml
                  overwrite: true
                  contents:
                    inline: |
                      apiVersion: metallb.io/v1beta1
                      kind: IPAddressPool
                      metadata:
                        name: kubernetes-vip-ip-pool
                        namespace: metallb-system
                      spec:
                        addresses:
                          - 192.168.122.203/32
                        serviceAllocation:
                          priority: 100
                          namespaces:
                            - default
                          serviceSelectors:
                            - matchExpressions:
                              - {key: "serviceType", operator: In, values: [kubernetes-vip]}
                      ---
                      apiVersion: metallb.io/v1beta1
                      kind: L2Advertisement
                      metadata:
                        name: ip-pool-l2-adv
                        namespace: metallb-system
                      spec:
                        ipAddressPools:
                          - kubernetes-vip-ip-pool
                - path: /var/lib/rancher/rke2/server/manifests/endpoint-svc.yaml
                  overwrite: true
                  contents:
                    inline: |
                      apiVersion: v1
                      kind: Service
                      metadata:
                        name: kubernetes-vip
                        namespace: default
                        labels:
                          serviceType: kubernetes-vip
                      spec:
                        ports:
                        - name: rke2-api
                          port: 9345
                          protocol: TCP
                          targetPort: 9345
                        - name: k8s-api
                          port: 6443
                          protocol: TCP
                          targetPort: 6443
                        type: LoadBalancer
            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
        kubelet:
          extraArgs:
          - provider-id=metal3://BAREMETALHOST_UUID
        nodeName: "localhost.localdomain"
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      nodeReuse: True
      template:
        spec:
          automatedCleaningMode: metadata
          dataTemplate:
            name: emea-spa-cluster-3
          hostSelector:
            matchLabels:
              cluster-role: control-plane
              deploy-region: emea-spa
              cluster-type: group-3
          image:
            checksum: http://fileserver.local:8080/eibimage-downstream-cluster.raw.sha256
            checksumType: sha256
            format: raw
            url: http://fileserver.local:8080/eibimage-downstream-cluster.raw
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3DataTemplate
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      clusterName: emea-spa-cluster-3
      metaData:
        objectNames:
        - key: name
          object: machine
        - key: local-hostname
          object: machine
        - key: local_hostname
          object: machine
Nota
Nota

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

65.4 Transformación del archivo de aprovisionamiento de CAPI a ClusterClass

65.4.1 Definición de ClusterClass

El siguiente código define un recurso ClusterClass, una plantilla declarativa para desplegar de forma coherente tipos específicos de clústeres de Kubernetes. Esta especificación incluye configuraciones comunes de infraestructura y del plano de control, lo que permite un aprovisionamiento eficiente y una gestión uniforme del ciclo de vida en todo un Fleet de clústeres. En el siguiente ejemplo de ClusterClass hay algunas variables definidas que se reemplazarán durante el proceso de instanciación del clúster utilizando los valores reales solicitados para cada instancia de clúster. En el ejemplo se utilizan las siguientes variables:

  • metallbHelmChartVersion: Esta variable opcional permite especificar la versión del gráfico de Helm MetalLB que se desplegará en el clúster; cuando no se proporciona, el gráfico de Helm MetalLB no se desplegará.

  • endpointCopierOperatorHelmChartVersion: Esta variable opcional permite especificar la versión del gráfico de Helm Endpoint Copier Operator que se desplegará en el clúster (cuando también se ha proporcionado una versión para el gráfico de Helm MetalLB); cuando no se proporciona, el gráfico de Helm Endpoint Copier Operator no se desplegará.

  • controlPlaneMachineTemplateImageURL: Esta variable obligatoria permite especificar la URL de la imagen que se utilizará para aprovisionar las máquinas del plano de control.

  • controlPlaneMachineTemplateHostSelectorDeployRegion: Esta variable obligatoria permite especificar el valor del selector de host deploy-region para las máquinas del plano de control.

  • controlPlaneMachineTemplateHostSelectorClusterType: Esta variable obligatoria permite especificar el valor del selector de host cluster-type para las máquinas del plano de control.

  • controlPlaneMachineTemplateDataTemplateName: Esta variable obligatoria permite especificar el nombre del objeto de la API Metal3DataTemplate que se utilizará para las máquinas del plano de control.

  • controlPlaneEndpointHost: Esta variable obligatoria permite especificar el nombre de host o la dirección IP del punto de conexión del plano de control.

  • tlsSan: Esta variable obligatoria permite especificar la lista de nombres alternativos del sujeto (SAN) TLS para el punto de conexión del plano de control.

El archivo de definición de ClusterClass consta de los siguientes cuatro recursos:

  • ClusterClass: Este recurso encapsula toda la definición de la clase de clúster, incluidas las plantillas del plano de control y de la infraestructura. Además, incluye la lista de variables que se reemplazarán durante el proceso de instanciación (y define los parches que las utilizan).

  • RKE2ControlPlaneTemplate: Este recurso define la plantilla del plano de control, especificando la configuración deseada para los nodos del plano de control. Además, algunos parámetros serán reemplazados por los valores correctos durante el proceso de instanciación.

  • Metal3ClusterTemplate: Este recurso define la plantilla de infraestructura, especificando la configuración deseada para la infraestructura subyacente. Incluye parámetros tales como el punto de conexión del plano de control y el indicador cloudProviderEnabled (true|false). Además, algunos parámetros serán reemplazados por los valores correctos durante el proceso de instanciación.

  • Metal3MachineTemplate: Este recurso define el modelo de plantilla de máquina para los nodos del plano de control, proporcionando los marcadores de posición para que esos parámetros sean reemplazados por los valores correctos durante el proceso de instanciación.

    apiVersion: controlplane.cluster.x-k8s.io/v1beta2
    kind: RKE2ControlPlaneTemplate
    metadata:
      name: example-controlplane
      namespace: emea-spa
    spec:
      template:
        spec:
          rolloutStrategy:
            type: "RollingUpdate"
            rollingUpdate:
              maxSurge: 1
          registrationMethod: "control-plane-endpoint"
          registrationAddress: TO-BE-PATCHED-AUTOMATICALLY  # This will be replaced by the involved patch when applying the cluster instance
          serverConfig:
            cni: cilium
            cniMultusEnable: true
            tlsSan:
            - TO-BE-PATCHED-AUTOMATICALLY    # This will be replaced by the involved patch when applying the cluster instance
          agentConfig:
            format: ignition
            additionalUserData:
              config: |          # This will be replaced by the involved patch when applying the cluster instance
                TO-BE-PATCHED-AUTOMATICALLY
            kubelet:
              extraArgs:
              - provider-id=metal3://BAREMETALHOST_UUID
            nodeName: "localhost.localdomain"
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3ClusterTemplate
    metadata:
      name: example-cluster-template
      namespace: emea-spa
    spec:
      template:
        spec:
          controlPlaneEndpoint:
            host: TO-BE-PATCHED-AUTOMATICALLY  # This will be replaced by the involved patch when applying the cluster instance
            port: 6443
          cloudProviderEnabled: false
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    metadata:
      name: example-controlplane-machineinfrastructure
      namespace: emea-spa
    spec:
      nodeReuse: true
      template:
        spec:
          automatedCleaningMode: metadata
          dataTemplate:
            name: to-be-patched-automatically  # This will be replaced by the involved patch when applying the cluster instance
          hostSelector:
            matchLabels:  # The labels used to identify the BMHs to select.
              cluster-role: control-plane
              deploy-region: TO-BE-PATCHED-AUTOMATICALLY # This will be replaced by the involved patch when applying the cluster instance
              cluster-type: TO-BE-PATCHED-AUTOMATICALLY  # This will be replaced by the involved patch when applying the cluster instance
          image:
            checksum: http://TO-BE-PATCHED-AUTOMATICALLY # This will be replaced by the involved patch when applying the cluster instance
            checksumType: sha256
            format: raw
            url: http://TO-BE-PATCHED-AUTOMATICALLY      # This will be replaced by the involved patch when applying the cluster instance
    ---
    apiVersion: cluster.x-k8s.io/v1beta2
    kind: ClusterClass
    metadata:
      name: example-clusterclass
      namespace: emea-spa
    spec:
      infrastructure:
        templateRef:
          kind: Metal3ClusterTemplate
          apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
          name: example-cluster-template
      controlPlane:
        templateRef:
          kind: RKE2ControlPlaneTemplate
          apiVersion: controlplane.cluster.x-k8s.io/v1beta2
          name: example-controlplane
        machineInfrastructure:
          templateRef:
            kind: Metal3MachineTemplate
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            name: example-controlplane-machineinfrastructure
      variables:
      - name: metallbHelmChartVersion
        required: false
        schema:
          openAPIV3Schema:
            type: string
      - name: endpointCopierOperatorHelmChartVersion
        required: false
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneMachineTemplateImageURL
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneMachineTemplateHostSelectorDeployRegion
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneMachineTemplateHostSelectorClusterType
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneMachineTemplateDataTemplateName
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneEndpointHost
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: tlsSan
        required: true
        schema:
          openAPIV3Schema:
            type: array
            items:
              type: string
      patches:
      - name: setControlPlaneMachineTemplateImageURL
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3MachineTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/image/url"
            valueFrom:
              variable: controlPlaneMachineTemplateImageURL
          - op: replace
            path: "/spec/template/spec/image/checksum"
            valueFrom:
              template: "{{ .controlPlaneMachineTemplateImageURL }}.sha256"
      - name: setControlPlaneMachineTemplateHostSelectorDeployRegion
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3MachineTemplate
            matchResources:
              controlPlane: true
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/hostSelector/matchLabels/deploy-region"
            valueFrom:
              variable: controlPlaneMachineTemplateHostSelectorDeployRegion
      - name: setControlPlaneMachineTemplateHostSelectorClusterType
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3MachineTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/hostSelector/matchLabels/cluster-type"
            valueFrom:
              variable: controlPlaneMachineTemplateHostSelectorClusterType
      - name: setControlPlaneMachineTemplateDataTemplateName
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3MachineTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/dataTemplate/name"
            valueFrom:
              variable: controlPlaneMachineTemplateDataTemplateName
      - name: setControlPlaneEndpoint
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3ClusterTemplate
            matchResources:
              infrastructureCluster: true  # Added to select InfraCluster
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/controlPlaneEndpoint/host"
            valueFrom:
              variable: controlPlaneEndpointHost
      - name: setRegistrationAddress
        definitions:
        - selector:
            apiVersion: controlplane.cluster.x-k8s.io/v1beta2
            kind: RKE2ControlPlaneTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/registrationAddress"
            valueFrom:
              variable: controlPlaneEndpointHost
      - name: setTlsSan
        definitions:
        - selector:
            apiVersion: controlplane.cluster.x-k8s.io/v1beta2
            kind: RKE2ControlPlaneTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/serverConfig/tlsSan"
            valueFrom:
              variable: tlsSan
      - name: updateAdditionalUserData
        definitions:
        - selector:
            apiVersion: controlplane.cluster.x-k8s.io/v1beta2
            kind: RKE2ControlPlaneTemplate
            matchResources:
              controlPlane: true
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/agentConfig/additionalUserData"
            valueFrom:
              template: |
                config: |
                  variant: fcos
                  version: 1.4.0
                  {{ if .metallbHelmChartVersion }}
                  storage:
                    files:
                    - path: /var/lib/rancher/rke2/server/manifests/metallb.yaml
                      overwrite: true
                      contents:
                        inline: |
                          apiVersion: helm.cattle.io/v1
                          kind: HelmChart
                          metadata:
                            name: metallb
                            namespace: kube-system
                          spec:
                            chart: oci://registry.suse.com/edge/charts/metallb
                            targetNamespace: metallb-system
                            version: {{ .metallbHelmChartVersion }}
                            createNamespace: true
                    {{ if .endpointCopierOperatorHelmChartVersion }}
                    - path: /var/lib/rancher/rke2/server/manifests/endpoint-copier-operator.yaml
                      overwrite: true
                      contents:
                        inline: |
                          apiVersion: helm.cattle.io/v1
                          kind: HelmChart
                          metadata:
                            name: endpoint-copier-operator
                            namespace: kube-system
                          spec:
                            chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
                            targetNamespace: endpoint-copier-operator
                            version: {{ .endpointCopierOperatorHelmChartVersion }}
                            createNamespace: true
                    - path: /var/lib/rancher/rke2/server/manifests/metallb-cr.yaml
                      overwrite: true
                      contents:
                        inline: |
                          apiVersion: metallb.io/v1beta1
                          kind: IPAddressPool
                          metadata:
                            name: kubernetes-vip-ip-pool
                            namespace: metallb-system
                          spec:
                            addresses:
                              - {{ .controlPlaneEndpointHost }}/32
                            serviceAllocation:
                              priority: 100
                              namespaces:
                                - default
                              serviceSelectors:
                                - matchExpressions:
                                  - {key: "serviceType", operator: In, values: [kubernetes-vip]}
                          ---
                          apiVersion: metallb.io/v1beta1
                          kind: L2Advertisement
                          metadata:
                            name: ip-pool-l2-adv
                            namespace: metallb-system
                          spec:
                            ipAddressPools:
                              - kubernetes-vip-ip-pool
                    - path: /var/lib/rancher/rke2/server/manifests/endpoint-svc.yaml
                      overwrite: true
                      contents:
                        inline: |
                          apiVersion: v1
                          kind: Service
                          metadata:
                            name: kubernetes-vip
                            namespace: default
                            labels:
                              serviceType: kubernetes-vip
                          spec:
                            ports:
                            - name: rke2-api
                              port: 9345
                              protocol: TCP
                              targetPort: 9345
                            - name: k8s-api
                              port: 6443
                              protocol: TCP
                              targetPort: 6443
                            type: LoadBalancer
                    {{ end }}
                  {{ end }}
                  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

65.4.2 Definición de instancia de clúster

Dentro del contexto de ClusterClass, una instancia de clúster se refiere a una instanciación específica y en ejecución de un clúster que ha sido creado basándose en una ClusterClass definida. Representa una ampliación concreta con sus configuraciones, recursos y estado operativo únicos, derivados directamente del plano especificado en la ClusterClass. Esto incluye el conjunto específico de máquinas, configuraciones de red y componentes de Kubernetes asociados que se están ejecutando activamente. Comprender la instancia de clúster es crucial para gestionar el ciclo de vida, realizar actualizaciones de versión, ejecutar operaciones de escalado y llevar a cabo la monitorización de un clúster desplegado en particular que se aprovisionó utilizando el marco de trabajo ClusterClass.

Para definir una instancia de clúster necesitamos definir los dos recursos siguientes:

  • Cluster: Este recurso representa la instancia de clúster real, incluyendo una referencia a su topology (es decir, el objeto ClusterClass), la versión de Kubernetes requerida, el número de nodos del plano de control a instanciar y los valores proporcionados para cada una de las variables definidas en el ClusterClass referenciado, que se utilizarán durante el proceso de instanciación.

  • Metal3DataTemplate: Este recurso proporciona metadatos adicionales para las máquinas en el clúster (solo máquinas del plano de control en este ejemplo), complementando el objeto Metal3MachineTemplate creado automáticamente por cada clúster instanciado. Tened en cuenta que no es posible definir un único recurso Metal3DataTemplate válido para todos los clústeres instanciados a partir de un ClusterClass común, ya que el campo clusterName en la especificación Metal3DataTemplate debe hacer referencia a la instancia de clúster específica a la que "pertenece".

    apiVersion: cluster.x-k8s.io/v1beta2
    kind: Cluster
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
      labels:
        cluster-api.cattle.io/rancher-auto-import: "true"
    spec:
      topology:
        classRef:
          name: example-clusterclass
          namespace: emea-spa
        version: v1.35.3+rke2r3
        controlPlane:
          replicas: 1
        variables:                       # Values to be replaced in the clusterclass template variables to create this specific cluster
        - name: endpointCopierOperatorHelmChartVersion
          value: 306.0.1+up0.3.0
        - name: metallbHelmChartVersion
          value: 306.0.2+up0.15.3
        - name: controlPlaneMachineTemplateImageURL
          value: http://fileserver.local:8080/eibimage-downstream-cluster.raw.sha256
        - name: controlPlaneMachineTemplateHostSelectorDeployRegion
          value: emea-spa
        - name: controlPlaneMachineTemplateHostSelectorClusterType
          value: group-3
        - name: controlPlaneMachineTemplateDataTemplateName
          value: emea-spa-cluster-3
        - name: controlPlaneEndpointHost
          value: 192.168.122.203
        - name: tlsSan
          value:
          - 192.168.122.203
          - https://192.168.122.203.sslip.io
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3DataTemplate
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      clusterName: emea-spa-cluster-3
      metaData:
        objectNames:
        - key: name
          object: machine
        - key: local-hostname
          object: machine
        - key: local_hostname
          object: machine
Nota
Nota

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

Este enfoque agiliza el proceso, permitiendo desplegar un clúster utilizando solo dos recursos una vez que se han definido los planos de ClusterClass.

Parte X Consejos y trucos

Consejos y trucos para los componentes de Edge

  • 66 Edge Image Builder
  • Si se encuentra en un entorno que no es Linux y sigue estas instrucciones para crear una imagen, es probable que esté ejecutando Podman a través de una máquina virtual. Por defecto, esta máquina virtual estará configurada para tener una pequeña cantidad de recursos del sistema asignados y puede caus…

  • 67 Metal3
  • Una vez creado un objeto de clúster Metalˆ3ˆ y sus objetos asociados correspondientes, se lleva a cabo un proceso para elegir qué BareMetalHost formará parte del clúster. Este proceso conecta un BareMetalHost con un Metal3MachineTemplate específico utilizando etiquetas de Kubernetes y selectores est…

66 Edge Image Builder

66.1 Común

  • Si se encuentra en un entorno que no es Linux y sigue estas instrucciones para crear una imagen, es probable que esté ejecutando Podman a través de una máquina virtual. Por defecto, esta máquina virtual estará configurada para tener una pequeña cantidad de recursos del sistema asignados y puede causar inestabilidad en Edge Image Builder durante operaciones que consumen muchos recursos, como el proceso de resolución de RPM. Tendrá que ajustar los recursos de la máquina Podman, ya sea utilizando Podman Desktop (rueda dentada de ajustes → icono de edición de máquina Podman) o directamente a través del podman-machine-set comando.

  • En este momento, Edge Image Builder no es capaz de crear imágenes en una configuración de arquitectura cruzada, es decir, tiene que ejecutarlo en:

    • AArch64sistemas (como Apple Silicon) para crear imágenes de SL Micro aarch64

    • AMD64/Intel 64sistemas para crear imágenes de SL Micro x86_64.

66.2 SUSE Linux Micro

  • La carga de módulos del kernel durante el arranque puede realizarse utilizando el archivo /etc/modprobe.d/module.conf correspondiente. Cree la carpeta os-files correspondiente utilizando Edge Image Builder:

.
├── definition.yaml
└── os-files
    └── etc
        └── modprobe.d
            └── module.conf

Para obtener más información, consulte la sección «Managing kernel modules» de la documentación de SUSE Linux Enterprise Server

66.3 Kubernetes

  • La creación de clústeres de Kubernetes de varios nodos requiere ajustar kubernetes la sección en el archivo de definición a:

    • listar todos los nodos de servidor y agente bajo kubernetes.nodes

    • establecer una dirección IP virtual que se utilizaría para que todos los nodos que no sean inicializadores se unan al clúster bajo kubernetes.network.apiVIP

    • opcionalmente, establecer un host de API para especificar una dirección de dominio para acceder al clúster bajo kubernetes.network.apiHost Para obtener más información sobre esta configuración, consulte la documentación de la sección de Kubernetes.

  • Edge Image Builder depende de los nombres de host de los diferentes nodos para determinar su tipo de Kubernetes (server o agent). Aunque esta configuración se gestiona en el archivo de definición, para la configuración de red general de las máquinas podemos utilizar la configuración DHCP tal y como se describe en Capítulo 13, Redes edge.

67 Metal3

67.1 `BareMetalHost`Selección de y asociación de clúster

Una vez creado un objeto de clúster Metalˆ3ˆ y sus objetos asociados correspondientes, se lleva a cabo un proceso para elegir qué BareMetalHost formará parte del clúster. Este proceso conecta un BareMetalHost con un Metal3MachineTemplate específico utilizando etiquetas de Kubernetes y selectores estándar.

Como ejemplo, cada BareMetalHost está etiquetado para identificar sus propiedades y el clúster previsto (p. ej., su rol de clúster, el nombre del clúster, la ubicación, etc.):

apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: mynode1
  labels:
    cluster-role: control-plane
    cluster: foobar
    location: madrid
    datacenter: xyz
<snip>
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: mynode2
  labels:
    cluster-role: worker
    cluster: foobar
    location: madrid
    datacenter: xyz
<snip>
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: mynode3
  labels:
    cluster-role: worker
    cluster: foobar2
    location: madrid
    datacenter: xyz
<snip>
...

Entonces, el objeto Metal3MachineTemplate utiliza el campo spec.hostSelector para coincidir con el BareMetalHost deseado.

Se pueden utilizar tanto matchLabels (para una coincidencia exacta de clave-valor) como matchExpressions (para reglas más complejas):

apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: Metal3MachineTemplate
metadata:
  name: foobar-cluster-controlplane
  namespace: mynamespace
spec:
  template:
    spec:
      hostSelector:
        matchLabels:
          cluster-role: control-plane
          cluster: foobar
<snip>
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: Metal3MachineTemplate
metadata:
  name: foobar-cluster-worker
  namespace: mynamespace
spec:
  template:
    spec:
      hostSelector:
        matchExpressions:
          - { key: cluster-role, operator: In, values: [worker] }
          - { key: cluster, operator: In, values: [foobar] }
<snip>
Nota
Nota

Los espacios de nombres de Kubernetes también se pueden utilizar para organizar mejor los diferentes objetos.

67.2 Limpiar las entradas de arranque EFI antiguas

A veces, el gestor de arranque UEFI contiene múltiples entradas para sistemas operativos antiguos que probablemente ya no sean necesarios (especialmente para hosts que se vuelven a aprovisionar varias veces). Podéis limpiar esas entradas antiguas siguiendo cualquiera de los siguientes procedimientos:

  • Eliminadlas directamente en la interfaz de configuración de la BIOS/EFI (el procedimiento exacto dependerá del hardware).

  • Ejecutad la shell UEFI bcfg como:

    # List the entries
    bcfg boot dump -b
    # Delete entry number X
    bcfg boot rm X
    # X is the number associated the entry to remove. For example, if the entry is "Boot0002 foobar", then X is 2.
  • Utilizad efibootmgr en un sistema Linux como:

    # List the entries
    efibootmgr -v
    # Delete entry number X
    efibootmgr -b X -B

El proceso puede dejar archivos huérfanos en la partición del sistema EFI (ESP), que normalmente se encuentran en subdirectorios nombrados por el proveedor (p. ej., EFI/opensuse o EFI/Microsoft). Aunque estos archivos suelen ser inofensivos, deben eliminarse si consumen un espacio excesivo, ya que pueden impedir la instalación de un nuevo SO o una actualización del gestor de arranque. La eliminación puede requerir montar explícitamente la ESP, que normalmente se monta como /boot/efi/EFI en sistemas Linux.

67.3 Configuración de red personalizada mediante el enfoque de dos secretos

Cuando Metal3 aprovisiona un nodo sin sistema operativo, éste pasa por dos fases distintas que pueden requerir cada una una configuración de red diferente:

  • La fase IPA, donde el ramdisk de Ironic Python Agent (IPA) se ejecuta durante la inspección y el aprovisionamiento del hardware

  • La fase del SO de destino, donde el sistema SLE Micro desplegado se ejecuta tras el primer arranque

El enfoque de dos secretos soluciona esto permitiendo un secreto de configuración de red independiente para cada fase, utilizando el campo preprovisioningNetworkDataName para la fase IPA y el campo networkData para la fase del SO de destino. Esto es especialmente útil cuando los nombres de las interfaces difieren entre fases, lo cual puede ocurrir porque el kernel de IPA y el kernel de SLE Micro pueden detectar el mismo hardware con nombres distintos.

67.3.1 Ejemplo de cambio de nombre de interfaz para VLANs

Un escenario común es cuando el hardware obtiene un nombre de interfaz largo basado en PCI, como enp1s0np123. Añadir una VLAN sobre él puede superar el límite estricto del kernel de Linux de 15 caracteres para los nombres de interfaz:

enp1s0np123.100   = 15 chars  (barely fits, risky)
enp1s0np123.3669  = 17 chars  (exceeds limit, fails)
eth0.3669         =  9 chars  (works)

La fase IPA debe hacer referencia a enp1s0np123 (el nombre detectado por el kernel), mientras que el SO de destino debe utilizar un nombre corto como eth0 para que eth0.3669 se mantenga por debajo del límite. nmc (nm-configurator) conecta ambas fases haciendo coincidir las interfaces mediante la dirección MAC en lugar del nombre: declarad name: eth0 junto con la dirección MAC del hardware, y nmc crea el perfil de NetworkManager con el nombre deseado independientemente de lo que haya asignado el kernel.

67.3.2 Requisitos previos:

67.3.2.1 Configuración de la imagen EIB

Según la guía de configuración de red estática, la imagen EIB debe incluir un script de primer arranque que lea la configuración de red de la partición config-2 que Metal3 escribe durante el aprovisionamiento. Cread el siguiente script en /opt/EIB/network/configure-network.sh:

#!/bin/bash
set -eux

# Source: https://documentation.suse.com/suse-edge/3.6/html/edge/quickstart-metal3.html#metal3-add-network-eib

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

A continuación, hacedlo ejecutable y compilad la imagen EIB de forma normal:

mkdir -p /opt/EIB/network
chmod +x /opt/EIB/network/configure-network.sh
Nota
Nota

=== EIB recoge automáticamente los scripts del directorio network/. Combustion los ejecuta en el primer arranque en initramfs, antes de que se inicie el SO completo. ===

Nota
Nota

=== El script también establece el nombre de host del nodo a partir del campo de metadatos de Metal3metal3-name. ===

67.3.3 Configuración de los dos secretos

Los siguientes ejemplos utilizan valores ficticios en todo momento: MAC de la NIC de datos aa:bb:cc:11:22:33, MAC de la NIC de arranque aa:bb:cc:44:55:66, IP del nodo 10.0.0.10/24, puerta de enlace 10.0.0.1, DNS 10.0.0.53, ID de VLAN 100 y dirección BMC 10.1.0.10.

Secreto 1 — fase IPA (static-networkdata-ipa.yaml): hace referencia al nombre de interfaz asignado por el kernel. Aquí se utiliza DHCP para simplificar el proceso durante la detección del hardware:

apiVersion: v1
kind: Secret
metadata:
  name: static-networkdata-ipa
  namespace: default
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: enp1s0np123
      type: ethernet
      state: up
      mac-address: "aa:bb:cc:11:22:33"
      ipv4:
        enabled: true
        dhcp: true
    dns-resolver:
      config:
        server:
        - 10.0.0.53

Secreto 2 — fase de SO de destino (static-networkdata-os.yaml): hace referencia al nombre corto deseado y declara la VLAN. Se utiliza la misma dirección MAC para que nmc pueda coincidir con la interfaz:

apiVersion: v1
kind: Secret
metadata:
  name: static-networkdata-os
  namespace: default
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: eth0
      type: ethernet
      state: up
      mac-address: "aa:bb:cc:11:22:33"
      mtu: 1500
      ipv4:
        enabled: false
        dhcp: false
    - name: eth0.100
      type: vlan
      state: up
      mtu: 1500
      vlan:
        base-iface: eth0
        id: 100
      ipv4:
        address:
        - ip: 10.0.0.10
          prefix-length: 24
        enabled: true
        dhcp: false
    dns-resolver:
      config:
        server:
        - 10.0.0.53
    routes:
      config:
      - destination: 0.0.0.0/0
        next-hop-address: 10.0.0.1
        next-hop-interface: eth0.100

El objeto BareMetalHost hace referencia a ambos secretos:

apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: my-node
  namespace: default
spec:
  online: true
  bootMACAddress: "aa:bb:cc:44:55:66"
  rootDeviceHints:
    deviceName: /dev/nvme0n1
  bmc:
    address: redfish-virtualmedia://10.1.0.10/redfish/v1/Systems/1/
    disableCertificateVerification: true
    credentialsName: my-node-credentials
  preprovisioningNetworkDataName: static-networkdata-ipa
  networkData:
    name: static-networkdata-os
Aviso
Aviso

preprovisioningNetworkDataName es un campo de cadena simple, mientras que networkData es un objeto SecretReference que requiere una subclave name:. La sintaxis difiere entre ambos y es una fuente común de errores.

Aplicad todos los objetos:

kubectl apply -f bmc-credentials.yaml
kubectl apply -f static-networkdata-ipa.yaml
kubectl apply -f static-networkdata-os.yaml
kubectl apply -f baremetalhost.yaml

Tras el aprovisionamiento, acceded por SSH al nodo y verificad:

# Interface names
ip link show
# Expected: eth0 and eth0.100@eth0

# IP on VLAN interface
ip addr show eth0.100

# NetworkManager profiles
nmcli connection show

# VLAN details
nmcli connection show eth0.100 | grep -E '(vlan.parent|vlan.id)'

Parte XI Solución de problemas

Esta sección proporciona orientación para diagnosticar y resolver problemas comunes con SUSE Telco Cloud ampliaciones y operaciones. Abarca diversos temas, ofreciendo pasos de resolución de problemas específicos de los componentes, herramientas clave y ubicaciones de registros relevantes.

68 Principios generales de resolución de problemas

Antes de profundizar en problemas específicos de los componentes, considera estos principios generales:

  • Comprobar registros: Los registros son la fuente principal de información. La mayoría de las veces, los errores se explican por sí mismos y contienen pistas sobre lo que falló.

  • Comprobar relojes: Tener diferencias de reloj entre sistemas puede provocar todo tipo de errores diferentes. Aseguraos de que los relojes estén sincronizados. Se puede indicar a EIB que fuerce la sincronización del reloj en el momento del arranque, véase Configuración de la hora del SO (Capítulo 5, Clústeres independientes con Edge Image Builder).

  • Problemas de arranque: Si el sistema se queda bloqueado durante el arranque, anotad los últimos mensajes mostrados. Acceded a la consola (física o a través de BMC) para observar los mensajes de arranque.

  • Problemas de red: Verificad la configuración de la interfaz de red (ip a), la tabla de enrutamiento (ip route), probad la conectividad desde/hacia otros nodos y servicios externos (ping, nc). Aseguraos de que las reglas del firewall no estén bloqueando los puertos necesarios.

  • Verificar el estado del componente: Utilizad kubectl get y kubectl describe para los recursos de Kubernetes. Utilizad kubectl get events --sort-by='.lastTimestamp' -n <namespace> para ver los eventos en un espacio de nombres de Kubernetes concreto.

  • Verificar el estado de los servicios: Utilizad systemctl status <service> para los servicios de systemd.

  • Comprobar la sintaxis: El software espera una estructura y una sintaxis determinadas en los archivos de configuración. Para los archivos yaml, por ejemplo, utilizad yamllint o herramientas similares para verificar la sintaxis correcta.

  • Aislar el problema: Intentad acotar el problema a un componente o capa específicos (por ejemplo, red, almacenamiento, SO, Kubernetes, Metal3, Ironic,…​).

  • Documentación: Consultad siempre la SUSE Telco Cloud documentación oficial y también la documentación del sentido ascendente para obtener información detallada.

  • Versiones: SUSE Telco Cloud es una versión preconfigurada y probada exhaustivamente de diferentes componentes de SUSE. Las versiones de cada componente por cada versión de SUSE Telco Cloud pueden consultarse en la SUSE Telco Cloud matriz de compatibilidad.

  • Problemas conocidos: Para cada versión de SUSE Telco Cloud existe una sección de «Problemas conocidos» en las notas de la versión que contiene información sobre problemas que se corregirán en futuras versiones, pero que pueden afectar a la actual.

69 Solución de problemas de Kiwi

Kiwi se utiliza para generar imágenes actualizadas de SUSE Linux Micro que se usarán con Edge Image Builder.

Problemas comunes
  • SL Micro Version Mismatch: La versión del sistema operativo del host de compilación debe coincidir con la versión del sistema operativo que se está compilando (host SL Micro 6.0 → imagen SL Micro 6.0).

  • SELinux en modo exigente: Debido a ciertas limitaciones, actualmente es necesario desactivar SELinux temporalmente para poder crear imágenes con Kiwi. Comprobad el estado de SELinux con getenforce y desactivadlo antes de ejecutar el proceso de compilación con setenforce 0.

  • Host de compilación no registrado: El proceso de compilación utiliza las suscripciones del host de compilación para poder extraer paquetes de SUSE SCC. Si el host no está registrado, fallará.

  • Error en la prueba del dispositivo de bucle: La primera vez que se ejecuta el proceso de compilación de Kiwi, fallará poco después de iniciarse con \"ERROR: La prueba inicial del dispositivo de bucle falló, por favor, reintentad la ejecución del contenedor. Esto es un síntoma de que se están creando dispositivos de bucle en el sistema host subyacente que no son inmediatamente visibles dentro de la imagen del contenedor. Volved a ejecutar el proceso de compilación de Kiwi y debería continuar sin problemas.

  • Permisos faltantes: El proceso de compilación requiere ejecutarse como usuario raíz (o mediante sudo).

  • Privilegios incorrectos: El proceso de compilación requiere el indicador --privileged al ejecutar el contenedor. Comprobad dos veces que esté presente.

Registros
  • Registros del contenedor de compilación: Comprobad los registros del contenedor de compilación. Los registros se generan en el directorio que se utilizó para almacenar los artefactos. Consultad también los registros de docker o podman para obtener la información necesaria.

  • Directorios de compilación temporales: Kiwi crea directorios temporales durante el proceso de compilación. Comprobadlos para ver si hay registros o artefactos intermedios si la salida principal es insuficiente.

Pasos para la solución de problemas
  1. Revisad la salida de build-image: El mensaje de error en la salida de la consola suele ser muy indicativo.

  2. Comprobad el entorno de compilación: Aseguraos de que se cumplen todos los requisitos previos para el propio Kiwi (por ejemplo, docker/podman, SELinux, espacio en disco suficiente) en la máquina que ejecuta Kiwi.

  3. Inspeccionad los registros del contenedor de compilación: Revisad los registros del contenedor fallido para obtener errores más detallados (véase más arriba).

  4. Verificad el archivo de definición: Si utilizáis un archivo de definición de imagen de Kiwi personalizado, comprobad de nuevo el archivo por si hubiera errores tipográficos o de sintaxis.

70 Solución de problemas de Edge Image Builder (EIB)

EIB se utiliza para crear imágenes SUSE Telco Cloud personalizadas.

Problemas comunes
  • Código SCC incorrecto: Asegúrese de que el código SCC utilizado en el archivo de definición de EIB coincida con la versión y la arquitectura de SL Micro.

  • Dependencias faltantes: Asegúrese de que no falten paquetes ni herramientas en el entorno de compilación.

  • Tamaño de imagen incorrecto: Para imágenes raw, el parámetro diskSize es obligatorio y depende en gran medida de las imágenes, los RPM y otros artefactos que se incluyan en la imagen.

  • Permisos: Si almacena un script en el directorio custom/files, asegúrese de que tenga permisos de ejecución, ya que esos archivos solo están disponibles en el momento de la combustión, pero EIB no realiza cambios.

  • Dependencias de grupos del sistema operativo: Al crear una imagen con usuarios y grupos personalizados, los grupos que se establezcan como “primaryGroup” deben crearse explícitamente.

  • Las claves ssh de usuario del sistema operativo requieren una carpeta de inicio: Al crear una imagen con usuarios con claves ssh, la carpeta de inicio también debe crearse con createHomeDir=true.

  • Problemas de combustión: EIB depende de la combustión para la personalización del SO y el despliegue de todos los demás componentes SUSE Telco Cloud. Esto también incluye los scripts personalizados que se colocan en la carpeta custom/scripts. Tenga en cuenta que el proceso de combustión se ejecuta en el momento initrd, por lo que el sistema no está completamente arrancado cuando se ejecutan los scripts.

  • Tamaño de la máquina Podman: Como se explica en la sección de consejos y trucos de EIB (Parte X, “Consejos y trucos”), verifique que la máquina podman tenga suficiente CPU/memoria para ejecutar el contenedor EIB en sistemas operativos que no sean Linux.

  • Imagen incorrecta: Asegúrese de que la imagen base que se utiliza se descargue correctamente verificando el checksum. Si está compilando la imagen con kiwi-builder (Capítulo 64, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi), compruebe también el archivo de suma generado por el proceso.

Registros
  • Salida de EIB: La salida de consola del comando eib build es crucial.

  • Registros del contenedor de compilación: Compruebe los registros del contenedor de compilación. Los registros se generan en el directorio que se utilizó para almacenar los artefactos. Consulte también docker logs o podman logs para obtener la información necesaria.

    Nota
    Nota

    Para obtener más información, consulte Depuración.

  • Directorios de compilación temporales: EIB crea directorios temporales durante el proceso de compilación. Compruebe estos directorios en busca de registros intermedios o artefactos si la salida principal es insuficiente.

  • Registros de combustión: Si la imagen que se está creando con EIB no arranca por cualquier motivo, hay disponible una shell de root. Conéctese a la consola del host (ya sea físicamente, a través de BMC, etc.) y compruebe los registros de combustión con journalctl -u combustion y, en general, todos los registros del sistema operativo con journalctl para encontrar la causa raíz del fallo.

Pasos para la solución de problemas
  1. Revise la salida de eib-build: El mensaje de error en la salida de la consola suele ser muy indicativo.

  2. Compruebe el entorno de compilación: Asegúrese de que se cumplen todos los requisitos previos para el propio EIB (por ejemplo, docker/podman, espacio en disco suficiente) en la máquina que ejecuta EIB.

  3. Inspeccione los registros del contenedor de compilación: Revise los registros del contenedor fallido para obtener errores más detallados (véase más arriba).

  4. Verifique la configuración de eib: Compruebe dos veces el archivo de configuración eib en busca de errores tipográficos o rutas incorrectas a los archivos de origen o scripts de compilación.

    • Pruebe los componentes individualmente: Si su compilación de EIB implica scripts o etapas personalizados, ejecútelos de forma independiente para aislar los fallos.

71 Solución de problemas de Edge Networking (NMC)

NMC se inyecta en las imágenes EIB de SL Micro para configurar la red de los hosts Edge en el momento del arranque mediante combustión. También se ejecuta en el flujo de trabajo de Metal3 como parte del proceso de inspección. Pueden producirse problemas cuando el host arranca por primera vez o durante el proceso de inspección de Metal3.

Problemas comunes
  • El host no puede arrancar correctamente la primera vez: Los archivos de definición de red mal formados pueden provocar que la fase de combustión falle y, a continuación, el host muestre una shell de root.

  • Los archivos no se generan correctamente: Asegúrese de que los archivos de red coincidan con el formato NMState.

  • Las interfaces de red no están configuradas correctamente: Asegúrese de que las direcciones MAC coincidan con las interfaces que se utilizan en el host.

  • Desajuste entre los nombres de las interfaces: SL Micro habilita Predictable Naming Scheme for Network Interfaces de forma predeterminada, por lo que ya no existe eth0, sino otros esquemas de nomenclatura como enp2s0.

Registros
  • Registros de combustión: Como nmc se utiliza durante la combustión, compruebe los registros de combustión con journalctl -u combustion en el host que se está aprovisionando.

  • Registros de NetworkManager: En el flujo de trabajo de ampliación Metal3, nmc forma parte de la ejecución de IPA y se ejecuta como una dependencia del servicio NetworkManager utilizando la funcionalidad ExecStartPre de systemd. Comprobad los registros de NetworkManager en el host de IPA como journalctl -u NetworkManager (consultad la sección Solución de problemas de aprovisionamiento de red dirigida (Capítulo 72, Solución de problemas de aprovisionamiento de red dirigida) para entender cómo acceder al host cuando se inicia con IPA).

Pasos para la solución de problemas
  1. Verificad la sintaxis yaml: los archivos de configuración de nmc son archivos yaml, comprobad la sintaxis correcta con yamllint o herramientas similares.

  2. Ejecutad nmc manualmente: Como nmc forma parte del contenedor EIB, para depurar cualquier problema, se puede utilizar un comando podman local.

    1. Cread una carpeta temporal para almacenar los archivos de nmc.

      mkdir -p ${HOME}/tmp/foo
    2. Guardad los archivos de nmc en esa ubicación.

      ❯ tree --noreport ${HOME}/tmp/foo
      /Users/johndoe/tmp/foo
      ├── host1.example.com.yaml
      └── host2.example.com.yaml
    3. Ejecutad el contenedor EIB con nmc como punto de entrada y el comando generate para realizar las mismas tareas que nmc realizaría en el momento de la combustión:

      podman run -it --rm -v ${HOME}/tmp/foo:/tmp/foo:Z --entrypoint=/usr/bin/nmc registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 generate --config-dir /tmp/foo --output-dir /tmp/foo/
      
      [2025-06-04T11:58:37Z INFO  nmc::generate_conf] Generating config from "/tmp/foo/host2.example.com.yaml"...
      [2025-06-04T11:58:37Z INFO  nmc::generate_conf] Generating config from "/tmp/foo/host1.example.com.yaml"...
      [2025-06-04T11:58:37Z INFO  nmc] Successfully generated and stored network config
    4. Observad los registros y los archivos que se generan en la carpeta temporal.

72 Solución de problemas de aprovisionamiento de red dirigida

Los escenarios de aprovisionamiento de red dirigida implican el uso de elementos de Metal3 y CAPI para aprovisionar el clúster de sentido descendente. También incluye EIB para crear una imagen de SO. Pueden producirse problemas cuando el host se inicia por primera vez o durante los procesos de inspección o aprovisionamiento.

Problemas comunes
  • Firmware antiguo: Verificad que todo el firmware de los hosts físicos utilizados esté actualizado. Esto incluye el firmware de BMC, ya que a veces Metal3 requiere versiones específicas/actualizadas.

  • Fallo en el aprovisionamiento debido a errores SSL: Si el servidor web que aloja las imágenes utiliza https, Metal3 debe configurarse para inyectar y confiar en el certificado de la imagen IPA. Consultad la carpeta Kubernetes (Sección 29.4, “Kubernetes folder”) para saber cómo incluir un archivo ca-additional.crt en el chart de Metal3.

  • Problemas de certificados al iniciar los hosts con IPA: Algunos proveedores de servidores verifican la conexión SSL al adjuntar imágenes ISO de medios virtuales al BMC, lo que puede causar un problema porque los certificados generados para el despliegue de Metal3 están autofirmados. Puede ocurrir que el host se inicie pero caiga en una shell UEFI. Consultad Deshabilitar TLS para la conexión de ISO de medios virtuales (Sección 4.7.2, “Deshabilitación de TLS para la conexión de ISO de virtualmedia”) para saber cómo solucionarlo.

  • Referencia de nombre o etiqueta incorrecta: Si el clúster hace referencia a un nodo con un nombre o etiqueta incorrectos, el clúster aparece como desplegado, pero el BMH permanece como «Available». Comprobad las referencias en los objetos implicados para los BMH.

  • Problemas de comunicación con el BMC: Aseguraos de que los pods de Metal3 que se ejecutan en el clúster de gestión puedan acceder al BMC de los hosts que se están aprovisionando (normalmente la red del BMC está muy restringida).

  • Estado del host bare metal incorrecto: El objeto BMH pasa por diferentes estados (inspecting, preparing, provisioned, etc.) durante su ciclo de vida Ciclo de vida de la máquina de estados. Si se detecta un estado incorrecto, comprobad el campo status del objeto BMH, ya que contiene más información que kubectl get bmh <name> -o jsonpath=’{.status}’| jq.

  • Host que no se desaprovisiona: En caso de que falle el desaprovisionamiento de un host, se puede intentar su eliminación tras añadir la anotación «detached» al objeto BMH de la siguiente manera: kubectl annotate bmh/<BMH> baremetalhost.metal3.io/detached=””.

  • Errores de imagen: Verificad que la imagen que se está compilando con EIB para el clúster de sentido descendente esté disponible, tenga una suma de comprobación correcta y no sea demasiado grande para descomprimir o para el disco.

  • Discrepancia en el tamaño del disco: Por defecto, el disco no se expandirá para ocupar todo el espacio. Tal y como se explica en la sección Growfs script (Sección 4.4.4.1.2, “Script Growfs”), es necesario incluir un script growfs en la imagen que se está compilando con EIB para los hosts del clúster downstream.

  • Proceso de limpieza bloqueado: El proceso de limpieza se reintenta varias veces. Si debido a un problema con el host la limpieza ya no es posible, desactive la limpieza primero estableciendo el campo automatedCleanMode en disabled en el objeto BMH.

    Aviso
    Aviso

    No se recomienda eliminar manualmente el finalizador cuando el proceso de limpieza tarda más de lo deseado o falla. Al hacerlo, se elimina el registro del host de Kubernetes, pero se deja en Ironic. La acción que se está ejecutando actualmente continúa en segundo plano, y un intento de añadir el host de nuevo puede fallar debido al conflicto.

  • Problemas con los pods de Metal3/Rancher Turtles/CAPI: El flujo de despliegue para todos los componentes necesarios es:

    • El controlador de Rancher Turtles despliega el controlador del operador de CAPI.

    • El controlador del operador de CAPI despliega entonces los controladores del proveedor (núcleo de CAPI, CAPM3 y plano de control/bootstrap de RKE2).

Verificad que todos los pods se estén ejecutando correctamente y, de lo contrario, consultad los registros.

Registros
  • Registros de Metal3: Verificad los registros de los diferentes pods.

    kubectl logs -n metal3-system -l app.kubernetes.io/component=baremetal-operator
    kubectl logs -n metal3-system -l app.kubernetes.io/component=ironic
    Nota
    Nota

    El pod metal3-ironic contiene al menos 4 contenedores diferentes (ironic-httpd,` ironic-log-watch`, ironic y ironic-ipa-downloader (init)) en el mismo pod. Utilizad el flag -c al usar kubectl logs para verificar los registros de cada uno de los contenedores.

    Nota
    Nota

    El contenedor ironic-log-watch expone los registros de la consola de los hosts tras la inspección/aprovisionamiento, siempre que la conectividad de red permita enviar estos registros de vuelta al clúster de gestión. Esto puede ser útil en casos en los que hay errores de aprovisionamiento pero no tengáis acceso directo a los registros de la consola del BMC.

  • Registros de Rancher Turtles: Verificad los registros de los diferentes pods.

    kubectl logs -n cattle-turtles-system -l control-plane=controller-manager
    kubectl logs -n cattle-turtles-system -l app.kubernetes.io/name=cluster-api-operator
    kubectl logs -n rke2-bootstrap-system -l cluster.x-k8s.io/provider=bootstrap-rke2
    kubectl logs -n rke2-control-plane-system -l cluster.x-k8s.io/provider=control-plane-rke2
    kubectl logs -n cattle-capi-system -l cluster.x-k8s.io/provider=cluster-api
    kubectl logs -n capm3-system -l cluster.x-k8s.io/provider=infrastructure-metal3
  • Registros de BMC: Normalmente, los BMC tienen una interfaz de usuario donde se puede realizar la mayor parte de la interacción. Suele haber una sección de "registros" que se puede observar para detectar posibles problemas (no poder acceder a la imagen, fallos de hardware, etc.).

  • Registros de consola: Conectad a la consola del BMC (a través de la interfaz web del BMC, serie, etc.) y comprobad si hay errores en los registros que se están escribiendo.

Pasos para la resolución de problemas
  1. Verificad el estado de BareMetalHost:

    • kubectl get bmh -A muestra el estado actual. Buscad provisioning, ready, error, registering.

    • kubectl describe bmh -n <namespace> <bmh_name> proporciona eventos y condiciones detallados que explican por qué un BMH podría estar bloqueado.

  2. Probad la conectividad de RedFish:

    • Utilizad curl desde el plano de control de Metal3 para probar la conectividad con los BMC a través de Redfish.

    • Aseguraos de que se proporcionen las credenciales de BMC correctas en la definición de BareMetalHost-Secret.

  3. Verificad el estado de los pods de turtles/CAPI/metal3: Aseguraos de que los contenedores en el clúster de gestión estén activos y en funcionamiento: kubectl get pods -n metal3-system y kubectl get pods -n cattle-turtles-system (consultad también cattle-capi-system, capm3-system, rke2-bootstrap-system y rke2-control-plane-system).

  4. Verificad que el punto de conexión de ironic sea accesible desde el host que se está aprovisionando: El host que se está aprovisionando debe poder acceder al punto de conexión de Ironic para informar a Metal3. Comprobad la IP con kubectl get svc -n metal3-system metal3-metal3-ironic e intentad acceder a ella mediante curl/nc.

  5. Verificad que la imagen de IPA sea accesible desde el BMC: La imagen de IPA es servida por el punto de conexión de Ironic y debe ser accesible desde el BMC, ya que se utiliza como un CD virtual.

  6. Verificad que la imagen del SO sea accesible desde el host que se está aprovisionando: La imagen que se utiliza para aprovisionar el host debe ser accesible desde el propio host (cuando se ejecuta IPA), ya que se descargará temporalmente y se escribirá en el disco.

  7. Examinad los registros de los componentes de Metal3: Consulte más arriba.

  8. Volved a activar la inspección de BMH: Si una inspección falló o el hardware de un host disponible cambió, se puede activar un nuevo proceso de inspección anotando el objeto BMH con inspect.metal3.io: "". Consultad la guía Control de la inspección de Metal3 para obtener más información.

  9. Consola de IPA para equipo sin sistema operativo: Para solucionar problemas de IPA existen un par de alternativas:

    • Habilitar el «autologin». Esto permite que el usuario raíz inicie sesión automáticamente al conectarse a la consola de IPA.

      Aviso
      Aviso

      Esto es solo para fines de depuración, ya que proporciona acceso completo al host.

      Para habilitar el autologin, el valor global.ironicKernelParams de helm de Metal3 debería ser similar a: console=ttyS0 suse.autologin=ttyS0 (dependiendo de la consola, ttyS0 puede cambiarse). A continuación, se debe realizar un redespliegue del chart de Metal3. (Nota: ttyS0 es un ejemplo, esto debería coincidir con el terminal real, p. ej., puede ser tty1 en muchos casos en bare metal; esto se puede verificar observando la salida de la consola desde el ramdisk de IPA al arrancar, donde /etc/issue imprime el nombre de la consola).

      Otra forma de hacerlo es cambiando el parámetro IRONIC_KERNEL_PARAMS en el configmap ironic en el espacio de nombres metal3-system. Esto puede ser más sencillo, ya que se puede hacer mediante la edición de kubectl pero se sobrescribirá al actualizar el chart. A continuación, es necesario reiniciar el pod de Metal3 con kubectl delete pod -n metal3-system -l app.kubernetes.io/component=ironic.

    • Inyectar una clave ssh para el raíz en el IPA.

      Aviso
      Aviso

      Esto es solo para fines de depuración, ya que proporciona acceso completo al host.

      Para inyectar la clave ssh para el raíz, se debe utilizar el valor de helm de Metal3debug.ironicRamdiskSshKey. A continuación, se debe realizar un redespliegue del chart de Metal3.

      Otra forma de hacerlo es cambiando el parámetro IRONIC_RAMDISK_SSH_KEY en el ironic configmap en el espacio de nombres metal3-system. Esto puede ser más sencillo, ya que se puede hacer mediante la edición de kubectl pero se sobrescribirá al actualizar el chart. A continuación, es necesario reiniciar el pod de Metal3 con kubectl delete pod -n metal3-system -l app.kubernetes.io/component=ironic.

73 Solución de problemas de otros componentes

Las guías de solución de problemas de otros SUSE Telco Cloud componentes pueden consultarse en su documentación oficial:

También puede consultar la base de conocimientos de SUSE.

74 Recopilación de diagnósticos para el soporte

Al ponerse en contacto con el soporte de SUSE, es fundamental proporcionar información de diagnóstico completa.

Información esencial a recopilar
  • Descripción detallada del problema: ¿Qué ha ocurrido?, ¿cuándo ha ocurrido?, ¿qué estaba haciendo?, ¿cuál es el comportamiento esperado y cuál es el comportamiento real?

  • Pasos para reproducir: ¿Puede reproducir el problema de forma fiable? En caso afirmativo, enumere los pasos exactos.

  • Versiones de los componentes: versión de SUSE Telco Cloud, versiones de los componentes (RKE2/K3, EIB, Metal3, Elemental, etc.).

  • Registros relevantes:

    • Salida de journalctl (filtrada por servicio si es posible, o registros de arranque completos).

    • Registros de pods de Kubernetes (kubectl logs).

    • Registros de los componentes de Metal³/Elemental.

    • Registros de compilación de EIB y otros registros

  • Información del sistema:

    • uname -a

    • df -h

    • ip a

    • /etc/os-release

  • Archivos de configuración: Archivos de configuración relevantes para Elemental, Metal3, EIB, tales como valores de gráficos helm, configmaps, etc.

  • Información de Kubernetes: Nodos, servicios, despliegues, etc.

  • Objetos de Kubernetes afectados: BMH, MachineRegistration, etc.

Cómo recopilar
  • Para registros: Redirija la salida del comando a archivos (por ejemplo, journalctl -u k3s > k3s_logs.txt).

  • Para recursos de Kubernetes: Utilice kubectl get <resource> -o yaml > <resource_name>.yaml para obtener definiciones YAML detalladas.

  • Para información del sistema: Recopile la salida de los comandos enumerados anteriormente.

  • For SL Micro: Consulte la documentación Guía de resolución de problemas de SUSE Linux Micro sobre cómo recopilar información del sistema para obtener asistencia con supportconfig.

  • Para RKE2/Rancher: Consulte el artículo El script recopilador de registros de Linux de Rancher v2.x para ejecutar dicho script.

  • Para Edge (Nessie): Nessie 1.1.0 es una potente herramienta de diagnóstico diseñada para recopilar registros y datos de configuración de entornos SUSE Telco Cloud. Recopila información exhaustiva tanto del sistema anfitrión como de los clústeres de Kubernetes, lo que la hace inestimable para la resolución de problemas y la asistencia.

    • Nessie tiene dos «modos»: un modo Kubernetes y un modo de sistema.

      • Para recopilar registros de un clúster SUSE Telco Cloud, ejecute (siempre que tenga acceso al archivo kubeconfig localmente):

        podman run --rm --privileged \
          -v /etc/rancher/k3s/k3s.yaml:/etc/rancher/k3s/k3s.yaml:ro \
          -v /var/log/journal:/var/log/journal:ro \
          -v /run/systemd:/run/systemd:ro \
          -v /etc/machine-id:/etc/machine-id:ro \
          -v /tmp:/tmp \
          -e NESSIE_LOG_DIR="/tmp" \
          -e NESSIE_ZIP_DIR="/tmp" \
          registry.suse.com/edge/3.6/nessie:1.1.0
        Nota
        Nota

        Ajuste las rutas del archivo k3s.yaml/rke2.yaml si es necesario. Consulte Nessie para obtener más información. Debería poder ejecutar este contenedor en modo sin privilegios si tiene los permisos adecuados (normalmente los archivos k3s.yaml / rke2-server.yaml son propiedad de root).

      • Para recopilar registros en el modo de sistema desde el sistema operativo real, ejecute:

        podman run --rm --privileged \
          -v /var/log/journal:/var/log/journal:ro \
          -v /run/systemd:/run/systemd:ro \
          -v /etc/machine-id:/etc/machine-id:ro \
          -v /tmp:/tmp \
          -e NESSIE_LOG_DIR="/tmp" \
          -e NESSIE_ZIP_DIR="/tmp" \
          -e NESSIE_VERBOSE="1" \
          -e NESSIE_SKIP_POD_LOGS="true" \
          -e NESSIE_SKIP_K8S_CONFIGS="true" \
          -e NESSIE_SKIP_METRICS="true" \
          registry.suse.com/edge/3.6/nessie:1.1.0
        Nota
        Nota

        Asegúrese de consultar Nessie para obtener más detalles e información sobre cómo ejecutar Nessie en su entorno. Asimismo, debería poder ejecutar este contenedor en modo sin privilegios siempre que tenga los permisos adecuados.

Contactar con el soporte. Consulte el artículo disponible en Instrucciones para trabajar eficazmente con el soporte técnico de SUSE y el manual de soporte ubicado en Manual de soporte técnico de SUSE para obtener más detalles sobre cómo ponerse en contacto con el soporte de SUSE.

Parte XII Apéndice

  • 75 Notas de la versión
  • SUSE Telco Cloud 3.6 es una solución integral, estrechamente integrada y exhaustivamente validada para abordar los desafíos únicos del despliegue de infraestructura y aplicaciones nativas de nube en edge. Su objetivo principal es proporcionar una plataforma con lineamientos predefinidos, pero altame…

75 Notas de la versión

75.1 Resumen

SUSE Telco Cloud 3.6 es una solución integral, estrechamente integrada y exhaustivamente validada para abordar los desafíos únicos del despliegue de infraestructura y aplicaciones nativas de nube en edge. Su objetivo principal es proporcionar una plataforma con lineamientos predefinidos, pero altamente flexible, escalable y segura que abarca la creación de imágenes para el despliegue inicial, el aprovisionamiento e incorporación de nodos, el despliegue de aplicaciones, la observabilidad y la gestión del ciclo de vida.

La solución está diseñada con la idea de que no existe una plataforma edge única debido a los requisitos y expectativas muy variados de nuestros clientes. Los despliegues en edge nos empujan a resolver, y a evolucionar continuamente, algunos de los problemas más desafiantes, incluyendo la escalabilidad masiva, la disponibilidad de red restringida, las limitaciones de espacio físico, las nuevas amenazas de seguridad y vectores de ataque, las variaciones en la arquitectura de hardware y los recursos del sistema, el requisito de desplegar e interactuar con infraestructura y aplicaciones heredadas, y las soluciones de los clientes que tienen una vida útil prolongada.

SUSE Telco Cloud se ha creado desde cero con el mejor software de código abierto, en consonancia tanto con nuestros 30 años de historia ofreciendo plataformas SUSE Linux seguras, estables y certificadas, como con nuestra experiencia proporcionando una gestión de Kubernetes altamente escalable y rica en funciones con nuestra cartera Rancher. SUSE Telco Cloud se basa en estas capacidades para ofrecer una funcionalidad que puede abordar un gran número de segmentos de mercado, incluyendo el comercio minorista, la medicina, el transporte, la logística, las telecomunicaciones, la fabricación inteligente y el IoT industrial.

Para obtener más información sobre las actualizaciones del ciclo de vida de soporte del producto para SUSE Telco Cloud, consulte Product Support Lifecycle.

Nota
Nota

SUSE Telco Cloud es un derivado de SUSE Edge, con optimizaciones y componentes adicionales que permiten a la plataforma abordar los requisitos que se encuentran en los casos de uso de telecomunicaciones.

75.2 Acerca de

Estas notas de la versión son, a menos que se especifique y explique explícitamente, idénticas en todas las arquitecturas, y la versión más reciente, junto con las notas de la versión de todos los demás productos de SUSE, están siempre disponibles en línea en https://www.suse.com/releasenotes.

Las entradas solo se enumeran una vez, pero pueden referenciarse en varios lugares si son importantes y pertenecen a más de una sección. Las notas de la versión suelen enumerar solo los cambios que se produjeron entre dos versiones consecutivas. Ciertas entradas importantes de las notas de la versión de versiones anteriores del producto pueden repetirse. Para facilitar la identificación de estas entradas, contienen una nota al respecto.

Sin embargo, las entradas repetidas se proporcionan solo por cortesía. Por lo tanto, si se salta una o más versiones, consulte también las notas de la versión de las versiones omitidas. Si solo lee las notas de la versión actual, podría pasar por alto cambios importantes que pueden afectar al comportamiento del sistema. Las versiones de SUSE Telco Cloud se definen como x.y.z, donde 'x' denota la versión principal, 'y' denota la versión menor y 'z' denota la versión de parche, también conocida como "z-stream". Los ciclos de vida del producto SUSE Telco Cloud se definen en torno a una versión menor determinada, p. ej. "3.6", pero se distribuyen con parches posteriores a lo largo de su ciclo de vida, p. ej. "3.6.1".

Nota
Nota

SUSE Telco Cloud Las versiones z-stream están estrechamente integradas y probadas exhaustivamente como una pila versionada. La actualización de cualquier componente individual a versiones diferentes a las enumeradas anteriormente probablemente resulte en tiempo de inactividad del sistema. Aunque es posible ejecutar clústeres Edge en configuraciones no probadas, no se recomienda y puede llevar más tiempo proporcionar una resolución a través de los canales de soporte.

75.3 Versión 3.6.1

Fecha de disponibilidad: 26 de junio de 2026

Fecha de finalización del soporte completo: 27 de noviembre de 2026

Fecha de finalización del soporte de mantenimiento: 27 de mayo de 2028

EOL: 28 de mayo de 2028

Resumen: SUSE Telco Cloud 3.6.1 es la primera versión z-stream en el flujo de versiones SUSE Telco Cloud 3.6.

75.3.1 Nuevas funciones

75.3.2 Corrección de fallos y actualizaciones de seguridad

75.3.3 Problemas conocidos

Aviso
Aviso

Si va a desplegar nuevos clústeres, siga Capítulo 64, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi para crear primero imágenes nuevas. Esto se recomienda para los clústeres de gestión y descendentes a fin de garantizar que las imágenes contengan las últimas correcciones de seguridad y de fallos.

  • Al realizar el despliegue a través de Edge Image Builder, los manifiestos HelmChartConfigs pueden fallar si se colocan en el directorio de configuración kubernetes/manifests. En su lugar, se recomienda colocar cualquier HelmChartConfigs en /var/lib/rancher/{rke2/k3s}/server/manifests/ utilizando la interfaz os-files de EIB. Consulte Sección 29.1, “Estructura del directorio” para ver un ejemplo. Si no se hace esto, los nodos podrían permanecer en estado NotReady durante el inicio inicial, tal como se comenta en #8357 RKE2 issue.

  • En las versiones 1.34 y 1.35 de RKE2/K3s, es posible que el directorio /etc/cni utilizado para almacenar las configuraciones de CNI no notifique a containerd cuando se escriben archivos en él debido a ciertas condiciones relacionadas con overlayfs (véase el #8356 RKE2 issue). Esto, a su vez, provoca que el despliegue de RKE2/K3s se quede bloqueado esperando a que se inicie la CNI y que los nodos de RKE2/K3s permanezcan en estado NotReady. Esto puede observarse a nivel de nodo con kubectl describe node <affected_node>:

Conditions:
  Type   Status  LastHeartbeatTime                LastTransitionTime               Reason           Message
  ----   ------  -----------------                ------------------               ------           -------
  Ready  False   Thu, 05 Jun 2025 17:41:28 +0000  Thu, 05 Jun 2025 14:38:16 +0000  KubeletNotReady  container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized

Como solución alternativa, se puede montar un volumen tmpfs en el directorio /etc/cni antes de que se inicie RKE2. Esto evita el uso de overlayfs, que provoca que containerd no reciba notificaciones, y las configuraciones deberían reescribirse cada vez que se reinicie el nodo y se vuelvan a ejecutar los initcontainers de los pods. Si utiliza EIB, puede tratarse de un script 04-tmpfs-cni.sh en el directorio custom/scripts (como se explica aquí) que tenga el siguiente aspecto:

#!/bin/bash
mkdir -p /etc/cni
mount -t tmpfs -o mode=0700,size=5M tmpfs /etc/cni
echo "tmpfs /etc/cni tmpfs defaults,size=5M,mode=0700 0 0" >> /etc/fstab
  • En este momento no hay documentación oficial ni ejemplos disponibles para configurar SyncE mediante synce4l y GNSS mediante gpsd; estos temas se tratarán en futuras versiones.

  • Algunos repositorios de contenedores solo son accesibles actualmente a través de IPv4; por este motivo, se requiere un repositorio local en el clúster de gestión para un clúster de sentido descendente que solo utilice IPv6.

75.3.4 Versiones de los componentes

La siguiente tabla describe los componentes individuales que conforman la versión 3.6.1, incluyendo la versión, la versión del gráfico de Helm (si procede) y desde dónde se puede extraer el artefacto publicado en formato binario. Siga la documentación asociada para ver ejemplos de uso y despliegue.

Nombre

Versión

Versión del gráfico de Helm

Ubicación del artefacto (URL/Imagen)

SUSE Linux Micro

6.2 (el más reciente)

N/D

Página de descarga de SUSE Linux Micro

SUSE Linux Micro

6.2 (el más reciente)

N/D

Las sumas de comprobación y las firmas están disponibles para su descarga en Página de descarga de SUSE Linux Micro
SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso
SL-Micro.x86_64-6.2-Base-RT-SelfInstall-GM.install.iso
SL-Micro.x86_64-6.2-Base-GM.raw.xz
SL-Micro.x86_64-6.2-Base-RT-GM.raw.xz

SUSE Multi-Linux Manager

5.1

N/D

Página de descarga de SUSE Multi-Linux Manager

K3s

1.35.4

N/D

Versión de K3s de sentido ascendente

RKE2

1.35.4

N/D

Versión upstream de RKE2

SUSE Rancher Prime

2.14.2

2.14.2

Repositorio de Helm de Rancher Prime
https://prime.ribs.rancher.io/rancher/v2.14.2/rancher-images.txt[Rancher 2.14.2 Container Images]

SUSE Storage (Longhorn)

1.11.2

1.11.2

Repositorio de Helm de SUSE Storage
https://apps.rancher.io/applications/suse-storage/components[SUSE Storage Container Images]

SUSE Security (NeuVector)

5.5.2

109.0.2+up2.10.2

Repositorio de Helm de Rancher Charts
registry.rancher.com/rancher/neuvector-controller:5.5.2
registry.rancher.com/rancher/neuvector-enforcer:5.5.2
registry.suse.com/rancher/neuvector-compliance-config:1.0.12

Proveedores de Rancher Turtles (CAPI)

0.26.2

306.0.7+up0.26.2

registry.suse.com/edge/3.6/rancher-turtles-providers-chart:306.0.7+up0.26.2
registry.rancher.com/rancher/cluster-api-controller:v1.12.2
registry.rancher.com/rancher/turtles:v0.26.2
registry.suse.com/rancher/cluster-api-provider-rke2-bootstrap:v0.24.3
registry.suse.com/rancher/cluster-api-provider-rke2-controlplane:v0.24.3

Metal3

0.15.0

306.0.29+up0.15.0

registry.suse.com/edge/3.6/metal3-chart:306.0.29+up0.15.0
registry.suse.com/edge/3.6/baremetal-operator:0.12.3.0
registry.suse.com/edge/3.6/ironic:35.0.0.2
registry.suse.com/edge/3.6/ironic-ipa-downloader:3.1.1
registry.suse.com/edge/3.6/ironic-python-agent:3.0.9

MetalLB

0.15.3

306.0.2+up0.15.3

registry.suse.com/edge/3.6/metallb-chart:306.0.2+up0.15.3
registry.suse.com/edge/3.6/metallb-controller:v0.15.3
registry.suse.com/edge/3.6/metallb-speaker:v0.15.3

Elemental

1.9.0

1.9.0

registry.suse.com/rancher/elemental-operator-chart:1.9.0
registry.suse.com/rancher/elemental-operator-crds-chart:1.9.0
registry.suse.com/rancher/elemental-operator:1.9.0

Extensión del panel de control de Elemental

3.0.1

3.0.1

Helm Chart de la extensión de Elemental

Edge Image Builder

1.3.3.1

N/D

registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1

KubeVirt

1.7.0

306.0.2+up0.7.0

registry.suse.com/edge/3.6/kubevirt-chart:306.0.2+up0.7.0
registry.suse.com/suse/sles/15.7/virt-operator:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-api:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-controller:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-handler:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-launcher:1.7.0-150700.3.16.2

Extensión del panel de control de KubeVirt

1.3.3

306.0.4+up1.3.3

registry.suse.com/edge/3.6/kubevirt-dashboard-extension-chart:306.0.4+up1.3.3

Importador de datos en contenedores (CDI)

1.64.0

306.0.2+up0.7.0

registry.suse.com/edge/3.6/cdi-chart:306.0.2+up0.7.0
registry.suse.com/suse/sles/15.7/cdi-operator:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-controller:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-apiserver:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-uploadproxy:1.64.0-150700.9.6.1

Operador de Endpoint Copier

0.3.0

306.0.1+up0.3.0

registry.suse.com/edge/3.6/endpoint-copier-operator-chart:306.0.1+up0.3.0
registry.suse.com/edge/3.6/endpoint-copier-operator:0.3.0

Operador de red SR-IOV

1.6.0

306.0.4+up1.6.0

registry.suse.com/edge/3.6/sriov-network-operator-chart:306.0.4+up1.6.0
registry.suse.com/edge/3.6/sriov-crd-chart:306.0.4+up1.6.0

Upgrade Controller

0.19.1

109.0.1

Repositorio de Helm de Rancher Charts
registry.rancher.com/rancher/system-upgrade-controller:v0.19.1

Upgrade Controller

0.1.3

306.0.4+up0.1.3

registry.suse.com/edge/3.6/upgrade-controller-chart:306.0.4+up0.1.3
registry.suse.com/edge/3.6/upgrade-controller:0.1.3
registry.rancher.com/rancher/kubectl:v1.35.2
registry.suse.com/edge/3.6/release-manifest:3.6.1

SUSE Private Registry

1.1.1

1.1.1

oci://registry.suse.com/private-registry/private-registry-helm[Repositorio de Helm de SUSE Private Registry]
registry.suse.com/private-registry/harbor-core:1.1.1-1.19
registry.suse.com/private-registry/harbor-jobservice:1.1.1-1.19
registry.suse.com/private-registry/harbor-portal:1.1.1-1.20
registry.suse.com/private-registry/harbor-registry:1.1.1-1.19
registry.suse.com/private-registry/harbor-registryctl:1.1.1-1.19
registry.suse.com/private-registry/harbor-trivy-adapter:1.1.1-1.24

Kiwi Builder

10.2.29.1

N/D

registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1

Cert-Manager

1.20.1

1.20.1

Repositorio de Helm de Jetstack
quay.io/jetstack/cert-manager-controller:v1.20.1
quay.io/jetstack/cert-manager-webhook:v1.20.1
quay.io/jetstack/cert-manager-cainjector:v1.20.1

75.4 Versión 3.6.0

Fecha de disponibilidad: 27 de mayo de 2026

Fecha de finalización del soporte completo: 27 de noviembre de 2026

Fecha de finalización del soporte de mantenimiento: 27 de mayo de 2028

EOL: 28 de mayo de 2028

Resumen: SUSE Telco Cloud 3.6.0 es la primera versión en la línea de lanzamientos SUSE Telco Cloud 3.6.

75.4.1 Nuevas funciones

  • Actualizado a Kubernetes 1.35.3 y Rancher Prime 2.14.1

  • Actualizado a SUSE Security (NeuVector) 5.5.1 Notas de la versión de NeuVector

  • Actualizado a SUSE Storage (Longhorn) 1.11.1 Notas de la versión de Longhorn (upstream)

  • Actualizado a Rancher Turtles (CAPI) 0.26.1 Documentación de Rancher Turtles

  • Actualizado a MetalLB 0.15.3 Notas de la versión (upstream)

  • Actualizado a KubeVirt 1.7.0 y CDI (Importador de datos en contenedores) 1.64.0

  • Actualizado a Elemental 1.9.0 Notas de la versión de Elemental

  • Actualizado a Cert-Manager 1.20.1 Notas de la versión (upstream)

  • Actualizado Metal3/Ironic a 0.15.0 con Ironic 35.0.0

  • El modo BGP para MetalLB era una vista previa tecnológica en SUSE Telco Cloud 3.5 y ahora es totalmente compatible

  • El protocolo de tiempo de precisión (PTP) en despliegues descendentes era una vista previa tecnológica en SUSE Telco Cloud 3.5 y ahora es totalmente compatible, junto con la compatibilidad con SyncE y GNSS

  • Los despliegues de clústeres descendentes IPv6 de pila única ya son compatibles; no obstante, tenga en cuenta que esto requiere un clúster de gestión de pila dual (los clústeres de gestión de pila única siguen siendo una vista previa tecnológica)

75.4.2 Correcciones de errores y actualizaciones de seguridad

75.4.3 Problemas conocidos

Aviso
Aviso

Si va a desplegar nuevos clústeres, siga Capítulo 64, Creación de imágenes actualizadas de SUSE Linux Micro con Kiwi para crear primero imágenes nuevas. Esto se recomienda para los clústeres de gestión y de sentido descendente a fin de garantizar que las imágenes contengan las últimas correcciones de seguridad y de fallos.

  • Al desplegar a través de Edge Image Builder, los manifiestos HelmChartConfigs pueden fallar si se colocan en el directorio de configuración kubernetes/manifests. En su lugar, se recomienda colocar cualquier HelmChartConfigs en /var/lib/rancher/{rke2/k3s}/server/manifests/ utilizando la interfaz os-files de EIB. Si desea ver un ejemplo, consulte Sección 29.1, “Estructura del directorio”. Si no se hace esto, los nodos podrían permanecer en estado NotReady durante el inicio inicial, tal como se comenta en #8357 RKE2 issue.

  • En las versiones 1.34 y 1.35 de RKE2/K3s, es posible que el directorio /etc/cni utilizado para almacenar las configuraciones de CNI no notifique a containerd cuando se escriben archivos en él debido a ciertas condiciones relacionadas con overlayfs (véase el #8356 RKE2 issue). Esto, a su vez, provoca que el despliegue de RKE2/K3s se quede bloqueado esperando a que se inicie la CNI, y que los nodos de RKE2/K3s permanezcan en estado NotReady. Esto puede observarse a nivel de nodo con kubectl describe node <affected_node>:

Conditions:
  Type   Status  LastHeartbeatTime                LastTransitionTime               Reason           Message
  ----   ------  -----------------                ------------------               ------           -------
  Ready  False   Thu, 05 Jun 2025 17:41:28 +0000  Thu, 05 Jun 2025 14:38:16 +0000  KubeletNotReady  container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized

Como solución alternativa, se puede montar un volumen tmpfs en el directorio /etc/cni antes de que se inicie RKE2. Esto evita el uso de overlayfs, que provoca que containerd no reciba notificaciones, y las configuraciones deberían reescribirse cada vez que se reinicie el nodo y se vuelvan a ejecutar los initcontainers de los pods. Si utiliza EIB, puede tratarse de un guion 04-tmpfs-cni.sh en el directorio custom/scripts (como se explica aquí) que tenga el siguiente aspecto:

#!/bin/bash
mkdir -p /etc/cni
mount -t tmpfs -o mode=0700,size=5M tmpfs /etc/cni
echo "tmpfs /etc/cni tmpfs defaults,size=5M,mode=0700 0 0" >> /etc/fstab
  • En este momento no hay documentación oficial ni ejemplos disponibles para configurar SyncE mediante synce4l y GNSS mediante gpsd; estos temas se tratarán en futuras versiones.

  • Algunos repositorios de contenedores solo son accesibles actualmente a través de IPv4; por este motivo, se requiere un registro local en el clúster de gestión para un clúster de sentido descendente que solo utilice IPv6.

75.4.4 Versiones de los componentes

La siguiente tabla describe los componentes individuales que conforman la versión 3.6.0, incluida la versión, la versión del gráfico de Helm (si procede) y desde dónde se puede extraer el artefacto publicado en formato binario. Siga la documentación asociada para ver ejemplos de uso y despliegue.

Nombre

Versión

Versión del chart de Helm

Ubicación del artefacto (URL/Imagen)

SUSE Linux Micro

6.2 (el más reciente)

N/D

Página de descarga de SUSE Linux Micro

SUSE Linux Micro

6.2 (el más reciente)

N/D

Las sumas de comprobación y las firmas están disponibles para descargar en Página de descarga de SUSE Linux Micro
SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso
SL-Micro.x86_64-6.2-Base-RT-SelfInstall-GM.install.iso
SL-Micro.x86_64-6.2-Base-GM.raw.xz
SL-Micro.x86_64-6.2-Base-RT-GM.raw.xz

SUSE Multi-Linux Manager

5.1

N/D

Página de descarga de SUSE Multi-Linux Manager

K3s

1.35.3

N/D

Versión en sentido ascendente de K3s

RKE2

1.35.3

N/D

Versión en sentido ascendente de RKE2

SUSE Rancher Prime

2.14.1

2.14.1

Repositorio de Helm de Rancher Prime
https://prime.ribs.rancher.io/rancher/v2.14.1/rancher-images.txt[Rancher 2.14.1 Container Images]

SUSE Storage (Longhorn)

1.11.1

1.11.1

Repositorio de Helm de SUSE Storage
https://apps.rancher.io/applications/suse-storage/components[SUSE Storage Container Images]

SUSE Security (NeuVector)

5.5.1

109.0.1+up2.8.13

Repositorio de Helm de Rancher Charts
registry.rancher.com/rancher/neuvector-controller:5.5.1
registry.rancher.com/rancher/neuvector-enforcer:5.5.1
registry.suse.com/rancher/neuvector-compliance-config:1.0.12

Proveedores de Rancher Turtles (CAPI)

0.26.1

306.0.6+up0.26.1

registry.suse.com/edge/3.6/rancher-turtles-providers-chart:306.0.6+up0.26.1
registry.rancher.com/rancher/cluster-api-controller:v1.12.2
registry.rancher.com/rancher/turtles:v0.26.1
registry.suse.com/rancher/cluster-api-provider-rke2-bootstrap:v0.24.3
registry.suse.com/rancher/cluster-api-provider-rke2-controlplane:v0.24.3

Metal3

0.15.0

306.0.26+up0.15.0

registry.suse.com/edge/3.6/metal3-chart:306.0.26+up0.15.0
registry.suse.com/edge/3.6/baremetal-operator:0.12.3.0
registry.suse.com/edge/3.6/ironic:35.0.0.1
registry.suse.com/edge/3.6/ironic-ipa-downloader:3.1.1
registry.suse.com/edge/3.6/ironic-python-agent:3.0.8

MetalLB

0.15.3

306.0.2+up0.15.3

registry.suse.com/edge/3.6/metallb-chart:306.0.2+up0.15.3
registry.suse.com/edge/3.6/metallb-controller:v0.15.3
registry.suse.com/edge/3.6/metallb-speaker:v0.15.3

Elemental

1.9.0

1.9.0

registry.suse.com/rancher/elemental-operator-chart:1.9.0
registry.suse.com/rancher/elemental-operator-crds-chart:1.9.0
registry.suse.com/rancher/elemental-operator:1.9.0

Extensión del panel de control de Elemental

3.0.1

3.0.1

Gráfico de Helm de la extensión de Elemental

Edge Image Builder

1.3.3.1

N/D

registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1

KubeVirt

1.7.0

306.0.2+up0.7.0

registry.suse.com/edge/3.6/kubevirt-chart:306.0.2+up0.7.0
registry.suse.com/suse/sles/15.7/virt-operator:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-api:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-controller:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-handler:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-launcher:1.7.0-150700.3.16.2

Extensión del panel de control de KubeVirt

1.3.3

306.0.4+up1.3.3

registry.suse.com/edge/3.6/kubevirt-dashboard-extension-chart:306.0.4+up1.3.3

Importador de datos en contenedores (CDI)

1.64.0

306.0.2+up0.7.0

registry.suse.com/edge/3.6/cdi-chart:306.0.2+up0.7.0
registry.suse.com/suse/sles/15.7/cdi-operator:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-controller:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-apiserver:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-uploadproxy:1.64.0-150700.9.6.1

Operador de Endpoint Copier

0.3.0

306.0.1+up0.3.0

registry.suse.com/edge/3.6/endpoint-copier-operator-chart:306.0.1+up0.3.0
registry.suse.com/edge/3.6/endpoint-copier-operator:0.3.0

Operador de red SR-IOV

1.6.0

306.0.4+up1.6.0

registry.suse.com/edge/3.6/sriov-network-operator-chart:306.0.4+up1.6.0
registry.suse.com/edge/3.6/sriov-crd-chart:306.0.4+up1.6.0

Controlador de actualización del sistema

0.19.1

109.0.1

Repositorio de Helm de Rancher Charts
registry.rancher.com/rancher/system-upgrade-controller:v0.19.1

Upgrade Controller

0.1.3

306.0.3+up0.1.3

registry.suse.com/edge/3.6/upgrade-controller-chart:306.0.3+up0.1.3
registry.suse.com/edge/3.6/upgrade-controller:0.1.3
registry.rancher.com/rancher/kubectl:v1.35.2
registry.suse.com/edge/3.6/release-manifest:3.6.0

SUSE Private Registry

1.1.1

1.1.1

oci://registry.suse.com/private-registry/private-registry-helm[Repositorio Helm de SUSE Private Registry]
registry.suse.com/private-registry/harbor-core:1.1.1-1.19
registry.suse.com/private-registry/harbor-jobservice:1.1.1-1.19
registry.suse.com/private-registry/harbor-portal:1.1.1-1.20
registry.suse.com/private-registry/harbor-registry:1.1.1-1.19
registry.suse.com/private-registry/harbor-registryctl:1.1.1-1.19
registry.suse.com/private-registry/harbor-trivy-adapter:1.1.1-1.24

Kiwi Builder

10.2.29.1

N/D

registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1

Cert-Manager

1.20.1

1.20.1

Repositorio Helm de Jetstack
quay.io/jetstack/cert-manager-controller:v1.20.1
quay.io/jetstack/cert-manager-webhook:v1.20.1
quay.io/jetstack/cert-manager-cainjector:v1.20.1

75.5 Funciones eliminadas

A menos que se indique lo contrario, esto se aplica a la versión 3.6.0 y a todas las versiones z-stream posteriores.

  • Akri era una oferta de vista previa tecnológica en versiones anteriores de Edge y ha quedado obsoleta a partir de la 3.4.0. Ahora se ha eliminado por completo de la oferta.

75.6 Tecnología en fase preliminar.

A menos que se indique lo contrario, esto se aplica a la versión 3.6.0 y a todas las versiones z-stream posteriores.

  • Los despliegues de clústeres de gestión IPv6 de pila única son una oferta de vista previa tecnológica y no están sujetos al ámbito de soporte estándar.

75.7 Verificación de componentes

Los componentes mencionados anteriormente pueden verificarse utilizando los datos de la Lista de materiales de software (SBOM); por ejemplo, utilizando cosign como se indica a continuación:

Descargue la clave pública del contenedor SUSE Telco Cloud desde la fuente de claves de firma de SUSE:

> cat key.pem
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7N0S2d8LFKW4WU43bq7Z
IZT537xlKe17OQEpYjNrdtqnSwA0/jLtK83m7bTzfYRK4wty/so0g3BGo+x6yDFt
SVXTPBqnYvabU/j7UKaybJtX3jc4SjaezeBqdi96h6yEslvg4VTZDpy6TFP5ZHxZ
A0fX6m5kU2/RYhGXItoeUmL5hZ+APYgYG4/455NBaZT2yOywJ6+1zRgpR0cRAekI
OZXl51k0ebsGV6ui/NGECO6MB5e3arAhszf8eHDE02FeNJw5cimXkgDh/1Lg3KpO
dvUNm0EPWvnkNYeMCKR+687QG0bXqSVyCbY6+HG/HLkeBWkv6Hn41oeTSLrjYVGa
T3zxPVQM726sami6pgZ5vULyOleQuKBZrlFhFLbFyXqv1/DokUqEppm2Y3xZQv77
fMNogapp0qYz+nE3wSK4UHPd9z+2bq5WEkQSalYxadyuqOzxqZgSoCNoX5iIuWte
Zf1RmHjiEndg/2UgxKUysVnyCpiWoGbalM4dnWE24102050Gj6M4B5fe73hbaRlf
NBqP+97uznnRlSl8FizhXzdzJiVPcRav1tDdRUyDE2XkNRXmGfD3aCmILhB27SOA
Lppkouw849PWBt9kDMvzelUYLpINYpHRi2+/eyhHNlufeyJ7e7d6N9VcvjR/6qWG
64iSkcF2DTW61CN5TrCe0k0CAwEAAQ==
-----END PUBLIC KEY-----

Verifique el hash de la imagen del contenedor, por ejemplo, utilizando crane:

> crane digest registry.suse.com/edge/3.6/baremetal-operator:0.12.3.0 --platform linux/amd64
sha256:example-digest-placeholder
Nota
Nota

Para imágenes multiarquitectura, también es necesario especificar una plataforma al obtener el resumen (digest), p. ej., --platform linux/amd64 o --platform linux/arm64. Si no se hace esto, se producirá un error en el siguiente paso (Error: no matching attestations).

Verifique con cosign:

> cosign verify-attestation --type spdxjson --key key.pem registry.suse.com/edge/3.6/baremetal-operator@sha256:example-digest-placeholder > /dev/null
#
Verification for registry.suse.com/edge/3.6/baremetal-operator@sha256:example-digest-placeholder --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The signatures were verified against the specified public key

Extraiga los datos de la SBOM como se describe en la documentación de SBOM de SUSE:

> cosign verify-attestation --type spdxjson --key key.pem registry.suse.com/edge/3.6/baremetal-operator@sha256:example-digest-placeholder | jq '.payload | @base64d | fromjson | .predicate'

75.8 Pasos de actualización

Consulte Parte VIII, “Operaciones del día 2” para obtener detalles sobre cómo actualizar a una nueva versión.

75.9 Etapas de asistencia técnica de los productos

SUSE Telco Cloud cuenta con el respaldo del galardonado soporte de SUSE, un líder tecnológico consolidado con un historial probado en la prestación de servicios de soporte de calidad empresarial. Para obtener más información, consulte https://www.suse.com/lifecycle y la página de Política de soporte en https://www.suse.com/support/policy.html. Si tiene alguna pregunta sobre cómo abrir un caso de soporte, cómo clasifica SUSE los niveles de gravedad o el alcance del soporte, consulte el Manual de soporte técnico en https://www.suse.com/support/handbook/.

SUSE Telco Cloud «3.6» cuenta con 24 meses de soporte de producción, con 6 meses iniciales de «soporte completo», seguidos de 18 meses de «soporte de mantenimiento». Tras estas fases de soporte, el producto alcanza el «fin de vida útil» (EOL) y deja de recibir soporte. Puede encontrar más información sobre las fases del ciclo de vida en la siguiente tabla:

Soporte completo (6 meses)

Durante el periodo de soporte completo se publicarán correcciones de errores urgentes y de alta prioridad seleccionadas, y el resto de los parches (no urgentes, mejoras, nuevas capacidades) se publicarán siguiendo el calendario de lanzamientos habitual.

Soporte de mantenimiento (18 meses)

Durante este periodo, solo se publicarán correcciones críticas mediante parches. Es posible que se publiquen otras correcciones de errores a discreción de SUSE, pero no debe esperarse que así sea.

Fin de vida útil (EOL)

Una vez que una versión de producto alcanza su fecha de fin de vida útil, el cliente puede seguir utilizando el producto dentro de los términos del acuerdo de licencia del producto. Los planes de soporte de SUSE no se aplican a las versiones de productos que han superado su fecha de EOL.

A menos que se indique explícitamente, todos los componentes enumerados se consideran de disponibilidad general (GA) y están cubiertos por el alcance estándar de soporte de SUSE. Algunos componentes pueden aparecer como «Technology Preview», donde SUSE proporciona a los clientes acceso a características y funcionalidades tempranas previas a la GA para su evaluación, pero no están sujetos a las políticas de soporte estándar y no se recomiendan para casos de uso de producción. SUSE agradece enormemente los comentarios y sugerencias sobre las mejoras que se pueden realizar en los componentes de Technology Preview, pero SUSE se reserva el derecho de dejar obsoleta una característica de Technology Preview antes de que esté disponible de forma general si no satisface las necesidades de nuestros clientes o no alcanza el estado de madurez que requerimos.

Tenga en cuenta que SUSE debe dejar obsoletas ocasionalmente características o cambiar las especificaciones de la API. Las razones para que una característica quede obsoleta o para el cambio de una API podrían incluir que una característica se actualice o sea reemplazada por una nueva implementación, un nuevo conjunto de características, que la tecnología en sentido ascendente ya no esté disponible o que la comunidad en sentido ascendente haya introducido cambios incompatibles. No se pretende que esto ocurra nunca dentro de una versión menor determinada (x.z), por lo que todas las versiones z-stream mantendrán la compatibilidad de la API y la funcionalidad de las características. SUSE se esforzará por proporcionar avisos de obsolescencia con suficiente antelación en las notas de la versión, junto con soluciones alternativas, sugerencias y medidas de mitigación para minimizar la interrupción del servicio.

El equipo de SUSE Telco Cloud también agradece los comentarios de la comunidad, donde se pueden plantear problemas dentro del repositorio de código respectivo en https://www.github.com/suse-edge.

75.10 Obtención del código fuente

Este producto de SUSE incluye materiales con licencia para SUSE bajo la Licencia Pública General de GNU (GPL) y otras licencias de código abierto. La GPL requiere que SUSE proporcione el código fuente que corresponde al material con licencia GPL, y SUSE cumple con todos los demás requisitos de las licencias de código abierto. Como tal, SUSE pone a disposición todo el código fuente, que generalmente se puede encontrar en el repositorio de GitHub de SUSE Telco Cloud (https://www.github.com/suse-edge), el repositorio de GitHub de SUSE Rancher (https://www.github.com/rancher) para los componentes dependientes y, específicamente para SUSE Linux Micro, el código fuente está disponible para su descarga en https://www.suse.com/download/sle-micro en el «Medio 2».

75.11 Información legal

SUSE no otorga ninguna garantía respecto al contenido y el uso de esta documentación y, específicamente, renuncia a cualquier garantía explícita o implícita de posibilidad de comercialización o adecuación para un fin determinado. Asimismo, SUSE se reserva el derecho a revisar esta publicación y a realizar cambios en su contenido en cualquier momento, sin obligación de notificar tales cambios a ninguna persona o entidad.

Asimismo, SUSE no otorga ninguna garantía con respecto a ningún programa de software, y específicamente rechaza cualquier garantía explícita o implícita de comercialización o adecuación para un fin determinado. Por otra parte, SUSE se reserva el derecho a realizar cambios en cualquiera de las partes o en la totalidad del software de SUSE en cualquier momento, sin obligación de notificar de tales cambios a ninguna persona ni entidad.

Los productos o la información técnica que se proporcionan bajo este Acuerdo pueden están sujetos a los controles de exportación de Estados Unidos o a la legislación sobre comercio de otros países. Usted se compromete a cumplir todas las normativas de control de exportaciones y a obtener las licencias o clasificaciones necesarias para exportar, reexportar o importar los entregables. Usted acepta no realizar exportaciones ni reexportaciones a las entidades que se incluyan en las listas actuales de exclusión de exportaciones de EE. UU., así como a ningún país terrorista o sometido a embargo, tal y como queda recogido en las leyes de exportación de EE. UU. Usted acepta no utilizar los entregables para fines finales prohibidos relacionados con armamento nuclear, de misiles o químico/biológico. Consulte https://www.suse.com/company/legal/ para obtener más información sobre la exportación del software de SUSE. SUSE no asume ninguna responsabilidad por los fallos que cometa el usuario en la obtención de los permisos de exportación necesarios.

Copyright © 2024 SUSE LLC.

Este documento de notas de la versión cuenta con una licencia Creative Commons Attribution-NoDerivatives 4.0 International License (CC-BY-ND-4.0). Debería haber recibido una copia de la licencia junto con este documento. Si no es así, consulte https://creativecommons.org/licenses/by-nd/4.0/.

SUSE posee derechos de propiedad intelectual relacionados con la tecnología incorporada en el producto descrito en este documento. En concreto, y sin limitación, estos derechos de propiedad intelectual pueden incluir una o más de las patentes de EE. UU. que aparecen en https://www.suse.com/company/legal/ y una o más patentes adicionales o solicitudes de patentes pendientes en EE. UU. y en otros países.

Para consultar las marcas comerciales de SUSE, véase la lista de marcas comerciales y marcas de servicio de SUSE (https://www.suse.com/company/legal/). Todas las marcas comerciales de otros fabricantes son propiedad de sus propietarios respectivos. Para obtener información sobre la marca SUSE y los requisitos de uso, consulte las directrices publicadas en https://brand.suse.com/.