documentation.suse.com / Documentación de SUSE Edge / Documentación del producto / Configuración de funciones de telecomunicaciones

41 Configuración de funciones de telecomunicaciones

Esta sección documenta y explica la configuración de las funciones específicas para telecomunicaciones en clústeres desplegados mediante SUSE Edge for Telco.

Se utiliza el método de despliegue de aprovisionamiento de red dirigida, descrito en la sección sobre aprovisionamiento automatizado (Capítulo 42, Aprovisionamiento de red dirigida totalmente automatizado).

En esta sección se tratan los siguientes temas:

41.1 Imagen del kernel en tiempo real

Usar una imagen de kernel en tiempo real no es necesariamente mejor que usar un kernel estándar. Se trata de un kernel diferente, optimizado para un caso práctico concreto. El kernel en tiempo real está optimizado para reducir la latencia a costa del rendimiento. No se recomienda el uso del kernel en tiempo real para fines generales, pero en nuestro caso, es el kernel recomendado para cargas de trabajo de telecomunicaciones, donde la latencia es un factor clave.

Hay cuatro funciones principales:

  • Ejecución determinista:

    Se consigue una mayor previsibilidad: se garantiza que los procesos empresariales críticos se completan a tiempo, siempre, y ofrece un servicio de alta calidad, incluso con cargas elevadas del sistema. Al proteger los recursos clave del sistema para los procesos de alta prioridad, se garantiza una mayor previsibilidad para las aplicaciones en las que el tiempo es importante.

  • Baja fluctuación:

    La baja fluctuación basada 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 hace referencia a la capacidad de un proceso de subir de prioridad si existe un proceso de mayor prioridad que requiere que el de menor prioridad finalice antes para poder completar su tarea. SUSE Linux Enterprise Real Time resuelve estos problemas de inversión de prioridad para los procesos críticos.

  • Interrupciones de subprocesos:

    En un sistema operativo de uso general, no se pueden interrumpir los procesos que se ejecutan en modo de interrupción. Con SUSE Linux Enterprise Real Time, estas interrupciones se encapsulan en subprocesos del kernel, que son interrumpibles. De esta forma, los procesos de mayor prioridad definidos por el usuario pueden interrumpir tanto interrupciones duras como suaves.

    En nuestro caso, si ha instalado una imagen en tiempo real como SUSE Linux Micro RT, el kernel en tiempo real ya está instalado. Puede descargar la imagen del kernel en tiempo real del Centro de servicios al cliente de SUSE.

    Nota
    Nota

    Para obtener más información sobre el kernel en tiempo real, visite SUSE Real Time.

41.2 Argumentos del kernel para baja latencia y alto rendimiento

