Todos los productos
Search
Centro de documentos

Container Service for Kubernetes:CPU topology-aware scheduling

Última actualización: Sep 09, 2026

Cuando varias aplicaciones se ejecutan en el mismo nodo, la contención de recursos de CPU y los cambios de contexto degradan las cargas de trabajo sensibles a la latencia. La programación de CPU con detección de topología fija los procesos de la aplicación a núcleos de CPU específicos. Esto elimina las variaciones de rendimiento provocadas por la migración entre núcleos y el acceso a memoria entre nodos NUMA (Non-Uniform Memory Access).

Cómo funciona

De forma predeterminada, Kubernetes utiliza el Completely Fair Scheduler (CFS) del kernel para distribuir los intervalos de tiempo de CPU entre todos los núcleos. El CFS ignora la topología física de la CPU y puede generar una latencia impredecible en aplicaciones sensibles al rendimiento.

El CPU Manager de Kubernetes (con la directiva static) permite vincular pods a núcleos de CPU exclusivos, pero presenta tres limitaciones:

  • Falta de detección de topología a nivel de clúster: el kube-scheduler nativo opera únicamente a nivel de nodo y no tiene visibilidad de la topología de CPU de todo el clúster.

  • Falta de compatibilidad con NUMA: la directiva static no considera la arquitectura NUMA al asignar núcleos. Esto puede forzar el acceso a memoria entre nodos NUMA e introducir latencia adicional.

  • Guaranteed QoS only: esta directiva aplica únicamente a pods con la clase de QoS Guaranteed. No es compatible con pods Burstable ni BestEffort.

ACK resuelve estas limitaciones mediante la colaboración entre el kube-scheduler de ACK y ack-koordinator, basados en el Scheduling Framework de Kubernetes:

  1. Reporte de topología del nodo: ack-koordinator detecta continuamente la topología física local de la CPU (sockets, nodos NUMA y cachés) y envía estos datos al centro de programación.

  2. Programación global con detección de topología: el kube-scheduler usa los datos de topología de todo el clúster para seleccionar el nodo óptimo de cada pod y planificar la asignación de núcleos. De forma predeterminada, el programador busca el núcleo con menos aplicaciones vinculadas. El esquema de asignación resultante se escribe en la anotación del pod.

  3. Fijación local de núcleos: cuando el pod llega al nodo de destino, ack-koordinator lee su anotación y modifica el archivo cpuset.cpus en el cgroup del pod. Así vincula el pod a los núcleos físicos asignados.

Casos de uso

La programación de CPU con detección de topología ofrece mejores resultados en las siguientes cargas de trabajo:

  • Aplicaciones sensibles a la latencia: los sistemas de negociación de alta frecuencia y los pipelines de procesamiento de datos en tiempo real no toleran retrasos por cambios de contexto de CPU. Sin la fijación de CPU, el programador CFS puede migrar el proceso entre núcleos durante la ejecución. Esto resulta inofensivo en un entorno de pruebas, pero genera un impacto medible en producción bajo carga.

  • Aplicaciones sensibles a NUMA: las cargas de trabajo en servidores multisocket (como las instancias Elastic Bare Metal de AMD o Intel) presentan una latencia notable cuando los accesos a memoria cruzan límites NUMA. Fijar los núcleos dentro de un solo nodo NUMA elimina esta sobrecarga.

  • Cómputo determinista: los trabajos de cómputo científico y análisis de big data requieren un throughput de CPU estable y predecible. La fijación elimina la variabilidad que introduce compartir núcleos con otras cargas de trabajo.

  • Aplicaciones heredadas que ignoran los límites de CPU del contenedor: algunas aplicaciones generan hilos según el número total de núcleos físicos del host, en lugar del límite de CPU del contenedor. Estas aplicaciones se benefician de la fijación, ya que vincula el proceso a un conjunto específico de núcleos.

Importante

