Ajusta el rendimiento de los nodos

Una forma de mejorar el rendimiento de las aplicaciones basadas en contenedores es aumentar los recursos del clúster. Para ello, agrega nodos a los nodos, como CPU o memoria. Sin embargo, este enfoque puede llegar a ser costoso. Ajustar los nodos del clúster para obtener un mejor rendimiento te ayuda a optimizar el uso de los recursos de tus cargas de trabajo de una manera rentable. En este documento, se describe cómo usar el operador de ajuste de rendimiento para ajustar nodos trabajadores y, así, optimizar el rendimiento de las cargas de trabajo de GKE en Bare Metal.

Para aprovechar al máximo el hardware y el software subyacentes, los diferentes tipos de aplicaciones, en especial las de alto rendimiento, se benefician del ajuste de la configuración de los nodos de la siguiente manera:

  • CPU dedicadas para cargas de trabajo sensibles al rendimiento
  • CPUs reservadas para daemons y servicios estándar de Kubernetes
  • El tamaño de las páginas de memoria aumenta cuando se generan 1 GiB (gibibyte) o 2 MiB (mebibyte).
  • Distribución de la carga de trabajo basada en la arquitectura del sistema, como procesadores de varios núcleos y NUMA

Con el operador de ajuste de rendimiento, puedes configurar el rendimiento a nivel de nodo mediante la creación de recursos personalizados de Kubernetes que aplican configuraciones de rendimiento. Estos son los beneficios:

  • Interfaz de configuración única y unificada: con el Operador de ajuste de rendimiento, puedes actualizar uno o más manifiestos PerformanceTuningProfile que se pueden aplicar a los nodos trabajadores con selectores de nodos. No es necesario que configures cada nodo de forma individual con varios ajustes de configuración y políticas. Este enfoque te permite administrar las configuraciones a nivel del nodo y del contenedor de una manera única y unificada.

  • Persistencia y confiabilidad: También obtienes toda la confiabilidad que proporciona Kubernetes con su arquitectura de alta disponibilidad. Los recursos personalizados PerformanceTuningProfile se pueden actualizar cuando lo desees y su configuración persiste en las operaciones principales del clúster, como las actualizaciones.

El operador de ajuste de rendimiento trabaja mediante la organización de las siguientes funciones y herramientas de Kubernetes y del sistema operativo (SO) relacionadas con el rendimiento:

Para evitar conflictos, cuando uses el operador de ajuste de rendimiento, te recomendamos que no uses las herramientas y funciones de Kubernetes y SO de forma independiente.

Requisitos previos y limitaciones

A continuación, se incluyen los requisitos previos y las limitaciones para usar el operador de ajuste de rendimiento:

  • Solo para Red Hat Enterprise Linux (RHEL): El operador de ajuste de rendimiento es compatible con los nodos que ejecutan solo versiones compatibles de RHEL.

  • Clúster de usuario o híbrido con nodos trabajadores: El operador de ajuste de rendimiento solo se puede usar con nodos trabajadores en clústeres híbridos o de usuario. No se admite el uso del operador de ajuste de rendimiento para ajustar los nodos del plano de control. El operador de ajuste de rendimiento usa un selector de nodos para determinar cómo aplicar perfiles de ajuste. Para garantizar que los perfiles de ajuste se apliquen solo a los nodos trabajadores, el nodeSelector en cada recurso personalizado de perfil debe incluir la etiqueta de nodo trabajador estándar node-role.kubernetes.io/worker: "". Si el nodeSelector en un perfil de ajuste coincide con las etiquetas de un nodo del plano de control, ese nodo no se ajusta y se establece una condición de error. Para obtener más información sobre las condiciones de error, consulta Verifica el estado. Asegúrate de que el clúster funcione correctamente antes de instalar el operador de ajuste de rendimiento y aplicar perfiles de ajuste.

  • TuneD 2.22.0: El operador de ajuste de rendimiento requiere que la versión 2.22.0 de TuneD esté preinstalada en los nodos trabajadores que deseas ajustar. Para obtener más información sobre TuneD, incluidas las instrucciones de instalación, consulta Cómo comenzar a usar TuneD en la documentación de Red Hat Enterprise Linux. El operador de ajuste de rendimiento usa TuneD con el perfil cpu-partitioning. Si no tienes este perfil, puedes instalarlo con el siguiente comando:

    dnf install -y tuned-profiles-cpu-partitioning
    
  • Requisitos de recursos de carga de trabajo: Para aprovechar al máximo el ajuste de rendimiento, debes comprender bien los requisitos de memoria y CPU (solicitudes y límites de recursos) para tus cargas de trabajo.

  • Recursos de nodo disponibles: Encuentra los recursos de CPU y memoria para tus nodos. Puedes obtener información detallada de la CPU y la memoria de tu nodo en los archivos /proc/cpuinfo y /proc/meminfo, respectivamente. También puedes usar kubectl get nodes a fin de recuperar la cantidad de recursos de procesamiento y memoria (status.allocatable) que tiene un nodo trabajador y que están disponibles para los Pods.

  • Requiere vaciado: Como parte del proceso de ajuste, el operador de ajuste de rendimiento primero vacía los nodos y, luego, aplica un perfil de ajuste. Como resultado, los nodos pueden informar un estado NotReady durante el ajuste de rendimiento. Te recomendamos que uses la estrategia de actualización progresiva (spec.updateStrategy.type: rolling) en lugar de una actualización por lotes para minimizar la falta de disponibilidad de las cargas de trabajo.

  • Requiere reinicio: Para que se apliquen los cambios de ajuste de nodos, el operador de ajuste de rendimiento reinicia el nodo después de aplicar el perfil de ajuste.