Es importante configurar los argumentos del kernel para que el kernel en tiempo real funcione correctamente y ofrezca el mejor rendimiento y una baja latencia para ejecutar cargas de trabajo de telecomunicaciones. Hay algunos conceptos importantes que hay que tener en cuenta al configurar los argumentos del kernel para este caso práctico:

  • Elimine kthread_cpus cuando use el kernel en tiempo real de SUSE. Este parámetro controla en qué CPU se crean los subprocesos del kernel. También controla qué CPU están permitidas para el PID 1 y para cargar módulos del kernel (el ayudante del espacio de usuario kmod). Este parámetro no se reconoce y no tiene ningún efecto.

  • Use isolcpus, nohz_full, rcu_nocbs e irqaffinity para aislar los núcleos de CPU. Para obtener una lista completa de las técnicas de fijación de CPU, consulte el capítulo sobre fijación de CPU mediante Tuned y argumentos del kernel (Sección 41.3, “Fijación de CPU mediante Tuned y argumentos del kernel”).

  • Añade los indicadores domain,nohz,managed_irq al argumento del kernel isolcpus. Si no se añade 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 kernel. El indicador nohz detiene la marca del programador en las CPU especificadas (si solo se puede ejecutar una tarea en una CPU), y el indicador managed_irq evita el enrutamiento de interrupciones externas gestionadas (dispositivos) en las CPU especificadas. Tenga en cuenta que las líneas IRQ de los dispositivos NVMe están totalmente gestionadas por el kernel y, como consecuencia, se enrutarán a los núcleos no aislados (de mantenimiento). Por ejemplo, la línea de comandos que se proporciona 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 del disco en cualquier aplicación sensible al tiempo que se ejecute en los núcleos aislados, pero puede requerir atención y un diseño cuidadoso para las cargas de trabajo centradas en el almacenamiento.

  • Ajuste las marcas (ticks, interrupciones periódicas del temporizador del kernel):

    • skew_tick=1: a veces, las marcas pueden ocurrir simultáneamente. En lugar de que todas las CPU reciban su marca de temporizador exactamente al mismo tiempo, skew_tick=1 hace que se produzcan en momentos ligeramente distintos. Esto ayuda a reducir la fluctuación del sistema, lo que se traduce en tiempos de respuesta a las interrupciones más consistentes y más bajos (un requisito esencial para las aplicaciones sensibles a la latencia).

    • nohz=on: detiene la marca del temporizador periódico en las CPU inactivas.

    • nohz_full=<núcleos-cpu>: detiene la marca del temporizador periódico en las CPU especificadas que están dedicadas a aplicaciones en tiempo real.

  • Inhabilite la gestión de excepciones de comprobación de máquina (MCE) especificando mce=off. Las MCE son errores de hardware detectados por el procesador y desactivarlas puede evitar que los registros sean excesivamente grandes.

  • Añada nowatchdog para inhabilitar el watchdog de bloqueo suave, que se implementa como un temporizador que se ejecuta en el contexto de interrupción dura del temporizador. Cuando caduca (es decir, cuando se detecta un bloqueo suave), muestra una advertencia (en el contexto de interrupción dura) y ejecuta cualquier objetivo de latencia. Incluso si no caduca nunca, pasa a la lista de temporizadores, lo que aumenta ligeramente la sobrecarga de cada interrupción del temporizador. Esta opción también inhabilita el watchdog de NMI, por lo que las NMI no pueden interferir.

  • nmi_watchdog=0 inhabilita el watchdog de NMI (interrupción no enmascarable). Se puede omitir si se usa nowatchdog.

  • RCU (Read-Copy-Update, leer-copiar-actualizar) es un mecanismo del kernel que permite el acceso simultáneo y sin bloqueos de muchos lectores a datos compartidos. Una retrollamada RCU, una función que se activa tras un "periodo de gracia", garantiza que todos los lectores anteriores hayan terminado, de modo que los datos antiguos puedan recuperarse de forma segura. Ajustamos RCU, especialmente para cargas de trabajo sensibles, con el fin de descargar estas retrollamadas de CPU dedicadas (fijadas), evitando que las operaciones del kernel interfieran con tareas críticas y sensibles al tiempo.

    • Especifique las CPU fijadas en rcu_nocbs para que las retrollamadas de RCU no se ejecuten en ellas. Esto ayuda a reducir la fluctuación y la latencia de las cargas de trabajo en tiempo real.

    • rcu_nocb_poll hace que las CPU sin retrollamada realicen sondeos periódicos para comprobar si es necesario gestionar la retrollamada. Esto puede reducir la sobrecarga de interrupciones.

    • rcupdate.rcu_cpu_stall_suppress=1 suprime las advertencias de bloqueo de la CPU por RCU, que en ocasiones 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, lo que hace que las secciones críticas de lectura sean más receptivas.

    • rcupdate.rcu_normal_after_boot=1, cuando se usa con rcu_expedited, permite que RCU vuelva al funcionamiento normal (no acelerado) después del arranque del sistema.

    • rcupdate.rcu_task_stall_timeout=0 inhabilita el detector de bloqueo de tareas RCU, lo que evita posibles advertencias o interrupciones del sistema provocadas por tareas RCU de larga duración.

    • rcutree.kthread_prio=99 establece la prioridad del subproceso del kernel de retrollamadas de RCU al máximo posible (99), lo que garantiza que se programen y gestionen las retrollamadas de RCU con rapidez cuando sea necesario.

  • Añada ignition.platform.id=openstack para Metal3 y Cluster API a fin de aprovisionar/desaprovisionar correctamente el clúster. Esto lo utiliza el agente Python de Metal3, que tiene su origen en Openstack Ironic.

  • Elimine intel_pstate=passive. Esta opción configura intel_pstate para que funcione con reguladores cpufreq genéricos; pero, para que esto funcione, inhabilita los estados P gestionados por hardware (HWP) como efecto secundario. Para reducir la latencia del hardware, no se recomienda utilizar esta opción para cargas de trabajo en tiempo real.

  • Reemplace intel_idle.max_cstate=0 processor.max_cstate=1 por idle=poll. Para evitar las transiciones de estado C, se usa la opción idle=poll para inhabilitar las transiciones de estado C y mantener la CPU en el estado C más alto. La opción intel_idle.max_cstate=0 inhabilita intel_idle, por lo que se usa acpi_idle, y acpi_idle.max_cstate=1 establece el estado C máximo para acpi_idle. En arquitecturas AMD64/Intel 64, el primer estado C de ACPI es siempre POLL, pero usa 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() después de 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 cerrado, esperando activamente a que se reprogramen las tareas. Esto minimiza la latencia al salir del estado de inactividad, pero a costa de mantener la CPU funcionando a toda velocidad en el subproceso inactivo.

  • Desactive C1E en BIOS. Es importante desactivar el estado C1E en el BIOS para 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 trata sobre parámetros adicionales, incluyendo las páginas enormes e IOMMU.

Se proporciona un ejemplo de argumentos del kernel para un servidor Intel de 32 núcleos, que incluye 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 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 net.ifnames=0 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í hay otro ejemplo de configuración para un servidor AMD de 64 núcleos. Entre los 128 procesadores lógicos (0-127), los primeros 8 núcleos (0-7) se destinan a 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 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 net.ifnames=0 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

41.3 Fijación de CPU mediante Tuned y argumentos del kernel

