Ajustar el rendimiento de los nodos

Una forma de mejorar el rendimiento de las aplicaciones basadas en contenedores es aumentar los recursos del clúster añadiendo nodos o recursos, como CPUs o memoria, a los nodos. Sin embargo, este enfoque puede resultar caro. Ajustar los nodos de tu clúster para mejorar el rendimiento te ayuda a optimizar el uso de los recursos de tus cargas de trabajo de forma rentable. En este documento se describe cómo usar el operador de ajuste del rendimiento para ajustar los nodos de trabajador y optimizar el rendimiento de las cargas de trabajo de Google Distributed Cloud.

Para sacar el máximo partido del hardware y el software subyacentes, diferentes tipos de aplicaciones, especialmente las de alto rendimiento, se benefician de la optimización de los ajustes de los nodos, como los siguientes:

  • CPUs dedicadas para cargas de trabajo sensibles al rendimiento
  • CPUs reservadas para los daemons y servicios estándar de Kubernetes
  • Tamaños de página de memoria aumentados con páginas enormes de 1 GiB (gibibyte) o 2 MiB (mebibyte)
  • Distribución de la carga de trabajo basada en la arquitectura del sistema, como procesadores multinúcleo y NUMA

Con Performance Tuning Operator, puede configurar los ajustes de rendimiento a nivel de nodo creando recursos personalizados de Kubernetes que apliquen configuraciones de rendimiento. Estas son las ventajas:

  • Interfaz de configuración única y unificada: con Performance Tuning Operator, puedes actualizar uno o varios manifiestos PerformanceTuningProfile que se pueden aplicar a los nodos de trabajo con selectores de nodos. No es necesario configurar cada nodo individualmente con varios ajustes de configuración y políticas. Este enfoque te permite gestionar las configuraciones de nivel de nodo y de nivel de contenedor de forma unificada.

  • Persistencia y fiabilidad: también obtienes toda la fiabilidad que ofrece Kubernetes con su arquitectura de alta disponibilidad. Los recursos personalizados de PerformanceTuningProfile se pueden actualizar cuando quieras y sus ajustes se conservan en las operaciones principales del clúster, como las actualizaciones.

Performance Tuning Operator funciona orquestando las siguientes funciones y herramientas de Kubernetes y del sistema operativo (SO) relacionadas con el rendimiento:

Para evitar conflictos, cuando uses Performance Tuning Operator, te recomendamos que no uses las herramientas y funciones de Kubernetes y del SO mencionadas anteriormente de forma independiente.

Requisitos previos y limitaciones

Estos son los requisitos previos y las limitaciones para usar el operador Performance Tuning:

  • Solo Red Hat Enterprise Linux (RHEL): Performance Tuning Operator se admite en nodos que ejecutan versiones compatibles de RHEL.

  • Clúster de usuario o híbrido con nodos de trabajo: Performance Tuning Operator solo se puede usar con nodos de trabajo en clústeres de usuario o híbridos. No se admite el uso del operador de ajuste del 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 los perfiles de ajuste. Para asegurarse de que los perfiles de ajuste solo se apliquen a los nodos de trabajador, el nodeSelector de cada recurso personalizado de perfil debe incluir la etiqueta de nodo de trabajador estándar node-role.kubernetes.io/worker: "". Si el nodeSelector de 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 Comprobar el estado. Asegúrate de que tu clúster funciona correctamente antes de instalar el operador de ajuste del rendimiento y aplicar los perfiles de ajuste.

  • TuneD 2.22.0: el operador de ajuste del rendimiento requiere que la versión 2.22.0 de TuneD esté preinstalada en los nodos de trabajo que quieras ajustar. Para obtener más información sobre TuneD, incluidas las instrucciones de instalación, consulta el artículo Empezar a usar TuneD de 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 las cargas de trabajo: para sacar el máximo partido a la optimización del rendimiento, debes conocer bien los requisitos de memoria y CPU (solicitudes y límites de recursos) de tus cargas de trabajo.

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

  • Requiere purga: como parte del proceso de ajuste, el operador de ajuste del rendimiento primero purga los nodos y, después, aplica un perfil de ajuste. Por lo tanto, es posible que los nodos muestren el estado NotReady durante la optimización del rendimiento. Te recomendamos que uses la estrategia de actualización continua (spec.updateStrategy.type: rolling) en lugar de una actualización por lotes para minimizar el tiempo de inactividad de la carga de trabajo.

  • Requiere reiniciar: para que los cambios de ajuste de nodos surtan efecto, Performance Tuning Operator reinicia el nodo después de aplicar el perfil de ajuste.