No habilite la programación de CPU con detección de topología en los siguientes escenarios:

  • Entornos con sobreasignación de CPU: la fijación de núcleos los reserva de manera exclusiva. Esto es incompatible con el modelo de recursos compartidos de la sobreasignación y provoca desperdicio de recursos.

  • Aplicaciones de uso general o intensivas en E/S: los servicios web, el middleware y la mayoría de las cargas de trabajo limitadas por E/S no son sensibles al cambio de núcleos de CPU, por lo que no obtienen ninguna ventaja con la fijación.

Elegir una directiva de fijación

ACK proporciona dos directivas de fijación:

Directiva

Anotación

Comportamiento de fijación

Recomendada para

General

cpuset-scheduler: "true"

Fijación 1:1: vincula exactamente la cantidad de núcleos indicada en resources.limits.cpu y prioriza los núcleos del mismo nodo NUMA

La mayoría de las cargas de trabajo sensibles a la latencia

Automática

cpuset-scheduler: "true" y cpu-policy: "static-burst"

Analiza la topología y el uso de recursos en tiempo real. Puede fijar más núcleos de los solicitados y prioriza un clúster completo de núcleos físicos (CCX/CCD en CPU AMD)

Máquinas AMD de gran escala con 32 núcleos o más

Requisitos previos

Antes de empezar, asegúrese de contar con lo siguiente:

  • Un clúster administrado de ACK de edición Pro

  • Un node pool con cpuManagerPolicy establecido en none. Para obtener más información, consulte Customize kubelet configurations for a node pool

  • ack-koordinator instalado en la versión 0.2.0 o posterior. Para consultar las instrucciones de instalación, consulte ack-koordinator

Paso 1: Desplegar una aplicación de ejemplo

Esta guía utiliza un Deployment de Nginx para demostrar la programación de CPU con detección de topología.

  1. Cree un archivo llamado nginx-app.yaml con el siguiente contenido:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      namespace: default
      labels:
        app: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/nginx_optimized:20240221-1.20.1-2.3.0
            ports:
            - containerPort: 80
            command:
            - "sleep"
            - "infinity"
            resources:
              requests:
                cpu: 4
                memory: 8Gi
              limits:
                # CPU limit must be an integer to enable pinning
                cpu: 4
                memory: 8Gi
  2. Despliegue la aplicación:

    kubectl apply -f nginx-app.yaml
  3. Log on to the node where the pod is running y recopile el UID del pod y el ID del contenedor.

    1. Obtenga el nombre del pod:

      kubectl get pods -n default

      El nombre del pod tiene un formato similar a nginx-deployment-6f5899*****.

    2. Obtenga el UID del pod:

      # Replace <your-pod-name> with the actual pod name
      kubectl get pod <your-pod-name> -n default -o jsonpath='{.metadata.uid}{"\n"}'

      Resultado esperado:

      a78a02b5-c87f-4e74-9ddd-254c163*****
    3. Obtenga el ID del contenedor:

      # Replace <your-pod-name> with the actual pod name
      kubectl describe pod <your-pod-name> -n default

      En el resultado, busque Container ID dentro de Containers. Quite el prefijo containerd:// para obtener el ID sin formato:

      Containers:
        nginx:
          Container ID:   containerd://b8b88a70096aabb0aea197dd2aba78d15bcbe9145198ef46a0474b31*****
  4. Compruebe la versión de cgroup del nodo:

    • cgroup_root: el nodo usa cgroup v1

    • cgroup2fs: el nodo usa cgroup v2

    stat -fc %T /sys/fs/cgroup/
  5. Compruebe el estado actual de fijación de CPU con el comando correspondiente a su versión de cgroup. Antes de habilitar la fijación, el resultado muestra el rango completo de núcleos. Esto significa que el contenedor puede usar todos los núcleos del nodo:

    • cgroup v1: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus ``

    • cgroup v2: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus.effective ``

    En la ruta de cgroup, reemplace los guiones ( - ) del UID del pod por guiones bajos ( _ ). Por ejemplo, a78a02b5-c87f-4e74-9ddd-254c163***` becomes `a78a02b5_c87f_4e74_9ddd_254c163*** .
    0-31

Paso 2: Habilitar la programación de CPU con detección de topología

Habilite la programación de CPU con detección de topología mediante la adición de anotaciones a la especificación del pod.