tuned es una herramienta de ajuste del sistema que supervisa las condiciones del sistema para optimizar el rendimiento usando varios perfiles predefinidos. Una característica clave es su capacidad para aislar los núcleos de la CPU para cargas de trabajo específicas, como aplicaciones en tiempo real. Esto evita que el sistema operativo utilice esos 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 se deseen aislar. En este ejemplo, dedicamos 60 de los 64 núcleos (1-30,33-62) a la aplicación y los 4 núcleos restantes para tareas de mantenimiento. Tenga 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.

A continuación, debemos modificar la opción GRUB para aislar los núcleos de CPU y otros parámetros importantes para el uso de las CPU. Es importante personalizar las opciones siguientes con las especificaciones reales de su hardware:

ParámetroValorDescripción

isolcpus

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

Aísla los núcleos 1-30 y 33-62. domain indica que estas CPU forman parte del dominio de aislamiento. nohz habilita el funcionamiento sin marcas en estas CPU aisladas cuando están inactivas para reducir las interrupciones. managed_irq aísla las CPU fijadas para que no sean objeto de 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 distribuir las interrupciones del temporizador entre las CPU aisladas.

nohz

on

Si está habilitada, la interrupción periódica del temporizador del kernel (la "marca") se detendrá en cualquier núcleo de CPU que esté inactivo. Esto beneficia principalmente a las CPU de mantenimiento (0,31,32,63). De este modo se ahorra energía y se reducen los despertares innecesarios en esos núcleos de uso general.

nohz_full

1-30,33-62

En el caso de los núcleos aislados, esto detiene la marca incluso si la CPU está ejecutando una sola tarea activa. Es decir, hace que la CPU funcione en modo totalmente sin marcas (o "dyntick"). El kernel solo proporcionará interrupciones del temporizador cuando sean realmente necesarias.

rcu_nocbs

1-30,33-62

Esta opción descarga el procesamiento de retrollamada de RCU de los núcleos de CPU especificados.

rcu_nocb_poll

 

Cuando esta opción está definida, las CPU sin retrollamada de RCU realizarán sondeos periódicos para comprobar si es necesario gestionar las retrollamadas, en lugar de que se activen 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.

idle

poll

Esto minimiza la latencia al salir del estado inactivo, pero a costa de mantener la CPU funcionando a toda velocidad en el subproceso inactivo.

nmi_watchdog

0

Esta opción inhabilita únicamente el watchdog de NMI. Se puede omitir si se ha definido nowatchdog.

nowatchdog

 

Esta opción inhabilita el watchdog de bloqueo suave, que se implementa como un temporizador que se ejecuta en el contexto de interrupción dura 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:

Edite el archivo /etc/default/grub con los parámetros anteriores. El archivo tendrá este aspecto:

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 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 net.ifnames=0 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"

Actualice la configuración de GRUB:

$ transactional-update grub.cfg
$ reboot

Para comprobar que los parámetros se han aplicado después del rearranque, puede utilizar el siguiente comando para comprobar la línea de comandos del kernel:

$ cat /proc/cmdline

Puede usar otro guion para ajustar la configuración de la CPU, que básicamente realiza los siguientes pasos:

  • Definir el regulador de la CPU como performance.

  • Desactivar la migración del temporizador a las CPU aisladas.

  • Migrar los subprocesos kdaemon a las CPU de mantenimiento.

  • Definir la latencia de las CPU aisladas en el valor más bajo posible.

  • Retrasar las actualizaciones de vmstat a 300 segundos.

El guion está disponible en el repositorio de ejemplos de SUSE Edge for Telco.

41.4 Configuración de la CNI

41.4.1 Cilium

Cilium es el complemento de CNI predeterminado para SUSE Edge for Telco. Para habilitar Cilium en el clúster RKE2 como complemento predeterminado hay que configurar lo siguiente 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, con --cni=cilium en la línea del servidor del archivo /etc/systemd/system/rke2-server.

Para usar el operador de red SR-IOV descrito en la siguiente sección (Sección 41.5, “SR-IOV”), use Multus con otro complemento de CNI, como Cilium o Calico, como complemento secundario.

cni:
- multus
- cilium
Nota
Nota

Para obtener más información sobre los complementos de CNI, visite Network Options (Opciones de red).

41.5 SR-IOV

SR-IOV permite que un dispositivo, como un adaptador de red, divida el acceso a sus recursos entre varias funciones de hardware PCIe. Hay diferentes formas de desplegar SR-IOV, y aquí mostramos dos:

  • Opción 1: usar los complementos de dispositivo de CNI SR-IOV y un mapa de configuración para configurarlo correctamente.

  • Opción 2 (recomendada): usar el chart de Helm de SR-IOV en Rancher Prime para facilitar este despliegue.

Opción 1: Instalación de complementos de dispositivo de CNI SR-IOV y un mapa de configuración para configurarlo correctamente

  • Prepare el mapa de configuración para el complemento de dispositivo

Obtenga la información para rellenar el mapa de configuración desde el comando lspci:

$ lspci | grep -i acc
8a:00.0 Processing accelerators: Intel Corporation Device 0d5c