Instalar el operador de ajuste de rendimiento

Performance Tuning Operator se compone principalmente de dos controladores (un Deployment y un DaemonSet) que interactúan entre sí para ajustar los nodos en función de la configuración de tu perfil. Performance Tuning Operator no se instala de forma predeterminada con Google Distributed Cloud. Descarga los manifiestos del operador de ajuste del rendimiento de Cloud Storage y usa kubectl apply para crear recursos del operador de ajuste del rendimiento en tu clúster.

Para habilitar la optimización del rendimiento con los valores predeterminados de tu clúster, sigue estos pasos:

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

  2. En el directorio performance-tuning, descarga el paquete más reciente del operador de ajuste del rendimiento del segmento de lanzamiento de Cloud Storage:

    gcloud storage cp gs://anthos-baremetal-release/node-performance-tuning/0.1.0-gke.47 . --recursive
    

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

  3. Como usuario root, aplica todos los manifiestos de Performance Tuning Operator de forma recursiva a tu clúster de usuario (o híbrido):

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

    Una vez que se hayan creado y se estén ejecutando Deployment y DaemonSet, tu única interacción será editar y aplicar manifiestos PerformanceTuningProfile.

Revisa los requisitos de recursos de tus cargas de trabajo

Antes de ajustar tus nodos, debes conocer los requisitos de recursos de computación y memoria de tus cargas de trabajo. Si tus nodos de trabajo tienen recursos suficientes, se pueden ajustar para proporcionar memoria garantizada (estándar y páginas enormes) a tus cargas de trabajo en la clase de calidad del servicio (QoS) garantizada.

Kubernetes asigna clases de QoS a cada uno de tus pods en función de las restricciones de recursos que especifiques para los contenedores asociados. A continuación, Kubernetes usa las clases de calidad del servicio para determinar cómo programar tus pods y contenedores, así como para asignar recursos a tus cargas de trabajo. Para aprovechar al máximo la optimización de nodos en tus cargas de trabajo, estas deben tener ajustes de solicitudes o límites de recursos de CPU o memoria.

Para que se te asigne una clase de QoS garantizada, tus pods deben cumplir 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 las 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.

El siguiente fragmento de la especificación de Pod muestra los ajustes de recursos de CPU que cumplen los requisitos de la clase de 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 recuperes los detalles de un pódcast con kubectl get pods, la sección status debería incluir la clase de calidad del servicio 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 el artículo Clases de calidad del servicio de los pods de la documentación de Kubernetes. Para obtener instrucciones sobre cómo configurar tus pods y contenedores para que se les asigne una clase de QoS, consulta Configurar la calidad del servicio para los pods.

Requisitos de CPU

Al optimizar un nodo, puedes especificar un conjunto de núcleos de CPU reservados (spec.cpu.reservedCPUs) para ejecutar daemons del sistema Kubernetes, como kubelet y el tiempo de ejecución del contenedor. Este mismo conjunto de CPUs reservadas también ejecuta los daemons del sistema operativo, como sshd y udev. El resto de los núcleos de CPU se asignan como aislados. Las CPUs aisladas están pensadas para aplicaciones con uso intensivo de CPU, que requieren tiempo de CPU dedicado sin interferencias de otras aplicaciones ni interrupciones de la red u otros dispositivos.

