Publications

Combien de contrôleurs Jenkins? Votre chaîne d’intégration reflète votre organisation

Par environnement, par organisation, par ligne de produit ou par technologie: quatre façons de découper Jenkins, leurs critères, leurs compromis, et ce qu’elles disent de qui possède quoi

Il arrive toujours un moment où un seul contrôleur Jenkins ne suffit plus. Les jobs s’accumulent, les builds deviennent plus fréquents, de nouvelles équipes arrivent, et le redémarrage après une mise à jour prend de plus en plus de temps. Deux voies s’ouvrent alors. La croissance verticale charge davantage le contrôleur existant: plus de jobs, plus de builds, plus d’équipes qui en dépendent. La croissance horizontale crée des contrôleurs supplémentaires pour accueillir les nouvelles équipes ou les nouveaux projets.

La seconde voie pose aussitôt une question qui paraît technique: combien de contrôleurs, et découpés selon quoi? Dans les équipes avec lesquelles je travaille, nous avons comparé quatre découpages: par environnement, par organisation, par ligne de produit et, en hybride, par technologie, auxquels s’ajoute une installation en haute disponibilité active/passive. La comparaison a surtout montré une chose: la réponse dépend moins de Jenkins que de la façon dont l’organisation répartit la responsabilité de ses produits.

Un mot de vocabulaire d’abord. Cet été, le projet Jenkins a retenu le terme «controller» pour remplacer «master», comme «agent» avait remplacé «slave» avec Jenkins 2.0. J’écris donc «contrôleur» et «agent».

Le contrôleur orchestre, les agents construisent

Le contrôleur est le nœud d’origine d’une installation Jenkins. Il administre les agents et orchestre leur travail: il planifie les jobs sur les agents et les surveille. Les agents exécutent les builds, sur des machines locales ou dans le cloud.

Cette séparation est la première décision de mise à l’échelle, avant même de parler du nombre de contrôleurs. Des nœuds de build dédiés, distincts du contrôleur, libèrent ses ressources pour la planification et empêchent les builds de modifier des données potentiellement sensibles dans $JENKINS_HOME. Un contrôleur qui ne construit rien supporte aussi une croissance verticale bien plus importante qu’un contrôleur qui fait les deux. Bien des installations qui semblent manquer de contrôleurs manquent en réalité d’agents.

Quatre critères pour juger un découpage

Avant de comparer les options, il faut savoir sur quoi on les juge. Quatre critères reviennent dans chaque cas.

  • L’impact d’une panne. Quand un contrôleur tombe, quels produits s’arrêtent? Un contrôleur en panne demande un redémarrage manuel, puis la relance des jobs que la panne a interrompus.
  • La visibilité du flux complet. Peut-on suivre un changement du commit à la production au même endroit, ou le flux est-il coupé entre plusieurs contrôleurs?
  • Le cloisonnement des accès. Qui voit quoi, et combien coûte la configuration de la sécurité?
  • Le coût d’exploitation. Chaque contrôleur demande des mises à jour régulières de ses plugins et du cœur de Jenkins, des sauvegardes de sa configuration et de son historique de builds, et ses propres réglages de sécurité et de rôles. Dix contrôleurs, c’est dix fois ce travail.

Par environnement

Un contrôleur pour le développement, un pour la préproduction, un pour la production. C’est souvent le premier découpage qui vient à l’esprit, parce qu’il calque la séparation des environnements.

Il a deux avantages réels. Chaque contrôleur peut porter les plugins propres aux besoins de son environnement, et l’accès à un environnement se restreint facilement aux seules personnes qui l’utilisent: le contrôleur de production n’est ouvert qu’à ceux qui déploient en production.

Ses inconvénients pèsent plus lourd. Un pipeline ne peut plus traverser les environnements: il s’arrête à la frontière d’un contrôleur, et personne ne voit le flux complet d’un changement. Les jobs sont dupliqués d’un environnement à l’autre, avec les écarts qui finissent par s’y glisser. Et la panne d’un seul contrôleur bloque le flux de tous les produits: si le contrôleur de préproduction tombe, plus rien n’avance vers la production.

Par organisation

Un contrôleur par division ou par unité métier. Les avantages ressemblent à ceux du découpage précédent: des plugins adaptés aux besoins de chaque équipe, un accès aux projets d’une division réservé à ses membres. Les agents y sont volontiers multi-technologies, puisqu’une division construit plusieurs sortes de produits.

Les inconvénients aussi se ressemblent. Les pipelines entre divisions deviennent difficiles, le flux complet n’est visible nulle part dès qu’un produit dépend d’une autre division, et la panne d’un contrôleur arrête tous les produits de la division. S’y ajoute une configuration de sécurité compliquée: un contrôleur qui héberge plusieurs produits doit cloisonner chacun d’eux pour ses propres équipes.

Par ligne de produit

Un contrôleur par produit ou par ligne de produits. C’est l’option que nous privilégions, et les quatre critères expliquent pourquoi.

