Diseña tu infraestructura para Agent Substrate en GKE

Google Kubernetes Engine (GKE) te permite escalar clústeres de Agent Substrate en GKE para admitir cargas de trabajo de agentes de IA de alta simultaneidad y, al mismo tiempo, minimizar los costos de procesamiento inactivo. Si combinas grupos de nodos de infraestructura del sistema dedicados con ComputeClasses personalizadas y búferes de capacidad, puedes aislar los componentes críticos del sistema, automatizar el resguardo de hardware en las series de máquinas de Compute Engine y mantener activa la capacidad de los trabajadores en espera.

Lee este documento para ajustar el tamaño de los componentes de tu clúster de GKE, aislar la infraestructura del sistema y los grupos de nodos de la base de datos, configurar el aprovisionamiento automático de nodos para los recursos de WorkerPool y planificar el mantenimiento y las actualizaciones del clúster. Este documento está dirigido a los administradores de plataformas que aprovisionan y administran Agent Substrate en la infraestructura de GKE.

Antes de comenzar

Antes de configurar la infraestructura de tu clúster para el escalamiento, asegúrate de que tu entorno cumpla con los siguientes requisitos:

  • Modo y versión del clúster de GKE: debes usar un clúster de GKE Standard en el que tanto el plano de control como los grupos de nodos ejecuten la versión 1.37 o una posterior. Los clústeres de Autopilot de GKE no son compatibles con Agent Substrate en GKE.
  • Instalación de Agent Substrate en GKE: Debes tener una instalación existente de Agent Substrate en GKE o planificar la instalación de Agent Substrate en GKE con el aislamiento de nodos de infraestructura del sistema habilitado. Para conocer los pasos de instalación, consulta Instala Agent Substrate en GKE.

Ajusta el tamaño de tu clúster de Agent Substrate

Ajusta el tamaño del clúster para el pico de usuarios en simultáneo y las tasas de reanudación máximas, en lugar de los promedios. Los nodos trabajadores deben contener la cantidad máxima de actores que se ejecutan al mismo tiempo, y los componentes de la infraestructura del sistema y las rutas de acceso de almacenamiento deben mantenerse al día con la tasa más rápida de reanudaciones y suspensiones de actores.

Estima los picos de carga de trabajo

Si no tienes mediciones de producción, estima tu pico de usuarios en simultáneo y la tasa de reanudación a partir de la cantidad total de actores registrados (total_actors), la fracción promedio de actores que se ejecutan de forma simultánea (average_active_fraction), el multiplicador de ráfagas de tráfico (burst_factor) y la duración promedio que un actor permanece activo por turno (average_seconds_active_per_resume):

peak_running_actors = total_actors × average_active_fraction × burst_factor
peak_resume_rate    = peak_running_actors / average_seconds_active_per_resume

Por ejemplo, si tienes 100,000 actores en total con un 10% de actividad en promedio (10,000 actores) y un factor de ráfaga de dos, tu clúster debe admitir 20,000 actores en ejecución máxima. Si cada Actor se ejecuta durante un promedio de 100 segundos antes de suspenderse, mantener ese pico requiere 200 reanudaciones por segundo y 200 suspensiones por segundo.

Agent Substrate en GKE no suspende automáticamente los actores inactivos; tu aplicación o el organizador deben activar la suspensión.

Ajusta el tamaño del plano de datos

En esta sección, se abordan las prácticas recomendadas para ajustar el tamaño del plano de datos, incluidos los Pods de Worker, los nodos de GKE, el ancho de banda de las instantáneas y el agente de nodo de atelet.

Calcula los Pods de trabajador y los nodos de GKE

Cada Pod de trabajador en un WorkerPool aloja varios actores. Un Worker puede aceptar un Actor nuevo mientras aloja menos Actores que el límite establecido por la marca --max-actors en el contenedor ateworker (1000 predeterminado) y tiene suficiente capacidad de CPU y memoria restante para ajustarse a los límites de ActorTemplate. Para obtener más información sobre cómo interactúan los límites de Worker con los de Actor, consulta la guía de código abierto Ajusta el tamaño de los recursos en la API de Agent Substrate.

Calcula la cantidad necesaria de Pods de trabajador con un 20% de capacidad de programación disponible (el factor 0.8):

slots_per_worker = min(max_actors, worker_memory / actor_memory, worker_cpu / actor_cpu)
total_workers    = peak_running_actors / (slots_per_worker × 0.8)

En esta fórmula, la variable max_actors se establece de forma predeterminada en 1000 (configurada por la marca --max-actors). Resta la memoria que el trabajador reserva para su propio proceso del valor worker_memory. Para los recursos de WorkerPool de microVM, agrega la sobrecarga de memoria del monitor de máquina virtual (VMM) por actor que informa el Worker al valor actor_memory, ya que la ubicación cuenta esa sobrecarga en relación con la capacidad del Worker.

Con un Pod de trabajador por nodo, la cantidad de trabajadores es igual a la cantidad de nodos trabajadores de GKE. No asignes el 100% de la CPU y la memoria asignables de un nodo al Pod de trabajador. Deja capacidad en cada nodo para el DaemonSet atelet (en el espacio de nombres ate-system) y los daemons del sistema de GKE. GKE Standard admite hasta 65,000 nodos por clúster y hasta 512 Pods por nodo. El máximo predeterminado es de 110 Pods por nodo (configurable con la marca --max-pods-per-node), y los clústeres grandes tienen requisitos adicionales.

Determina el tamaño del ancho de banda de las instantáneas y los discos de los nodos