Para programar un pod en las CPUs aisladas de un nodo de trabajo, sigue estos pasos:

  • Configura el pod para que tenga una calidad de servicio (QoS) garantizada.

  • Los requisitos y los límites de la CPU deben especificarse con números enteros. Si especificas recursos de CPU parciales en tu especificación de pod, como cpu: 0.5 o cpu: 250m (250 milinúcleos), no se puede garantizar la programación.

Requisitos de memoria

Cuando ajustas un nodo con Performance Tuning Operator, puedes crear páginas enormes y asociarlas a los nodos de acceso a memoria no uniforme (NUMA) de la máquina. En función de la configuración de los pods y los nodos, los pods se pueden programar con afinidad de nodo NUMA.

Crear un perfil de ajuste del rendimiento

Una vez que hayas instalado el operador Performance Tuning, solo interactuarás con el clúster que ejecute tus cargas de trabajo. Los PerformanceTuningProfile recursos personalizados se crean directamente en el clúster de usuarios o en 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 del recurso determina los nodos a los que se aplica el perfil de ajuste. Para aplicar un perfil a un nodo, coloque la etiqueta del 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 Comprobar el estado.

Asigna el espacio de nombres PerformanceTuningProfile a tu recurso personalizado kube-system.

Para ajustar uno o varios nodos de trabajo, sigue estos pasos:

  1. Edita el archivo de manifiesto PerformanceTuningProfile.

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

  2. (Opcional) En los nodos de trabajo a los que vas a aplicar un perfil, añade etiquetas que coincidan con el par clave-valor spec.nodeSelector.

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

  3. Aplica el manifiesto a tu clúster.

    kubectl apply -f PROFILE_MANIFEST --kubeconfig KUBECONFIG
    

    Haz los cambios siguientes:

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

Eliminar un perfil de ajuste

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

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

  2. Actualiza o elimina las etiquetas del nodo para que el perfil de ajuste no lo vuelva a seleccionar.

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

Pausar un perfil de ajuste

Si necesitas realizar tareas de mantenimiento en tu clúster, puedes pausar temporalmente la optimización editando el recurso personalizado PerformanceTuningProfile. Te recomendamos que pauses la optimización antes de realizar operaciones críticas en el clúster, como una actualización del clúster.

Si no se puede aplicar un perfil, también puedes pausar la optimización. Si el proceso de ajuste no se completa correctamente, el controlador puede seguir intentando ajustar el nodo, lo que puede provocar que el nodo se reinicie una y otra vez. Si observas que el estado del nodo cambia entre los estados preparado y no preparado, pausa el ajuste para que puedas recuperarte del estado incorrecto.

Para pausar la optimización, sigue estos pasos:

  1. Edita el manifiesto de recursos personalizados PerformanceTuningProfile para asignar el valor true a spec.paused.

  2. Usa kubectl apply para actualizar el recurso.

Cuando se pausa el ajuste del rendimiento, el controlador del operador de ajuste del rendimiento detiene todas sus operaciones. Al pausar, se evita el riesgo de que las operaciones del controlador de Performance Tuning Operator entren en conflicto con las operaciones de cualquier controlador de Google Distributed Cloud.

Referencia de recurso PerformanceTuningProfile

En esta sección se describe cada uno de los campos del recurso personalizado PerformanceTuningProfile. Este recurso se usa para crear un perfil de ajuste para uno o varios nodos de tu clúster. Todos los campos del recurso se pueden modificar después de crear el perfil. Los perfiles deben estar en el espacio de nombres kube-system.

