Contactez-nous

Eviter d'exécuter des builds sur le noeud master (utiliser des agents)

Découvrez pourquoi il est crucial d'éviter d'exécuter des builds sur le master Jenkins et comment utiliser des agents (nodes) pour améliorer sécurité, performance et flexibilité.

Le rôle du master Jenkins et les risques liés à l'exécution locale des builds

Le noeud master de Jenkins, parfois appelé contrôleur, est le cerveau de votre système d'automatisation. Il héberge l'interface web, gère les configurations des jobs et des pipelines, stocke les historiques de build, planifie et distribue les tâches, et s'occupe de nombreuses autres fonctions critiques. C'est le pivot central sans lequel votre CI/CD ne peut fonctionner. Par défaut, lors d'une installation fraîche de Jenkins, le master est également configuré pour pouvoir exécuter des builds directement sur lui-même. Si cela peut sembler pratique pour une première prise en main ou des tests très simples, c'est une pratique fortement déconseillée en environnement de production ou même pour un usage régulier.

Exécuter les builds directement sur le master expose ce dernier à une série de risques et de limitations qui peuvent compromettre sa stabilité, sa sécurité et ses performances globales. Comprendre ces écueils est la première étape pour adopter une architecture Jenkins plus robuste et évolutive basée sur l'utilisation d'agents distribués.

Ce chapitre va détailler pourquoi il est impératif d'isoler les charges de travail des builds du master et comment la mise en place d'agents Jenkins (nodes) permet de pallier ces problèmes, offrant une solution plus sécurisée, flexible et performante pour vos besoins d'automatisation.

Les dangers d'exécuter les builds sur le master Jenkins

Laisser le master Jenkins exécuter les tâches de build (compilation, tests, packaging, etc.) peut entraîner plusieurs conséquences négatives critiques :

1. Surcharge des ressources et instabilité du master : Les processus de build sont souvent gourmands en ressources système : CPU, mémoire vive (RAM), entrées/sorties disque (I/O), et réseau. Si ces ressources sont monopolisées par un ou plusieurs builds s'exécutant sur le master, les performances de l'interface Jenkins elle-même peuvent se dégrader considérablement. L'interface peut devenir lente, voire inaccessible, et le master peut peiner à orchestrer d'autres tâches. Dans les cas extrêmes, une surconsommation de mémoire par un build peut entraîner un crash du processus Jenkins (Out Of Memory Error), rendant l'ensemble du système CI/CD indisponible.