Instalar un operador de ajuste de rendimiento

El operador de ajuste de rendimiento consta principalmente de dos controladores (un Deployment y un DaemonSet) que interactúan entre sí para ajustar los nodos según la configuración de tu perfil. El operador de ajuste de rendimiento no está instalado con GKE en Bare Metal de forma predeterminada. Debes descargar los manifiestos del operador de ajuste de rendimiento desde Cloud Storage y usar kubectl apply para crear recursos del operador de ajuste de rendimiento en tu clúster.

Para habilitar el ajuste de rendimiento con valores predeterminados en tu clúster, haz lo siguiente:

  1. Crea un directorio performance-tuning en la estación de trabajo de administrador.

  2. Desde el directorio performance-tuning, descarga el paquete más reciente del operador de ajuste de rendimiento del bucket de versión de Cloud Storage:

    gsutil cp -r gs://anthos-baremetal-release/node-performance-tuning/0.1.0-gke.47 .
    

    Los archivos descargados incluyen manifiestos para la Deployment de performance-tuning-operator y el DaemonSet de nodeconfig-controller-manager. También se incluyen los manifiestos para las funciones relacionadas, como el control de acceso basado en roles (RBAC) y el control de admisión dinámico.

  3. Como usuario raíz, aplica todos los manifiestos del operador de ajuste de rendimiento de manera recursiva en tu clúster de usuario (o híbrido):

    kubectl apply -f performance-tuning --recursive –-kubeconfig USER_KUBECONFIG
    

    Una vez que se crean y ejecutan la Deployment y el DaemonSet, tu única interacción es editar y aplicar manifiestos de PerformanceTuningProfile.

Revisa los requisitos de los recursos para tus cargas de trabajo

Antes de poder ajustar los nodos, debes comprender los requisitos de recursos de procesamiento y memoria de tus cargas de trabajo. Si tus nodos trabajadores tienen suficientes recursos, se pueden ajustar para proporcionar memoria garantizada (estándar y de gran tamaño) para tus cargas de trabajo en la clase de calidad de servicio (QoS) garantizada.

Kubernetes asigna clases de QoS a cada uno de tus Pods, según las restricciones de recursos que especifiques para los contenedores asociados. Luego, Kubernetes utiliza clases de QoS para determinar cómo programar tus Pods y contenedores, y asignar recursos a tus cargas de trabajo. Para aprovechar al máximo el ajuste de nodos en tus cargas de trabajo, estas deben tener solicitudes de recursos de CPU o memoria o una configuración de límites.