El siguiente archivo de manifiesto de perfil de ejemplo de numa para nodos con 8 núcleos de CPU especifica las siguientes asignaciones de recursos:

  • Se reservan 4 núcleos de CPU (0-3) para la sobrecarga del sistema de Kubernetes.

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

  • La memoria de los nodos 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 de 1 GiB para el uso del nodo NUMA 0.

  • Se reservan 5 páginas de memoria de 2 MiB para el nodo NUMA 1.

  • 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 recursos personalizados PerformanceTuningProfile relacionada del grupo anthos.gke.io de tu clúster. La definición de recurso personalizado se instala una vez que se añade la anotación de la función de vista previa al recurso de clúster autogestionado.

Configuración de CPU

Propiedad Descripción
cpu.reservedCPUs Obligatorio. Mutable. Cadena. Este campo define un conjunto de núcleos de CPU que se reservarán para los daemons del sistema de Kubernetes, como kubelet, el tiempo de ejecución del contenedor y el detector de problemas de nodos. Estos núcleos de CPU también se usan para los daemons del sistema operativo, como sshd y udev.

El campo cpu.reservedCPUs acepta una lista de números de CPU o intervalos de números de CPU. Asegúrate de que la lista de CPUs no se solape con la lista especificada con cpu.isolatedCPUs. La unión de las CPUs que se indican en estos dos campos debe incluir todas las CPUs del nodo.

cpu.isolatedCPUs Opcional. Mutable. Cadena. El campo cpu.isolatedCPUs define un conjunto de CPUs que se usan exclusivamente para aplicaciones sensibles al rendimiento. CPU Manager programa los contenedores solo en las CPUs no reservadas, según las clases de calidad del servicio (QoS) de Kubernetes. Para asegurarte de que las cargas de trabajo se ejecuten en las CPUs aisladas, configura los pods con la clase de QoS garantizada y asigna un recurso de CPU al pod o al contenedor. Para garantizar la programación de pods, debes especificar unidades de CPU enteras, no recursos de CPU parciales (cpu: "0.5").
apiVersion: v1
kind: Pod
...
spec:
  containers:
  ...
    resources:
      limits:
        cpu: "1"
      requests:
        cpu: "1"
  ...

Maximizar las CPUs aisladas para las cargas de trabajo proporciona el mejor rendimiento. Este campo acepta una lista de números de CPU o intervalos de números de CPU. Asegúrate de que la lista de CPUs no se solape con la lista especificada con cpu.reservedCPUs y de que la unión de las listas de estos dos campos incluya todas las CPUs del nodo.

cpu.balanceIsolated Opcional. Mutable. Booleano. Valor predeterminado: true. Este campo especifica si el conjunto de CPUs aisladas es apto o no para el balanceo de carga automático de las cargas de trabajo entre las CPUs. Si asignas el valor false a este campo, tus cargas de trabajo tendrán que asignar cada hilo de forma explícita a una CPU específica para distribuir la carga entre las CPUs. Con las asignaciones explícitas de CPU, obtienes el rendimiento más predecible para las cargas de trabajo garantizadas, pero añade más complejidad a tus cargas de trabajo.
cpu.globallyEnableIRQLoadBalancing Obligatorio. Mutable. Booleano. Valor predeterminado: true. Este campo especifica si se debe habilitar o no el balanceo de carga de solicitudes de interrupción (IRQ) para el conjunto de CPUs aisladas.

Configuración de la memoria

Propiedad Descripción
defaultHugePageSize Opcional. Mutable. Enumeración: 1G o 2M. Este campo define el tamaño predeterminado de las páginas enormes en los parámetros de arranque del kernel. Las páginas enormes se asignan en el momento del arranque, antes de que la memoria se fragmente. Es importante tener en cuenta que, si se define el tamaño predeterminado de las páginas enormes en 1 G, se eliminarán todas las carpetas relacionadas con 2 M del nodo. Si el tamaño predeterminado de las páginas enormes es de 1 GB, no podrás configurar páginas enormes de 2 MB en el nodo.
pages Opcional. Mutable. Número entero. Este campo especifica el número de páginas enormes que se van a crear en el momento del arranque. Este campo acepta una matriz de páginas. Comprueba la memoria disponible de tus nodos antes de especificar páginas enormes. No solicites más páginas enormes de las necesarias ni reserves toda la memoria para páginas enormes. Tus cargas de trabajo también necesitan memoria estándar.