Cada suspensión de Actor escribe una instantánea en el disco del nodo local en la ruta de acceso del directorio /var/lib/ate. En el modo SYNCHRONOUS, el agente atelet sube la instantánea a Cloud Storage antes de que se devuelva la operación de suspensión. En el modo ASYNCHRONOUS, el agente de atelet programa la carga en Cloud Storage después de un retraso de aproximadamente el valor de la marca --snapshot-upload-delay (5m predeterminado) desde que se toma la instantánea. Agent Substrate almacena en caché la instantánea más reciente en el nodo durante el período configurado en la marca --snapshot-detach-delay, que tiene un valor predeterminado de 30m. Un Actor que se reanuda dentro de ese período se programa en el mismo nodo y se restablece desde el disco local en lugar de descargar la instantánea desde Cloud Storage.

Estima el tamaño de tu instantánea sin comprimir (snapshot_size) como el límite de memoria de ActorTemplate más los datos escritos en el sistema de archivos raíz escribible o en los directorios duraderos. El manejo de archivos dispersos y la compresión zstd reducen el tamaño de la instantánea comprimida (compressed_snapshot_size) que se transfiere desde y hacia Cloud Storage, donde Agent Substrate almacena hasta dos instantáneas por actor (la instantánea anterior y la instantánea en curso):

  • Ancho de banda máximo de Cloud Storage (en cada dirección): peak_resume_rate × compressed_snapshot_size
  • Capacidad de procesamiento máxima de escritura en el disco del nodo por nodo: 2 × peak_resume_rate × snapshot_size / total_nodes (tanto las descargas de reanudación como los puntos de control de suspensión escriben en el disco del nodo).

El disco de arranque hyperdisk-balanced predeterminado de 100 GiB en GKE proporciona 3,600 IOPS y 290 MiB/s de capacidad de procesamiento (el rendimiento predeterminado escala con el tamaño del disco), lo que puede limitar las operaciones de instantáneas en condiciones de E/S de invitado intensas. Cuando crees grupos de nodo trabajador, activa un disco dedicado en la ruta de acceso del directorio /var/lib/ate/snapshots o aumenta el rendimiento del disco de arranque con las marcas --boot-disk-provisioned-iops y --boot-disk-provisioned-throughput con el comando gcloud container node-pools create.

Verifica la cuota del Servicio de tokens de seguridad

Cada transferencia de instantáneas hacia o desde Cloud Storage requiere un token con alcance para el Actor, que el componente ate-api-server solicita a la API del Servicio de tokens de seguridad (STS). El componente ate-api-server realiza hasta una solicitud de STS por Actor cada 20 a 40 minutos (por lo general, en la primera reanudación de esa ventana) y reutiliza el token hasta 20 minutos antes de que venza.

La cuota de STS Exchange token global requests se establece de forma predeterminada en 6,000 solicitudes por proyecto por minuto y se comparte con Workload Identity Federation for GKE:

  • Cuota de STS requerida (solicitudes por minuto): Se estima que es hasta 60 veces la tasa máxima de reanudaciones de los actores cuya última transferencia de instantánea fue hace más de 20 minutos, más la capacidad de la federación de identidades para cargas de trabajo para GKE. Si no conoces esa tasa, usa la fórmula 60 × peak_resume_rate como resguardo. Por ejemplo, 200 currículums por segundo requieren hasta 12,000 solicitudes por minuto.
  • Cómo aumentar la cuota: Solicita un aumento de cuota en la página Cuotas y límites del sistema en la consola de Google Cloud . Las transferencias de instantáneas funcionan sin la API de Security Token Service habilitada en tu proyecto, pero debes habilitar la API para que la cuota aparezca en la página Cuotas y límites del sistema. Para obtener más información, consulta Cuota para la API de Exchange Token en Security Token Service en la documentación de Workload Identity Federation para GKE.

Ajusta el agente de nodo atelet

El DaemonSet atelet ejecuta un Pod por nodo trabajador para restablecer y crear puntos de control de los actores. En cada Pod de atelet, el contenedor de objectstore-plugin comprime y transfiere instantáneas hacia y desde Cloud Storage.

En la siguiente tabla, se describen los parámetros de configuración de tamaño clave para los contenedores de atelet y objectstore-plugin:

Configuración Predeterminado Orientación sobre el tamaño
CPU y memoria de los contenedores atelet y objectstore-plugin Solicitudes: 50 mCPU, 128 MiB de memoria; sin límites Configura la QoS con aumento de actividad sin límites de memoria omitiendo los límites de memoria en ambos contenedores, ya que alcanzar un límite de memoria detiene el agente de nodo y detiene todas las reanudaciones en el nodo. Aumenta las solicitudes de CPU y memoria para que coincidan con el uso máximo medido en un nodo completo con tu tasa máxima de reanudación, de modo que los Pods de trabajador no consuman los recursos que necesita el agente de atelet.
La marca --upload-memory-budget (contenedor objectstore-plugin) y la marca --snapshot-upload-workers (contenedor atelet) Presupuesto de 512 MiB; 2 trabajadores de carga

Para evitar que las cargas de instantáneas simultáneas se pongan en cola en nodos de varios actores con altas tasas de suspensión, haz lo siguiente:

  • Aumenta el valor de la marca --upload-memory-budget (y establece la solicitud de memoria del contenedor objectstore-plugin en un valor superior a este presupuesto).
  • Aumenta el valor de la marca --snapshot-upload-workers.
