Google Kubernetes Engine (GKE) vous permet de faire évoluer les clusters Agent Substrate sur GKE pour prendre en charge les charges de travail d'agents IA à forte simultanéité, tout en minimisant les coûts de calcul inactifs. En combinant des pools de nœuds d'infrastructure système dédiés avec des ComputeClasses personnalisées et des tampons de capacité, vous pouvez isoler les composants système critiques, automatiser le remplacement du matériel sur les séries de machines Compute Engine et maintenir la capacité des nœuds de calcul de secours.
Lisez ce document pour redimensionner les composants de votre cluster GKE, isoler l'infrastructure système et les pools de nœuds de base de données, configurer le provisionnement automatique des nœuds pour les ressources WorkerPool, et planifier la maintenance et les mises à niveau du cluster. Ce document est destiné aux administrateurs de plate-forme qui provisionnent et gèrent Agent Substrate sur l'infrastructure GKE.
Avant de commencer
Avant de configurer l'infrastructure de votre cluster pour le scaling, assurez-vous que votre environnement répond aux exigences suivantes :
- Mode et version du cluster GKE : vous devez utiliser un cluster GKE Standard dans lequel le plan de contrôle et les pools de nœuds exécutent la version 1.37 ou une version ultérieure. Les clusters GKE Autopilot ne sont pas compatibles avec Agent Substrate sur GKE.
- Installation d'Agent Substrate sur GKE : vous devez disposer d'une installation d'Agent Substrate sur GKE ou prévoir d'installer Agent Substrate sur GKE avec l'isolation des nœuds d'infrastructure système activée. Pour connaître la procédure d'installation, consultez Installer Agent Substrate sur GKE.
Redimensionner votre cluster Agent Substrate
Dimensionnez votre cluster en fonction des pics de simultanéité et des taux de reprise de pointe plutôt que des moyennes. Les nœuds de calcul doivent contenir le nombre maximal d'acteurs exécutés simultanément, et les composants de l'infrastructure système et les chemins de stockage doivent suivre le rythme le plus rapide de reprise et de suspension des acteurs.
Estimer les pics de charge de travail
Si vous ne disposez pas de mesures de production, estimez votre simultanéité maximale et votre taux de reprise à partir du nombre total d'acteurs enregistrés (total_actors), de la fraction moyenne d'acteurs exécutés simultanément (average_active_fraction), de votre multiplicateur de pics de trafic (burst_factor) et de la durée moyenne pendant laquelle un acteur reste actif par tour (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_resumePar exemple, si vous avez 100 000 acteurs au total, dont 10 % sont actifs en moyenne (10 000 acteurs) et un facteur de burst de deux, votre cluster doit accepter 20 000 acteurs en cours d'exécution au maximum. Si chaque acteur s'exécute pendant 100 secondes en moyenne avant d'être suspendu, le maintien de ce pic nécessite 200 reprises par seconde et 200 suspensions par seconde.
Agent Substrate sur GKE ne suspend pas automatiquement les acteurs inactifs. Votre application ou votre orchestrateur doit déclencher la suspension.
Dimensionner le plan de données
Cette section décrit les bonnes pratiques de dimensionnement du plan de données, y compris les pods de nœuds de calcul, les nœuds GKE, la bande passante des instantanés et l'agent de nœud atelet.
Calculer les pods de nœuds de calcul et les nœuds GKE
Chaque pod de nœud de calcul d'un WorkerPool héberge plusieurs acteurs. Un nœud de calcul peut accepter un nouvel acteur s'il héberge moins d'acteurs que la limite définie par l'option --max-actors sur le conteneur ateworker (par défaut 1000) et s'il dispose d'une capacité de processeur et de mémoire suffisante pour respecter les limites d'ActorTemplate. Pour en savoir plus sur l'interaction entre les limites des nœuds de calcul et celles des acteurs, consultez le guide Open Source Right-sizing resources in the Agent Substrate API (Dimensionner correctement les ressources dans l'API Agent Substrate).
Calculez le nombre requis de pods de calcul avec une capacité de planification disponible de 20 % (facteur 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)Dans cette formule, la variable max_actors est définie par défaut sur 1000 (configurée par l'option --max-actors). Soustrayez la mémoire que le nœud de calcul réserve pour son propre processus de la valeur worker_memory. Pour les ressources WorkerPool de microVM, ajoutez à la valeur actor_memory la surcharge de mémoire du moniteur de machine virtuelle (VMM) par acteur signalée par le nœud de calcul, car l'emplacement comptabilise cette surcharge dans la capacité du nœud de calcul.
Avec un pod de calcul par nœud, le nombre de nœuds de calcul est égal au nombre de nœuds de calcul GKE. N'allouez pas 100 % du processeur et de la mémoire d'un nœud au pod de nœud de calcul. Laissez de la capacité sur chaque nœud pour le DaemonSet atelet (dans l'espace de noms ate-system) et les daemons système GKE.
GKE Standard accepte jusqu'à 65 000 nœuds par cluster et jusqu'à 512 pods par nœud. La valeur maximale par défaut est de 110 pods par nœud (configurable avec l'option --max-pods-per-node), et les clusters de grande taille sont soumis à des exigences supplémentaires.
Dimensionner la bande passante des instantanés et les disques des nœuds
Chaque suspension d'acteur écrit un instantané sur le disque du nœud local sous le chemin d'accès au répertoire /var/lib/ate. En mode SYNCHRONOUS, l'agent atelet importe l'instantané dans Cloud Storage avant que l'opération de suspension ne soit renvoyée. En mode ASYNCHRONOUS, l'agent atelet planifie l'importation vers Cloud Storage après un délai d'environ la valeur de l'option --snapshot-upload-delay (par défaut 5m) à partir du moment où l'instantané est pris. Agent Substrate met en cache le dernier instantané sur le nœud pendant la période configurée dans l'option --snapshot-detach-delay, qui est définie par défaut sur 30m. Un acteur qui reprend son exécution dans ce délai est planifié sur le même nœud et restauré à partir du disque local au lieu de télécharger l'instantané depuis Cloud Storage.
Estimez la taille de votre instantané non compressé (snapshot_size) en additionnant la limite de mémoire ActorTemplate et toutes les données écrites dans le système de fichiers racine accessible en écriture ou dans les répertoires durables. La gestion des fichiers creux et la compression zstd réduisent la taille de l'instantané compressé (compressed_snapshot_size) transféré vers et depuis Cloud Storage, où Agent Substrate stocke jusqu'à deux instantanés par acteur (l'instantané précédent et l'instantané en cours) :
- Bande passante Cloud Storage maximale (dans chaque direction) :
peak_resume_rate × compressed_snapshot_size - Pic de débit d'écriture sur le disque du nœud par nœud :
2 × peak_resume_rate × snapshot_size / total_nodes(les téléchargements de reprise et les points de contrôle de suspension écrivent sur le disque du nœud).
Le disque de démarrage hyperdisk-balanced de 100 Gio par défaut dans GKE fournit 3 600 IOPS et un débit de 290 Mio/s (les performances par défaut évoluent en fonction de la taille du disque), ce qui peut limiter les opérations d'instantané en cas d'E/S d'invité importantes. Lorsque vous créez des pools de nœuds de calcul, installez un disque dédié sur le chemin d'accès au répertoire /var/lib/ate/snapshots ou augmentez les performances du disque de démarrage en utilisant les options --boot-disk-provisioned-iops et --boot-disk-provisioned-throughput avec la commande gcloud container node-pools create.
Vérifier le quota de Security Token Service
Chaque transfert d'instantané vers ou depuis Cloud Storage nécessite un jeton limité à l'acteur, que le composant ate-api-server demande à l'API Security Token Service (STS). Le composant ate-api-server effectue jusqu'à une requête STS par acteur toutes les 20 à 40 minutes (généralement lors de la première reprise dans cette fenêtre) et réutilise le jeton jusqu'à 20 minutes avant l'expiration.
Le quota STS Exchange token global requests est défini par défaut sur 6 000 requêtes par projet et par minute. Il est partagé avec Workload Identity Federation for GKE :
- Quota STS requis (requêtes par minute) : estimation jusqu'à 60 fois le taux maximal de reprises pour les acteurs dont le dernier transfert d'instantané remonte à plus de 20 minutes, plus la capacité de Workload Identity Federation for GKE. Si vous ne connaissez pas ce taux, utilisez la formule
60 × peak_resume_ratecomme solution de secours. Par exemple, 200 reprises par seconde nécessitent jusqu'à 12 000 requêtes par minute. - Comment augmenter le quota : demandez une augmentation de quota sur la page Quotas et limites du système de la console Google Cloud . Les transferts d'instantanés fonctionnent sans que l'API Security Token Service soit activée dans votre projet, mais vous devez l'activer pour que le quota apparaisse sur la page Quotas et limites du système. Pour en savoir plus, consultez Quota pour l'API Exchange Token dans Security Token Service dans la documentation de Workload Identity Federation for GKE.
Régler l'agent de nœud atelet
Le DaemonSet atelet exécute un pod par nœud de calcul pour restaurer et créer des points de contrôle pour les acteurs. Dans chaque pod atelet, le conteneur objectstore-plugin compresse et transfère les instantanés vers et depuis Cloud Storage.
Le tableau suivant décrit les principaux paramètres de dimensionnement des conteneurs atelet et objectstore-plugin :
| Paramètre | Par défaut | Conseils de dimensionnement |
|---|---|---|
Processeur et mémoire des conteneurs atelet et objectstore-plugin
|
Requêtes : 50 mCPU, 128 Mio de mémoire ; aucune limite |
Configurez la QoS avec possibilité de dépassement sans limites de mémoire en omettant les limites de mémoire sur les deux conteneurs, car l'atteinte d'une limite de mémoire arrête l'agent de nœud et interrompt toutes les reprises sur le nœud. Augmentez les demandes de processeur et de mémoire pour qu'elles correspondent au pic d'utilisation mesuré sur un nœud complet à votre taux de reprise maximal, afin que les pods de nœuds de calcul ne consomment pas les ressources nécessaires à l'agent atelet.
|
--upload-memory-budget (conteneur objectstore-plugin) et --snapshot-upload-workers (conteneur atelet)
|
Budget de 512 Mio ; 2 workers d'importation |
Pour éviter que les importations d'instantanés simultanées ne soient mises en file d'attente sur les nœuds multi-acteurs présentant des taux de suspension élevés, procédez comme suit :
|
--drain-timeout flag and
terminationGracePeriodSeconds field
|
5 minutes (option --drain-timeout) ; 330 secondes (champ terminationGracePeriodSeconds)
|
Contrôle la durée pendant laquelle l'agent atelet termine les restaurations et les importations d'instantanés en cours lorsque son pod s'arrête pendant le drainage ou la mise à niveau d'un nœud. Si vous augmentez la valeur de l'option --drain-timeout pour les instantanés volumineux, augmentez également la valeur du champ terminationGracePeriodSeconds sur le DaemonSet atelet afin que l'agent kubelet n'arrête pas l'agent atelet avant la fin des importations.
|
Dimensionner les composants de l'infrastructure système et la base de données
Pour les déploiements de composants système sans état dans l'espace de noms ate-system qui évoluent horizontalement, estimez le nombre d'instances répliquées requis avec 35 % de capacité disponible (le facteur 0.65) plus une instance répliquée de rechange (+ 1) pour tolérer les perturbations de nœuds :
replicas = ceil(peak_load / (capacity_per_replica × 0.65)) + 1Le scaling horizontal cesse d'améliorer le débit lorsqu'une dépendance partagée (comme les limites de processeur ou de connexion PostgreSQL) atteint sa capacité maximale. Dimensionnez ensemble les composants de l'infrastructure de votre système et la base de données. Pour en savoir plus sur les options de composant, consultez le guide d'installation de l'opérateur Open Source.
Le tableau suivant décrit les règles de ressources et de scaling pour chaque composant d'infrastructure système :
| Composant | Règles de QoS et de ressources | Scaling et réglage de la connexion |
|---|---|---|
Routeur d'Ingress (atenet-router) |
Configurez la QoS garantie : définissez des demandes et des limites de processeur et de mémoire correspondantes afin que l'environnement d'exécution Go aligne son nombre de threads sur le budget de processeur du conteneur. | Effectuez un scaling horizontal des instances répliquées en fonction du pic de requêtes d'entrée par seconde, de la surcharge mTLS et de la taille des charges utiles des requêtes. |
Serveur d'API (ate-api-server) |
Configurez la QoS garantie : définissez des demandes et des limites de processeur et de mémoire correspondantes afin que l'environnement d'exécution Go aligne son nombre de threads sur le budget de processeur du conteneur. |
Faites évoluer les instances répliquées en fonction des cycles de reprise et de suspension par seconde (environ 4 ms de processeur par cycle de reprise et de suspension) et de la charge de recherche des requêtes d'entrée. Définissez explicitement le paramètre ateapi.postgres.poolMaxConns. Chaque instance répliquée ouvre jusqu'à poolMaxConns + 6 connexions à la base de données, et la somme de toutes les instances répliquées doit rester inférieure au paramètre PostgreSQL max_connections.
|
| Base de données (PostgreSQL) |
Configurez la QoS avec possibilité de dépassement avec une mémoire garantie : définissez des demandes de mémoire égales aux limites pour verrouiller le cache shared_buffers en mémoire et éviter l'éviction pour cause de mémoire insuffisante (OOM). Omettez les limites de processeur lors de l'exécution sur un nœud ate-postgres dédié afin que la limitation du processeur du noyau ne ralentisse pas les pics de point de contrôle et d'autovacuum.
|
Effectuez un scaling vertical de ce StatefulSet à instance unique. Provisionnez suffisamment de processeurs pour rester à moins de 80 % d'utilisation en cas de charge de pointe, suffisamment de RAM pour mettre en cache la table Actor (avec le paramètre shared_buffers défini sur environ 25 % de la mémoire) et une StorageClass basée sur SSD définie au moment de l'installation avec le paramètre ateapi.postgres.storageClass (par exemple, la StorageClass dynamic-rwo sur C4 ou N4, ou la StorageClass premium-rwo sur C3 ou N2). Augmentez le paramètre max_connections dans le ConfigMap postgres-config (fichier postgresql.conf) pour qu'il s'adapte à toutes les instances répliquées ate-api-server.
|
Proxy de sortie (atenet-egress) |
Règles de ressources : définissez une requête de processeur de 512 mCPU (limite de 8 vCPU) et une requête de mémoire de 512 Mio (limite de 1 Gio). Augmentez les demandes et les limites si le trafic Actor sortant subit une latence accrue. | Effectuez un scaling horizontal des instances répliquées en fonction du trafic des requêtes sortantes d'Actor. |
Contrôleur de nœud de calcul (ate-controller) |
Règles de ressources : conservez une instance répliquée (pas d'élection de leader). Définissez les demandes de processeur et de mémoire en fonction de l'utilisation maximale lors des événements de scaling horizontal WorkerPool de grande envergure. |
Si l'enregistrement de nouveaux pods de nœuds de calcul prend trop de temps dans les grands parcs, augmentez la valeur de l'option --worker-sync-concurrency (par défaut, 2).
|
Contrôleur de certificat (podcertificate-controller)
|
Règles de ressources : s'exécute dans l'espace de noms podcertificate-controller-system pour signer les certificats mTLS des nouveaux pods de nœuds de calcul avant qu'ils ne puissent accepter les acteurs.
|
Pour les parcs de milliers de nœuds de calcul, augmentez les valeurs du paramètre podcert.workersPerSigner (par défaut 0, qui conserve la valeur par défaut du fichier manifeste de 1 nœud de calcul par signataire), l'option --kube-api-qps (par défaut 5) et l'option --kube-api-burst (par défaut 10).
|
Fournisseur d'identité (ate-idp-server) |
Règles de ressources : diffuse le document de découverte OpenID Connect (OIDC) et le jeu de clés Web JSON (JWKS) dans l'espace de noms ate-system pour valider les jetons Web JSON (JWT) de l'acteur. Définissez les demandes de processeur et de mémoire en fonction du volume maximal de requêtes JWKS.
|
Effectuez un scaling horizontal des instances répliquées si les tiers de confiance interrogent le point de terminaison JWKS à des taux de requêtes élevés sans mettre en cache les clés. |
Fournisseur d'identifiants (k8s-credential-provider)
|
Règles de ressources : s'exécute dans l'espace de noms ate-system lorsque l'injection d'identifiants de secret Kubernetes est activée. Définissez les demandes de processeur et de mémoire en fonction du volume d'injection d'identifiants sortants.
|
Effectuez un scaling horizontal des instances répliquées en fonction du taux de requêtes Actor sortantes qui nécessitent l'injection d'identifiants de secret Kubernetes au niveau du proxy atenet-egress.
|
Isoler l'infrastructure système et les pools de nœuds de calcul
Dans les clusters de production, la planification des acteurs à forte rotation et le trafic des instantanés sur les nœuds de calcul peuvent entrer en concurrence avec les composants de l'infrastructure système pour le processeur, la mémoire et les E/S de disque. Séparez votre cluster GKE en trois niveaux de pools de nœuds distincts :
- Pool de nœuds de base de données (étiquette
ate-postgres) : pool de nœuds dédié pour le StatefulSet PostgreSQL, qui stocke toutes les métadonnées des acteurs et des nœuds de calcul. - Pool de nœuds d'infrastructure système (étiquette
ate-system-infra) : pool de nœuds dédié aux services d'infrastructure système restants (composantsatenet-router,ate-api-server,atenet-egress,ate-controller,ate-idp-serveretk8s-credential-provider). - Pools de nœuds de calcul (WorkerPool) : pools de nœuds à scaling dynamique gérés par des ComputeClasses personnalisées GKE et des tampons de capacité GKE pour héberger des bacs à sable Actor actifs.
Vous pouvez isoler les composants de l'infrastructure de la base de données et du système sur des nœuds dédiés lorsque vous installez Agent Substrate sur GKE à l'aide du paramètre cordonSystemInfraComponents (ou de l'option --cordon-system-infra-components). Avant l'installation, vous devez créer les deux pools de nœuds avec les libellés et les rejets NoSchedule requis :
# 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
Remplacez les éléments suivants :
CLUSTER_NAME: nom de votre cluster GKE Standard.LOCATION: zone ou région Compute Engine du plan de contrôle de votre cluster.POSTGRES_ZONE: une seule zone Compute Engine pour le StatefulSet PostgreSQL à instance répliquée unique. Pour un cluster régional, spécifiez une zone dans la région du cluster afin que le pool de nœuds provisionne un seul nœud dans la zone où le disque persistant du StatefulSet sera créé. Pour un cluster zonal, spécifiez la zone du cluster.POSTGRES_MACHINE_TYPE: type de machine Compute Engine dimensionné pour votre instance PostgreSQL.SYSTEM_INFRA_MACHINE_TYPE: type de machine Compute Engine dimensionné pour les composants de l'infrastructure de votre système (par exemple, le type de machinec3-standard-8).
Dans un cluster régional, l'option --num-nodes s'applique par zone (par exemple, la définition de l'option --num-nodes=2 sur trois zones crée six nœuds au total). Pour placer le pool de nœuds ate-system-infra-pool dans des zones spécifiques, ajoutez l'option --node-locations.
Si vous activez le paramètre cordonSystemInfraComponents lors de l'installation et que l'un des pools de nœuds est manquant, les pods système correspondants restent à l'état Pending.
Automatiser le ciblage matériel à l'aide de ComputeClasses personnalisées
Les ComputeClasses personnalisées GKE vous permettent de définir des listes de séries de machines Compute Engine prioritaires pour vos nœuds WorkerPool et de basculer automatiquement vers des séries de machines secondaires si une zone rencontre une indisponibilité des ressources.
Sélectionner une série de machines Compute Engine par environnement d'exécution
Configurez une ComputeClass distincte pour chaque environnement d'exécution de bac à sable :
- Environnement d'exécution MicroVM (Cloud Hypervisor) : définissez le champ
enableNestedVirtualization: truedans vos priorités ComputeClass et ciblez les séries de machines Compute Engine x86 compatibles avec la virtualisation imbriquée (comme N4, C3, C4 ou N2), ou utilisez des types de machines Bare Metal x86, qui exécutent KVM de manière native et ne nécessitent pas le champenableNestedVirtualization. Les VM et séries de machines basées sur ARM répertoriées dans Restrictions de la virtualisation imbriquée ne sont pas compatibles. - Environnement d'exécution gVisor : ciblez les séries de machines Compute Engine x86 à usage général ou optimisées pour le calcul (telles que N4, C3, C4 ou N2) sans virtualisation imbriquée activée. Les séries de machines qui s'exécutent sur des microarchitectures de processeur mixtes (comme E2) et les VM Arm ne sont pas compatibles avec Agent Substrate sur GKE. Toutes les ressources WorkerPool sélectionnées par un ActorTemplate doivent partager la même architecture de processeur.
Pour une comparaison détaillée, consultez Sélectionner un environnement d'exécution de bac à sable.
Règles ComputeClass requises pour Agent Substrate
Lorsque vous créez une ComputeClass pour Agent Substrate sur des nœuds de calcul GKE, suivez ces règles :
- Utilisez des ComputeClasses basées sur des nœuds : n'utilisez pas la facturation basée sur les pods (le champ
podFamily), qui n'est pas compatible avec la virtualisation imbriquée. - Ne définissez pas le champ
nodePoolConfig.sandbox.type: microvm: ce paramètre active l'environnement d'exécution Kata pour GKE Sandbox sur les charges de travail basées sur des pods et applique un rejetsandbox.gke.io/runtime=microvmqui empêche la planification d'Agent Substrate sur les nœuds de calcul GKE. Agent Substrate sur GKE gère son propre environnement d'exécution microVM et ne nécessite que la virtualisation imbriquée Compute Engine sur les nœuds Container-Optimized OS standards (type d'imagecos_containerd). Configurer les paramètres
sysctldu noyau Linux pour une densité de bac à sable élevée : si un nœud de calcul exécute plus d'environ 800 bacs à sable simultanés, vous devez augmenter les limites du noyau Linux pour la surveillance du système de fichiers (paramètresfs.inotify.*) et pour la table de voisinage ARP (Address Resolution Protocol) (paramètresnet.ipv4.neigh.default.gc_thresh*). Le programme d'installation n'applique ces paramètres qu'aux clusters qu'il crée. Lorsque vous configurez des ComputeClasses personnalisées (à l'aide du champpriorityDefaults.nodeSystemConfig.linuxNodeConfig.sysctls) ou que vous précréez des pools de nœuds de calcul (à l'aide de l'option--system-config-from-file), appliquez vous-même les valeurssysctlsuivantes :fs.inotify.max_user_instances:65536fs.inotify.max_user_watches:1048576net.ipv4.neigh.default.gc_thresh1:4096net.ipv4.neigh.default.gc_thresh2:16384net.ipv4.neigh.default.gc_thresh3:32768
Pour en savoir plus sur la configuration des paramètres
sysctldes nœuds, consultez Options de configuration Sysctl.
Choisir un modèle de scaling à la hausse pour les ressources WorkerPool de microVM
Les pods de nœuds de calcul MicroVM demandent la ressource étendue ate.dev/kvm: 1, qui est annoncée par le plug-in d'appareil atelet uniquement après le démarrage d'un nœud et le démarrage de l'agent atelet. Étant donné que le provisionnement automatique des nœuds GKE ne voit pas la ressource étendue ate.dev/kvm sur les modèles de nœuds non provisionnés, un pod de nœud de calcul microVM en attente ne peut pas déclencher la création automatique d'un nouveau pool de nœuds à partir de zéro instance répliquée par GKE. Toutefois, si un pool de nœuds comporte déjà au moins un nœud en cours d'exécution, GKE peut effectuer un scaling à la hausse de ce pool de nœuds.
Le tableau suivant compare les modèles compatibles pour le scaling des ressources WorkerPool de microVM sur GKE :
| Modèle | Fonctionnement | Scaling à zéro instance ? | Création de remplacement multipriorité en cas d'indisponibilité des ressources ? | Utilisation optimale |
|---|---|---|---|---|
Pools créés automatiquement avec le champ minimumCapacity
|
Définit les champs nodePoolAutoCreation.enabled: true et minimumCapacity.targetNodeCount: 1 avec des priorités machineType explicites.
|
Non (maintient un nœud chaud en cours d'exécution) |
Uniquement lors du provisionnement initial pour le champ minimumCapacity au niveau de la classe ; le basculement en cours de burst nécessite de définir le champ minimumCapacity.targetNodeCount: 1 sur chaque entrée de remplacement dans le champ spec.priorities[] (en conservant un nœud chaud par priorité)
|
Vous souhaitez automatiser la création de pools de nœuds et toujours conserver au moins un nœud de calcul en cours d'exécution. |
| Pools créés automatiquement avec des tampons de capacité |
Combine le champ nodePoolAutoCreation.enabled: true avec un CapacityBuffer actif ou en veille dont le PodTemplate omet la ressource étendue ate.dev/kvm.
|
Suspension en mode veille (par exemple, environ 8 % du coût de calcul d'exécution sur un nœud c3-standard-4 avec un disque de démarrage de 100 Gio par défaut)
|
Oui (les espaces réservés de tampon déclenchent le remplacement du provisionnement automatique des nœuds entre les priorités) | Vous souhaitez un scaling en rafale rapide (1 à 4 secondes d'activité, ou 20 à 35 secondes pour reprendre les nœuds de secours et 50 à 85 secondes jusqu'à ce que les nouveaux nœuds de calcul soient prêts) avec un faible coût d'inactivité. |
| Pools de nœuds précréés avec zéro nœud et des étiquettes de modèle de nœud |
Précrée des pools de nœuds avec autoscaling à zéro nœud avec l'étiquette clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 et les référence dans le champ spec.priorities[].nodepools de la classe ComputeClass.
|
Oui (0 nœud réel, aucun coût de calcul inactif) | Oui, sur les pools de nœuds précréés | Vous souhaitez un véritable scaling à zéro instance sans maintenir de tampons de capacité de secours. |
Exemple : ComputeClass avec le champ minimumCapacity
Lorsque vous utilisez le champ minimumCapacity, chaque entrée du champ spec.priorities doit spécifier un champ machineType explicite au lieu de spécifier uniquement le champ 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
Pour cibler un WorkerPool sur cette ComputeClass, ajoutez le champ nodeSelector:
{cloud.google.com/compute-class: substrate-microvm} au modèle de pod WorkerPool.
Lorsqu'une classe ComputeClass bascule entre différentes séries de machines x86 (par exemple, de N4 à C3 ou N2), la restauration d'un instantané durable avec fidélité de la mémoire (mode SNAPSHOT_FIDELITY_MEMORY) nécessite un nœud de calcul dont les fonctionnalités de processeur sont un sur-ensemble des fonctionnalités de processeur de l'instantané. Si aucun nœud de calcul compatible n'a de capacité, Agent Substrate rétrograde la restauration vers la fidélité du système de fichiers racine (mode SNAPSHOT_FIDELITY_ROOTFS), ce qui préserve le système de fichiers racine et les données de volume durables tout en redémarrant les processus de l'acteur.
Exemple : Effectuer un scaling à partir de zéro avec des pools de nœuds précréés à zéro nœud
Enregistrez les paramètres
sysctldu noyau Linux haute densité dans un fichiersystem-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'Précréez vos pools de nœuds de virtualisation imbriquée principaux et de remplacement à zéro nœud avec l'option
--system-config-from-file=system-config.yamlet l'étiquetteclusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096afin que l'autoscaler de cluster GKE sache que le pool vide fournit la ressource étendueate.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:NoScheduleRemplacez les éléments suivants :
CLUSTER_NAME: nom de votre cluster GKE Standard.LOCATION: zone ou région Compute Engine de votre cluster. L'utilisation des options--total-min-nodeset--total-max-nodesdéfinit les limites d'autoscaling sur l'ensemble du pool de nœuds plutôt que par zone.
Référencez les pools précréés par ordre de priorité dans votre 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: DoNotScaleUpLe champ
priorityDefaultsne s'applique pas aux priorités qui utilisent le champnodepools, car les paramètres de nœud proviennent des pools de nœuds précréés. Comme pour les priorités de remplacement créées automatiquement, la reprise d'un acteur sur une série de machines de remplacement dont les fonctionnalités de processeur ne sont pas un sur-ensemble des fonctionnalités de processeur de l'instantané rétrograde la restauration en modeSNAPSHOT_FIDELITY_ROOTFSet redémarre les processus de l'acteur.
Pour en savoir plus sur la configuration de ComputeClass, consultez Contrôler les attributs des nœuds soumis à l'autoscaling avec des ComputeClasses personnalisées.
Configurer des tampons de capacité pour le scaling en mode rafale de WorkerPool
Lorsqu'un pic de trafic d'acteur dépasse la capacité de vos pods WorkerPool en cours d'exécution, les nouveaux pods de nœud de calcul doivent attendre le provisionnement des nœuds Compute Engine, l'initialisation de l'agent atelet et le préchauffage des éléments du bac à sable avant de pouvoir diffuser des acteurs. Les tampons de capacité GKE déplacent le provisionnement des nœuds et le préchauffage des éléments atelet hors du chemin critique :
- Tampons de capacité actifs (stratégie
buffer.x-k8s.io/active-capacity) : maintiennent les nœuds préprovisionnés en cours d'exécution et prêts, de sorte que les nouveaux pods de nœuds de calcul soient planifiés en une à quatre secondes, au coût d'exécution total de la VM Compute Engine. - Tampons de capacité de secours (stratégie
buffer.gke.io/standby-capacity) : provisionnez des nœuds et laissez l'agentateletinitialiser et préchauffer les ressources de bac à sable (le binairerunscou les images Cloud Hypervisor et Kata) sur le disque pendant la fenêtre d'initialisation de secours avant que GKE ne suspende les VM Compute Engine. Cette fenêtre est définie par défaut sur cinq minutes (5m) et est configurée par l'annotationbuffer.gke.io/standby-capacity-init-timesur CapacityBuffer. Augmentez la valeur de cette annotation si le préchauffage des éléments prend plus de cinq minutes. Lorsqu'un burst se produit, GKE réactive les nœuds suspendus en 20 à 35 secondes environ, et la préparation de bout en bout du WorkerPool (planification des pods de nœuds de calcul, émission de certificats de pods et enregistrement de la capacité auprès du composantate-api-server) se termine en 50 à 85 secondes environ. Lorsqu'elle est suspendue, vous ne payez que pour la mémoire de la VM suspendue et le stockage du disque de démarrage. Par exemple, le stockage suspendu coûte environ 8 % du coût de calcul d'un nœudc3-standard-4en cours d'exécution avec un disque de démarragehyperdisk-balancedde 100 Gio par défaut. Le pourcentage exact varie en fonction de la forme de la machine, de la taille du disque de démarrage et des IOPS ou du débit provisionnés.
Pour en savoir plus sur les stratégies de mise en mémoire tampon, consultez Stratégies pour réduire la latence de démarrage.
Limites et règles concernant les tampons de capacité
Lorsque vous configurez des tampons de capacité pour Agent Substrate sur GKE, appliquez les règles suivantes :
- Restrictions de configuration de machine Compute Engine pour les tampons de secours : la suspension d'instance Compute Engine n'est pas compatible avec les VM auxquelles des disques SSD locaux sont associés, ni avec les configurations de machine disposant de plus de 208 Go de mémoire (comme le type de machine
c3-highmem-88ou les configurations Bare Metal). Pour les formes de nœuds de calcul volumineuses ou les nœuds avec des disques SSD locaux, utilisez des tampons de capacité actifs plutôt que des tampons de secours. - Évitez de faire pointer le champ
scalableRefvers un WorkerPool ou un déploiement de microVM sans instance répliquée :- Le contrôleur GKE CapacityBuffer ne peut pas résoudre une ressource personnalisée (
kind: WorkerPool) lorsque le pool est mis à l'échelle sur zéro instance répliquée. - Pour les ressources WorkerPool microVM, ne faites pas non plus pointer le champ
scalableRefvers le déploiement sous-jacent, car le modèle de pod de déploiement inclut la ressource étendueate.dev/kvm: 1(ce qui empêche le provisionnement automatique des nœuds d'effectuer un scaling horizontal d'un pool vide). Configurez plutôt les tampons en référençant un PodTemplate (dans le champpodTemplateRef) qui sélectionne la ComputeClass sans demander la ressource étendueate.dev/kvm. - Pour les ressources WorkerPool gVisor (qui ne demandent pas la ressource étendue
ate.dev/kvm), vous pouvez pointer le champscalableRefdirectement vers le déploiement sous-jacent du WorkerPool ou utiliser un PodTemplate.
- Le contrôleur GKE CapacityBuffer ne peut pas résoudre une ressource personnalisée (
Exemple : CapacityBuffer de secours utilisant un PodTemplate
Le fichier manifeste suivant définit un PodTemplate et un CapacityBuffer de secours qui fonctionnent pour les ressources de pool de nœuds de calcul microVM ou 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
Remplacez les éléments suivants :
WORKERPOOL_NAMESPACE: espace de noms Kubernetes de votre WorkerPool (par exemple,my-workerpool).COMPUTE_CLASS_NAME: nom de la ComputeClass personnalisée ciblée par votre WorkerPool (par exemple,substrate-microvm).WORKER_CPU_REQUESTetWORKER_MEMORY_REQUEST: demandes de processeur et de mémoire d'un seul pod de nœud de calcul dans votre WorkerPool (par exemple,2processeurs et4Gide mémoire sur un nœud à 4 vCPU), en laissant de la capacité de nœud pour l'agentateletet les daemons système GKE. En faisant correspondre ces valeurs aux requêtes d'un pod de nœud de calcul, vous vous assurez que chaque instance répliquée de tampon provisionne un nœud de calcul de secours plutôt que de regrouper plusieurs espaces réservés de tampon sur un seul nœud.BUFFER_REPLICAS: nombre de nœuds de calcul de secours à préchauffer (par exemple,4nœuds).
Lorsque vous utilisez des tampons de capacité de secours, ajoutez une tolérance pour le rejet buffer.gke.io/standby-capacity-node-suspended (avec le champ operator:
"Exists") au DaemonSet atelet afin que les pods atelet de remplacement puissent rester programmés sur les nœuds de secours suspendus (par exemple, lors d'une mise à jour progressive du DaemonSet). Pour obtenir un exemple de configuration de DaemonSet, consultez Précharger des images sur des tampons de secours.
Si plusieurs charges de travail partagent la même ComputeClass, ajoutez des tolérances de séparation des charges de travail et des libellés nodeSelector correspondants à votre modèle de pod WorkerPool et au PodTemplate de tampon afin que GKE provisionne des nœuds dédiés avec rejets que les autres charges de travail ne revendiquent pas. Ajoutez également une tolérance correspondante au DaemonSet atelet afin que l'agent atelet puisse planifier sur ces nœuds dédiés. Pour obtenir des instructions détaillées, consultez Configurer des tampons de capacité.
Gérer les interactions entre les mises à niveau et l'autoscaler
Cette section explique comment gérer les mises à jour du DaemonSet atelet, les événements de scaling à la baisse de l'autoscaler de cluster et les mises à niveau de nœuds sans perturber les acteurs actifs.
Mettre à jour le DaemonSet atelet avec des tampons de secours
Les nœuds de tampon de secours suspendus portent le rejet buffer.gke.io/standby-capacity-node-suspended et un rejet inaccessible lorsqu'ils sont suspendus. Par conséquent, l'agent kubelet sur un nœud suspendu ne peut pas accuser réception des suppressions de pods. Assurez-vous que le DaemonSet atelet tolère le rejet buffer.gke.io/standby-capacity-node-suspended (avec le champ operator:
"Exists"). Même avec cette tolérance, lors d'une mise à jour progressive standard du DaemonSet atelet (avec le champ maxUnavailable: 1), les pods des nœuds suspendus passent à l'état Terminating et peuvent bloquer la progression de la mise à jour sur les nœuds en cours d'exécution.
Avant de mettre à jour le DaemonSet atelet sur un cluster avec des nœuds de secours suspendus, effectuez l'une des opérations suivantes :
- Pour que les nœuds de secours inaccessibles n'épuisent pas le budget de mise à jour, définissez le champ
spec.updateStrategy.rollingUpdate.maxUnavailablesur le DaemonSetateletsur une valeur supérieure au nombre maximal de nœuds de secours suspendus. Avant de mettre à jour le DaemonSet
atelet, effectuez un scaling temporaire de vos instances répliquées CapacityBuffer de secours sur0et attendez que l'autoscaler de cluster supprime tous les nœuds de tampon de secours suspendus (généralement 10 à 15 minutes). Pour vérifier si des nœuds signalent toujours un état de conditionSuspendeddeTrue, exécutez la commande suivante :kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'
Protéger les acteurs actifs lors de la réduction de la capacité et des mises à niveau
Étant donné que les acteurs actifs s'exécutent dans des bacs à sable gérés par l'agent atelet plutôt que sous forme de pods Kubernetes individuels, les demandes de processeur et de mémoire d'un nœud peuvent sembler faibles pour l'autoscaler de cluster GKE, même si un pod de nœud de calcul sur ce nœud héberge des acteurs actifs. Lorsqu'un nœud est drainé, l'agent kubelet envoie un signal SIGTERM au pod de nœud de calcul, et le nœud de calcul transmet le signal SIGTERM au processus principal de chaque conteneur de chaque acteur qu'il héberge. Chaque acteur actif dispose ensuite de 30 minutes maximum pour être suspendu avant l'arrêt du nœud de calcul. Attribuez à chaque acteur avec état un gestionnaire SIGTERM qui ne se ferme pas sur le signal et qui appelle la méthode SuspendActor avec le mode DURABILITY_MODE_SYNCHRONOUS. Un acteur dont le processus principal se termine sur le signal SIGTERM perd immédiatement l'état non enregistré. Si le pod de nœud de calcul s'arrête alors qu'il héberge toujours un acteur actif, l'acteur passe à l'état ACTOR_STATE_CRASHED.
Pour minimiser les perturbations lors des événements de scaling à la baisse et des mises à niveau de clusters GKE, appliquez les pratiques suivantes :
- Évitez d'utiliser des VM Spot pour les nœuds WorkerPool avec état, car la préemption des VM Spot ne fournit qu'un préavis d'arrêt de 15 secondes à 2 minutes avant d'arrêter le nœud.
- Coordonnez le drainage dans votre orchestrateur afin que les acteurs actifs soient soumis à un point de contrôle et suspendus avant l'arrêt des pods de nœuds de calcul, ou empêchez l'autoscaler de cluster d'évincer les pods de nœuds de calcul actifs (par exemple, en utilisant l'annotation de pod
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"). Si vous définissez l'annotationsafe-to-evict: "false"de manière statique dans le modèle de pod WorkerPool, l'autoscaler de cluster ne réduit pas la capacité d'un nœud lorsqu'un pod de nœud de calcul est planifié sur celui-ci, même si ce nœud de calcul n'héberge aucun acteur actif. Pour libérer les nœuds inactifs, vous devez effectuer un scaling à la baisse des instances répliquées WorkerPool ou gérer l'annotation de manière dynamique. Pour en savoir plus sur le cycle de vie de l'éviction des nœuds de calcul et la récupération des acteurs plantés avec la méthodeRevertActor, consultez Éviction dans le guide de l'API Agent Substrate. - Configurez les mises à niveau de la surutilisation GKE et consultez la section Mettre à niveau dans un environnement aux ressources limitées afin que les nouveaux nœuds de calcul soient provisionnés avant que les nœuds de calcul existants ne soient isolés et vidés.
Étapes suivantes
- Découvrez comment choisir le modèle d'orchestration, l'environnement d'exécution de bac à sable, les contrôles d'isolation et les options de stockage appropriés dans Planifier une architecture pour les charges de travail d'agents IA sur GKE.
- Apprenez-en plus sur les ComputeClasses personnalisées GKE et les tampons de capacité GKE.
- Découvrez d'autres ressources dans le dépôt GitHub Agent Substrate.