Importante

No especifique nodeName directamente en un pod cuando use esta función. El kube-scheduler no participa en la programación de pods con nodeName configurado, por lo que la selección de núcleos con detección de topología no se aplica. Utilice nodeSelector o afinidad de nodo en su lugar.

Directiva de fijación general

La directiva de fijación general vincula al pod exactamente la cantidad de núcleos especificada en resources.limits.cpu y prioriza los núcleos del mismo nodo NUMA.

Configuración:

  • Para un pod: agregue cpuset-scheduler: "true" en metadata.annotations.

  • Para una carga de trabajo como un Deployment: agregue cpuset-scheduler: "true" en spec.template.metadata.annotations.

  • resources.limits.cpu debe ser un número entero.

Ejemplo:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      annotations:
        cpuset-scheduler: "true"  # Enables CPU topology-aware scheduling
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/nginx_optimized:20240221-1.20.1-2.3.0
        ports:
        - containerPort: 80
        command:
        - "sleep"
        - "infinity"
        resources:
          requests:
            cpu: 4
            memory: 8Gi
          limits:
            cpu: 4       # Must be an integer
            memory: 8Gi

Comprobar la fijación:

Una vez que el pod esté en ejecución, compruebe que la fijación de núcleos está activa con uno de los siguientes métodos.

  • Verificación:

    Puede consultarla de dos maneras.

    Consultar el archivo de cgroup del nodo

    Consulte el archivo de cgroup en el nodo: el resultado muestra un conjunto de ID de núcleo que coincide con limits.cpu: 4, lo cual confirma que la fijación está activa:

    • cgroup v1: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus ``

    • cgroup v2: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus.effective ``

    0-3

    Consultar la anotación del pod

    Consulte la anotación del pod:

    • "nginx": el contenedor llamado nginx.

    • "0": el ID del nodo NUMA. Todos los núcleos fijados están en el nodo NUMA 0, lo que evita la pérdida de rendimiento por accesos a memoria entre nodos NUMA.

    • "elems": {"0":{},"1":{},"2":{},"3":{}}: los ID de los núcleos físicos de CPU a los que se fijó el contenedor (núcleos 0 a 3), que coinciden con limits.cpu: 4.

    # Replace <your-pod-name> with the actual pod name
    kubectl get pod <your-pod-name> -n default -o yaml | grep "cpuset:"

    Resultado esperado:

    cpuset: '{"nginx":{"0":{"elems":{"0":{},"1":{},"2":{},"3":{}}}}}'

    Significado de los campos del resultado:

Directiva de fijación automática

La directiva de fijación automática está optimizada para hardware específico. Analiza la topología de CPU y el uso de recursos del nodo en tiempo real, y prioriza vincular al pod un clúster completo de núcleos físicos (como un CCX o CCD en CPU AMD). La cantidad de núcleos fijados puede superar la solicitada para maximizar la localidad de CPU y la concurrencia.

Utilice esta directiva en tipos de máquinas AMD de gran escala con 32 núcleos o más.

Configuración:

  • Agregue dos anotaciones: cpuset-scheduler: "true" y cpu-policy: "static-burst".

    • Para un pod: agréguelas en metadata.annotations.

    • Para una carga de trabajo como un Deployment: agréguelas en spec.template.metadata.annotations.

  • resources.limits.cpu debe ser un número entero.

Ejemplo:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      annotations:
        cpuset-scheduler: "true"    # Enables CPU topology-aware scheduling
        cpu-policy: "static-burst"  # Enables automatic pinning and NUMA affinity
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/nginx_optimized:20240221-1.20.1-2.3.0
        ports:
        - containerPort: 80
        command:
        - "sleep"
        - "infinity"
        resources:
          requests:
            cpu: 4
            memory: 8Gi
          limits:
            cpu: 4       # Must be an integer
            memory: 8Gi

Comprobar la fijación:

La directiva automática puede fijar más núcleos de los solicitados. Compruebe el resultado con uno de los siguientes métodos.

  • Verificación:

    La directiva de fijación automática analiza la topología de CPU y el uso de recursos del nodo en tiempo real. La cantidad de núcleos fijados puede ser mayor que la solicitada explícitamente para el pod. Puede comprobar el estado de fijación de dos maneras.

    Consultar el archivo de cgroup del nodo

    Consulte el archivo de cgroup en el nodo: el resultado muestra los núcleos fijados específicos (más de los 4 solicitados en este ejemplo), lo cual confirma que la fijación está activa:

    • cgroup v1: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus ``

    • cgroup v2: ``shell # Replace <POD_UID> and <CONTAINER_ID> with the actual values cat /sys/fs/cgroup/kubepods.slice/kubepods-pod<POD_UID>.slice/cri-containerd-<CONTAINER_ID>.scope/cpuset.cpus.effective ``

    0-7

    Consultar la anotación del pod

    Consulte la anotación del pod:

    • "nginx": el contenedor llamado nginx.

    • "0": el ID del nodo NUMA. Todos los núcleos fijados están en el nodo NUMA 0, lo que evita los accesos a memoria entre nodos NUMA.

    • "elems": los ID de los núcleos físicos a los que se fijó el contenedor (núcleos 0 a 7). La directiva automática puede fijar más núcleos de los solicitados para alinearse con el límite del clúster de núcleos físicos.

    # Replace <your-pod-name> with the actual pod name
    kubectl get pod <your-pod-name> -n default -o yaml | grep "cpuset:"

    Resultado esperado:

    cpuset: '{"nginx":{"0":{"elems":{"0":{},"1":{},"2":{},"3":{},"4":{},"5":{},"6":{},"7":{}}}}}'

    Significado de los campos del resultado:

Aplicar en producción

Observability

Integre el clúster con Alibaba Cloud Prometheus monitoring antes y después de habilitar la fijación de núcleos. Supervise las siguientes métricas para observar el efecto de la fijación en sus cargas de trabajo:

  • Métricas de la aplicación: tiempo de respuesta (RT) y QPS

  • Métricas del nodo: uso de CPU y estrangulamiento de CPU

Despliegue gradual

En Deployments con varias réplicas, utilice versiones canary o actualizaciones graduales para habilitar o deshabilitar la directiva de fijación de forma progresiva. Esto reduce el riesgo de una regresión generalizada del rendimiento.

Deshabilitar la programación de CPU con detección de topología

  1. Edite el archivo YAML de la aplicación. Elimine la anotación cpuset-scheduler: "true" y, si existe, la anotación cpu-policy: "static-burst" de spec.template.metadata.annotations.

  2. Aplique el archivo YAML modificado fuera del horario de mayor actividad. Los cambios surten efecto después de reiniciar el pod.

Importante

Al deshabilitar la fijación de CPU, los procesos del pod dejan de estar vinculados a núcleos físicos específicos y pueden ejecutarse en cualquier núcleo disponible del nodo. Tenga en cuenta los siguientes impactos potenciales:

  • El uso de CPU puede aumentar ligeramente debido a los cambios de contexto entre núcleos.

  • En aplicaciones intensivas en cómputo, pueden reaparecer las variaciones de rendimiento causadas por la contención de recursos de CPU.

  • Si varios pods con alta carga comparten el mismo núcleo, se pueden generar picos de carga que activen el estrangulamiento de CPU.

Facturación

La instalación y el uso de ack-koordinator son gratuitos. Pueden aplicarse cargos adicionales en los siguientes casos:

  • ack-koordinator es un componente no administrado que consume recursos de los nodos worker después de la instalación. Configure las solicitudes de recursos de cada módulo durante la instalación.

  • Si selecciona la opción Enable Prometheus monitoring for ACK-Koordinator y utiliza Alibaba Cloud Prometheus, las métricas de monitoreo se contabilizan como métricas personalizadas y generan cargos. El costo depende del tamaño del clúster y de la cantidad de aplicaciones. Antes de habilitar esta opción, revise la información de facturación de Prometheus para conocer la cuota gratuita y los precios. Haga un seguimiento de su consumo mediante la consulta de sus datos de uso.

Pasos siguientes