La marca --drain-timeout y el campo terminationGracePeriodSeconds 5 minutos (marca --drain-timeout); 330 segundos (campo terminationGracePeriodSeconds) Controla cuánto tiempo tarda el agente de atelet en finalizar las restablecimientos en curso y las cargas de instantáneas cuando su Pod se detiene durante un vaciado o una actualización de nodo. Si aumentas el valor de la marca --drain-timeout para las instantáneas grandes, también aumenta el valor del campo terminationGracePeriodSeconds en el DaemonSet atelet para que el agente kubelet no detenga el agente atelet antes de que finalicen las cargas.

Ajusta el tamaño de los componentes de la infraestructura del sistema y la base de datos

Para los Deployments de componentes del sistema sin estado en el espacio de nombres ate-system que escalan de forma horizontal, estima el recuento de réplicas requerido con un 35% de capacidad disponible (el factor 0.65) más una réplica de repuesto (+ 1) para tolerar interrupciones de nodos:

replicas = ceil(peak_load / (capacity_per_replica × 0.65)) + 1

El escalamiento horizontal deja de mejorar la capacidad de procesamiento después de que una dependencia compartida (como la CPU de PostgreSQL o los límites de conexión) alcanza su capacidad. Ajusta el tamaño de los componentes de la infraestructura del sistema y de la base de datos de forma conjunta. Para obtener más información sobre las marcas de componentes, consulta la guía de instalación del operador de código abierto.

En la siguiente tabla, se describen las reglas de recursos y escalamiento para cada componente de la infraestructura del sistema:

Componente Reglas de QoS y recursos Ajuste de escalamiento y conexión
Router de entrada (atenet-router) Configura la QoS garantizada: Establece solicitudes y límites de CPU y memoria que coincidan para que el entorno de ejecución de Go alinee su recuento de subprocesos con el presupuesto de CPU del contenedor. Escala las réplicas de forma horizontal según las solicitudes de entrada máximas por segundo, la sobrecarga de mTLS y los tamaños de carga útil de las solicitudes.
Servidor de la API (ate-api-server) Configura la QoS garantizada: Establece solicitudes y límites de CPU y memoria que coincidan para que el entorno de ejecución de Go alinee su recuento de subprocesos con el presupuesto de CPU del contenedor. Escala las réplicas según los ciclos máximos de reanudación y suspensión por segundo (aproximadamente 4 ms de CPU por ciclo de reanudación y suspensión) y la carga de búsqueda de solicitudes de entrada. Establece de forma explícita el parámetro de configuración ateapi.postgres.poolMaxConns. Cada réplica abre hasta poolMaxConns + 6 conexiones de base de datos, y la suma de todas las réplicas debe ser menor que el parámetro de configuración max_connections de PostgreSQL.
Base de datos (PostgreSQL) Configura la QoS con ráfagas con memoria garantizada: establece las solicitudes de memoria iguales a los límites para bloquear la caché de shared_buffers en la memoria y ayudar a evitar la expulsión por falta de memoria (OOM). Omite los límites de CPU cuando se ejecute en un nodo de ate-postgres dedicado para que la limitación de CPU del kernel no ralentice las ráfagas de puntos de control y autovacuum. Escala este StatefulSet de instancia única de forma vertical. Aprovisiona suficiente CPU para mantenerte en menos del 80% de uso en la carga máxima, suficiente RAM para almacenar en caché la tabla Actor (con el parámetro shared_buffers establecido en aproximadamente el 25% de la memoria) y una StorageClass respaldada por SSD establecida en el momento de la instalación con el parámetro de configuración ateapi.postgres.storageClass (por ejemplo, la StorageClass dynamic-rwo en C4 o N4, o la StorageClass premium-rwo en C3 o N2). Aumenta el parámetro max_connections en el ConfigMap postgres-config (el archivo postgresql.conf) para que se ajuste a todas las réplicas de ate-api-server.
Proxy de salida (atenet-egress) Reglas de recursos: Establece una solicitud de CPU de 512 mCPU (límite de 8 CPU virtuales) y una solicitud de memoria de 512 MiB (límite de 1 GiB). Aumenta las solicitudes y los límites si el tráfico saliente del Actor experimenta una mayor latencia. Escala las réplicas de forma horizontal según el tráfico de solicitudes salientes del actor.
Controlador de trabajador (ate-controller) Reglas de recursos: Mantén una réplica (sin elección de líder). Establece solicitudes de CPU y memoria en función del uso máximo durante los eventos de escalamiento horizontal grandes de WorkerPool. Si los Pods de trabajador nuevos tardan demasiado en registrarse en flotas grandes, aumenta el valor de la marca --worker-sync-concurrency (el valor predeterminado es 2).
Controlador de certificados (podcertificate-controller) Reglas de recursos: Se ejecuta en el espacio de nombres podcertificate-controller-system para firmar certificados de mTLS para Pods de trabajadores nuevos antes de que puedan aceptar actores. Para flotas de miles de trabajadores, aumenta los valores de la configuración podcert.workersPerSigner (el valor predeterminado es 0, que mantiene el valor predeterminado del manifiesto de 1 trabajador por firmante), la marca --kube-api-qps (el valor predeterminado es 5) y la marca --kube-api-burst (el valor predeterminado es 10).
Proveedor de identidad (ate-idp-server) Reglas de recursos: Entrega el documento de descubrimiento de OpenID Connect (OIDC) y el conjunto de claves web JSON (JWKS) en el espacio de nombres ate-system para verificar los tokens web JSON (JWT) del actor. Establece solicitudes de CPU y memoria en función del volumen máximo de consultas de JWKS. Escala las réplicas de forma horizontal si las partes de confianza consultan el extremo de JWKS con porcentajes de solicitudes altos sin almacenar en caché las claves.
Proveedor de credenciales (k8s-credential-provider) Reglas de recursos: Se ejecuta en el espacio de nombres ate-system cuando se habilita la inserción de credenciales de Secret de Kubernetes. Establece solicitudes de CPU y memoria según el volumen de inserción de credenciales salientes. Escala las réplicas de forma horizontal según la tasa de solicitudes salientes de Actor que requieren la inserción de credenciales de Secret de Kubernetes en el proxy de atenet-egress.

