Hot Posts

6/recent/ticker-posts

Ma Publicité

Soutenez la Création

Aidez-moi à partager du contenu exclusif.

Soutenir

Recent Posts

Nouveau Drop

Boutique Officielle

Soutenez le blog monblog-sa-abasse et découvrez nos vêtements & accessoires exclusifs en édition limitée.

Découvrir la collection
Paiement Sécurisé
Livraison Monde

Automatisation GitOps : Déployer ses configurations de serveurs automatiquement avec GitHub/GitLab Actions et Ansible

Automatisation GitOps : Déployer ses configurations de serveurs automatiquement avec GitHub/GitLab Actions et Ansible

Salle de serveurs moderne avec des câbles verts et bleus lumineux connectés aux racks, sur lesquels sont superposés des symboles abstraits d’automatisation et de synchronisation du code.

Pourquoi GitOps change vraiment la gestion de configuration (et pourquoi l’Ansible « à la main » ne suffit plus)

Le scénario classique, vous le connaissez. Un mardi soir, petite modif « rapide » sur un serveur de prod. Juste un fichier de conf. Juste un restart. Et puis, deux semaines plus tard, quelqu’un déploie la même appli sur un autre serveur. Sauf que... il n’a pas la modif. Ou pire, il a une autre modif, faite « à la main » aussi, mais pas exactement pareil. Et là on découvre le drift. Les serveurs qui étaient censés être identiques ne le sont plus. Les rollbacks deviennent douloureux parce qu’on ne sait plus ce qui a changé, ni quand, ni pourquoi.

Ansible a souvent été la première marche. On écrit des playbooks, on les lance depuis son laptop, on se dit que c’est déjà mieux que du SSH artisanal. Oui. Mais « Ansible à la main », c’est souvent une promesse incomplète.

GitOps, dit simplement, c’est ça : Git comme source de vérité + automatisation + traçabilité. En clair, si ce n’est pas dans Git, ce n’est pas censé exister. Et si c’est dans Git, un mécanisme automatique est capable de l’appliquer, de manière répétable, et de laisser une trace.

La différence entre « infrastructure as code » et « GitOps » est subtile mais importante. L’IaC dit : « on décrit l’état voulu dans du code ». GitOps ajoute : « et on met une boucle de contrôle qui déclenche l’application de cet état à partir de Git, avec des garde fous ». Ce n’est pas juste du code. C’est un processus.

Concrètement, vous gagnez :

  • Reproductibilité : un serveur reconstruit ou un nouveau node rejoint le cluster, on applique la même config, point.
  • Audit : qui a changé quoi, quand, via un commit, une PR, une approbation.
  • Rollback : revert d’un commit, redeploy, on revient à une config connue.
  • Standardisation : mêmes users, mêmes règles SSH, mêmes packages, mêmes services.
  • Onboarding plus simple : un nouveau dans l’équipe lit le repo, lance les commandes standard, comprend le flux.

Mais. GitOps ne résout pas tout tout seul.

  • Si vos playbooks sont mal écrits, non idempotents, fragiles, GitOps va juste automatiser le chaos.
  • Les secrets restent un sujet brûlant.
  • La gouvernance compte : qui peut déployer quoi, sur quels environnements.
  • Les tests aussi : si vous ne testez rien, vous déployez juste plus vite... des erreurs.

Le modèle cible : GitHub/GitLab Actions + Ansible pour configurer des serveurs automatiquement

Le modèle qu’on vise ici est volontairement pragmatique.

Un flux type :

commit → CI/CD → tests → déploiement Ansible → validation post-déploiement.

Ansible s’insère parfaitement au milieu : playbooks et rôles pour configurer l’OS, installer des packages, gérer des services, des users, faire du hardening, déployer des templates. Et tout ça, de façon idempotente.

