Un runner CI démarre et disparaît en quelques minutes, le conteneur n'a pas de disque persistant et souvent pas d'IP fixe, alors qu'un proxy externe doit être reconnecté à chaque exécution : passer par une application de bureau, à la main, ne fonctionne pas. Voyons comment transmettre correctement un proxy à un conteneur et à un pipeline : sans identifiants dans l'image, en tenant compte de l'adresse flottante du runner, avec un contrôle du trafic et de l'isolation entre jobs parallèles.
Transmettre les paramètres par variables d'environnement
La méthode standard pour fournir un proxy à un conteneur et à une étape de pipeline consiste à utiliser les variables HTTP_PROXY, HTTPS_PROXY et NO_PROXY (ainsi que leurs équivalents en minuscules, que certaines bibliothèques lisent à la place des majuscules). La valeur est une chaîne de connexion avec identifiant et mot de passe : protocole, identifiants, hôte, port. La plupart des clients HTTP, des gestionnaires de paquets et des utilitaires en ligne de commande prennent ces variables en compte automatiquement, sans modifier le code de l'application.
NO_PROXY énumère à part les adresses et les domaines appelés directement : services internes du réseau de conteneurs, registre d'images local, adresses de service entre les étapes d'un même pipeline. Sans NO_PROXY correct, le trafic interne passe lui aussi par le proxy externe, ce qui augmente la consommation et la latence sans aucun bénéfice. Les variables se définissent au niveau de l'étape, et non de l'ensemble du pipeline, si les tâches n'ont pas besoin des mêmes adresses : la compilation se fait en direct, tandis que l'étape de vérifications externes passe par un canal situé dans la zone géographique voulue.
Pourquoi ne pas figer les identifiants dans l'image
Un conteneur est construit par couches, et chaque couche arrive dans le registre d'images et y reste, même si le secret est supprimé dans la couche suivante : une commande qui ajoute l'identifiant et le mot de passe dans une variable d'environnement pendant la construction les laisse lisibles via l'historique des couches, même si la commande suivante les supprime. Les outils d'analyse d'images détectent ces identifiants en quelques secondes, aussi bien dans les registres publics que privés : un registre privé n'est pas synonyme de sécurité.
Le bon schéma consiste à injecter le secret à l'exécution et non à la construction : variables d'environnement, stockage chiffré du pipeline ou volume monté au lancement et qui n'entre dans aucune couche de l'image. L'image reste identique pour tous les environnements ; seule change la valeur que le système de CI fournit au démarrage du job.
La liste blanche d'IP ne fonctionne pas avec des runners à adresse flottante
Autoriser l'accès par l'adresse IP du runner n'est une solution viable que pour une infrastructure dédiée à adresse permanente. Un runner cloud reçoit un conteneur issu d'un pool commun à chaque exécution, et l'IP externe change d'un job à l'autre, parfois même au milieu d'une étape lors de la recréation du nœud : une adresse inscrite dans la liste blanche devient obsolète dès l'exécution suivante, et l'accès se met à échouer sans cause visible dans le code lui-même.
La seule solution durable est ici l'authentification par couple identifiant et mot de passe, rattaché au compte et non à l'adresse. C'est le même principe que pour le client de bureau : la chaîne de connexion contient les identifiants au lieu de s'appuyer sur une liste statique d'adresses autorisées, que le runner est physiquement incapable de garantir. Le fonctionnement de la rotation des adresses attribuées avec ce type d'authentification est expliqué dans l'article sur la rotation d'IP par API.
Consommation de trafic en CI et comment la limiter
Un pipeline qui sollicite le proxy externe à chaque étape de chaque exécution accumule du trafic plus vite qu'il n'y paraît au départ : mille vérifications de pages avec images représentent déjà 3 à 5 Go, et une exécution quotidienne sur une centaine d'adresses en supervision génère environ 1,5 à 3 Go par mois pour un seul scénario, sans compter les relances en cas d'étape instable.
Trois leviers aident à limiter la consommation : la mise en cache des dépendances et des artefacts de build, pour que seuls les appels réellement externes sortent, et non la reconstruction des mêmes éléments à chaque exécution ; la désactivation des médias lorsque le scénario n'a besoin que du texte ou d'une réponse d'API ; et une adresse de centre de données à prix mensuel fixe pour les tâches sans sensibilité géographique, qui n'est pas facturée au trafic, si bien que les exécutions de test n'alourdissent pas la facture en gigaoctets. La règle d'économie est détaillée dans l'article proxys bon marché ou chers.
Isolation entre tâches parallèles
Un pipeline avec des jobs parallèles, scénario typique en CI, ne doit pas faire passer toutes les branches par la même adresse attribuée : si l'une des étapes subit un blocage de réputation ou un captcha de la part du site cible, tous les jobs parallèles partageant cette IP en pâtissent, y compris ceux qui n'y sont pour rien.
La solution pratique est une session distincte, ou un segment d'identifiants distinct, pour chaque branche parallèle, avec le numéro du job ou de l'étape comme identifiant. Pour les canaux à attribution d'adresse par session, cela signifie que chaque tâche obtient automatiquement sa propre IP, à condition que l'identifiant de session soit réellement unique à chaque exécution et non codé en dur une fois pour tout le pipeline.
Questions fréquentes
Peut-on utiliser le même compte proxy dans plusieurs pipelines à la fois ?
Techniquement oui, mais sur un canal avec une limite commune de sessions parallèles, cela crée une concurrence pour les sessions entre des pipelines sans rapport : l'un évince les sessions de l'autre lors des pics de charge. Pour plusieurs pipelines actifs, il est plus pratique de les répartir sur des segments d'identifiants distincts, même au sein d'un seul forfait.
Comment transmettre un proxy à un conteneur si l'outil qu'il contient ne gère pas les variables d'environnement ?
Certains utilitaires ignorent HTTP_PROXY et exigent l'adresse dans leur propre fichier de configuration ou via une option de ligne de commande : on transmet alors explicitement la chaîne de connexion lors de l'appel de l'outil, en la lisant dans la même variable au niveau du script enveloppant l'étape.
Faut-il restreindre le proxy aux seuls domaines externes réellement appelés par le pipeline ?
Oui, si le compte prend en charge ce réglage : cela permet moins d'économiser du trafic que d'éviter les appels accidentels vers des adresses internes et de service à cause d'une erreur dans NO_PROXY, qui passeraient sinon inaperçus jusqu'à l'analyse des journaux.
Des proxys avec authentification par identifiant et mot de passe pour la CI, prêts à être transmis par variables d'environnement sans dépendre de l'adresse du runner, sont disponibles dans la rubrique proxys. La documentation sur l'intégration et les limites se trouve dans l'API proxy.