Aísla la infraestructura del sistema y los grupos de nodo trabajador

En los clústeres de producción, la programación de actores con alta deserción y el tráfico de instantáneas en los nodos trabajadores pueden competir con los componentes de la infraestructura del sistema por la CPU, la memoria y la E/S de disco. Separa tu clúster de GKE en tres niveles de grupos de nodos distintos:

  • Grupo de nodos de la base de datos (etiqueta ate-postgres): Es un grupo de nodos dedicado para el StatefulSet de PostgreSQL, que almacena todos los metadatos de Actor y Worker.
  • Grupo de nodos de infraestructura del sistema (etiqueta ate-system-infra): Es un grupo de nodos dedicado para los servicios de infraestructura del sistema restantes (los componentes atenet-router, ate-api-server, atenet-egress, ate-controller, ate-idp-server y k8s-credential-provider).
  • Grupos de nodos trabajadores (WorkerPool): Son grupos de nodos con escalamiento dinámico administrados por ComputeClasses personalizadas de GKE y búferes de capacidad de GKE para alojar entornos de pruebas de Actor activos.

Puedes aislar los componentes de la infraestructura de la base de datos y del sistema en nodos dedicados cuando instalas Agent Substrate en GKE con el parámetro de configuración cordonSystemInfraComponents (o la marca --cordon-system-infra-components). Antes de la instalación, debes crear ambos grupos de nodos con las etiquetas y los taints de NoSchedule necesarios:

# 1. Create the dedicated PostgreSQL node pool
gcloud container node-pools create ate-postgres-pool \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
    --node-locations=POSTGRES_ZONE \
    --machine-type=POSTGRES_MACHINE_TYPE \
    --num-nodes=1 \
    --node-labels=ate.dev/workloadType=ate-postgres \
    --node-taints=ate.dev/workloadType=ate-postgres:NoSchedule

# 2. Create the dedicated system infrastructure node pool
gcloud container node-pools create ate-system-infra-pool \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
    --machine-type=SYSTEM_INFRA_MACHINE_TYPE \
    --num-nodes=2 \
    --node-labels=ate.dev/workloadType=ate-system-infra \
    --node-taints=ate.dev/workloadType=ate-system-infra:NoSchedule

Reemplaza lo siguiente:

  • CLUSTER_NAME: Es el nombre de tu clúster estándar de GKE.
  • LOCATION: Es la zona o región de Compute Engine del plano de control del clúster.
  • POSTGRES_ZONE: Es una sola zona de Compute Engine para el StatefulSet de PostgreSQL de una sola réplica. En el caso de un clúster regional, especifica una zona dentro de la región del clúster para que el grupo de nodos aprovisione un solo nodo en la zona en la que se creará el disco persistente del StatefulSet. En el caso de un clúster zonal, especifica la zona del clúster.
  • POSTGRES_MACHINE_TYPE: Es el tipo de máquina de Compute Engine dimensionado para tu instancia de PostgreSQL.
  • SYSTEM_INFRA_MACHINE_TYPE: Es el tipo de máquina de Compute Engine con el tamaño adecuado para los componentes de la infraestructura de tu sistema (por ejemplo, el tipo de máquina c3-standard-8).

En un clúster regional, la marca --num-nodes se aplica por zona (por ejemplo, si configuras la marca --num-nodes=2 en tres zonas, se crearán seis nodos en total). Para colocar el grupo de nodos ate-system-infra-pool en zonas específicas, agrega la marca --node-locations.

Si habilitas el parámetro de configuración cordonSystemInfraComponents durante la instalación y falta alguno de los grupos de nodos, los Pods del sistema correspondientes permanecerán en el estado Pending.

Automatiza la segmentación de hardware con ComputeClasses personalizadas

Las ComputeClasses personalizadas de GKE te permiten definir listas priorizadas de series de máquinas de Compute Engine para tus nodos de WorkerPool y recurrir automáticamente a series de máquinas secundarias si una zona experimenta falta de disponibilidad de recursos.

Selecciona la serie de máquinas de Compute Engine por entorno de ejecución

Configura una ComputeClass independiente para cada entorno de ejecución de zona de pruebas:

  • Entorno de ejecución de MicroVM (Cloud Hypervisor): Establece el campo enableNestedVirtualization: true en tus prioridades de ComputeClass y orienta las series de máquinas de Compute Engine x86 que admiten la virtualización anidada (como N4, C3, C4 o N2), o usa tipos de máquinas bare metal x86, que ejecutan KVM de forma nativa y no requieren el campo enableNestedVirtualization. No se admiten las VMs basadas en Arm ni las series de máquinas que se indican en Restricciones de la virtualización anidada.
  • Entorno de ejecución de gVisor: Se orienta a series de máquinas de Compute Engine x86 de uso general o con optimización para procesamiento (como N4, C3, C4 o N2) sin la virtualización anidada habilitada. Las series de máquinas que se ejecutan en microarquitecturas de CPU mixtas (como E2) y las VMs basadas en Arm no son compatibles con Agent Substrate en GKE. Todos los recursos de WorkerPool que selecciona un ActorTemplate deben compartir la misma arquitectura de CPU.