Para que se les asigne una clase de QoS garantizada, los Pods deben cumplir con los siguientes requisitos:

  • En cada contenedor del Pod:
    • Especifica valores para las solicitudes de recursos de memoria (spec.containers[].resources.requests.memory) y los límites (spec.containers[].resources.limits.memory).
    • El valor de los límites de memoria debe ser igual al valor de solicitudes de memoria.
    • Especifica valores para las solicitudes de recursos de CPU (spec.containers[].resources.requests.cpu) y los límites (spec.containers[].resources.limits.cpu).
    • El valor de los límites de CPU debe ser igual al valor de las solicitudes de CPU.

En el siguiente extracto de especificaciones del Pod, se muestra la configuración de recursos de la CPU que cumple con los requisitos de la clase QoS garantizada:

spec:
  containers:
  - name: sample-app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "128Mi"
        cpu: "2"
      limits:
        memory: "128Mi"
        cpu: "2"
  ...

Cuando recuperas detalles del pod con kubectl get pods, la sección status debe incluir la clase QoS asignada, como se muestra en el siguiente ejemplo:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2023-09-22T21:05:23Z"
  generateName: my-deployment-6fdd69987d-
  labels:
    app: metrics
    department: sales
    pod-template-hash: 6fdd69987d
  name: my-deployment-6fdd69987d-7kv42
  namespace: default
  ...
spec:
  containers:
  ...
status:
  conditions:
  - lastProbeTime: null
    lastTransitionTime: "2023-09-22T21:05:23Z"
    status: "True"
    type: Initialized
  ...
  qosClass: BestEffort
  startTime: "2023-09-22T21:05:23Z"

Para obtener más información sobre las clases de QoS, consulta Clases de calidad de servicio de Pods en la documentación de Kubernetes. Si quieres obtener instrucciones para configurar tus Pods y contenedores a fin de que se les asigne una clase de QoS, consulta Configura la Calidad de servicio de los Pods.

Requisitos de CPU

Cuando ajustas un nodo, puedes especificar un conjunto de núcleos de CPU reservados (spec.cpu.reservedCPUs) para ejecutar daemons del sistema de Kubernetes, como kubelet y entorno de ejecución del contenedor. Este mismo conjunto de CPU reservadas también ejecuta daemons del sistema operativo, como sshd y udev. El resto de los núcleos de CPU en el área se asignan como aislados. Las CPU aisladas están diseñadas para aplicaciones vinculadas a la CPU, que requieren un tiempo de CPU dedicado sin interferencia de otras aplicaciones ni interrupciones de la red o de otros dispositivos.

Para programar un Pod en las CPU aisladas de un nodo trabajador, haz lo siguiente:

  • Configurar el Pod para garantizar una calidad de servicio (QoS) garantizada

  • Los requisitos y límites de CPU deben especificarse en números enteros. Si especificas recursos de CPU parciales en las especificaciones de tu Pod, como cpu: 0.5 o cpu: 250m (250 millicores), no se puede garantizar la programación.

Requisitos de la memoria

Cuando ajustas un nodo con el operador de ajuste de rendimiento, puedes crear grandes páginas y asociarlas con los nodos de acceso no uniforme a la memoria (NUMA) en la máquina. Según la configuración de Pods y nodos, los Pods se pueden programar con la afinidad de NUMA nodos.

Cómo crear un perfil de ajuste de rendimiento

Después de instalar el operador de ajuste de rendimiento, solo interactuarás con el clúster que ejecuta tus cargas de trabajo. Puedes crear recursos personalizados de PerformanceTuningProfile directamente en el clúster de usuario o el clúster híbrido, no en el clúster de administrador. Cada recurso PerformanceTuningProfile contiene un conjunto de parámetros que especifica la configuración de rendimiento que se aplica a un nodo.

El nodeSelector en el recurso determina los nodos a los que se aplica el perfil de ajuste. Para aplicar un perfil a un nodo, coloca la etiqueta de par clave-valor correspondiente en el nodo. Se aplica un perfil de ajuste a los nodos que tienen todas las etiquetas especificadas en el campo nodeSelector.

Puedes crear varios recursos PerformanceTuningProfile en un clúster. Si más de un perfil coincide con un nodo determinado, se establece una condición de error en el status del recurso personalizado PerformanceTuningProfile. Para obtener más información sobre la sección status, consulta Cómo verificar el estado.

Establece el espacio de nombres para tu recurso personalizado PerformanceTuningProfile en kube-system.