Pourquoi GitHub Actions ou GitLab CI, plutôt qu’un serveur CI dédié ? Souvent pour des raisons simples :

  • Zéro infra CI à maintenir au début.
  • Intégration native au repo : PR, reviews, checks, environnements, permissions.
  • Coûts et friction réduits.
  • Et si le réseau est un problème, vous pouvez utiliser des runners auto hébergés (self hosted) dans votre VPC, votre LAN, derrière VPN, etc.

Quand choisir GitHub Actions vs GitLab CI ? Ça dépend de votre contexte, mais les critères pratiques sont souvent :

  • Disponibilité et gestion des runners.
  • Variables et secrets, scopes par environnement.
  • Modèle de permissions et protection.
  • Expérience de l’équipe : si vous êtes déjà très GitLab, restez simple.

Dernier point important sur le périmètre. Ici, on parle surtout de configuration « day 1 / day 2 » : durcissement, comptes, services, tuning, observabilité. Pas forcément du provisioning complet de VM, même si ça peut venir après.

Pré-requis et choix d’architecture (pour éviter de se tirer une balle dans le pied)

Avant d’écrire votre premier workflow, posez ces bases. Sérieusement. Parce que beaucoup de projets GitOps échouent sur des détails « invisibles » au début.

Inventaire

Statique ou dynamique.

  • inventories/dev/hosts.iniinventories/prod/hosts.ini
  • Dynamique : plugin cloud (AWS, GCP, Azure), CMDB, etc. Puissant, mais plus de moving parts.

Organisez vos groupes (dev, staging, prod) et vos variables par host et group. Ne mélangez pas tout. C’est souvent là que la prod se fait surprendre.

Accès aux serveurs

Vous avez besoin de SSH. Donc :

  • Clés SSH (idéalement dédiées à la CI).
  • Bastion si nécessaire.
  • Réseau : VPN, ip allowlist, accès des runners.
  • Si vous utilisez des runners partagés cloud, attention : ouvrir la prod à Internet « juste pour la CI » est une pente dangereuse. Le plus propre est souvent un runner self hosted dans le réseau.

Idempotence

En GitOps, l’idempotence n’est pas un bonus. C’est non négociable.

Si vous devez rejouer le playbook demain, dans une semaine, après un incident, ça doit fonctionner et ne pas casser l’existant. Sinon, vous ne pouvez pas faire confiance au modèle.

Stratégie d’environnements

Branches vs dossiers vs fichiers de vars. Il n’y a pas une vérité unique, mais il faut une règle claire.

  • mainprod
  • Dossiers d’inventaire séparés par environnement, c’est souvent le plus simple.
  • Promotion staging → prod via merge, tag, ou pipeline manuel validé.

Gestion des permissions

Qui peut déployer en prod ?

  • Protection des branches.
  • Approvals obligatoires.
  • Environnements protégés (GitHub Environments, GitLab protected environments).
  • Jobs manuels pour prod, au minimum au début.

Structurer le dépôt Git : une organisation simple qui tient dans la durée

Un repo Ansible GitOps, c’est comme une armoire. Si vous jetez tout en vrac, ça marche trois semaines. Après… c’est fini.

Une arborescence simple et durable :

text . ├── playbooks/ │ ├── base.yml │ ├── web.yml │ ├── db.yml │ └── hardening.yml ├── roles/ │ ├── users/ │ ├── ssh_hardening/ │ ├── firewall/ │ ├── nginx/ │ └── monitoring/ ├── inventories/ │ ├── dev/ │ │ ├── hosts.ini │ │ └── group_vars/ │ ├── staging/ │ │ ├── hosts.ini │ │ └── group_vars/ │ └── prod/ │ ├── hosts.ini │ └── group_vars/ ├── group_vars/ ├── host_vars/ ├── files/ ├── templates/ ├── requirements.yml ├── Makefile └── README.md

Conventions de nommage :

  • base.ymlweb.ymlhardening.yml
  • --tags ssh,users,firewall
  • Handlers bien nommés, pas « restart service » partout.