Para obtener una comparación detallada, consulta Selecciona un entorno de ejecución de zona de pruebas.

Reglas de ComputeClass obligatorias para Agent Substrate

Cuando crees una ComputeClass para Agent Substrate en los nodos trabajadores de GKE, sigue estas reglas:

  • Usa ComputeClasses basadas en nodos: No uses la facturación basada en Pods (el campo podFamily), que no admite la virtualización anidada.
  • No configures el campo nodePoolConfig.sandbox.type: microvm: ese parámetro de configuración habilita el entorno de ejecución de Kata para GKE Sandbox en cargas de trabajo basadas en Pods y aplica un taint sandbox.gke.io/runtime=microvm que impide que se programe Agent Substrate en los trabajadores de GKE. Agent Substrate en GKE administra su propio entorno de ejecución de microVM y solo requiere la virtualización anidada de Compute Engine en nodos estándar de Container-Optimized OS (tipo de imagen cos_containerd).
  • Configura los parámetros de sysctl del kernel de Linux para una alta densidad de la zona de pruebas: Si un nodo trabajador ejecuta más de 800 zonas de pruebas simultáneas, debes aumentar los límites del kernel de Linux para la supervisión del sistema de archivos (parámetros fs.inotify.*) y para la tabla de vecinos del protocolo de resolución de direcciones (ARP) (parámetros net.ipv4.neigh.default.gc_thresh*). El instalador aplica esta configuración solo a los clústeres que crea. Cuando configures ComputeClasses personalizadas (con el campo priorityDefaults.nodeSystemConfig.linuxNodeConfig.sysctls) o crees previamente grupos de nodo trabajador (con la marca --system-config-from-file), aplica los siguientes valores de sysctl por tu cuenta:

    • fs.inotify.max_user_instances: 65536
    • fs.inotify.max_user_watches: 1048576
    • net.ipv4.neigh.default.gc_thresh1: 4096
    • net.ipv4.neigh.default.gc_thresh2: 16384
    • net.ipv4.neigh.default.gc_thresh3: 32768

    Para obtener más información sobre cómo configurar los parámetros de sysctl del nodo, consulta Opciones de configuración de sysctl.

Elige un patrón de escalamiento vertical para los recursos de WorkerPool de microVM

Los Pods de trabajadores de MicroVM solicitan el recurso extendido ate.dev/kvm: 1, que anuncia el complemento de dispositivo atelet solo después de que se inicia un nodo y se inicia el agente atelet. Debido a que el aprovisionamiento automático de nodos de GKE no ve el recurso extendido ate.dev/kvm en las plantillas de nodos no aprovisionados, un Pod de trabajador de microVM pendiente no puede activar GKE para la creación automática de un nuevo grupo de nodos a partir de cero réplicas por sí solo. Sin embargo, si un grupo de nodos ya tiene al menos un nodo en ejecución, GKE puede escalarlo verticalmente.

En la siguiente tabla, se comparan los patrones admitidos para escalar los recursos de WorkerPool de microVMs en GKE:

Patrón Cómo funciona ¿Se reduce la escala a 0 nodos? ¿Resguardo de prioridad múltiple para la falta de disponibilidad de recursos? Se usa mejor cuando
Grupos creados automáticamente con el campo minimumCapacity Establece los campos nodePoolAutoCreation.enabled: true y minimumCapacity.targetNodeCount: 1 con prioridades machineType explícitas. No (mantiene 1 nodo de preparación en ejecución) Solo en el aprovisionamiento inicial para el campo minimumCapacity a nivel de la clase; el resguardo a mitad de la ráfaga requiere configurar el campo minimumCapacity.targetNodeCount: 1 en cada entrada de resguardo en el campo spec.priorities[] (manteniendo 1 nodo de preparación por prioridad) Quieres que la creación del grupo de nodos sea automática y que siempre haya al menos 1 nodo trabajador en ejecución.
Grupos creados automáticamente con búferes de capacidad Combina el campo nodePoolAutoCreation.enabled: true con un CapacityBuffer activo o en espera cuya PodTemplate omita el recurso extendido ate.dev/kvm. Se suspende en espera (por ejemplo, aproximadamente el 8% del costo de procesamiento en ejecución en un nodo c3-standard-4 con un disco de arranque predeterminado de 100 GiB) Sí (los marcadores de posición de búfer activan el resguardo del aprovisionamiento automático de nodos en todas las prioridades) Quieres un escalamiento rápido de ráfagas (de 1 a 4 segundos activo, o de 20 a 35 segundos para reanudar los nodos en espera y de 50 a 85 segundos hasta que los trabajadores nuevos estén listos) con un costo de inactividad bajo.
Grupos de nodos de 0 nodos creados previamente con etiquetas de plantilla de nodo Crea previamente grupos de 0 nodos con ajuste de escala automático con la etiqueta clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 y hace referencia a ellos en el campo spec.priorities[].nodepools de ComputeClass. Sí (0 nodos reales, sin costo de procesamiento inactivo) Sí, en los grupos de nodos creados previamente Quieres una verdadera reducción de escala a cero sin mantener búferes de capacidad en espera.

Ejemplo: ComputeClass con el campo minimumCapacity

Cuando usas el campo minimumCapacity, cada entrada en el campo spec.priorities debe especificar un campo machineType explícito en lugar de solo especificar el campo machineFamily:

apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
  name: substrate-microvm
spec:
  priorityDefaults:
    enableNestedVirtualization: true
    nodeSystemConfig:
      linuxNodeConfig:
        sysctls:
          fs.inotify.max_user_instances: 65536
          fs.inotify.max_user_watches: 1048576
          net.ipv4.neigh.default.gc_thresh1: 4096
          net.ipv4.neigh.default.gc_thresh2: 16384
          net.ipv4.neigh.default.gc_thresh3: 32768
  priorities:
  - machineType: n4-standard-4
  - machineType: c3-standard-4
  - machineType: n2-standard-4
  nodePoolAutoCreation:
    enabled: true
  minimumCapacity:
    targetNodeCount: 1
  nodePoolConfig:
    imageType: cos_containerd
  whenUnsatisfiable: DoNotScaleUp

Para orientar un WorkerPool a esta ComputeClass, agrega el campo nodeSelector: {cloud.google.com/compute-class: substrate-microvm} a la plantilla del Pod de WorkerPool.

Cuando una ComputeClass recurre a diferentes series de máquinas x86 (como de N4 a C3 o N2), restablecer una instantánea duradera con fidelidad de memoria (el modo SNAPSHOT_FIDELITY_MEMORY) requiere un trabajador cuyas funciones de CPU sean un superconjunto de las funciones de CPU de la instantánea. Si ningún Worker compatible tiene capacidad, Agent Substrate cambia la restauración a la fidelidad del sistema de archivos raíz (el modo SNAPSHOT_FIDELITY_ROOTFS), que conserva el sistema de archivos raíz y los datos de volumen duraderos mientras se reinician los procesos del Actor.

Ejemplo: Escala desde cero con grupos de nodos de 0 nodos creados previamente

  1. Guarda la configuración de sysctl del kernel de Linux de alta densidad como un archivo system-config.yaml:

    linuxConfig:
      sysctl:
        fs.inotify.max_user_instances: '65536'
        fs.inotify.max_user_watches: '1048576'
        net.ipv4.neigh.default.gc_thresh1: '4096'
        net.ipv4.neigh.default.gc_thresh2: '16384'
        net.ipv4.neigh.default.gc_thresh3: '32768'
    
  2. Crea con anticipación tus grupos de nodos de virtualización anidada principales y de resguardo en 0 nodos con la marca --system-config-from-file=system-config.yaml y la etiqueta clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 para que el escalador automático del clúster de GKE sepa que el grupo vacío proporciona el recurso extendido ate.dev/kvm:

    # Primary N4 pool (0 nodes)
    gcloud container node-pools create microvm-n4-pool \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --machine-type=n4-standard-4 \
        --enable-nested-virtualization \
        --system-config-from-file=system-config.yaml \
        --num-nodes=0 \
        --enable-autoscaling --total-min-nodes=0 --total-max-nodes=10 \
        --node-labels=cloud.google.com/compute-class=substrate-microvm-zero,clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 \
        --node-taints=cloud.google.com/compute-class=substrate-microvm-zero:NoSchedule
    
    # Fallback C3 pool (0 nodes)
    gcloud container node-pools create microvm-c3-pool \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --machine-type=c3-standard-4 \
        --enable-nested-virtualization \
        --system-config-from-file=system-config.yaml \
        --num-nodes=0 \
        --enable-autoscaling --total-min-nodes=0 --total-max-nodes=10 \
        --node-labels=cloud.google.com/compute-class=substrate-microvm-zero,clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 \
        --node-taints=cloud.google.com/compute-class=substrate-microvm-zero:NoSchedule
    

    Reemplaza lo siguiente:

    • CLUSTER_NAME: Es el nombre de tu clúster de GKE Standard.
    • LOCATION: la zona o región de Compute Engine del clúster. Si usas las marcas --total-min-nodes y --total-max-nodes, se establecen los límites de escalado automático en todo el grupo de nodos, en lugar de por zona.
  3. Haz referencia a los grupos creados previamente en orden de prioridad en tu ComputeClass:

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: substrate-microvm-zero
    spec:
      nodePoolAutoCreation:
        enabled: false
      priorities:
      - nodepools:
        - microvm-n4-pool
      - nodepools:
        - microvm-c3-pool
      whenUnsatisfiable: DoNotScaleUp
    

    El campo priorityDefaults no se aplica a las prioridades que usan el campo nodepools, ya que la configuración de los nodos proviene de los grupos de nodos creados previamente. Al igual que con las prioridades de resguardo creadas automáticamente, reanudar un Actor en una serie de máquinas de resguardo cuyas funciones de CPU no sean un superconjunto de las funciones de CPU de la instantánea cambia a una versión anterior el restablecimiento al modo SNAPSHOT_FIDELITY_ROOTFS y reinicia los procesos del Actor.

Para obtener más información sobre la configuración de ComputeClass, consulta Controla los atributos de los nodos con ajuste de escala automático con ComputeClasses personalizadas.

Configura búferes de capacidad para el escalamiento de ráfagas de WorkerPool

