Maîtrisez l'optimisation des exécuteurs Jenkins pour des builds plus rapides
Optimisez les performances de votre CI/CD en maîtrisant la configuration des exécuteurs Jenkins. Ce guide expert explique comment calculer le nombre optimal d'exécuteurs en fonction des contraintes CPU et E/S, réduisant les temps d'attente dans la file d'attente et maximisant le débit des agents. Découvrez des stratégies de configuration essentielles, notamment l'utilisation du parallélisme Pipeline, la gestion des agents statiques et dynamiques, et l'identification des goulots d'étranglement à l'aide de métriques clés comme la longueur de la file d'attente et l'attente E/S. Mettez en œuvre ces étapes concrètes pour obtenir des builds plus rapides et un environnement Jenkins plus efficace.
Maîtrisez l'optimisation des exécuteurs Jenkins pour des builds plus rapides
L'optimisation des exécuteurs Jenkins est en réalité une planification de capacité en petites pièces. Un exécuteur est un emplacement où Jenkins peut exécuter du travail sur un nœud. Ajoutez trop peu d'emplacements et les travaux attendent dans la file d'attente. Ajoutez-en trop et chaque build se bat pour le CPU, la mémoire, le disque, le réseau, et parfois le même cache de dépendances.
L'objectif n'est pas "plus d'exécuteurs." L'objectif est un temps de retour total plus court sans rendre les builds individuels peu fiables.
Gardez les exécuteurs du contrôleur à zéro
Pour la plupart des installations Jenkins modernes, le contrôleur doit planifier le travail, servir l'interface utilisateur, stocker la configuration des travaux et coordonner les agents. Il ne doit pas compiler de code ni exécuter de suites de tests.
Définissez les exécuteurs du contrôleur à 0 sauf si vous avez un petit travail administratif délibéré qui doit s'y exécuter. Un build chargé sur le contrôleur peut affamer l'interface utilisateur, retarder la planification de la file d'attente et rendre les problèmes de plugins plus difficiles à diagnostiquer. Si le contrôleur devient instable, chaque équipe utilisant Jenkins le ressent.
Déplacez le travail de build vers des agents avec des étiquettes claires :
linux && docker
linux && maven
windows && visualstudio
large-memory
Les étiquettes font partie de l'optimisation des exécuteurs car un travail attendant linux && docker ne se soucie pas que vous ayez des exécuteurs Windows inactifs.
Commencez par le type de charge de travail, pas par une formule universelle
Pour les builds à forte charge CPU, commencez près du nombre de cœurs CPU physiques ou virtuels. Une VM de build à 8 cœurs exécutant une compilation C++ ou de grandes suites de tests Java pourrait commencer avec 6 à 8 exécuteurs, puis descendre ou monter en fonction des mesures.
Pour les builds à forte charge E/S, vous pouvez exécuter plus d'exécuteurs que de cœurs CPU car les travaux passent du temps à attendre des téléchargements réseau, des téléchargements d'artefacts ou des services de test. Un agent à 8 cœurs avec beaucoup de dépendances pourrait bien gérer 10 à 12 exécuteurs. Il pourrait aussi s'effondrer à 6 si le disque est lent ou la mémoire insuffisante.
La mémoire fixe souvent la limite réelle. Si chaque build peut utiliser 2 Go de RAM et que l'agent a 16 Go, huit exécuteurs ne laissent aucune place pour le système d'exploitation, le démon Docker, les environnements d'exécution de langage, les tests de navigateur ou le cache du système de fichiers. Dans ce cas, quatre ou cinq exécuteurs peuvent être plus rapides que huit car la machine évite le swapping.
Utilisez une feuille de calcul comme celle-ci :
RAM de l'agent : 32 Go
réserve pour le système d'exploitation et les démons : 4 Go
utilisable pour les builds : 28 Go
pic typique d'un build : 3 Go
exécuteurs de départ : 8 ou 9, puis validez sous charge
Les chiffres n'ont pas besoin d'être parfaits. Ils doivent être suffisamment explicites pour que vous puissiez les ajuster après avoir observé des builds réels.
Surveillez les raisons de la file d'attente
La file d'attente de build Jenkins vous indique pourquoi le travail attend. "En attente du prochain exécuteur disponible" est différent de "Il n'y a aucun nœud avec l'étiquette." Le premier suggère une pression de capacité. Le second suggère un problème d'étiquette ou de provisionnement d'agent.
Lorsque les développeurs se plaignent que Jenkins est lent, vérifiez :
- Longueur de la file d'attente par étiquette.
- Temps d'attente moyen dans la file d'attente.
- Rotation des agents en ligne/hors ligne.
- Builds bloqués en attente de ressources verrouillées.
- Étapes de pipeline parallèles consommant plus d'exécuteurs que prévu.
Un seul pipeline avec dix branches parallèles peut consommer dix emplacements d'exécuteurs. Cela peut être exactement ce que vous voulez pour une matrice de tests. Cela peut aussi affamer tous les autres travaux sur une petite installation Jenkins.
Utilisez un exécuteur par agent jetable
Pour les agents Kubernetes et de nombreux agents créés dans le cloud, un exécuteur par pod ou instance est généralement le modèle le plus propre. Le pod est l'unité d'isolation. Si vous avez besoin de plus de concurrence, créez plus de pods au lieu de regrouper des builds non liés dans le même espace de travail jetable.
Ce modèle rend les demandes de ressources importantes :
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
memory: "6Gi"
Si les demandes sont trop faibles, Kubernetes peut regrouper trop d'agents Jenkins sur un seul nœud. Jenkins voit des exécuteurs disponibles, mais le nœud du cluster est surchargé. Si les limites sont trop strictes, les builds échouent avec des erreurs mémoire qui ressemblent à des problèmes d'application.
Pour les agents VM statiques, plusieurs exécuteurs peuvent convenir. Assurez-vous simplement que la disposition de l'espace de travail, les répertoires de cache et les installations d'outils sont conçus pour des travaux simultanés.
Limitez les travaux bruyants
Certains travaux ne doivent pas exécuter autant de copies que Jenkins peut en planifier. Les tests d'intégration de base de données, les tests de navigateur, les tests de charge et les builds d'image peuvent rapidement saturer les systèmes partagés.
Utilisez la limitation au niveau du travail, les ressources verrouillables ou les contrôles de pipeline :
pipeline {
agent { label 'linux && docker' }
options {
disableConcurrentBuilds()
}
stages {
stage('Build Image') {
steps {
sh 'docker build -t app:${BUILD_NUMBER} .'
}
}
}
}
Pour une base de données de staging partagée, un verrou est plus clair :
lock('staging-db') {
sh './run-integration-tests.sh'
}
Cela peut faire attendre un travail, mais cela empêche cinq travaux d'échouer ensemble et de gaspiller tout leur temps d'exécuteur.
Mesurez l'agent, pas seulement Jenkins
Jenkins peut vous renseigner sur le temps de file d'attente et l'utilisation des exécuteurs. Le système d'exploitation vous indique si le nombre d'exécuteurs est raisonnable.
Sur les agents Linux, vérifiez :
uptime
mpstat 1
iostat -xz 1
free -h
df -h
docker system df
Un CPU élevé avec une faible attente E/S signifie un travail lié au CPU. Une attente E/S élevée signifie que l'ajout d'exécuteurs ralentira probablement les builds. L'utilisation du swap pendant les builds est un signal fort pour réduire les exécuteurs ou augmenter la mémoire. Un disque presque plein peut ralentir l'extraction, l'archivage et les builds Docker.
Examinez également la durée individuelle des builds. Si le temps de file d'attente diminue d'une minute mais que chaque build devient cinq minutes plus lent, le nombre d'exécuteurs plus élevé n'est pas un gain.
Ajustez par petits changements
Modifiez progressivement le nombre d'exécuteurs. Passez un agent de 4 à 6, observez pendant quelques jours chargés, puis décidez. Les grands sauts cachent la cause des régressions.
Gardez des notes :
2026-05-24 : linux-build-03 exécuteurs 4 -> 6
Raison : file d'attente pour linux && maven en moyenne 12 minutes
Surveillance : CPU, iowait, contention du cache Maven, durée du build
Retour arrière : définir à 4 si la durée du build au p95 augmente plus que prévu
Ce court enregistrement aide lorsque quelqu'un demande pourquoi l'agent est lent deux semaines plus tard.
L'objectif pratique
Une configuration Jenkins saine a la plupart des agents occupés pendant les périodes de pointe, des files d'attente courtes pour les étiquettes courantes, pas de swap, une durée de build prévisible et aucun build sur le contrôleur. Elle dispose également d'une capacité suffisante par étiquette pour qu'un agent Docker manquant ne laisse pas des travaux Maven non liés en attente.
L'optimisation des exécuteurs n'est pas un réglage unique. Elle change lorsque vos équipes ajoutent des étapes parallèles, passent à des suites de tests plus grandes, adoptent des builds Docker ou migrent de VM statiques vers des agents Kubernetes. Révisez-la lorsque le temps de file d'attente devient visible, lorsque les agents commencent à swapper, ou lorsque la solution la plus rapide suggérée est "ajoutez simplement plus d'exécuteurs." Parfois, c'est correct. Souvent, la meilleure solution est un nouveau pool d'agents, de meilleures étiquettes, ou moins de copies simultanées du travail qui nuit à tout le monde.
Les étapes parallèles ont besoin d'un budget
Le parallélisme Pipeline peut être un grand avantage, mais il consomme rapidement des exécuteurs. Un build matriciel sur quatre versions Java et trois systèmes d'exploitation peut créer douze branches. Si chaque branche s'exécute sur un agent séparé, ce seul build peut consommer douze exécuteurs avant même que les étapes de déploiement ne commencent.
C'est acceptable lorsque l'équipe l'a prévu. C'est douloureux lorsqu'une seule pull request affame les builds de release. Mettez des limites autour des travaux à grande éventail :
options {
parallelsAlwaysFailFast()
}
Utilisez des étiquettes qui envoient les branches coûteuses au bon pool, et envisagez d'exécuter la matrice complète sur main tout en exécutant une matrice plus petite sur les pull requests. L'objectif est un retour rapide là où cela compte, pas une concurrence maximale partout.
Séparez les attentes interactives et par lots
Tous les travaux Jenkins ne méritent pas le même objectif de file d'attente. Un build de correctif de production, un travail de validation de pull request, un scan de sécurité nocturne et un travail de nettoyage hebdomadaire peuvent tous s'exécuter dans Jenkins, mais ils ne devraient pas rivaliser également.
Vous pouvez les séparer avec des étiquettes, des périodes de silence, des limitations et des fenêtres planifiées. Les travaux nocturnes lourds doivent s'exécuter lorsque le trafic PR interactif est faible. Les tests de charge de longue durée doivent avoir leurs propres agents. Les travaux de release peuvent mériter une capacité réservée ou une étiquette que les travaux de branche ordinaires ne peuvent pas utiliser.
Cela relève moins de la politique que de la fiabilité. Si chaque charge de travail partage un pool d'exécuteurs, la charge de travail la plus bruyante définit l'expérience pour tout le monde.
Ce qu'il faut documenter
Pour chaque pool d'agents, conservez un petit enregistrement :
étiquette : linux && docker
type d'agent : VM statique
exécuteurs par agent : 4
charges de travail principales : builds d'images Docker, tests d'intégration
limites connues : E/S disque et croissance des couches Docker
nettoyage : docker prune nocturne, nettoyage de l'espace de travail après le build
propriétaire : équipe plateforme
Cet enregistrement rend les futurs réglages beaucoup plus faciles. Lorsque le temps de file d'attente augmente, vous pouvez décider d'ajouter plus d'agents du même type, de diviser une charge de travail dans un nouveau pool, ou de réduire la concurrence sur les travaux à l'origine de la contention.