userssshfirewallnginxdockermonitoring

Et surtout, versionnez tout ce qui est configuration. Le drift, c’est l’ennemi silencieux. Une règle quasi politique aide beaucoup : pas de modif manuelle en prod. Si quelqu’un doit « hotfix », ok, mais il ouvre une PR ensuite pour réconcilier Git avec la réalité. Sinon Git cesse d’être la source de vérité.

Ajoutez une doc légère dans le repo : un README qui explique comment lancer en local, comment marche le pipeline, et un petit schéma texte du flux. Pas besoin d’un roman.

Mettre Ansible « prêt CI » : lint, tests et exécution locale identique à la CI

La CI sert à éliminer les « chez moi ça marche ».

ansible-lint

ansible-lint

  • tâches non nommées,
  • shell
  • templates qui changent à chaque run,
  • permissions incohérentes,
  • pratiques douteuses sur les handlers.

Vous pouvez démarrer avec les règles par défaut, puis assouplir si nécessaire. Mais évitez l’inverse. Si vous commencez sans lint, vous n’y reviendrez pas.

Tests rapides

Avant de déployer, au minimum :

  • ansible-playbook --syntax-check
  • --check--diff

--check

Molecule (optionnel)

Molecule, c’est super pour tester des rôles dans des containers ou VMs éphémères. Mais c’est un coût de setup.

Quand ça vaut le coup ? Quand vos rôles sont réutilisés, partagés, ou critiques. Ou quand vous commencez à avoir des régressions fréquentes.

Versions figées

Un classique : le pipeline cassé parce qu’une collection Ansible a changé.

requirements.ymlrequirements.txtpyproject

Une commande standard local = CI

Makefile

Exemple :

makefile lint: \tansible-lint

syntax: \tansible-playbook -i inventories/staging/hosts.ini playbooks/base.yml --syntax-check

check: \tansible-playbook -i inventories/staging/hosts.ini playbooks/base.yml --check --diff

deploy-staging: \tansible-playbook -i inventories/staging/hosts.ini playbooks/site.yml

deploy-prod: \tansible-playbook -i inventories/prod/hosts.ini playbooks/site.yml

L’idée : tout le monde lance les mêmes commandes. Moins de débats. Moins de surprises.

Gestion des secrets en GitOps : la partie la plus sensible (et la plus souvent ratée)

On ne commit jamais :

  • clés privées SSH,
  • mots de passe,
  • tokens API,
  • certificats non publics,
  • .env

Options réalistes :

  • Ansible Vault : simple, intégré. Mais la gestion de la clé Vault devient votre point sensible.
  • GitHub Secrets / GitLab CI variables : pratique pour injecter des secrets au runtime CI. Bon pour commencer.
  • SOPS (souvent avec age ou KMS) : bon compromis GitOps, secrets chiffrés versionnés dans Git, déchiffrés en CI.
  • HashiCorp Vault : plus lourd, mais excellent pour rotation, TTL, politiques.

-vvv

Séparez les secrets par environnement. Et limitez les scopes : un secret de prod ne doit jamais être accessible à un job qui tourne sur une branche non protégée.

Implémentation GitHub Actions : workflow complet (lint → dry-run → déploiement)

Un workflow GitHub Actions typique, en étapes.

  1. Checkout du code
  2. Setup Python + Ansible
  3. Installation des dépendances
  4. ansible-lint
  5. syntax-check
  6. check
  7. Déploiement staging
  8. Déploiement prod avec approbation

Un exemple de workflow simplifié :

yaml name: ansible-gitops

on: pull_request: push: branches: [ "main" ] workflow_dispatch:

jobs: lint-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4

  - uses: actions/setup-python@v5
    with:
      python-version: "3.12"

  - name: install deps
    run: |
      python -m pip install --upgrade pip
      pip install ansible ansible-lint
      ansible-galaxy collection install -r requirements.yml

  - name: ansible-lint
    run: ansible-lint

  - name: syntax-check
    run: ansible-playbook -i inventories/staging/hosts.ini playbooks/site.yml --syntax-check

  - name: check mode (staging)
    run: ansible-playbook -i inventories/staging/hosts.ini playbooks/site.yml --check --diff

deploy-staging: if: github.ref == 'refs/heads/main' needs: [ lint-and-test ] runs-on: ubuntu-latest environment: staging steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: install deps run: | pip install ansible ansible-galaxy collection install -r requirements.yml

  - name: deploy staging
    env:
      SSH_PRIVATE_KEY: ${{ secrets.STAGING_SSH_KEY }}
    run: |
      mkdir -p ~/.ssh
      echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
      chmod 600 ~/.ssh/id_rsa
      ansible-playbook -i inventories/staging/hosts.ini playbooks/site.yml

deploy-prod: if: github.ref == 'refs/heads/main' needs: [ deploy-staging ] runs-on: ubuntu-latest environment: prod steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: install deps run: | pip install ansible ansible-galaxy collection install -r requirements.yml

  - name: deploy prod
    env:
      SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_KEY }}
    run: |
      mkdir -p ~/.ssh
      echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
      chmod 600 ~/.ssh/id_rsa
      ansible-playbook -i inventories/prod/hosts.ini playbooks/site.yml --serial 2

Deux points importants ici :

  • deploy-prodprodmain
  • --serial

Côté artefacts et logs, vous pouvez rediriger la sortie Ansible vers un fichier et l’uploader, ou générer un petit résumé. Le minimum, c’est que l’historique de run soit consultable.

Stratégie de déclenchement recommandée :

  • PR : lint + tests uniquement.
  • main
  • workflow_dispatch

Implémentation GitLab CI : pipeline équivalent (stages, environnements, approbations)

stageslinttestdeploy

.gitlab-ci.yml

yaml stages:

  • lint
  • test
  • deploy

image: python:3.12-slim

before_script:

  • pip install --upgrade pip
  • pip install ansible ansible-lint
  • ansible-galaxy collection install -r requirements.yml

lint: stage: lint script: - ansible-lint rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH

syntax_check: stage: test script: - ansible-playbook -i inventories/staging/hosts.ini playbooks/site.yml --syntax-check rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH

deploy_staging: stage: deploy environment: name: staging script: - mkdir -p ~/.ssh - echo "$STAGING_SSH_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ansible-playbook -i inventories/staging/hosts.ini playbooks/site.yml rules: - if: $CI_COMMIT_BRANCH == "main"

deploy_prod: stage: deploy environment: name: prod script: - mkdir -p ~/.ssh - echo "$PROD_SSH_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ansible-playbook -i inventories/prod/hosts.ini playbooks/site.yml --serial 2 when: manual rules: - if: $CI_COMMIT_BRANCH == "main"

Runners :

  • Shared runners, c’est bien pour lint et tests.
  • Pour déployer vers des serveurs privés, un runner self managed, tagué, dans le bon réseau, c’est souvent obligatoire.

Variables GitLab :

  • maskedprotected
  • scopes par environnement si besoin.
  • et attention aux pipelines sur branches non protégées : ne leur donnez jamais accès à la prod.

Approvals et protections :

  • branches protégées,
  • merge requests obligatoires,
  • when: manual
  • environnements protégés selon édition GitLab.

Comparaison rapide, côté ops : GitLab est très confortable sur la notion d’environnements et de variables protégées, GitHub est très fluide sur l’intégration repo et les environnements avec reviewers. Les deux marchent. Le point qui compte le plus reste souvent le réseau et les runners.

Stratégies de déploiement sûres : comment éviter le « push qui casse tout »

Trois axes.

Déploiement progressif

  • --serial
  • prod_canaryprod
  • --tags nginx