Cuando un aumento repentino del tráfico de Actor supera la capacidad de los Pods de WorkerPool en ejecución, los Pods de Worker nuevos deben esperar a que se aprovisionen los nodos de Compute Engine, se inicialice el agente de atelet y se precalienten los recursos de la zona de pruebas antes de que puedan entregar Actors. Los búferes de capacidad de GKE quitan el aprovisionamiento de nodos y el precalentamiento de recursos de atelet de la ruta crítica:

  • Búferes de capacidad activos (estrategia buffer.x-k8s.io/active-capacity): Mantienen los nodos aprovisionados previamente en ejecución y listos para que los Pods de trabajador nuevos se programen en uno a cuatro segundos, con el costo total de ejecución de la VM de Compute Engine.
  • Búferes de capacidad en espera (estrategia buffer.gke.io/standby-capacity): aprovisiona nodos y permite que el agente atelet inicialice y prepare los recursos de la zona de pruebas (el objeto binario runsc o las imágenes de Cloud Hypervisor y Kata) en el disco durante el período de inicialización en espera antes de que GKE suspenda las VMs de Compute Engine. Esta ventana se establece de forma predeterminada en cinco minutos (5m) y se configura con la anotación buffer.gke.io/standby-capacity-init-time en CapacityBuffer. Aumenta el valor de esta anotación si el calentamiento previo de los recursos tarda más de cinco minutos. Cuando se produce una ráfaga, GKE reanuda los nodos suspendidos en aproximadamente 20 a 35 segundos, y la preparación de extremo a extremo del WorkerPool (programación de Pods de trabajadores, emisión de certificados de Pods y registro de capacidad con el componente ate-api-server) se completa en aproximadamente 50 a 85 segundos. Mientras está suspendida, solo pagas por la memoria de la VM suspendida y el almacenamiento del disco de arranque. Por ejemplo, el almacenamiento suspendido cuesta aproximadamente el 8% del costo de procesamiento en ejecución en un nodo c3-standard-4 con un disco de arranque hyperdisk-balanced predeterminado de 100 GiB; el porcentaje exacto varía según la forma de la máquina, el tamaño del disco de arranque y las IOPS o la capacidad de procesamiento aprovisionadas.

Para obtener más información sobre las estrategias de búfer, consulta Estrategias para reducir la latencia de inicio.

Limitaciones y reglas para los búferes de capacidad

Cuando configures búferes de capacidad para Agent Substrate en GKE, aplica las siguientes reglas:

  • Restricciones de forma de máquina de Compute Engine para los búferes en espera: La suspensión de instancias de Compute Engine no se admite en VMs con SSD locales conectadas ni en formas de máquina con más de 208 GB de memoria (como el tipo de máquina c3-highmem-88 o las formas de equipos físicos). Para formas de nodo trabajador grandes o nodos con SSD locales, usa búferes de capacidad activos en lugar de búferes en espera.
  • Evita apuntar el campo scalableRef a un WorkerPool de 0 réplicas o a un Deployment de microVM:
    • El controlador CapacityBuffer de GKE no puede resolver un recurso personalizado (kind: WorkerPool) cuando el grupo se escala a 0 réplicas.
    • En el caso de los recursos WorkerPool de microVM, tampoco apuntes el campo scalableRef a la Deployment subyacente, ya que la plantilla de Pod de implementación incluye el recurso extendido ate.dev/kvm: 1 (que evita que el aprovisionamiento automático de nodos escale horizontalmente un grupo vacío). En su lugar, configura los búferes haciendo referencia a un PodTemplate (en el campo podTemplateRef) que seleccione la ComputeClass sin solicitar el recurso extendido ate.dev/kvm.
    • Para los recursos de WorkerPool de gVisor (que no solicitan el recurso extendido ate.dev/kvm), puedes apuntar el campo scalableRef directamente al Deployment subyacente de WorkerPool o usar un PodTemplate.

Ejemplo: CapacityBuffer en espera con una PodTemplate

En el siguiente manifiesto, se definen un PodTemplate y un CapacityBuffer en espera que funcionan para los recursos de WorkerPool de microVM o gVisor:

apiVersion: v1
kind: PodTemplate
metadata:
  name: substrate-worker-buffer-template
  namespace: WORKERPOOL_NAMESPACE
template:
  spec:
    nodeSelector:
      cloud.google.com/compute-class: COMPUTE_CLASS_NAME
    containers:
    - name: buffer-placeholder
      image: registry.k8s.io/pause:3.9
      resources:
        requests:
          cpu: "WORKER_CPU_REQUEST"
          memory: "WORKER_MEMORY_REQUEST"
---
apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
  name: substrate-standby-buffer
  namespace: WORKERPOOL_NAMESPACE
spec:
  podTemplateRef:
    name: substrate-worker-buffer-template
  replicas: BUFFER_REPLICAS
  provisioningStrategy: buffer.gke.io/standby-capacity

Reemplaza lo siguiente:

  • WORKERPOOL_NAMESPACE: Es el espacio de nombres de Kubernetes de tu WorkerPool (por ejemplo, my-workerpool).
  • COMPUTE_CLASS_NAME: Es el nombre de la ComputeClass personalizada a la que se orienta tu WorkerPool (por ejemplo, substrate-microvm).
  • WORKER_CPU_REQUEST y WORKER_MEMORY_REQUEST: Son las solicitudes de CPU y memoria de un solo Pod de trabajador en tu WorkerPool (por ejemplo, 2 CPU y 4Gi de memoria en un nodo de 4 CPU virtuales), lo que deja capacidad de nodo para el agente de atelet y los daemons del sistema de GKE. Hacer coincidir estos valores con las solicitudes de un Pod de trabajador ayuda a garantizar que cada réplica de búfer aprovisione un nodo trabajador en espera en lugar de empaquetar varios marcadores de posición de búfer en un solo nodo.
  • BUFFER_REPLICAS: Es la cantidad de nodos trabajadores en espera que se mantendrán precalentados (por ejemplo, 4 nodos).