Para ajustar uno o más nodos trabajadores, sigue estos pasos:

  1. Edita el manifiesto PerformanceTuningProfile.

    Para obtener información sobre cada campo del manifiesto y un manifiesto de muestra, consulta la referencia del recurso PerformanceTuningProfile.

  2. En los nodos trabajadores a los que aplicas un perfil, agrega etiquetas para que coincidan con el par clave-valor spec.nodeSelector (opcional).

    Si no se especifica ningún par clave-valor spec.nodeSelector en el recurso personalizado PerformanceTuningProfile, el perfil se aplica a todos los nodos trabajadores.

  3. Aplica el manifiesto al clúster.

    kubectl apply -f PROFILE_MANIFEST --kubeconfig KUBECONFIG
    

    Reemplaza lo siguiente:

    • PROFILE_MANIFEST: Es la ruta de acceso del archivo de manifiesto para el recurso personalizado PerformanceTuningProfile.
    • KUBECONFIG: Es la ruta de acceso del archivo kubeconfig del clúster.

Cómo quitar un perfil de ajuste

Para restablecer un nodo a su estado original sin ajustar, haz lo siguiente:

  1. Borra el recurso personalizado PerformanceTuningProfile del clúster.

  2. Actualiza o quita las etiquetas del nodo para que el perfil de ajuste no lo seleccione otra vez.

Si tienes varios perfiles de ajuste asociados con el nodo, repite los pasos anteriores según sea necesario.

Cómo pausar un perfil de ajuste

Si necesitas realizar mantenimiento en tu clúster, puedes pausar de forma temporal el ajuste mediante la edición del recurso personalizado PerformanceTuningProfile. Te recomendamos que pauses el ajuste antes de realizar operaciones críticas del clúster, como actualizar el clúster.

La aplicación de un perfil no tiene éxito es otro caso en el que puedes pausar el ajuste. Si el proceso de ajuste no funciona, el controlador puede seguir intentando ajustar el nodo, lo que puede provocar que este se reinicie una y otra vez. Si observas que el estado del nodo cambia entre el estado listo y no listo, pausa el ajuste para que puedas recuperarte del estado interrumpido.

Para pausar el ajuste, haz lo siguiente:

  1. Edita el manifiesto de recursos personalizados PerformanceTuningProfile para establecer spec.paused como true.

  2. Usa kubectl apply para actualizar el recurso.

Cuando se pausa el ajuste de rendimiento, el controlador del operador de ajuste de rendimiento detiene todas sus operaciones. Pausar evita el riesgo de que las operaciones del controlador del operador de ajuste de rendimiento entren en conflicto con cualquier operación del controlador de GKE en Bare Metal.

Referencia del recurso PerformanceTuningProfile

En esta sección, se describe cada uno de los campos del recurso personalizado PerformanceTuningProfile. Este recurso se usa con el fin de crear un perfil de ajuste para uno o más de los nodos del clúster. Todos los campos del recurso son mutables después de la creación del perfil. Los perfiles deben estar en el espacio de nombres kube-system.

En el siguiente manifiesto de perfil de muestra numa para nodos con 8 núcleos de CPU, se especifican las siguientes asignaciones de recursos:

  • 4 núcleos de CPU (0-3) están reservados para la sobrecarga del sistema de Kubernetes.

  • Se reservan 4 núcleos de CPU (4-7) solo para cargas de trabajo.

  • La memoria de nodo se divide en páginas de 2 MiB de forma predeterminada, en lugar de las páginas estándar de 4 Ki.

  • Se reservan 10 páginas de memoria con un tamaño de 1 GiB para que las use el nodo 0 de NUMA.

  • Se reservan 5 páginas de memoria con un tamaño de 2 MiB para que las use el nodo 1 de NUMA.

  • Topology Manager usa la política de mejor esfuerzo para programar cargas de trabajo.

apiVersion: anthos.gke.io/v1alpha1
kind: PerformanceTuningProfile
metadata:
  name: numa
  namespace: kube-system
spec:
  cpu:
    isolatedCPUs: 4-7
    reservedCPUs: 0-3
  defaultHugepagesSize: 2M
  nodeSelector:
    app: database
    node-role.kubernetes.io/worker: ""
  pages:
  - count: 10
    numaNode: 0
    size: 1G
  - count: 5
    numaNode: 1
    size: 2M
  topologyManagerPolicy: best-effort

