Lorsque les jobs GitLab CI/CD n'arrivent pas à atteindre les dépôts de paquets, les magasins d'artefacts, les registres de conteneurs ou les API internes, la cause racine est souvent le réseau. DNS, ports, routage, proxys, TLS et pare-feu peuvent se comporter différemment à l'intérieur d'un runner que sur une station de développement. Ce guide propose des étapes pratiques et sûres pour diagnostiquer et corriger ces différences avec des exemples reproductibles. Vous créerez un petit job de diagnostic en lecture seule, comparerez les sorties aux résultats attendus et appliquerez des changements ciblés sans risquer d'affecter d'autres parties de votre pipeline.
L'approche est simple : capturer un inventaire clair, exécuter un test pilote étroit, observer le chemin réseau et corriger uniquement ce que vos preuves justifient. En gardant le pilote petit et mesurable, vous pouvez itérer rapidement et réduire le retravail.
Inventaire des versions et de l'environnement
Avant de toucher à la configuration, répondez à ces questions. Un inventaire cohérent évite de poursuivre la mauvaise couche.
Ce qu'il faut enregistrer
| Élément | Exemple de valeur |
|---|---|
| Édition et version de GitLab | GitLab.com SaaS ou autogéré 17.x |
| Version de GitLab Runner | 17.x (exécuteur shell, Docker ou Kubernetes) |
| OS et architecture du runner | Ubuntu 22.04 x86_64 ; Windows Server 2022 |
| Type d'exécuteur | shell, docker, kubernetes |
| Zone réseau | LAN bureau, VLAN 120 DC, namespace k8s ci |
| Résolveurs DNS utilisés par les jobs | 10.0.0.10, 10.0.0.11 |
| Paramètres de proxy dans les jobs | http_proxy, https_proxy, NO_PROXY |
| IP de sortie attendue(s) | IP NAT 203.0.113.45 (exemple construit) |
| Propriétaires du pare-feu et fenêtre de changement | NetSec d'astreinte, quotidien 16h00-17h00 |
Comment le collecter (exemples Linux)
- Version du runner et exécuteur (exécuter sur l'hôte du runner) :
gitlab-runner --version
cat /etc/gitlab-runner/config.toml
- Configuration DNS visible pour les jobs (à l'intérieur du job) :
cat /etc/resolv.conf || true
getent hosts gitlab.com || true
- Variables d'environnement liées au proxy (à l'intérieur du job) :
( env | grep -iE '^(http|https|no)_proxy=' || true ) | sort
- Chemins réseau (sur l'hôte du runner ou dans le job si autorisé) :
ip addr show
ip route show
ss -tupan | head -n 50
Extraits pour runner Windows
- Résolution DNS :
Resolve-DnsName example.com
- Accessibilité du port :
Test-NetConnection example.com -Port 443
Documentez ces constats avec les identifiants de job afin de pouvoir comparer les exécutions réussies et celles en échec.
Chemin de configuration sûr
La méthode la plus sûre pour dépanner consiste à introduire un petit job de diagnostic en lecture seule qui sonde uniquement les points de terminaison qui vous intéressent. Évitez les modifications globales tant que le job n'a pas prouvé ce qui est cassé.
1) Ajouter un job de diagnostic
Le job suivant utilise des outils Linux standards. Il ne modifie pas l'état du système et sort avec un code non nul en cas d'échec évident.
# .gitlab-ci.yml (exemple construit)
stages:
- verify
net-verify:
stage: verify
image: alpine:3.20 # pour l'exécuteur docker ; retirer 'image' pour l'exécuteur shell
variables:
# Définir les proxys ici seulement si votre environnement l'exige
# http_proxy: "http://proxy.internal:3128"
# https_proxy: "http://proxy.internal:3128"
# NO_PROXY: "registry.internal,.svc,.cluster.local,10.0.0.0/8,127.0.0.1,localhost"
before_script:
- apk add --no-cache bind-tools curl openssl iproute2 busybox-extras
script:
- set -euxo pipefail
- echo "== DNS =="
- cat /etc/resolv.conf || true
- dig +short registry.internal || true
- echo "== Accessibilité TCP 443 =="
- nc -vz -w5 registry.internal 443 || true
- echo "== Négociation TLS et SNI =="
- echo | openssl s_client -connect registry.internal:443 -servername registry.internal -brief 2>/dev/null || true
- echo "== HTTP HEAD avec chronométrage =="
- curl -fsSILv https://registry.internal -o /dev/null -w 'code=%{http_code} connect=%{time_connect} ttfb=%%{time_starttransfer}\n'
- echo "== Routes et adresses =="
- ip addr show || true
- ip route show || true
Notes :
- Remplacez
registry.internalpar votre cible réelle (magasin d'artefacts, registre, API). - Si vous utilisez un exécuteur shell sur un hôte verrouillé, installez les outils équivalents via le gestionnaire de paquets de l'OS et lancez-les dans le script du job.
- Gardez les secrets hors des lignes de commande. Utilisez des variables CI masquées lorsque l'authentification est requise pour les vérifications HTTP(S).
2) Vérifier le DNS en premier
Une grande partie des échecs de connectivité CI proviennent de problèmes de résolution de noms. Validez :
- Le job résout les mêmes noms que votre poste de travail.
- Les types de réponse (A vs AAAA) sont cohérents avec votre réseau.
- Le domaine de recherche ne réécrit pas les noms de manière inattendue.
Diagnostics :
getent hosts internal.api.local || true
dig +search internal.api A AAAA +timeout=2 +tries=1 || true
Si des réponses IPv6 sont retournées mais que votre réseau ne transporte pas l'IPv6 de bout en bout, privilégiez l'IPv4 pendant l'investigation :
curl -4 -fsSIL https://internal.api.local
3) Valider les ports et le TLS
- Ports : confirmez que le port cible est ouvert depuis le job.
nc -vz -w3 registry.internal 443 || true
- TLS : confirmez le SNI, la chaîne de certificats et le protocole. Recherchez les erreurs de vérification de certificat ou des émetteurs inattendus (par exemple, un proxy d'interception d'entreprise).
echo | openssl s_client -connect registry.internal:443 -servername registry.internal -showcerts 2>/dev/null | awk '/Server certificate/ {p=1} p{print}'
Si une autorité de certification d'entreprise signe les certificats, installez-la dans l'environnement du runner plutôt que de désactiver la vérification. Par exemple, sur des runners basés Debian/Ubuntu :
# Écrire corporate-ca.crt via une variable CI protégée ou une image préconfigurée, puis :
sudo cp corporate-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
Évitez de désactiver la vérification TLS globalement. Si vous devez contourner temporairement la vérification pour confirmer que seule la confiance pose problème, limitez-le à une seule commande et rétablissez dès que l'AC est installée.
4) Inspecter le routage et le NAT
- Confirmez qu'une route par défaut existe et est correcte :
ip route show
- Tracez le chemin et repérez les trous noirs :
traceroute -n registry.internal || true
- Si votre organisation utilise le NAT, demandez à NetSec quelle IP de sortie votre runner utilise afin qu'ils puissent consulter les journaux du pare-feu. Gardez ce processus en dehors du job CI ; ne comptez pas sur des appels à des endpoints externes "what-is-my-ip" depuis CI.
5) Gérer les proxys délibérément
Si vos jobs doivent traverser un proxy, définissez les variables d'environnement au niveau le plus étroit qui fonctionne :
variables:
http_proxy: "http://proxy.internal:3128"
https_proxy: "http://proxy.internal:3128"
NO_PROXY: "registry.internal,.svc,.cluster.local,10.0.0.0/8,127.0.0.1,localhost"
Conseils :
NO_PROXYaccepte des suffixes de domaine comme.example.com. Listez les noms d'hôtes internes et les adresses de boucle locale pour éviter de proxyfier les services locaux.- Si seuls certains jobs ont besoin du proxy, définissez les variables au niveau du job, pas globalement.
- Certains outils lisent les variantes minuscules et majuscules ; définissez les deux en cas de doute.
6) Notes spécifiques à l'exécuteur
- Exécuteur shell : le job partage le réseau de l'hôte. Les pare-feu de l'hôte (ufw, nftables, Pare-feu Windows) affectent directement la connectivité.
- Exécuteur Docker : le job s'exécute derrière un pont défini par l'utilisateur. La résolution de noms, le MTU et le NAT sortant sont contrôlés par le pont Docker et l'hôte. Si vous devez ajouter des racines de confiance supplémentaires ou des correspondances d'hôtes, privilégiez la création d'image ou la configuration du runner plutôt que des drapeaux ad-hoc.
- Exécuteur Kubernetes : Les NetworkPolicies peuvent bloquer le trafic sortant. Vérifiez les règles de sortie du namespace, les politiques DNS et si le cluster utilise un proxy ou une passerelle de sortie.
Vérification et diagnostics
Après chaque modification, relancez le job de diagnostic et comparez ses sorties aux attentes ci-dessous. Gardez les différences petites et centrées sur le point de terminaison que vous essayez d'atteindre.
Résultats attendus par couche
| Couche | Exemple sain |
|---|---|
| DNS | dig retourne A/AAAA pour la cible ; getent hosts affiche les IP attendues |
| TCP | nc -vz host 443 signale succeeded ; pas de timeout |
| TLS | openssl s_client montre une chaîne valide vers une racine de confiance ; le SNI correspond |
| HTTP | curl -I retourne 200/302/401 selon la politique du point de terminaison ; les champs de temps sont faibles |
| Route | ip route affiche une route par défaut via la passerelle correcte ; traceroute progresse |
Exemples de sorties saines (exemples construits)
- DNS :
$ dig +short registry.internal
10.50.12.34
- TCP :
$ nc -vz -w3 registry.internal 443
registry.internal (10.50.12.34:443) open
- TLS :
$ echo | openssl s_client -connect registry.internal:443 -servername registry.internal -brief
Protocol : TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Server certificate
subject=CN = registry.internal
issuer=CN = Corp-Root-CA
Verification: OK
- Chronométrage HTTP :
$ curl -fsSILv https://registry.internal -o /dev/null -w 'code=%{http_code} connect=%{time_connect} ttfb=%%{time_starttransfer}\n'
< HTTP/1.1 200 OK
code=200 connect=0.020 ttfb=0.085
Si les sorties ne correspondent pas aux attentes, revenez au Chemin de configuration sûr et ajustez uniquement la couche concernée.
Modes d'échec et récupération
Cette section liste les symptômes courants, leurs causes probables et des correctifs sûrs que vous pouvez annuler.
Symptômes courants et correctifs ciblés
| Symptôme | Cause probable | Premier correctif sûr |
|---|---|---|
getent hosts expire | Mauvais serveur DNS ou UDP/53 bloqué | Orienter le runner vers les bons résolveurs ; vérifier avec dig |
nc vers 443 expire | Pare-feu bloquant la sortie ou proxy requis | Ajouter les variables proxy au niveau du job ou demander une règle de pare-feu |
| Échec de vérification TLS | AC d'entreprise manquante ou interception TLS | Installer l'AC dans le magasin de confiance du runner ; éviter de désactiver la vérification |
curl résout seulement en IPv6 | DNS à vue partagée, IPv6 non routé | Privilégier l'IPv4 (-4) ou corriger la vue DNS pour CI |
traceroute s'arrête au saut 1 | Pare-feu local ou route par défaut incorrecte | Corriger le pare-feu hôte ; confirmer la route par défaut et la passerelle |
| TTFB HTTP lent | Limitation du proxy ou perte de paquets | Contourner le proxy pour les hôtes internes via NO_PROXY ; réessayer en dehors des heures de pointe |
Annulation et récupération
- .gitlab-ci.yml :
- Gardez toutes les modifications de diagnostic dans un job verify dédié.
- Pour annuler, supprimez uniquement ce job ou les variables que vous avez introduites.
- Magasin de confiance du runner :
- Avant d'ajouter une AC d'entreprise, sauvegardez les répertoires de confiance (par exemple,
/etc/ssl/certset/usr/local/share/ca-certificatessur Debian/Ubuntu). - Pour annuler, supprimez le fichier AC ajouté et lancez
update-ca-certificates.
- Modifications de proxy :
- Supprimez les variables proxy au niveau du job pour revenir au comportement antérieur.
- Paramètres de l'exécuteur Docker ou Kubernetes :
- Sauvegardez la configuration du runner avant modifications.
- Revenez au fichier de configuration précédent et redémarrez le runner si les changements n'aident pas.
Relancez toujours le job de diagnostic après une annulation pour confirmer le retour à la ligne de base connue.
Liste de contrôle opérationnelle
Utilisez cette liste pour assurer un dépannage cohérent et à faible risque.
- Inventaire
- Enregistrez les versions de GitLab et du Runner, l'exécuteur, l'OS, les résolveurs DNS et les variables proxy.
- Capturez l'IP de sortie attendue auprès de NetSec si applicable.
- Préparer les diagnostics
- Ajoutez un job verify qui exécute
dig,nc,openssl s_client,curl,ip route. - Limitez la portée aux points de terminaison ciblés. Aucun secret en ligne de commande.
- Exécuter et observer
- Sauvegardez les logs du job. Comparez les réponses DNS, l'état TCP, la chaîne TLS, les codes HTTP et les temps.
- Notez si les résultats diffèrent entre runners ou environnements.
- Appliquer des correctifs ciblés
- DNS : corrigez les résolveurs ou la politique DNS pour le runner.
- Ports : demandez des règles de sortie pare-feu ; testez avec
nc. - TLS : installez l'AC d'entreprise dans le magasin de confiance du runner.
- Proxys : définissez
http_proxy/https_proxy/NO_PROXYau niveau du job. - Routage : corrigez la route par défaut ou le pare-feu hôte, puis refaites
traceroute.
- Vérifier et documenter
- Relancez le job verify ; confirmez que les sorties répondent aux attentes.
- Enregistrez ce qui a changé et conservez le job verify pour de futures vérifications.
- Annuler si nécessaire
- Revenir uniquement sur les changements que vous avez introduits.
- Confirmer la ligne de base en relançant le job verify.
Conclusion
Le réseau à l'intérieur de GitLab CI/CD diffère des ordinateurs portables des développeurs de manière subtile mais importante. En capturant un inventaire d'environnement clair, en introduisant un job de diagnostic étroit et en validant chaque couche dans l'ordre (DNS, ports, TLS, routage, proxys, pare-feu), vous pouvez isoler rapidement les causes racines et les corriger avec un risque minimal. Gardez le job de diagnostic à portée de main dans votre dépôt pour vérifier de nouveaux environnements, runners ou points de terminaison. Lorsque les problèmes réapparaissent, suivez la liste de contrôle pour reproduire les résultats, appliquer des changements ciblés et confirmer les résultats.