Cuando uses búferes de capacidad en espera, agrega una tolerancia para la tolerancia buffer.gke.io/standby-capacity-node-suspended (con el campo operator: "Exists") al DaemonSet atelet para que los Pods atelet de reemplazo puedan permanecer programados en los nodos en espera suspendidos (por ejemplo, durante una actualización progresiva del DaemonSet). Para ver un ejemplo de configuración de DaemonSet, consulta Carga imágenes de forma previa en búferes en espera.

Si varias cargas de trabajo comparten la misma ComputeClass, agrega tolerancias de separación de cargas de trabajo y etiquetas nodeSelector coincidentes a la plantilla de Pod de WorkerPool y a la PodTemplate de búfer para que GKE aprovisione nodos con taints dedicados que otras cargas de trabajo no reclamen. También agrega una tolerancia coincidente al DaemonSet atelet para que el agente de atelet pueda programarse en esos nodos dedicados. Para obtener instrucciones paso a paso, consulta Configura búferes de capacidad.

Administra las actualizaciones y las interacciones del escalador automático

En esta sección, se describe cómo administrar las actualizaciones del DaemonSet de atelet, los eventos de reducción de escala vertical del escalador automático del clúster y las actualizaciones de nodos sin interrumpir los actores activos.

Actualiza el DaemonSet atelet con búferes en espera

Los nodos de búfer en espera suspendidos tienen el reproche buffer.gke.io/standby-capacity-node-suspended y un reproche de inaccesibilidad mientras están suspendidos, por lo que el agente kubelet en un nodo suspendido no puede confirmar las eliminaciones de Pods. Asegúrate de que el DaemonSet atelet tolere el reproche buffer.gke.io/standby-capacity-node-suspended (con el campo operator: "Exists"). Incluso con esa tolerancia, durante una actualización progresiva estándar del DaemonSet atelet (con el campo maxUnavailable: 1), los Pods en los nodos suspendidos ingresan al estado Terminating y pueden bloquear el progreso de la actualización en los nodos en ejecución.

Antes de actualizar el DaemonSet atelet en un clúster con nodos en espera suspendidos, haz una de las siguientes acciones:

  • Para que los nodos en espera inaccesibles no agoten el presupuesto de actualización, establece el campo spec.updateStrategy.rollingUpdate.maxUnavailable en el DaemonSet atelet en un valor mayor que la cantidad máxima de nodos en espera suspendidos.
  • Antes de actualizar el DaemonSet de atelet, escala de forma temporal las réplicas de CapacityBuffer en espera a 0 y espera hasta que el escalador automático del clúster quite todos los nodos de búfer en espera suspendidos (por lo general, de 10 a 15 minutos). Para verificar si algún nodo aún informa un estado de condición Suspended de True, ejecuta el siguiente comando:

    kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'
    

Protege los actores activos durante la reducción de escala vertical y las actualizaciones

Debido a que los actores activos se ejecutan dentro de zonas de pruebas administradas por el agente de atelet en lugar de como Pods de Kubernetes individuales, las solicitudes de CPU y memoria de un nodo pueden parecer bajas para el escalador automático del clúster de GKE, incluso mientras un Pod de trabajador en ese nodo aloja actores activos. Cuando se vacía un nodo, el agente kubelet envía un indicador SIGTERM al Pod de trabajador, y el trabajador reenvía el indicador SIGTERM al proceso principal de cada contenedor de cada actor que aloja. Cada Actor activo tiene hasta 30 minutos para suspenderse antes de que se detenga el Worker. Asigna a cada Actor con estado un controlador SIGTERM que no salga de la señal y que llame al método SuspendActor con el modo DURABILITY_MODE_SYNCHRONOUS. Un Actor cuyo proceso principal se cierra con la señal SIGTERM pierde el estado no guardado de inmediato. Si el Pod de trabajador se detiene mientras aloja un Actor activo, este ingresa al estado ACTOR_STATE_CRASHED.

Para minimizar las interrupciones durante los eventos de reducción de escala vertical y las actualizaciones de clúster de GKE, aplica las siguientes prácticas:

  • Evita usar VMs Spot para los nodos de WorkerPool con estado, ya que la interrupción de las VM Spot solo proporciona entre 15 segundos y 2 minutos de aviso de finalización antes de detener el nodo.
  • Coordina el vaciado en tu organizador para que los actores activos se guarden y suspendan antes de que se detengan los Pods de trabajador, o evita que el escalador automático del clúster desaloje los Pods de trabajador activos (por ejemplo, con la anotación de Pod cluster-autoscaler.kubernetes.io/safe-to-evict: "false"). Si configuras la anotación safe-to-evict: "false" de forma estática en la plantilla de Pod de WorkerPool, el escalador automático del clúster no reducirá la escala verticalmente de un nodo mientras un Pod de trabajador esté programado en él, incluso cuando ese trabajador aloje cero actores activos. Para liberar nodos inactivos, debes reducir la escala verticalmente de las réplicas de WorkerPool o administrar la anotación de forma dinámica. Para obtener más información sobre el ciclo de vida de expulsión de trabajadores y la recuperación de actores que fallaron con el método RevertActor, consulta Expulsión en la guía de la API de Agent Substrate.
  • Configura las actualizaciones de aumento de GKE y revisa Actualiza en un entorno con recursos limitados para que se aprovisionen nodos trabajadores nuevos antes de que se acordonen y vacíen los nodos trabajadores existentes.

¿Qué sigue?