Puedes recuperar la definición de recurso personalizado PerformanceTuningProfile relacionada del grupo anthos.gke.io en tu clúster. La definición de recurso personalizado se instala una vez que la anotación de la función de vista previa se agrega al recurso del clúster autoadministrado.

Configuración de CPU

Propiedad Descripción
cpu.reservedCPUs Obligatorio. Modificable. String. En este campo, se define un conjunto de núcleos de CPU que se reservarán para daemons del sistema de Kubernetes, como kubelet, el entorno de ejecución del contenedor y el detector de problemas de nodos. Estos núcleos de CPU también se usan para daemons del sistema del sistema operativo (SO), como sshd y udev.

El campo cpu.reservedCPUs toma una lista de números de CPU o rangos de números de CPU. Asegúrate de que la lista de CPU no se superponga con la lista especificada con cpu.isolatedCPUs. La unión de las CPU que se enumeran en estos dos campos debe incluir todas las CPU del nodo.

cpu.isolatedCPUs Opcional. Modificable. String. El campo cpu.isolatedCPUs define un conjunto de CPU que se usan exclusivamente para aplicaciones sensibles al rendimiento. El administrador de CPU programa los contenedores solo en las CPU no reservadas, de acuerdo con las clases de calidad de servicio (QoS) de Kubernetes. Para asegurarte de que las cargas de trabajo se ejecuten en las CPU aisladas, configura los Pods con la clase QoS garantizada y asigna un recurso de CPU al Pod o al contenedor. Para la programación garantizada de Pods, debes especificar unidades de CPU de números enteros, no recursos de CPU parciales (cpu: "0.5").

apiVersion: v1
kind: Pod
...
spec:
  containers:
  ...
    resources:
      limits:
        cpu: "1"
      requests:
        cpu: "1"
  ...

La maximización de CPUs aisladas para cargas de trabajo proporciona el mejor beneficio de rendimiento. Este campo toma una lista de números de CPU o rangos de números de CPU. Asegúrate de que la lista de CPU no se superponga con la lista especificada con cpu.reservedCPUs y de que la unión de las listas en estos dos campos incluya todas las CPU del nodo.

cpu.balanceIsolated Opcional. Modificable. Booleano. Valor predeterminado: true. Este campo especifica si el conjunto de CPU aisladas es apto para el balanceo de cargas automático de cargas de trabajo entre CPU. Cuando configuras este campo como false, tus cargas de trabajo deben asignar cada subproceso de forma explícita a una CPU específica para distribuir la carga entre las CPU. Con las asignaciones de CPU explícitas, obtienes el rendimiento más predecible para las cargas de trabajo garantizadas, pero agrega más complejidad a tus cargas de trabajo.
cpu.globallyEnableIRQLoadBalancing Obligatorio. Modificable. Booleano. Valor predeterminado: true. Este campo especifica si se debe habilitar el balanceo de cargas de solicitudes de interrupción (IRQ) para el conjunto de CPU aislado.

Configuración de la memoria

Propiedad Descripción
defaultHugePageSize Opcional. Modificable. Enumeración: 1G o 2M. Este campo define el tamaño predeterminado de bigpage en los parámetros de inicio del kernel. En el momento del inicio, estas páginas se asignan antes de que la memoria se fragmente. Es importante tener en cuenta que si se configura el tamaño predeterminado de largepages en 1 G, se quitan del nodo los 2 millones de carpetas relacionadas. Un tamaño de bigpage predeterminado de 1G evita que configures 2 millones de bigpages en el nodo.
pages Opcional. Modificable. Número entero. Este campo especifica la cantidad de bigpages que se crearán en el momento del inicio. Este campo acepta un array de páginas. Verifica la memoria disponible para tus nodos antes de especificar bigpages. No solicites más bigpages de lo necesario y tampoco reserves toda la memoria para largepages. Tus cargas de trabajo también necesitan memoria estándar.

Selección de nodos