Gating

  • lint + tests obligatoires avant deploy.
  • review de PR.
  • approbations pour prod.

Ça paraît bureaucratique, mais c’est juste de la mémoire externe. Quand vous êtes fatigué, c’est la CI qui vous empêche de faire une bêtise.

Concurrence et verrous

Empêchez deux déploiements simultanés sur prod.

  • GitHub : concurrency groups.
  • GitLab : resource groups.

Sinon, vous aurez un run qui change un fichier pendant qu’un autre redémarre un service. Et vous allez passer une heure à comprendre un bug qui n’en est pas un.

Re-run safe

Si vous ne pouvez pas relancer un déploiement sans stresser, vous n’êtes pas en GitOps. Utilisez l’idempotence, les handlers, et faites attention aux tâches non idempotentes. Parfois il faut refactorer. Oui, c’est du boulot. Mais c’est un investissement direct.

Validation post-déploiement : le chaînon manquant (et pourtant simple)

Déployer, ce n’est pas terminer. Terminer, c’est valider.

Tests de santé simples :

  • systemd
  • wait_for
  • uri
  • version de package, checksum de config, etc.

Vous pouvez le faire en Ansible, dans un playbook « post ».

Exemples utiles :

  • assert
  • failed_when
  • changed_when

Observabilité :

  • envoyer un résumé Slack/Teams/email.
  • annoter une release.
  • journaliser l’ID de pipeline et le commit déployé.

Rollback :

  • re run d’un tag Git connu.
  • revert commit.
  • revenir à une version précédente d’un rôle ou d’une collection.

Définissez une « definition of done » pour un déploiement de config. Par exemple : « playbook OK + endpoint 200 + service actif + pas d’erreurs dans les logs Nginx sur 2 minutes ». Ce n’est pas parfait, mais c’est déjà un filet.

Exemple de cas réel : durcissement SSH + utilisateurs + firewall + Nginx (workflow de bout en bout)

Mini scope, réaliste, très fréquent :

  • roles/ssh_hardening
  • roles/users
  • roles/firewall
  • roles/nginx

Variables par environnement.

Exemples :

  • En dev, vous autorisez le port 22 depuis votre IP de bureau.
  • En prod, SSH passe par un bastion, et vous limitez à une allowlist stricte.
  • En prod, Nginx écoute sur 80 et 443, en staging peut être seulement 80.
  • devops_test

Flux GitOps :

  1. Une PR introduit un changement, par exemple désactiver l’auth par mot de passe SSH.
  2. ansible-lintsyntax-check--check
  3. Review. On discute. On ajuste.
  4. main
  5. Déploiement auto sur staging.
  6. Validation post déploiement : SSH OK, Nginx répond.
  7. --serial 2
  8. Re validation prod.

Et surtout, traçabilité : le commit vous dit exactement « qui a changé quoi, quand, pourquoi ». Vous avez les commentaires de PR, les approvals, l’historique des runs. Quand un audit arrive, ou quand un incident arrive, vous ne fouillez pas des terminaux. Vous lisez Git.

Les erreurs fréquentes (et comment les éviter)

  1. Playbooks non idempotents
  2. shellchanged_when
  3. Inventaires mal séparés
  4. inventories/devstagingprod
  5. Runners sans accès réseau maîtrisé
  6. Ouvrir SSH prod à tous les IP d’un provider, ça arrive. Solution : runner self hosted dans le réseau, bastion, VPN, allowlist stricte.
  7. Absence de garde fous
  8. Déploiement direct sur prod, sans approbation, sans tests. Solution : gating obligatoire, job manuel pour prod, environnements protégés.
  9. Couplage trop fort
  10. site.yml

Conclusion : le « minimum viable GitOps » à mettre en place dès cette semaine