Le flux entier est visible, car toutes les étapes, de la construction au déploiement, se trouvent sur un seul contrôleur. Une panne n’affecte qu’un petit sous-ensemble de produits: si le contrôleur tombe, seul son produit attend. Et la technologie du produit est connue, ce qui cadre les plugins et les agents dont le contrôleur a besoin.

Le prix à payer est la sécurité. Comme toutes les étapes vivent sur le même contrôleur, déploiement en production compris, il faut concevoir une stratégie de restriction des autorisations, pour que chaque utilisateur n’accède pas à tout le contrôleur. Ce travail se fait une fois, mais il doit être pensé.

Hybride: les agents par technologie

Le quatrième découpage ne remplace pas les trois premiers, il les complète. Les contrôleurs suivent l’une des trois stratégies, et ce sont les agents qui se regroupent par technologie: un groupe pour Java, un pour .NET, un pour Node. Chaque groupe porte sa chaîne d’outils, et les contrôleurs y envoient les jobs selon la technologie du produit.

L’intérêt est de séparer deux questions que l’on confond souvent: qui orchestre (le contrôleur, découpé selon la responsabilité) et où l’on construit (l’agent, découpé selon les outils). Le plugin Kubernetes de Jenkins pousse cette logique plus loin: il démarre les agents à la demande, sous forme de pods, à partir de modèles qui décrivent les conteneurs dont un build a besoin.

La haute disponibilité active/passive

Découper réduit l’impact d’une panne, sans la supprimer. Pour les contrôleurs les plus critiques, nous avons étudié une installation active/passive.

Un répartiteur de charge, HAProxy dans ce montage, reçoit les requêtes et vérifie en continu l’état de deux contrôleurs: le nœud actif, qui sert, et le nœud passif, qui attend. Les deux s’appuient sur un système de fichiers partagé, Amazon EFS, qui porte le répertoire des jobs. Si le contrôleur actif ne répond plus au contrôle de santé, le répartiteur bascule vers le passif, qui retrouve les mêmes jobs.

Deux limites sont à connaître. Un seul nœud travaille à la fois sur le répertoire partagé: le montage ne répartit pas la charge, il raccourcit l’interruption. Et la bascule n’est pas instantanée: plus un contrôleur porte de jobs, plus Jenkins met de temps à se charger après une mise à jour ou une panne. Ranger les jobs dans des dossiers et des vues limite le nombre de ceux qu’il faut afficher au démarrage. Pour les projets critiques, mieux vaut aussi écrire leurs chaînes en jobs Pipeline, qui continuent de s’exécuter quand la connexion entre l’agent et le contrôleur est perdue.

La topologie dit qui possède quoi

En 1968, Melvin Conway observait que les organisations conçoivent des systèmes qui reproduisent leurs structures de communication. Une chaîne d’intégration n’y échappe pas, et les quatre découpages le montrent.

Découper par environnement reproduit une organisation où le développement, la préproduction et la production appartiennent à des équipes différentes: chacune a son contrôleur, et le changement passe de main en main, comme un ticket. Découper par organisation reproduit l’organigramme: les frontières entre divisions deviennent des frontières entre contrôleurs, et un produit qui les traverse n’a plus de flux visible. Découper par ligne de produit suppose, à l’inverse, qu’une équipe possède son produit de bout en bout, du commit à la production.

C’est pourquoi «combien de contrôleurs?» n’est pas d’abord une question pour l’équipe plateforme. C’est une question pour ceux qui décident de qui est responsable de quoi. Si personne ne possède le flux complet d’un produit, aucun découpage de Jenkins ne fera apparaître ce responsable; si une équipe le possède, le découpage par produit lui donne l’outil qui lui correspond. Changer la topologie sans changer la responsabilité déplace le problème: on obtient un contrôleur par produit, administré par une équipe centrale qui ne connaît aucun des produits.

Le découpage engage aussi un coût que la décision doit assumer. Chaque contrôleur est un système à entretenir: plugins, mises à jour du cœur, sauvegardes, rôles. Il lui faut un responsable nommé, et du temps. Une partie de ce coût se réduit: le plugin Configuration as Code décrit la configuration d’un contrôleur dans un fichier YAML versionné, ce qui évite de refaire à la main les réglages de sécurité et de rôles sur chaque instance. Mais quelqu’un doit tenir ce fichier.

Avant d’ajouter un contrôleur

Quatre questions préparent la décision.

  1. Avez-vous les ressources pour un système de build distribué? Si les builds tournent encore sur le contrôleur, commencez par des agents dédiés.
  2. Avez-vous les ressources pour maintenir plusieurs contrôleurs? Chacun demande ses mises à jour, ses sauvegardes, sa sécurité, et quelqu’un pour le redémarrer quand il tombe.
  3. Quels projets sont critiques? Isolez les plus vitaux sur leurs propres contrôleurs pour limiter l’impact d’une panne, et écrivez leurs chaînes en Pipeline.
  4. Le démarrage rapide compte-t-il? Plus un contrôleur porte de jobs, plus il met de temps à repartir après une mise à jour ou une panne.

Une cinquième se pose avant les quatre autres: qui possède le flux de chaque produit, du commit à la production? La réponse donne le découpage. Le nombre de contrôleurs en découle.