2. Risques de sécurité accrus : Les scripts de build exécutent du code, qui peut provenir de sources diverses (votre propre code, des dépendances tierces, des outils de build). Si un build s'exécute sur le master, tout code malveillant ou toute vulnérabilité exploitée dans ce build a un accès direct à l'environnement du master. Cela signifie un accès potentiel à toutes les configurations de Jenkins, aux credentials stockés (même s'ils sont chiffrés, le master a les clés), aux autres jobs, et au système de fichiers du master. Un master compromis peut avoir des conséquences désastreuses.

3. Pollution de l'environnement du master : Les builds installent souvent des outils, des bibliothèques, ou créent des fichiers temporaires. Si cela se produit sur le master, son environnement peut devenir "pollué" et incohérent. Des conflits de versions d'outils peuvent survenir entre différents jobs ou avec les besoins de Jenkins lui-même. Maintenir un environnement propre et stable sur le master devient alors un cauchemar.

4. Manque de flexibilité des environnements de build : Le master Jenkins a un environnement système fixe (OS, versions d'outils installés globalement). Si vos différents projets nécessitent des environnements de build variés (par exemple, un projet Java 8, un autre Java 11, un projet Node.js avec une version spécifique de npm, ou un build nécessitant Windows tandis que le master est sur Linux), il est très compliqué, voire impossible, de gérer cela proprement si tous les builds s'exécutent sur le master.

5. Difficulté à monter en charge (scalabilité) : Si tous les builds s'exécutent sur le master, la seule façon d'augmenter la capacité de build est de surdimensionner la machine du master, ce qui n'est ni économique ni toujours efficace. Vous ne pouvez pas facilement paralléliser un grand nombre de builds sans impacter lourdement le master.

La solution : les agents Jenkins (nodes) pour des builds distribués

La bonne pratique pour pallier tous ces problèmes est d'utiliser une architecture de builds distribués avec des agents Jenkins (anciennement appelés "slaves" ou "nodes"). Un agent Jenkins est une machine (physique, virtuelle, ou un conteneur) qui est connectée au master Jenkins et dont la tâche principale est d'exécuter les builds que le master lui délègue. Le master se concentre alors sur son rôle d'orchestration et de coordination, tandis que la charge de travail réelle des builds est répartie sur un ou plusieurs agents.

Les avantages de cette approche sont multiples :

  • Isolation des charges de travail : Les ressources consommées par les builds le sont sur les agents, n'impactant pas (ou peu) les performances du master.
  • Sécurité améliorée : Même si un agent est compromis par un build, l'impact est limité à cet agent. Le master et ses configurations restent protégés (à condition que la communication agent-master soit sécurisée et que les agents n'aient pas de droits excessifs).
  • Flexibilité des environnements de build : Vous pouvez configurer des agents avec des systèmes d'exploitation, des architectures (x86, ARM), et des ensembles d'outils totalement différents. Chaque projet peut alors cibler l'agent qui correspond à ses besoins spécifiques.
  • Scalabilité horizontale : Si vous avez besoin de plus de capacité de build, il suffit d'ajouter de nouveaux agents. Vous pouvez avoir un grand nombre d'agents pour exécuter de nombreux builds en parallèle.
  • Environnements de build éphémères et propres : Avec des agents basés sur des conteneurs (Docker par exemple), chaque build peut s'exécuter dans un environnement propre et isolé, qui est détruit après utilisation, garantissant l'absence de pollution entre les builds.

Jenkins supporte différents types d'agents et méthodes de connexion (par exemple, connexion SSH, JNLP). Vous pouvez configurer des agents statiques (toujours connectés) ou des agents dynamiques qui sont provisionnés à la demande (par exemple, via des plugins pour Docker, Kubernetes, AWS EC2, Azure VM Agents).

Configurer Jenkins pour utiliser des agents et désactiver les builds sur le master

La première étape pour mettre en place une architecture d'agents est d'ajouter un ou plusieurs agents à votre master Jenkins. Cela se fait via "Manage Jenkins" > "Manage Nodes and Clouds" > "New Node". Vous donnerez un nom à votre agent, choisirez son type (souvent "Permanent Agent" pour commencer), et configurerez la manière dont Jenkins s'y connectera (par exemple, via SSH en fournissant une clé et un utilisateur, ou en lançant un agent JNLP sur la machine de l'agent). Vous pouvez également assigner des labels à vos agents (ex: `linux`, `windows`, `docker-builder`, `java11`). Ces labels seront utilisés dans les `Jenkinsfiles` pour spécifier où un pipeline doit s'exécuter.

Une fois vos agents configurés et connectés, la prochaine étape cruciale est de désactiver l'exécution des builds sur le master. Pour cela, allez dans "Manage Jenkins" > "Configure System". Cherchez la section "Node Properties" ou une section relative au noeud master (il peut être listé comme "Built-In Node" ou "master"). Trouvez le paramètre "# of executors" (nombre d'exécuteurs) pour le master et réglez-le sur 0. Cela empêchera le master d'accepter de nouvelles tâches de build. Il continuera son rôle d'orchestrateur mais ne prendra plus de charge de travail lui-même.

Ensuite, dans vos `Jenkinsfiles` (en syntaxe Déclarative), vous utiliserez la directive `agent` pour spécifier où le pipeline, ou des étapes spécifiques, doivent s'exécuter :

pipeline {
    // Option 1: Exécuter sur n'importe quel agent disponible
    agent any

    // Option 2: Exécuter sur un agent ayant un label spécifique
    // agent { label 'linux-build-node' }

    // Option 3: Exécuter dans un conteneur Docker sur un agent compatible Docker
    // agent {
    //     docker {
    //         image 'maven:3.8.1-jdk-11' // L'image Docker à utiliser
    //         label 'docker-agent' // Optionnel: spécifier un agent ayant Docker et ce label
    //         args '-v /tmp:/tmp'   // Optionnel: arguments pour `docker run`
    //     }
    // }

    // Option 4: Aucun agent global, spécifié par stage (utile pour des pipelines multi-OS)
    // agent none 

    stages {
        stage('Build sur Linux') {
            // Si agent none au niveau pipeline, il faut le spécifier ici
            // agent { label 'linux-x64' } 
            steps {
                sh './build-linux.sh'
            }
        }
        stage('Build sur Windows') {
            agent { label 'windows-server-2019' } // Outrepasse l'agent global pour ce stage
            steps {
                bat 'build-windows.bat'
            }
        }
        stage('Test dans un conteneur spécifique') {
            agent { 
                docker { image 'python:3.9-slim' } 
            }
            steps {
                sh 'python my_tests.py'
            }
        }
    }
}

En adoptant cette configuration, vous créez un système Jenkins plus robuste, sécurisé, et prêt à évoluer avec vos besoins. Le master est protégé, et vos builds s'exécutent dans des environnements dédiés et contrôlés. C'est une étape fondamentale vers une infrastructure CI/CD de qualité professionnelle.