Si vous devez faire simple et utile, dès cette semaine :

  • un repo propre (structure claire, inventaires séparés),
  • ansible-lint
  • un pipeline CI qui fait lint + syntax check + éventuellement check mode,
  • secrets gérés proprement (Vault, secrets CI, ou SOPS), séparés par environnement,
  • déploiement automatique sur staging, puis prod avec approbation.

ssh_hardening

Le vrai cœur de GitOps, ce n’est pas l’outil. C’est la discipline : Git comme source de vérité, PRs, reviews, logs, et l’interdiction tacite des changements invisibles.

Et la prochaine étape, quand tout ça tient ? Inventaire dynamique, SOPS ou Vault plus mature, tests Molecule, runners dédiés, policies plus strictes. Mais pas avant d’avoir un socle simple qui marche, tous les jours.

Questions fréquemment posées

Qu'est-ce que GitOps et pourquoi révolutionne-t-il la gestion de configuration ?

GitOps est une approche qui combine Git comme source de vérité, automatisation et traçabilité pour gérer la configuration des infrastructures. Contrairement à l'Ansible "à la main", GitOps assure que toute modification est versionnée dans Git, appliquée automatiquement de manière répétable, et trace chaque changement, évitant ainsi le drift entre serveurs et facilitant les rollbacks.

Pourquoi l'utilisation d'Ansible seule ne suffit plus pour une gestion efficace ?

Bien qu'Ansible permette d'automatiser la configuration via des playbooks, son utilisation manuelle reste sujette aux erreurs humaines, au drift des configurations et à un manque de traçabilité. Sans intégration dans un processus GitOps, les modifications peuvent être appliquées de façon non standardisée, rendant les rollbacks et audits difficiles.

Quels sont les principaux bénéfices concrets apportés par GitOps ?

GitOps offre plusieurs avantages clés : reproductibilité des configurations sur tous les serveurs, audit complet des changements via commits et PRs, possibilité de rollback rapide en cas de problème, standardisation des environnements (utilisateurs, règles SSH, services), et facilitation de l'onboarding grâce à un flux clair basé sur le dépôt Git.

Comment s'intègre Ansible dans un pipeline GitOps avec GitHub Actions ou GitLab CI ?

Dans un modèle pragmatique GitOps, Ansible est utilisé pour configurer automatiquement les serveurs via des playbooks idempotents. Le flux typique est : commit → CI/CD (GitHub Actions ou GitLab CI) → tests → déploiement Ansible → validation post-déploiement. Ce processus permet d'automatiser la configuration tout en bénéficiant des outils natifs du dépôt pour la revue et la gestion des permissions.

Quels sont les critères pour choisir entre GitHub Actions et GitLab CI dans un contexte GitOps ?

Le choix dépend du contexte spécifique de l'équipe : gestion et disponibilité des runners (auto-hébergés ou cloud), gestion fine des variables et secrets par environnement, modèle de permissions et protection des branches, ainsi que l'expérience préalable de l'équipe avec une plateforme donnée. Par exemple, une équipe déjà familière avec GitLab privilégiera souvent GitLab CI pour sa simplicité d'intégration.

Quelles précautions prendre avant de lancer un projet GitOps pour éviter les échecs ?

Avant d'écrire le premier workflow, il est crucial de poser des bases solides telles qu'un inventaire clair (statique ou dynamique), garantir que les playbooks Ansible sont bien écrits et idempotents, définir une gouvernance claire sur qui peut déployer quoi et où, gérer correctement les secrets sensibles, et mettre en place une stratégie de tests rigoureuse afin d'éviter d'automatiser des erreurs.

Enregistrer un commentaire

0 Commentaires

Comments

Nouveau Drop

Boutique Officielle

Soutenez le blog monblog-sa-abasse et découvrez nos vêtements & accessoires exclusifs en édition limitée.

Découvrir la collection
Paiement Sécurisé
Livraison Monde

Ad Code

Soutenez la Création

Aidez-moi à partager du contenu exclusif.

Soutenir