Vos pods restent bloqués en Pending parce que le cluster manque de capacité.
Karpenter détecte ces pods en attente et déclenche le provisionnement en
quelques secondes — mais le temps jusqu’à un nœud Ready dépend du provider
cloud, du bootstrap (OS, runtime, CNI) et des pulls d’images. En pratique,
comptez 1 à 4 minutes selon votre environnement.
Les nœuds sont dimensionnés exactement pour vos pods et disparaissent automatiquement quand ils ne servent plus. Ce guide vous donne le modèle mental pour comprendre comment Karpenter fonctionne, son architecture interne, et pourquoi il surpasse les autoscalers traditionnels.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre les ressources clés : NodePool, NodeClass, NodeClaim, NodeOverlay
- Maîtriser la Disruption : consolidation, drift, expiration, budgets
- Comprendre le Scheduling : comment Karpenter simule et sélectionne les instances
- Visualiser l’architecture interne de Karpenter et le rôle de chaque contrôleur
- Distinguer ce que fait Karpenter vs ce que fait kube-scheduler
- Comparer Karpenter avec Cluster Autoscaler pour choisir le bon outil
Le problème que Karpenter résout
Section intitulée « Le problème que Karpenter résout »Dans un cluster Kubernetes traditionnel, l’autoscaling des nœuds repose sur le Cluster Autoscaler. Ce dernier ajuste le nombre de nœuds au sein de groupes de nœuds (Node Groups ou Auto Scaling Groups). Cette approche présente plusieurs limitations :
| Limitation | Impact |
|---|---|
| Rigidité | Vous devez créer et maintenir de nombreux groupes de nœuds pour différents types d’instances |
| Lenteur | L’ajout d’un nœud peut prendre plusieurs minutes (négociation avec ASG, attente de scaling) |
| Inefficacité | La sélection du type d’instance est limitée au groupe, pas optimisée pour le pod |
| Complexité | Gérer des centaines de groupes devient vite ingérable |
Karpenter élimine ces contraintes en provisionnant directement les instances sans passer par des groupes intermédiaires. Il analyse les pods en attente, détermine le type d’instance optimal parmi tous ceux disponibles, et crée immédiatement la capacité nécessaire.
Quand utiliser Karpenter
Section intitulée « Quand utiliser Karpenter »Karpenter brille quand :
- Vos workloads ont des besoins variés (architectures, types d’instances, spot/on-demand)
- Vous voulez une consolidation automatique des nœuds sous-utilisés
- La réactivité compte (pods schedulés en secondes, pas en minutes)
- Vous déployez sur un cloud avec un provider Karpenter disponible
Providers disponibles
Section intitulée « Providers disponibles »Karpenter est conçu pour être extensible. Plusieurs providers existent :
| Provider | Maintenu par | Maturité | NodeClass | Repo |
|---|---|---|---|---|
| AWS | AWS | ✅ Production | EC2NodeClass | aws/karpenter-provider-aws |
| Azure/AKS | Microsoft | ✅ Production | AKSNodeClass | Azure/karpenter-provider-azure |
| GCP/GKE | CloudPilot AI | 🔶 Preview | GCPNodeClass | cloudpilot-ai/karpenter-provider-gcp |
| Alibaba Cloud | CloudPilot AI | 🔶 Preview | ECSNodeClass | cloudpilot-ai/karpenter-provider-alibabacloud |
Les trois ressources fondamentales
Section intitulée « Les trois ressources fondamentales »Karpenter utilise trois Custom Resource Definitions (CRDs) qui travaillent ensemble. Comprendre leur rôle est essentiel pour configurer et dépanner Karpenter.
NodeClass : la configuration cloud
Section intitulée « NodeClass : la configuration cloud »La NodeClass répond à la question : “Comment créer un nœud chez mon provider ?”
Chaque provider cloud a sa propre NodeClass (EC2NodeClass pour AWS,
AKSNodeClass pour Azure. Elle contient :
- Image machine : AMI sur AWS, ca serait OMI sur Outscale
- Réseau : subnets, security groups
- IAM/Credentials : rôle pour le nœud
- User-data : script d’initialisation
apiVersion: karpenter.k8s.aws/v1kind: EC2NodeClassmetadata: name: defaultspec: role: "KarpenterNodeRole-my-cluster" amiSelectorTerms: - alias: al2023@latest subnetSelectorTerms: - tags: karpenter.sh/discovery: "my-cluster" securityGroupSelectorTerms: - tags: karpenter.sh/discovery: "my-cluster"NodePool : les contraintes de provisionnement
Section intitulée « NodePool : les contraintes de provisionnement »Le NodePool répond à la question : “Quels types de nœuds Karpenter peut-il créer ?”
Il définit :
- Requirements : architectures autorisées, types d’instances, zones de disponibilité
- Taints : restrictions sur les pods pouvant être schedulés
- Limites : capacité maximale du pool (CPU, mémoire)
- Disruption : comment et quand Karpenter peut supprimer des nœuds
apiVersion: karpenter.sh/v1kind: NodePoolmetadata: name: defaultspec: template: spec: nodeClassRef: group: karpenter.k8s.aws # ou karpenter.outscale.com, etc. kind: EC2NodeClass name: default requirements: - key: kubernetes.io/arch operator: In values: ["amd64"] - key: karpenter.sh/capacity-type operator: In values: ["spot", "on-demand"] limits: cpu: 100 memory: 200Gi disruption: consolidationPolicy: WhenEmptyOrUnderutilized consolidateAfter: 5mNodeClaim : la décision de provisionnement
Section intitulée « NodeClaim : la décision de provisionnement »Le NodeClaim est une ressource interne créée automatiquement par Karpenter. Il représente une “demande de nœud” avec des spécifications précises. Vous ne créez jamais de NodeClaim manuellement.
Un NodeClaim contient :
- Le type d’instance choisi
- La zone de disponibilité
- Le providerID (identifiant cloud de l’instance)
- Les conditions de progression (Launched, Registered, Initialized, Ready)
# Exemple de NodeClaim créé automatiquementapiVersion: karpenter.sh/v1kind: NodeClaimmetadata: name: default-abc123 labels: karpenter.sh/nodepool: defaultspec: requirements: - key: topology.kubernetes.io/zone operator: In values: ["eu-west-2a"] - key: node.kubernetes.io/instance-type operator: In values: ["m5.large"]status: providerID: aws:///eu-west-2a/i-0123456789abcdef0 conditions: - type: Ready status: "True"Architecture interne de Karpenter
Section intitulée « Architecture interne de Karpenter »Karpenter se compose de plusieurs contrôleurs qui travaillent ensemble pour gérer le cycle de vie complet des nœuds.
Provisioner Controller
Section intitulée « Provisioner Controller »Le Provisioner Controller est le cœur du provisionnement. Il surveille en
permanence les pods marqués comme Unschedulable par kube-scheduler et décide
quels nœuds créer.
Flux de travail :
- Observation : écoute les événements pods via l’API Kubernetes
- Batching : regroupe les pods pending pendant ~10 secondes max
(configurable via
--batch-max-duration) - Simulation : simule le scheduling pour déterminer les NodeClaims nécessaires
- Création : crée les ressources NodeClaim correspondantes
Le batching est crucial : au lieu de créer un nœud par pod, Karpenter attend jusqu’à 10 secondes (1s idle par défaut) pour regrouper plusieurs pods sur le même nœud si possible.
Disruption Controller
Section intitulée « Disruption Controller »Le Disruption Controller optimise le cluster en identifiant les nœuds à supprimer ou remplacer. Il opère selon un ordre de priorité :
- Drift : nœuds dont la configuration ne correspond plus au NodePool
- Consolidation : nœuds vides ou sous-utilisés
- Expiration : nœuds ayant dépassé leur durée de vie (
expireAfter)
Types de consolidation :
| Type | Description |
|---|---|
| Empty | Supprime les nœuds sans pods applicatifs (en parallèle) |
| Multi-Node | Migre les pods de plusieurs nœuds vers moins de nœuds |
| Single-Node | Remplace un nœud par un type d’instance moins cher |
Garbage Collection Controller
Section intitulée « Garbage Collection Controller »Le Garbage Collection Controller vérifie périodiquement (~30 secondes) que
chaque NodeClaim correspond à une VM réelle dans le cloud en appelant
CloudProvider.List().
Fonctionnement :
- Appelle
List()qui retourne toutes les VMs gérées par Karpenter - Compare cette liste avec les NodeClaims existants
- Si un NodeClaim n’a pas de VM correspondante → suppression immédiate
Termination Controller
Section intitulée « Termination Controller »Quand un nœud doit être supprimé, le Termination Controller gère la séquence de shutdown gracieux :
- Taint : ajoute
karpenter.sh/disrupted:NoSchedulepour empêcher de nouveaux pods - Drain : évince les pods via l’API Eviction (respecte les PDBs)
- Cleanup : attend que les VolumeAttachments soient supprimés
- Delete : appelle le cloud provider pour terminer l’instance
- Finalize : retire le finalizer pour permettre la suppression de l’objet Node
Qui fait quoi : Karpenter vs kube-scheduler
Section intitulée « Qui fait quoi : Karpenter vs kube-scheduler »Point critique : Karpenter provisionne des nœuds, mais c’est kube-scheduler qui schedule les pods dessus.
-
Un pod est créé → kube-scheduler le marque
Unschedulable(pas de nœud disponible) -
Karpenter observe ce pod Pending et analyse ses contraintes
-
Karpenter crée un NodeClaim → l’API cloud provisionne l’instance
-
Le kubelet s’enregistre → le node rejoint le cluster
-
kube-scheduler (pas Karpenter) schedule le pod sur le nouveau nœud
Cycle de vie d’un NodeClaim
Section intitulée « Cycle de vie d’un NodeClaim »Comprendre les phases d’un NodeClaim est essentiel pour le debugging.
| Phase | Condition | Que se passe-t-il ? |
|---|---|---|
| Created | — | Karpenter a détecté des pods pending et créé un objet NodeClaim |
| Launched | Launched=True | Le provider cloud a créé la VM (instance ID connu) |
| Registered | Registered=True | Le kubelet s’est connecté et Karpenter a lié le Node au NodeClaim |
| Initialized | Initialized=True | Le nœud est Ready au sens Kubernetes (CNI, runtime, DaemonSets critiques) |
| Ready | Ready=True | Les taints d’initialisation sont retirées, les pods applicatifs peuvent être schedulés |
Disruption : optimiser et maintenir le cluster
Section intitulée « Disruption : optimiser et maintenir le cluster »La Disruption est le mécanisme par lequel Karpenter supprime ou remplace des nœuds. Elle se divise en deux catégories : les méthodes graceful (respectent les budgets) et les méthodes forceful (drainent immédiatement).
Méthodes graceful (rate-limitées par budgets)
Section intitulée « Méthodes graceful (rate-limitées par budgets) »| Méthode | Déclencheur | Description |
|---|---|---|
| Drift | NodePool/NodeClass modifiés | Remplace les nœuds dont la config ne correspond plus |
| Consolidation | Sous-utilisation | Réduit les coûts en fusionnant les workloads |
Consolidation
Section intitulée « Consolidation »La consolidation s’exécute selon trois stratégies (dans cet ordre) :
- Empty Node — Supprime les nœuds vides en parallèle
- Multi-Node — Migre les pods de N nœuds vers moins de nœuds
- Single-Node — Remplace un nœud par un type moins cher
apiVersion: karpenter.sh/v1kind: NodePoolspec: disruption: consolidationPolicy: WhenEmptyOrUnderutilized # ou WhenEmpty consolidateAfter: 5m # attendre 5 min avant de considérer le nœudKarpenter détecte automatiquement si un NodeClaim ne correspond plus à son NodePool ou NodeClass :
- NodePool : changements dans
spec.template.spec.requirements - NodeClass : changements dans
amiSelectorTerms,subnetSelectorTerms,securityGroupSelectorTerms
Les nœuds driftés sont remplacés progressivement selon les budgets.
Méthodes forceful (non rate-limitées)
Section intitulée « Méthodes forceful (non rate-limitées) »| Méthode | Déclencheur | Description |
|---|---|---|
| Expiration | expireAfter atteint | Force le remplacement après une durée max |
| Interruption | Spot interruption, maintenance AWS | Évacuation préventive avant interruption cloud |
| Node Auto Repair | Node unhealthy > 30 min | Remplace les nœuds défectueux (alpha) |
apiVersion: karpenter.sh/v1kind: NodePoolspec: template: spec: expireAfter: 720h # 30 jours max terminationGracePeriod: 1h # temps max pour drainerDisruption Budgets
Section intitulée « Disruption Budgets »Limitez le nombre de nœuds perturbés simultanément :
apiVersion: karpenter.sh/v1kind: NodePoolspec: disruption: consolidationPolicy: WhenEmptyOrUnderutilized budgets: - nodes: "20%" # max 20% des nœuds en disruption reasons: ["Drifted", "Empty"] - nodes: "5" # plafond absolu - nodes: "0" # bloquer pendant maintenance schedule: "@daily" duration: 30m reasons: ["Underutilized"]Contrôles au niveau pod/nœud
Section intitulée « Contrôles au niveau pod/nœud »| Annotation | Effet |
|---|---|
karpenter.sh/do-not-disrupt: "true" sur pod | Bloque la disruption volontaire du nœud |
karpenter.sh/do-not-disrupt: "true" sur node | Bloque toute disruption volontaire |
Scheduling : sélection des instances
Section intitulée « Scheduling : sélection des instances »Quand Karpenter doit créer un nœud, il simule le scheduling pour choisir le type d’instance optimal.
Processus de sélection
Section intitulée « Processus de sélection »- Filtrage — Élimine les types incompatibles avec les requirements
- Simulation — Calcule combien de pods pending tiennent sur chaque type
- Scoring — Choisit le type le moins cher qui satisfait les contraintes
- Batching — Regroupe les pods pendant ~10s max (configurable)
Requirements et Well-Known Labels
Section intitulée « Requirements et Well-Known Labels »Les requirements dans le NodePool filtrent les types d’instances disponibles :
| Label | Description | Exemple |
|---|---|---|
kubernetes.io/arch | Architecture CPU | amd64, arm64 |
kubernetes.io/os | Système d’exploitation | linux, windows |
node.kubernetes.io/instance-type | Type exact | m5.large, c6i.xlarge |
topology.kubernetes.io/zone | Zone de disponibilité | eu-west-1a |
karpenter.sh/capacity-type | Spot ou On-Demand | spot, on-demand |
Priorité des pools (weight)
Section intitulée « Priorité des pools (weight) »Quand plusieurs NodePools peuvent satisfaire un pod, Karpenter utilise le weight :
apiVersion: karpenter.sh/v1kind: NodePoolmetadata: name: spot-poolspec: weight: 100 # Priorité haute → essayé en premier template: spec: requirements: - key: karpenter.sh/capacity-type operator: In values: ["spot"]---apiVersion: karpenter.sh/v1kind: NodePoolmetadata: name: on-demand-fallbackspec: weight: 10 # Priorité basse → fallback template: spec: requirements: - key: karpenter.sh/capacity-type operator: In values: ["on-demand"]NodeOverlay : ajuster prix et capacités (alpha)
Section intitulée « NodeOverlay : ajuster prix et capacités (alpha) »Les NodeOverlays permettent de modifier les informations d’instances que Karpenter utilise pour ses décisions :
- Ajuster les prix pour refléter vos Savings Plans ou contrats
- Ajouter des extended resources non détectées automatiquement
Ajustement des prix
Section intitulée « Ajustement des prix »apiVersion: karpenter.sh/v1alpha1kind: NodeOverlaymetadata: name: savings-plan-discountspec: requirements: - key: node.kubernetes.io/instance-type operator: In values: ["m5.large", "m5.xlarge", "m5.2xlarge"] priceAdjustment: "-30%" # Réduction de 30% (Savings Plan)Ajout de capacités
Section intitulée « Ajout de capacités »apiVersion: karpenter.sh/v1alpha1kind: NodeOverlaymetadata: name: custom-devicesspec: requirements: - key: node.kubernetes.io/instance-type operator: In values: ["g4dn.xlarge"] capacity: smarter-devices/fuse: "1" custom-hardware/inference-unit: "4"Résolution des conflits
Section intitulée « Résolution des conflits »Quand plusieurs overlays matchent le même type d’instance :
- weight le plus élevé gagne
- À weight égal, ordre alphabétique
- Les capacity sont fusionnées (pas de conflit)
| Champ | Comportement |
|---|---|
price / priceAdjustment | Le overlay avec le plus haut weight gagne |
capacity | Fusionné entre tous les overlays |
Ce qu’il faut retenir
Section intitulée « Ce qu’il faut retenir »- Karpenter provisionne, kube-scheduler schedule — ne confondez pas les rôles
- NodePool = contraintes (types, arch, limits) ; NodeClass = config cloud (AMI, réseau, IAM)
nodeClassRefcomplet :group,kind,name— les trois sont obligatoires- Toujours définir des
limits— sinon Karpenter peut créer des centaines de nœuds - 4 contrôleurs : Provisioner, Disruption, Termination, Garbage Collection
- Le GC Controller est critique — une erreur dans
List()supprime tous vos nœuds - Disruption graceful (consolidation, drift) respecte les budgets ; forceful (expiration, interruption) non
- NodeOverlay (alpha) permet d’ajuster prix et capacités pour la simulation
D’autres ressources
Section intitulée « D’autres ressources »Ressources
Section intitulée « Ressources »- Documentation officielle Karpenter — Référence complète
- Getting Started AWS — Guide d’installation AWS
- Concepts NodePools — Configuration détaillée
- Disruption — Consolidation, drift, expiration
- FAQ / Compatibility — Matrice de compatibilité Kubernetes
- CloudProvider Interface — API Go v1.9.0