L'isolation des runners permet de contrôler quels workflows peuvent s'exécuter sur quelles machines. C'est essentiel pour la sécurité et la gestion des ressources dans les grandes organisations.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre pourquoi isoler les runners (sécurité, performance, conformité)
- Router les jobs avec les labels et les groupes de runners
- Appliquer les patterns d'isolation : par environnement, confiance, équipe
- Contrôler l'accès au niveau dépôt ou organisation
- Segmenter le réseau pour cloisonner les runners
Pourquoi isoler les runners ?
Section intitulée « Pourquoi isoler les runners ? »Sans isolation, un parc de runners self-hosted forme un pool unique : tout job du dépôt ou de l'organisation peut atterrir sur n'importe quelle machine. Trois catégories de problèmes en découlent, et elles ne se traitent pas au même niveau : la première relève de la sécurité, la deuxième de la capacité, la troisième de la traçabilité.
Sécurité
Section intitulée « Sécurité »Une machine qui exécute à la fois un job de PR et un déploiement de production donne au premier l'accès aux ressources du second : réseau interne, jetons en cache, images construites. Séparer les runners, c'est décider à l'avance ce qu'un job de confiance moyenne est capable d'atteindre.
- Empêcher les PRs non fiables d'accéder au réseau de production
- Limiter l'impact d'un workflow compromis
- Respecter le principe de moindre privilège
Performance
Section intitulée « Performance »Les jobs se répartissent sur les runners qui portent les labels demandés, sans notion de priorité : une file de tests d'une équipe peut donc bloquer le déploiement d'une autre. Dédier des machines par usage garantit une capacité réservée à ce qui ne peut pas attendre.
- Réserver des runners puissants aux builds critiques
- Éviter la contention entre équipes
- Garantir des SLAs différents par projet
Conformité
Section intitulée « Conformité »Certaines contraintes ne se satisfont pas d'une bonne intention : données de production qui ne doivent jamais transiter par une machine de développement, traitements qui doivent rester dans une zone géographique donnée. Le rattachement d'un job à une machine identifiée est ce qui rend la démonstration possible lors d'un audit.
- Séparer les données sensibles par environnement
- Traçabilité des exécutions par équipe
- Respect des zones géographiques
Labels et groupes de runners
Section intitulée « Labels et groupes de runners »GitHub offre deux leviers complémentaires, qu'il ne faut pas confondre. Les
labels font du routage : ils expriment ce qu'un job demande et
déterminent la machine qui l'exécutera. Les groupes de runners font du
contrôle d'accès : ils déterminent quels dépôts ont le droit d'utiliser ces
machines. Un label seul n'interdit rien, n'importe quel workflow du dépôt peut
l'écrire dans son runs-on.
Labels personnalisés
Section intitulée « Labels personnalisés »Les labels identifient les capacités d'un runner : un job n'est distribué qu'aux machines portant tous ceux qu'il réclame. Ils se déclarent à l'enregistrement, mais restent modifiables ensuite depuis les réglages du dépôt ou de l'organisation.
# À l'enregistrement./config.sh --url https://github.com/ORG/REPO \ --token TOKEN \ --labels linux,x64,docker,gpu,productionUtilisation dans un workflow :
jobs: build: runs-on: [self-hosted, linux, docker]
deploy-prod: runs-on: [self-hosted, production]
ml-training: runs-on: [self-hosted, gpu]Groupes de runners (organisation)
Section intitulée « Groupes de runners (organisation) »Au niveau organisation, les groupes permettent de limiter l'accès : un runner appartient à exactement un groupe, et le groupe énumère les dépôts autorisés. C'est le seul mécanisme qui empêche réellement un dépôt d'envoyer un job vers une machine, là où les labels se contentent de l'aiguiller.
- Allez dans Settings > Actions > Runner groups
- Créez un groupe (ex:
production-runners) - Assignez des runners au groupe
- Définissez quels repos peuvent l'utiliser
# Seuls les repos autorisés peuvent utiliser ce runnerjobs: deploy: runs-on: group: production-runners labels: [linux, x64]Patterns d'isolation
Section intitulée « Patterns d'isolation »Trois découpages couvrent la plupart des besoins. Ils se combinent : un runner
peut être à la fois production, team-platform et gpu.
Par environnement
Section intitulée « Par environnement »Le découpage le plus courant fait correspondre un jeu de runners à chaque étage
de la chaîne de livraison. L'intérêt n'est pas le label en lui-même mais ce
qu'il implique derrière : chaque groupe de machines vit dans le réseau de
son environnement et n'a d'accès qu'aux bases et API correspondantes. La clé
environment: ajoute une seconde barrière, côté GitHub cette fois, avec ses
règles d'approbation et ses secrets propres.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ Dev Runners │ │ Staging Runners │ │ Prod Runners ││ │ │ │ │ ││ Labels: │ │ Labels: │ │ Labels: ││ - dev │ │ - staging │ │ - production ││ - self-hosted │ │ - self-hosted │ │ - self-hosted ││ │ │ │ │ ││ Accès: tous │ │ Accès: équipe QA │ │ Accès: ops │└─────────────────┘ └──────────────────┘ └─────────────────┘jobs: test: runs-on: [self-hosted, dev]
staging: runs-on: [self-hosted, staging] environment: staging # Protection supplémentaire
production: runs-on: [self-hosted, production] environment: productionPar niveau de confiance
Section intitulée « Par niveau de confiance »Ce découpage classe les jobs selon l'origine du code exécuté : un push sur
main a été relu et fusionné, une PR ne l'a pas encore été. Les runners
untrusted n'ont alors qu'un accès Internet sortant, sans route vers le
réseau interne ni secrets de production. L'expression ternaire dans runs-on
fait le choix au démarrage du job, à partir de github.event_name.
┌─────────────────────┐ ┌─────────────────────┐│ Trusted Runners │ │ Untrusted Runners ││ │ │ ││ Pour: │ │ Pour: ││ - Pushes sur main │ │ - PRs externes ││ - Tags de release │ │ - Forks ││ │ │ ││ Accès: │ │ Accès: ││ - Réseau interne │ │ - Internet seul ││ - Secrets sensibles │ │ - Secrets limités │└─────────────────────┘ └─────────────────────┘name: CI
on: push: branches: [main] pull_request:
jobs: test: # Code de confiance (push) → runner trusted ; PR → runner untrusted runs-on: - self-hosted - ${{ github.event_name == 'push' && 'trusted' || 'untrusted' }}Par équipe
Section intitulée « Par équipe »Ce troisième axe répond à un besoin de capacité et de refacturation plutôt que de sécurité : chaque équipe dispose de ses machines et ne subit pas la file d'attente des autres. Les labels se cumulent avec ceux des axes précédents, un job pouvant réclamer à la fois son équipe et un matériel particulier.
jobs: frontend-build: runs-on: [self-hosted, team-frontend]
backend-build: runs-on: [self-hosted, team-backend]
ml-training: runs-on: [self-hosted, team-data, gpu]Contrôle d'accès aux runners
Section intitulée « Contrôle d'accès aux runners »Le niveau d'enregistrement d'un runner détermine qui peut l'utiliser. Plus le périmètre est large, plus le contrôle d'accès doit être strict.
Repository level
Section intitulée « Repository level »Un runner enregistré au niveau repository n'apparaît que dans ce dépôt : aucun autre projet ne peut lui envoyer de job, même en devinant ses labels. Au prix d'une machine sous-utilisée et à maintenir pour un seul projet, ce runner :
- N'est accessible que par ce repository
- Isolation maximale
./config.sh --url https://github.com/OWNER/REPO ...Organization level
Section intitulée « Organization level »Un runner enregistré au niveau organisation est mutualisé, ce qui améliore son taux d'occupation mais élargit d'autant sa surface d'exposition. Le groupe n'y est plus optionnel, il redevient la frontière qui décide quels dépôts peuvent atteindre la machine. Un tel runner :
- Peut être partagé entre repos
- Contrôlé par les groupes
./config.sh --url https://github.com/ORG ...Workflow permissions
Section intitulée « Workflow permissions »Utilisez les environments pour ajouter une couche de contrôle : un environnement GitHub porte ses propres secrets, ses règles de protection et, si vous l'activez, une approbation manuelle avant démarrage. Le job reste en attente tant que l'approbation n'est pas donnée, et les secrets ne sont transmis au runner qu'à ce moment-là.
jobs: deploy: runs-on: [self-hosted, production] environment: name: production # Nécessite approbation manuelleRéseau et firewall
Section intitulée « Réseau et firewall »L'isolation par labels et par groupes se joue côté GitHub : elle décide où part un job. Elle ne dit rien de ce que la machine peut joindre une fois le job lancé. Un runner mal placé dans le réseau reste joignable depuis le job, quelle que soit la propreté des labels. Le cloisonnement réseau est donc la couche qui rend l'isolation logique effective.
Segmentation réseau
Section intitulée « Segmentation réseau »Chaque environnement occupe son propre sous-réseau, et un runner ne voit que les services du sien. Le job de dev qui tenterait d'atteindre la base de production échoue au niveau réseau, sans dépendre d'une configuration correcte du workflow.
┌─────────────────────────────────────────────────────────────┐│ VPC / Réseau │├─────────────────┬─────────────────┬─────────────────────────┤│ Subnet Dev │ Subnet Staging │ Subnet Production ││ │ │ ││ ┌─────────────┐ │ ┌─────────────┐ │ ┌─────────────────────┐ ││ │ Dev Runner │ │ │Staging Runner│ │ │ Prod Runner │ ││ │ │ │ │ │ │ │ │ ││ │ Accès: │ │ │ Accès: │ │ │ Accès: │ ││ │ - DB dev │ │ │ - DB staging│ │ │ - DB prod │ ││ │ - API dev │ │ │ - API staging│ │ │ - K8s prod │ ││ └─────────────┘ │ └─────────────┘ │ └─────────────────────┘ │└─────────────────┴─────────────────┴─────────────────────────┘Règles firewall par label
Section intitulée « Règles firewall par label »Les règles se construisent en liste blanche : on autorise le sous-réseau
utile et le port 443 vers GitHub, puis on jette le reste. Le DROP final est ce
qui limite l'exfiltration en cas de job compromis. Vérifiez que les miroirs
de paquets et les registres d'images restent joignables, faute de quoi les
premiers builds échoueront sur des délais d'attente réseau.
# Runner dev : accès limitéiptables -A OUTPUT -d 10.0.1.0/24 -j ACCEPT # Subnet deviptables -A OUTPUT -d 0.0.0.0/0 -p tcp --dport 443 -j ACCEPT # GitHubiptables -A OUTPUT -j DROP
# Runner production : accès plus large mais contrôléiptables -A OUTPUT -d 10.0.0.0/16 -j ACCEPT # Tout le VPCiptables -A OUTPUT -d 0.0.0.0/0 -p tcp --dport 443 -j ACCEPTiptables -A OUTPUT -j DROPExemple complet d'architecture
Section intitulée « Exemple complet d'architecture »Ce workflow met bout à bout les patterns du guide : tests sur runners mutualisés, build sur runners d'équipe, déploiements sur runners par environnement avec approbation pour la production.
name: CI/CD Pipeline
on: push: branches: [main, develop] pull_request:
# Aucun droit par défaut : chaque job demande le minimumpermissions: {}
jobs: # Tests sur runners mutualisés test: runs-on: [self-hosted, linux, shared] permissions: contents: read steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - run: npm test
# Build sur runners de l'équipe build: needs: test runs-on: [self-hosted, linux, team-platform] permissions: contents: read steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - run: docker build -t app .
# Déploiement staging (réseau staging) deploy-staging: if: github.ref == 'refs/heads/develop' needs: build runs-on: [self-hosted, staging-network] environment: staging steps: - run: kubectl --context staging apply -f k8s/
# Déploiement production (réseau prod, approbation requise) deploy-production: if: github.ref == 'refs/heads/main' needs: build runs-on: group: production-runners labels: [linux, x64] environment: name: production url: https://app.company.com steps: - run: kubectl --context production apply -f k8s/Bonnes pratiques
Section intitulée « Bonnes pratiques »Une architecture de runners se dégrade vite : les machines s'ajoutent au fil des besoins, les labels se multiplient et plus personne ne sait ce que fait un runner donné. Ces quatre habitudes maintiennent le parc compréhensible et, surtout, auditable.
1. Nommer clairement les labels
Section intitulée « 1. Nommer clairement les labels »Un label est la seule information dont dispose l'auteur d'un workflow pour
choisir sa machine : il doit décrire une capacité ou un périmètre, pas
un numéro de série. Un nom vague comme fast finit par désigner la machine la
plus lente du parc, sans que personne ose le corriger.
# ✅ Labels explicites--labels linux,x64,docker,production,team-platform
# ❌ Labels vagues--labels runner1,fast2. Documenter l'architecture
Section intitulée « 2. Documenter l'architecture »L'interface GitHub montre les runners et leurs labels, jamais l'intention derrière le découpage ni les règles réseau associées. Sans document de référence, la première question posée lors d'un incident ou d'un audit reste sans réponse. Maintenez un document décrivant :
- Quels runners existent
- Leurs labels et capacités
- Quels repos/équipes peuvent les utiliser
- Les règles réseau
3. Auditer régulièrement
Section intitulée « 3. Auditer régulièrement »L'écart se creuse toujours dans le même sens : des labels ajoutés à la main pour débloquer un job, jamais retirés ensuite. Cette requête liste les runners de l'organisation avec leurs labels effectifs, à comparer avec le document de référence.
# Lister les runners et leurs labelsgh api /orgs/ORG/actions/runners --jq '.runners[] | {name, labels: [.labels[].name]}'4. Automatiser le provisioning
Section intitulée « 4. Automatiser le provisioning »Un runner configuré à la main dérive : paquets installés au fil des dépannages, label ajouté puis oublié, machine impossible à recréer à l'identique. Décrire le provisionnement en Infrastructure as Code rend le parc reproductible et transforme un changement de labels en modification tracée dans Git. Trois briques se répartissent le travail :
- Terraform pour les VMs
- Helm/Kubernetes pour ARC
- Ansible pour la configuration
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »- L'isolation contrôle quel workflow tourne sur quelle machine, un levier de sécurité et de performance.
- Les labels routent les jobs ; les groupes de runners restreignent quels dépôts peuvent les utiliser.
- Séparez au minimum les runners trusted (push, releases) des runners untrusted (PR, forks).
- Un runner enregistré au niveau dépôt offre l'isolation maximale ; au niveau organisation, il se mutualise via les groupes.
- Complétez l'isolation logique par une segmentation réseau : chaque environnement dans son sous-réseau.