Selección de nodos

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

Por ejemplo, el siguiente nodeSelector especifica que el perfil de ajuste solo se aplica a los nodos de trabajador que tengan etiquetas app: database coincidentes:

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

Configuración de Kubelet

Propiedad Descripción
topologyManagerPolicy Opcional. Mutable. Enumeración: none, best-effort, restricted o single-numa-node. Valor predeterminado: best-effort. Este campo especifica la política del gestor de topología de Kubernetes que se usa para asignar recursos a tus cargas de trabajo en función de la clase de calidad del servicio (QoS) asignada. Para obtener más información sobre cómo se asignan las clases de QoS, consulta el artículo Configurar la calidad del servicio para pods.

Operaciones de perfil

Propiedad Descripción
paused Opcional. Mutable. Booleano. Define paused en true para evitar temporalmente que los controladores de DaemonSet ajusten los nodos seleccionados.
updateStrategy Opcional. Mutable. Especifica la estrategia para aplicar los cambios de configuración de ajuste a los nodos seleccionados.
updateStrategy.rollingUpdateMaxUnavailalble Opcional. Mutable. Número entero. Valor predeterminado: 1. Especifica el número máximo de nodos que se pueden ajustar al mismo tiempo. Este campo solo se aplica cuando type tiene el valor rolling.
updateStrategy.type Opcional. Mutable. Enumeración: batch o rolling. Valor predeterminado: rolling. Especifica cómo aplicar las actualizaciones de perfil a los nodos seleccionados. Si quieres aplicar la actualización a todos los nodos seleccionados al mismo tiempo, define type como batch. De forma predeterminada, las actualizaciones se implementan secuencialmente en nodos individuales, uno tras otro.

Comprobar estado

Una vez que se crea o actualiza el recurso personalizado PerformanceTuningProfile, un controlador ajusta los nodos seleccionados en función de la configuración proporcionada en el recurso. Para comprobar el estado de PerformanceTuningProfile, exponemos el siguiente campo en Status:

Propiedad Descripción
conditions Condition representa las últimas observaciones disponibles del estado actual del recurso de perfil.
conditions.lastTransitionTime Siempre se devuelve. Cadena (en formato de fecha y hora). La última vez que la condición ha pasado de un estado a otro. Esta hora suele indicar cuándo ha cambiado la condición subyacente. Si no se conoce esa hora, la hora indica cuándo cambió el campo de la API.
conditions.message Opcional. Cadena. Mensaje legible que indica detalles sobre la transición. Este campo puede estar vacío.
conditions.observedGeneration Opcional. Número entero. Si se define, este campo representa el metadata.generation en el que se ha basado la condición. Por ejemplo, si metadata.generation es 12, pero status.condition[x].observedGeneration es 9, la condición está obsoleta en relación con el estado actual de la instancia.
conditions.reason Obligatorio. Cadena. El motivo del último cambio de estado.
conditions.status Obligatorio. Estado de la condición: True, False o Unknown.
conditions.type Obligatorio. Type es el tipo de condición: Stalled o Reconciling.
readyNodes Número de nodos a los que se ha aplicado correctamente el perfil de ajuste.
reconcilingNodes Número de nodos seleccionados (o seleccionados anteriormente) que están en proceso de conciliación con el perfil de ajuste más reciente por parte del nodeconfig-controller-manager DaemonSet.
selectedNodes El número de notas que se han seleccionado. Es decir, el número de nodos que coinciden con el selector de nodos de este recurso personalizado PerformanceTuningProfile.

Siguientes pasos