Propiedad Descripción
nodeSelector Obligatorio. Modificable. Este campo siempre requiere la etiqueta de nodo trabajador de Kubernetes, node-role.kubernetes.io/worker:"", que garantiza que el ajuste de rendimiento se realice solo en los nodos trabajadores. Este campo toma una etiqueta de nodo opcional como un par clave-valor. Las etiquetas de pares clave-valor se usan para seleccionar nodos trabajadores específicos con etiquetas coincidentes. Cuando las etiquetas nodeSelector coinciden con las de un nodo trabajador, el perfil de rendimiento se aplica a ese nodo. Si no especificas una etiqueta de par clave-valor en tu perfil, se aplica a todos los nodos trabajadores del clúster.

Por ejemplo, el siguiente nodeSelector especifica que el perfil de ajuste se aplica solo a los nodos trabajadores con etiquetas app: database que coincidan:


...
spec:
  nodeSelector:
    app: database
    node-role.kubernetes.io/worker: ""
  ...

Configuración de Kubelet

Propiedad Descripción
topologyManagerPolicy Opcional. Modificable. Enumeración: none, best-effort, restricted o single-numa-node. Valor predeterminado: best-effort. En este campo, se especifica la política del Administrador de topologías de Kubernetes que se usa a fin de asignar recursos para las cargas de trabajo, según la clase de calidad de servicio (QoS) asignada. Si deseas obtener más información sobre cómo se asignan las clases de QoS, consulta Configura la calidad de servicio para los Pods.

Operaciones de perfil

Propiedad Descripción
paused Opcional. Modificable. Booleano. Configura paused como true para evitar de forma temporal que los controladores DaemonSet ajusten los nodos seleccionados.
updateStrategy Opcional. Modificable. Especifica la estrategia para aplicar los cambios de configuración de ajuste a los nodos seleccionados.
updateStrategy.rollingUpdateMaxUnavailalble Opcional. Modificable. Número entero. Valor predeterminado: 1. Especifica la cantidad máxima de nodos que se pueden ajustar al mismo tiempo. Este campo se aplica solo cuando type se establece en rolling.
updateStrategy.type Opcional. Modificable. Enumeración: batch o rolling. Valor predeterminado: rolling. Especifica cómo aplicar actualizaciones de perfiles a los nodos seleccionados. Si deseas aplicar la actualización a todos los nodos seleccionados al mismo tiempo, establece type en batch. De forma predeterminada, las actualizaciones se lanzan de forma secuencial en nodos individuales, uno después de la otra.

Verificar el estado

Después de crear o actualizar el recurso personalizado PerformanceTuningProfile, un controlador ajusta los nodos seleccionados en función de la configuración proporcionada en el recurso. Para verificar el estado de PerformanceTuningProfile, exponeremos el siguiente campo en Status:

Propiedad Descripción
conditions La condición representa las últimas observaciones disponibles del estado actual del recurso de perfil.
conditions.lastTransitionTime Siempre se muestra. Es una cadena (en formato de fecha y hora). La última vez que la condición cambió de un estado a otro. Este tiempo suele indicar cuándo cambió la condición subyacente. Si no se conoce la hora, la hora indicará cuándo cambió el campo de la API.
conditions.message Opcional. String. Un mensaje legible que indica los detalles de la transición. Este campo puede estar vacío.
conditions.observedGeneration Opcional. Número entero. Si se configura, este campo representa el metadata.generation en el que se configuró la condición. Por ejemplo, si metadata.generation es 12, pero status.condition[x].observedGeneration es 9, la condición está desactualizada con respecto al estado actual de la instancia.
conditions.reason Obligatorio. String. El motivo de la última transición de condición.
conditions.status Obligatorio. Estado de la condición: True, False o Unknown.
conditions.type Obligatorio. El tipo es el tipo de condición: Stalled o Reconciling.
readyNodes La cantidad de nodos a los que se aplicó correctamente el perfil de ajuste.
reconcilingNodes La cantidad de nodos seleccionados (o previamente seleccionados) que están en proceso de conciliación con el perfil de ajuste más reciente mediante el DaemonSet nodeconfig-controller-manager.
selectedNodes Es la cantidad de notas que se seleccionaron. Es decir, la cantidad de nodos que coinciden con el selector de nodos para este recurso personalizado PerformanceTuningProfile.

¿Qué sigue?