$ 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 mapa de configuración es un archivo JSON que describe los dispositivos utilizando filtros para detectarlos, y crea grupos para las interfaces. Lo importante es comprender qué son los filtros y los grupos. Los filtros se usan para detectar los dispositivos y los grupos, para crear las interfaces.

Es posible establecer filtros como:

  • vendorID: 8086 (Intel)

  • deviceID: 0d5c (tarjeta Accelerator)

  • driver: vfio-pci (controlador)

  • pfNames: p2p1 (nombre de interfaz física)

También es posible definir filtros con una sintaxis de interfaz más compleja, por ejemplo:

  • pfNames: ["eth1#1,2,3,4,5,6"] o [eth1#1-6] (nombre de interfaz física)

Para los grupos, es posible crear un grupo para la tarjeta FEC y otro para la tarjeta Intel, o incluso crear un prefijo en función de nuestro caso de uso:

  • resourceName: pci_sriov_net_bh_dpdk

  • resourcePrefix: Rancher.io

Hay muchas combinaciones posibles para descubrir y crear el grupo de recursos necesario para asignar funciones virtuales a los pods.

Nota
Nota

Para obtener más información sobre los filtros y los grupos, consulte sr-iov network device plug-in (Complemento de dispositivo de red sr-iov).

Después de configurar los filtros y los grupos que coincidan con las interfaces del hardware y el caso de uso, el mapa de configuración siguiente muestra un ejemplo útil:

apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": [
            {
                "resourceName": "intel_fec_5g",
                "devicetype": "accelerator",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["0d5d"]
                }
            },
            {
                "resourceName": "intel_sriov_odu",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p1"]
                }
            },
            {
                "resourceName": "intel_sriov_oru",
                "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 o ppc64le), por lo que se puede usar el mismo archivo para diferentes arquitecturas, desplegando un 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: rancher/hardened-sriov-network-device-plugin:v3.7.0-build20240816
        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
  • Después de aplicar el mapa de configuración y el daemonset, se desplegará el complemento de dispositivo y se detectarán las interfaces, que 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
  • Compruebe qué interfaces se han detectado y están disponibles en los nodos para los pods:

    $ kubectl get $(kubectl get nodes -oname) -o jsonpath='{.status.allocatable}' | jq
    {
      "cpu": "64",
      "ephemeral-storage": "256196109726",
      "hugepages-1Gi": "40Gi",
      "hugepages-2Mi": "0",
      "intel.com/intel_fec_5g": "1",
      "intel.com/intel_sriov_odu": "4",
      "intel.com/intel_sriov_oru": "4",
      "memory": "221396384Ki",
      "pods": "110"
    }
  • La tarjeta FEC es intel.com/intel_fec_5g y su valor es 1.

  • La función virtual VF es intel.com/intel_sriov_odu o intel.com/intel_sriov_oru si la despliega con un complemento de dispositivo y el mapa de configuración sin charts de Helm.

Importante
Importante

Si no hay interfaces, no tiene mucho sentido continuar, ya que la interfaz no estará disponible para los pods. Revise primero el mapa de configuración y los filtros para resolver el problema.

Opción 2 (recomendada): instalación con Rancher mediante el chart de Helm para la CNI SR-IOV y los complementos de dispositivo

  • Consiga Helm si no está presente:

$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
  • Instale SR-IOV.

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
  • Compruebe los crd y los pods de los recursos desplegados:

$ kubectl get crd
$ kubectl -n sriov-network-operator get pods
  • Compruebe la etiqueta de los nodos.

Con todos los recursos en ejecución, la etiqueta aparece automáticamente en su nodo:

$ kubectl get nodes -oyaml | grep feature.node.kubernetes.io/network-sriov.capable

feature.node.kubernetes.io/network-sriov.capable: "true"
  • Revise el daemonset para comprobar si las entradas sriov-network-config-daemon y sriov-rancher-nfd-worker nuevas están activas y listas:

$ kubectl get daemonset -A
NAMESPACE             NAME                            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                                           AGE
calico-system            calico-node                     1         1         1       1            1           kubernetes.io/os=linux                                  15h
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
kube-system              rke2-ingress-nginx-controller   1         1         1       1            1           kubernetes.io/os=linux                                  15h
kube-system              rke2-multus-ds                  1         1         1       1            1           kubernetes.io/arch=amd64,kubernetes.io/os=linux         15h

En unos minutos (la actualización puede tardar hasta 10 minutos), los nodos se detectan y se configuran capacidad de SR-IOV:

$ kubectl get sriovnetworknodestates.sriovnetwork.openshift.io -A
NAMESPACE             NAME     AGE
sriov-network-operator   xr11-2   83s
  • Compruebe las interfaces detectadas.

Las interfaces detectadas deben ser la dirección PCI del dispositivo de red. Compruebe esta información con el comando lspci en el host.

$ kubectl get sriovnetworknodestates.sriovnetwork.openshift.io -n kube-system -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 su interfaz no se detecta, asegúrese de que esté presente en el siguiente mapa de configuración:

$ kubectl get cm supported-nic-ids -oyaml -n sriov-network-operator

Si su dispositivo no aparece, edite el mapa de configuración y añada los valores correctos que se deban detectar (puede que sea necesario reiniciar el daemonset sriov-network-config-daemon).

  • Cree la directiva NetworkNodePolicy para configurar las funciones virtuales.

Se crearán algunas funciones virtuales (numVfs) desde el dispositivo (rootDevices) y se configurarán con el controlador deviceType y el MTU:

Nota
Nota

El campo resourceName no debe contener caracteres especiales y debe ser único en todo el clúster. En el ejemplo se usa deviceType: vfio-pci porque dpdk se usará junto a sr-iov. Si no utiliza dpdk, el valor de deviceType debe ser 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
  • Valide las configuraciones:

$ kubectl get $(kubectl get nodes -oname) -o jsonpath='{.status.allocatable}' | jq
{
  "cpu": "64",
  "ephemeral-storage": "256196109726",
  "hugepages-1Gi": "60Gi",
  "hugepages-2Mi": "0",
  "intel.com/intel_fec_5g": "1",
  "memory": "200424836Ki",
  "pods": "110",
  "rancher.io/intelnicsDpdk": "8"
}
  • Cree la red sr-iov (opcional, si se necesita una red diferente):

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: network-dpdk
  namespace: sriov-network-operator
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
  • Compruebe la red creada:

$ kubectl get network-attachment-definitions.k8s.cni.cncf.io -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: sriov-network-operator
    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: ""

41.6 DPDK

DPDK (Data Plane Development Kit, kit de desarrollo del plano de datos) 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. DPDK incluye bibliotecas de plano de datos y controladores de controlador 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 pools de objetos en la memoria y usa un anillo para almacenar los objetos libres; esto garantiza que los objetos se distribuyan de forma equitativa en todos los canales DRAM.

  4. Los controladores en modo de sondeo (Poll mode drivers, 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 muestran cómo habilitar DPDK y cómo crear funciones virtuales a partir de las NIC que se utilizarán en las interfaces de DPDK:

  • Instale el paquete de DPDK:

$ transactional-update pkg install dpdk dpdk-tools libdpdk-23
$ reboot
  • Parámetros del kernel:

Para usar DPDK, emplee algunos controladores para habilitar ciertos parámetros en el kernel:

ParámetroValorDescripción

iommu

pt

Esta opción permite el uso del controlador vfio para las interfaces de DPDK.

intel_iommu o amd_iommu

on

Esta opción permite el uso de vfio para las funciones virtuales.

Para habilitar los parámetros, añádalos 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 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 net.ifnames=0 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"

Actualice la configuración de GRUB y rearranque el sistema para aplicar los cambios:

$ transactional-update grub.cfg
$ reboot
  • Cargue el módulo del kernel vfio-pci y habilite SR-IOV en las tarjetas NIC:

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • Cree algunas funciones virtuales (VF) a partir de las tarjetas NIC.

Para crear funciones virtuales, por ejemplo, para dos NIC distintas, 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
  • Vincule las nuevas funciones virtuales 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
  • Compruebe 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.7 Aceleración vRAN (Intel ACC100/ACC200)

A medida que los proveedores de servicios de comunicaciones pasan de las redes 4G a las 5G, muchos están adoptando arquitecturas de redes de acceso por radio virtualizadas (vRAN) para obtener una mayor capacidad de canal y facilitar el despliegue de servicios y aplicaciones basados en la periferia. Las soluciones vRAN son perfectas 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 de la red.

Una de las cargas de trabajo de 4G y 5G que más recursos informáticos consume es la FEC de la capa 1 (L1) de la RAN, que resuelve los errores de transmisión de datos en canales de comunicación poco fiables o con ruido. La tecnología FEC detecta y corrige un número limitado de errores en los datos 4G o 5G, lo que elimina la necesidad de retransmisión. Dado que la transacción de aceleración de FEC no contiene información sobre el estado de las celdas, se puede virtualizar fácilmente, de forma que se puede aprovechar la agrupación y facilitar la migración de celdas.

  • Parámetros del kernel

Para habilitar la aceleración vRAN, es preciso habilitar los siguientes parámetros del kernel (si aún no están presentes):

ParámetroValorDescripción

iommu

pt

Esta opción permite el uso de vfio para las interfaces DPDK.

intel_iommu o amd_iommu

on

Esta opción permite el uso de vfio para las funciones virtuales.

Modifique 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 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 net.ifnames=0 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"

Actualice la configuración de GRUB y rearranque el sistema para aplicar los cambios:

$ transactional-update grub.cfg
$ reboot

Para verificar que los parámetros se han aplicado después del rearranque, compruebe la línea de comandos:

$ cat /proc/cmdline
  • Cargue los módulos del kernel vfio-pci para habilitar la aceleración vRAN:

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • Obtenga información de la interfaz Acc100:

$ lspci | grep -i acc
8a:00.0 Processing accelerators: Intel Corporation Device 0d5c
  • Vincule la interfaz física (PF) con el controlador vfio-pci:

$ dpdk-devbind.py -b vfio-pci 0000:8a:00.0
  • Cree las funciones virtuales (VF) a partir de la interfaz física (PF).

Cree dos VF desde la PF y vincúlelas con vfio-pci así:

$ echo 2 > /sys/bus/pci/devices/0000:8a:00.0/sriov_numvfs
$ dpdk-devbind.py -b vfio-pci 0000:8b:00.0
  • Configure acc100 con el archivo de configuración propuesto:

$ pf_bb_config ACC100 -c /opt/pf-bb-config/acc100_config_vf_5g.cfg
Tue Jun  6 10:49:20 2023:INFO:Queue Groups: 2 5GUL, 2 5GDL, 2 4GUL, 2 4GDL
Tue Jun  6 10:49:20 2023:INFO:Configuration in VF mode
Tue Jun  6 10:49:21 2023:INFO: ROM version MM 99AD92
Tue Jun  6 10:49:21 2023:WARN:* Note: Not on DDR PRQ version  1302020 != 10092020
Tue Jun  6 10:49:21 2023:INFO:PF ACC100 configuration complete
Tue Jun  6 10:49:21 2023:INFO:ACC100 PF [0000:8a:00.0] configuration complete!
  • Compruebe las nuevas funciones virtuales creadas desde la interfaz física FEC:

$ dpdk-devbind.py -s
Baseband devices using DPDK-compatible driver
=============================================
0000:8a:00.0 'Device 0d5c' drv=vfio-pci unused=
0000:8b:00.0 'Device 0d5d' drv=vfio-pci unused=

Other Baseband devices
======================
0000:8b:00.1 'Device 0d5d' unused=

41.8 Páginas enormes

Cuando un proceso utiliza RAM, la CPU lo marca como utilizado por ese proceso. Por motivos de eficiencia, la CPU asigna RAM en bloques de 4K bytes, que es el valor predeterminado en muchas plataformas. Esos bloques se denominan páginas. Las páginas se pueden intercambiar en el disco, etc.

Dado que el espacio de direcciones del proceso es virtual, la CPU y el sistema operativo deben recordar qué páginas pertenecen a cada proceso y dónde se almacena cada página. Cuanto más páginas haya, más tiempo llevará la búsqueda de asignación de memoria. Cuando un proceso usa 1 GB de memoria, eso supone 262 144 entradas que buscar (1 GB / 4 K). Si una entrada de la tabla de páginas consume 8 bytes, eso supone 2 MB (262 144 * 8) que buscar.

La mayoría de las arquitecturas actuales de CPU admiten páginas más grandes que las predeterminadas, lo que reduce el número de entradas que la CPU/SO debe buscar.

  • Parámetros del kernel

Para habilitar estas páginas enormes (huge pages), debemos añadir los siguientes parámetros del kernel. En este ejemplo, configuramos 40 páginas de 1 GB, aunque el tamaño de la página enorme y el número exacto de ellas deben adaptarse a los requisitos de memoria de su aplicación:

ParámetroValorDescripción

hugepagesz

1G

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 definidas anteriormente

default_hugepagesz

1G

Este es el valor predeterminado para obtener las páginas enormes

Modifique 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

Actualice la configuración de GRUB y rearranque el sistema para aplicar los cambios:

$ transactional-update grub.cfg
$ reboot

Para comprobar que los parámetros se han aplicado después del rearranque, puede consultar la línea de comandos:

$ cat /proc/cmdline
  • Uso de páginas enormes

Para usar las páginas enormes, debe montarlas:

$ mkdir -p /hugepages
$ mount -t hugetlbfs nodev /hugepages

Despliegue 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
...

41.9 Fijación de CPU en Kubernetes

41.9.1 Requisito previo

Debe tener la CPU ajustada al perfil de rendimiento descrito en esta sección (Sección 41.3, “Fijación de CPU mediante Tuned y argumentos del kernel”).

41.9.2 Configuración de Kubernetes para la fijación de CPU

Configure los argumentos de kubelet para implementar la gestión de la CPU en el clúster RKE2. Añada el siguiente bloque de configuración, como se muestra en el ejemplo siguiente, al archivo /etc/rancher/rke2/config.yaml. Asegúrese 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"

41.9.3 Aprovechamiento de CPU fijadas para cargas de trabajo

Hay tres formas de utilizar esa función utilizando la directiva estática definida en kubelet, dependiendo de las solicitudes y los límites que defina en su carga de trabajo:

  1. Clase de calidad de servicio BestEffort: si no se define ninguna solicitud o límite para la CPU, el pod se programa en la primera CPU disponible en el sistema.

    Este es un ejemplo de uso de la clase de calidad de servicio BestEffort:

    spec:
      containers:
      - name: nginx
        image: nginx
  2. Clase de calidad de servicio Burstable: si se define una solicitud para la CPU que no se ajusta a los límites establecidos, o si no hay ninguna solicitud de CPU.

    Ejemplos de uso de la clase de calidad de servicio Burstable:

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
          requests:
            memory: "100Mi"

    o

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
            cpu: "2"
          requests:
            memory: "100Mi"
            cpu: "1"
  3. Clase de calidad de servicio Guaranteed: si define una solicitud de CPU que es igual a los límites.

    Ejemplo de uso de la clase de calidad de servicio Guaranteed:

    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: "200Mi"
              cpu: "2"
            requests:
              memory: "200Mi"
              cpu: "2"

41.10 Programación compatible con NUMA

El acceso a la memoria no uniforme o arquitectura de memoria no uniforme (NUMA) es un diseño de memoria física utilizado en la arquitectura SMP (multiprocesadores) en la que el tiempo de acceso a la memoria depende de la ubicación de la memoria con respecto al procesador. En NUMA, un procesador puede acceder a su propia memoria local más rápido que a la memoria no local; es decir, la memoria local de otro procesador o la memoria compartida entre procesadores.

41.10.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

En este ejemplo, solo tenemos un nodo NUMA que muestra 64 CPU.

NUMA debe estar habilitado en el BIOS. Si dmesg no tiene registros de la inicialización de NUMA durante el arranque, es posible que los mensajes relacionados con NUMA del búfer del anillo del kernel se hayan sobrescrito.

41.11 MetalLB

MetalLB es una implementación de equilibrador de carga para clústeres bare metal de Kubernetes que utiliza protocolos de enrutamiento estándar como L2 y BGP como protocolos de anuncios. Se trata de un equilibrador de carga de red que se puede utilizar para exponer servicios de un clúster de Kubernetes al mundo exterior que necesite utilizar el tipo de servicios de Kubernetes LoadBalancer con bare metal.

Para habilitar MetalLB en el clúster RKE2, se deben seguir estos pasos:

  • Instale MetalLB con este 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: 303.0.0+up0.14.9
  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: 303.0.0+up0.2.1
  createNamespace: true
EOF
  • Cree la configuración 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 la IP virtual:

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 se ha creado la IP virtual y que los pods de MetalLB se están ejecutando:

$ kubectl get svc -n default
$ kubectl get pods -n default

41.12 Configuración del registro privado

Es posible configurar Containerd para que se conecte a registros privados y los use para extraer imágenes privadas en cada nodo.

Durante el inicio, RKE2 comprueba si existe un archivo registries.yaml en /etc/rancher/rke2/ y ordena a containerd que use cualquier registro definido en el archivo. Si desea utilizar un registro privado, cree este archivo como usuario root en cada nodo que vaya a utilizar el registro.

Para añadir el registro privado, cree 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, debe configurar este archivo antes de iniciar RKE2 en el nodo, o bien reiniciar RKE2 en cada nodo configurado.

Nota
Nota

Para obtener más información, consulte containerd registry configuration rke2 (Configuración del registro containerd en RKE2).

41.13 Protocolo de tiempo de precisión (PTP)

El protocolo de tiempo de precisión (PTP) es un protocolo de red desarrollado por el IEEE (Instituto de Ingenieros Eléctricos y Electrónicos) para permitir la sincronización del tiempo en submicrosegundos en una red informática. Desde su creación y durante las últimas dos décadas, el PTP se ha utilizado en muchos sectores. Recientemente, se ha observado un aumento de su adopción en las redes de telecomunicaciones como elemento fundamental para las redes 5G. Aunque se trata de un protocolo relativamente sencillo, su configuración puede variar significativamente en función de la aplicación. Por ese motivo, se han definido y estandarizado múltiples perfiles.

En esta sección solo se tratan los perfiles específicos de telecomunicaciones. Por lo tanto, se dará por sentado que la NIC cuenta con capacidad de marcación de tiempo y con un reloj de hardware PTP (PHC). Hoy en día, todos los adaptadores de red para telecomunicaciones incluyen compatibilidad con PTP en el hardware, pero puede verificarlo 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

Sustituya p1p1 por el nombre de la interfaz que se utilizará para PTP.

Las siguientes secciones explican cómo instalar y configurar PTP en SUSE Edge específicamente, pero se espera que el usuario esté familiarizado con los conceptos básicos de PTP. Para obtener una breve descripción general de PTP y la implementación incluida en SUSE Edge for Telco, consulte https://documentation.suse.com/sles/html/SLES-all/cha-tuning-ptp.html.

41.13.1 Instalación de los componentes de software de PTP

En SUSE Edge for Telco, 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 daemons son necesarios para que la sincronización del sistema funcione correctamente y deben estar configurados adecuadamente según su configuración. Esto se explica en la Sección 41.13.2, “Configuración de PTP para despliegues de telecomunicaciones”.

La mejor manera, y la más fácil, de integrar PTP en su clúster descendente es añadir el paquete linuxptp en packageList en el archivo de definición de Edge Image Builder (EIB). De esta forma, el software del plano de control de PTP se instalará automáticamente durante el aprovisionamiento del clúster. Consulte la documentación de EIB (Sección 3.3.4, “Configuración de paquetes RPM”) para obtener más información sobre la instalación de paquetes.

Esto es un ejemplo de manifiesto de EIB con linuxptp:

apiVersion: 1.0
image:
  imageType: RAW
  arch: x86_64
  baseImage: {micro-base-rt-image-raw}
  outputImageName: eibimage-slmicrort-telco.raw
operatingSystem:
  time:
    timezone: America/New_York
  kernelArgs:
    - ignition.platform.id=openstack
    - net.ifnames=1
  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
      - dpdk
      - dpdk-tools
      - libdpdk-23
      - pf-bb-config
      - open-iscsi
      - tuned
      - cpupower
      - linuxptp
    sccRegistrationCode: ${SCC_REGISTRATION_CODE}
Nota
Nota

El paquete linuxptp incluido en SUSE Edge for Telco no habilita ptp4l ni phc2sys de forma predeterminada. Si sus archivos de configuración específicos del sistema se despliegan en el momento del aprovisionamiento (consulte la Sección 41.13.3, “Integración de Cluster API”), deben habilitarse. Para ello, añádalos a la sección systemd del manifiesto, como en el ejemplo anterior.

Siga el proceso habitual para crear la imagen que se describe en la documentación de EIB (Sección 3.4, “Creación de la imagen”) y utilícela para desplegar su clúster. Si no tiene experiencia con EIB, comience por el Capítulo 11, Edge Image Builder.

41.13.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. Por eso, se definieron dos perfiles orientados a las telecomunicaciones: el ITU-T G.8275.1 y el ITU-T G.8275.2. Ambos tienen una alta tasa de mensajes de sincronización y otras características distintivas, como el uso de un algoritmo de reloj maestro óptimo (BMCA) alternativo. Este comportamiento exige ajustes específicos en el archivo de configuración utilizado por ptp4l, que se proporcionan en las siguientes secciones como referencia.

Nota
Nota
  • Ambas secciones solo cubren el caso de un reloj normal con una configuración de recepción de hora.

  • Los perfiles de este tipo deben utilizarse en una infraestructura PTP bien planificada.

  • Es posible que su red PTP específica requiera ajustes de configuración adicionales. Asegúrese de revisar y adaptar los ejemplos proporcionados si es necesario.

41.13.2.1 Perfil ITU-T G.8275.1 de PTP

El perfil G.8275.1 tiene las siguientes especificaciones:

  • Se ejecuta directamente en Ethernet y requiere soporte de red completo (los nodos/conmutadores adyacentes deben ser compatibles con PTP).

  • La configuración predeterminada del dominio 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 daemon se inicie correctamente. Puede hacerlo cambiando la línea OPTIONS= por:

OPTIONS="-f /etc/ptp4l-G.8275.1.conf -i $IFNAME --message_tag ptp-8275.1"

En concreto:

  • -f requiere el nombre del archivo de configuración que se va a utilizar; en este caso, /etc/ptp4l-G.8275.1.conf.

  • -i requiere el nombre de la interfaz que se va a utilizar. Sustituya $IFNAME por el nombre real de la interfaz.

  • --message_tag permite identificar mejor la salida de ptp4l en los registros del sistema y es opcional.

Una vez completados los pasos anteriores, se debe (re)iniciar el daemon ptp4l:

# systemctl restart ptp4l

Compruebe el estado de sincronización observando los registros con:

# journalctl -e -u ptp4l

41.13.2.2 Perfil ITU-T G.8275.2 de PTP

El perfil G.8275.2 tiene las siguientes especificaciones:

  • Funciona con IP y no requiere soporte de red completo (los nodos/conmutadores adyacentes pueden no ser compatibles con PTP).

  • La configuración predeterminada del dominio 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 se va a comunicar, como el reloj maestro o el reloj fronterizo que proporcionará la sincronización.

  • $IFNAME: indica a ptp4l qué interfaz debe utilizar para PTP.

Una vez creado el archivo, debe referenciarse en /etc/sysconfig/ptp4l junto con el nombre de la interfaz que se utilizará para PTP para que el daemon se inicie correctamente. Puede hacerlo cambiando la línea OPTIONS= por:

OPTIONS="-f /etc/ptp4l-G.8275.2.conf --message_tag ptp-8275.2"

En concreto:

  • -f requiere el nombre del 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, se debe (re)iniciar el daemon ptp4l:

# systemctl restart ptp4l

Compruebe el estado de sincronización observando los registros con:

# journalctl -e -u ptp4l

41.13.2.3 Configuración de phc2sys

Aunque no es obligatorio, se recomienda completar totalmente la configuración de ptp4l antes de pasar a phc2sys. phc2sys no requiere un archivo de configuración y sus parámetros de ejecución se pueden controlar ú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 la fuente de PHC.

41.13.3 Integración de Cluster API

Cada vez que se despliega un clúster mediante un clúster de gestión y un aprovisionamiento de red dirigido, tanto el archivo de configuración como las dos variables de configuración de /etc/sysconfig se pueden desplegar 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/v1beta1
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  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"
                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, como se describe en el Capítulo 42, Aprovisionamiento de red dirigida totalmente automatizado.

Nota
Nota
  • Este enfoque solo resulta útil 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, los hosts deberían tener una pila PTP operativa y en ejecución, y comenzarán a negociar su función PTP.

Documentation survey