Environnements et Déploiements : Maîtriser la Mise en Production
Dans le cycle de développement professionnel, la mise en production est l'étape la plus critique. Pour éviter les erreurs catastrophiques, on ne déploie jamais un code qui n'a pas été testé dans un environnement identique à la cible. L'objectif de ce chapitre est de transformer votre pipeline de simple outil de test en une véritable plateforme de livraison sécurisée et orchestrée.
Les Environnements : Suivre ses versions en temps réel
Les environnements GitLab permettent de définir où votre code est déployé. GitLab CI suit précisément chaque action, vous permettant de savoir en temps réel quelle version est en ligne sur quel serveur (Staging, Production, etc.).
Analyse détaillée du code de déploiement
Voici comment configurer vos jobs pour gérer deux environnements distincts avec des règles de sécurité strictes.
# Déploiement automatique sur l'environnement de test
deploy_staging:
stage: deploy
script:
- echo "Déploiement en cours sur le serveur de test..."
environment:
name: staging
url: https://staging.mon-app.com # Lien pour ouvrir l'app depuis GitLab
rules:
- if: $CI_COMMIT_BRANCH == "develop" # Uniquement si on est sur la branche de dev
# Déploiement sécurisé pour la production
deploy_production:
stage: deploy
script:
- echo "Déploiement en cours sur le serveur de production..."
environment:
name: production
url: https://www.mon-app.com
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Uniquement sur la branche principale
when: manual # Sécurité CRITIQUE : demande un clic humain pour valider
Explication des mots-clés :
- environment:name : Identifie l'environnement dans l'interface GitLab. Cela permet de grouper les déploiements et de voir l'historique par serveur.
- environment:url : Ajoute un bouton View deployment dans GitLab pour accéder directement à l'application.
- when: manual : C'est la sécurité indispensable. Le job apparaît avec une icône Play, il ne s'exécutera que si un responsable clique dessus, évitant les déploiements accidentels.
Échange de clés SSH
Le SSH (Secure Shell) ne fonctionne pas par magie : pour que votre Runner GitLab puisse se connecter à votre serveur de production sans taper de mot de passe, il doit y avoir une relation de confiance préalable. Cette confiance repose sur l'échange de clés asymétriques.
Imaginez un système de cadenas et de clé :
- La clé publique (Le cadenas) : Vous la placez sur votre serveur de destination. Elle peut être vue par tout le monde, elle ne sert qu'à verrouiller l'accès.
- La clé privée (La clé physique) : Elle reste cachée dans GitLab. C'est la seule capable d'ouvrir le cadenas (la clé publique) placé sur le serveur.
Générer la paire de clés
Sur votre propre ordinateur, vous devez générer ce couple de clés. Nous utiliserons l'algorithme ED25519, plus court, plus rapide et plus sécurisé que l'ancien RSA.
# Génération de la paire de clés (laissez le mot de passe vide pour la CI/CD)
ssh-keygen -t ed25519 -C "gitlab-ci-deploy"
Cela va créer deux fichiers :
- id_ed25519 : Votre clé privée (À NE JAMAIS PARTAGER).
- id_ed25519.pub : Votre clé publique.
Autoriser la clé sur le serveur (Le cadenas)
Vous devez maintenant dire à votre serveur de production : "J'autorise toute personne possédant la clé privée correspondante à se connecter". Pour cela, vous devez copier le contenu de votre clé publique (.pub) et l'ajouter dans le fichier suivant sur votre serveur :
~/.ssh/authorized_keys
# Commande rapide pour envoyer la clé publique sur le serveur
ssh-copy-id -i ~/.ssh/id_ed25519.pub utilisateur@ip_du_serveur
Configurer GitLab (La clé privée)
C'est ici que la sécurité est primordiale. Vous ne devez jamais mettre votre clé privée dans votre code source.
- Protéger la branche : Allez dans Settings > Repository > Protected branches et assurez-vous que main est protégée (seuls les Maintainers peuvent y pousser/fusionner).
- Configurer la variable : Allez dans Settings > CI/CD > Variables.
-
Paramètres de la variable :
- Key : SSH_PRIVATE_KEY
- Value : Collez votre clé privée ED25519.
- Type : Sélectionnez File (cela évite les problèmes de caractères spéciaux dans les scripts).
- Protect variable : C'est votre protection contre le vol de secrets par des branches non autorisées. En activant cette option, votre clé privée ne sera injectée que dans les pipelines s'exécutant sur des branches elles-mêmes protégées (comme main).
- Mask variable : Cela remplacera la clé par [MASKED] dans les logs si elle est affichée par erreur.
Le rôle du script dans le Pipeline
Une fois ces étapes manuelles terminées, le code que nous avons vu précédemment prend tout son sens. Le Runner va exécuter ces actions à chaque déploiement :
# 1. Démarre un agent SSH en mémoire
- eval $(ssh-agent -s)
# 2. Charge la clé privée depuis la variable GitLab vers l'agent
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
# 3. Vérifie l'identité du serveur pour éviter les attaques "Man-in-the-middle"
- ssh-keyscan -H $SERVER_IP >> ~/.ssh/known_hosts
Pourquoi ssh-keyscan ?
C'est une étape cruciale. Lors d'une première connexion, SSH vous demande toujours : "Êtes-vous sûr de vouloir vous connecter ?". En mode automatique (CI/CD), personne ne peut répondre "Oui". ssh-keyscan récupère l'empreinte du serveur à l'avance pour que la connexion soit validée automatiquement.
Script dans le Pipeline
Exemple de jobs de connexion sécurisée :
.ssh_setup: &ssh_setup
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- ssh-keyscan -H $SERVER_IP >> ~/.ssh/known_hosts
deploy_ssh:
<<: *ssh_setup
stage: deploy
script:
- rsync -avz --delete dist/ $SERVER_USER@$SERVER_IP:/var/www/html/
- rsync : C'est l'outil privilégié pour synchroniser les fichiers. Il n'envoie que les modifications, ce qui rend le déploiement ultra-rapide.
- ssh-keyscan : Enregistre l'empreinte du serveur pour éviter que le job ne s'arrête en demandant "Voulez-vous faire confiance à cet hôte ?".
Automatisation avancée : Triggers et Schedules
Les Déclencheurs (Triggers)
Un Trigger permet de lancer un pipeline via une requête externe (API). C'est utile pour lier GitLab à un outil de monitoring ou un autre projet qui vient de finir sa compilation.
Pour qu'un Trigger fonctionne, GitLab a besoin d'une preuve que l'appelant est autorisé : c'est le Token de déclenchement.
- Allez dans Settings > CI/CD > Pipeline triggers.
- Créez un nouveau jeton avec une description (ex: "Appel depuis CMS").
- Récupérez le jeton généré.
Exemple d'appel API pour déclencher un pipeline:
curl --request POST \
--form token=VOTRE_TOKEN_ICI \
--form ref=main \
https://gitlab.example.com/api/v4/projects/ID/trigger/pipeline
- token : Votre clé secrète pour prouver l'autorisation.
- ref : La branche sur laquelle vous voulez lancer le pipeline (ex: main).
- ID_DU_PROJET : Le numéro unique de votre projet (visible sur la page d'accueil du projet).
Plus d'information sur l'api ici
La Planification (Schedules)
Utile pour les tâches récurrentes (sauvegardes, tests de sécurité hebdomadaires) qui doivent s'exécuter indépendamment des commits.
"Planification via format Cron"
Maîtriser la syntaxe Cron
GitLab utilise le format Cron standard pour définir la fréquence. Un Cron est composé de 5 champs : minute, heure, jour du mois, mois, jour de la semaine.
| Syntaxe Cron | Fréquence | Usage typique |
|---|---|---|
| 0 2 * * * | Tous les jours à 2h00 | Backup de base de données. |
| 0 0 * * 0 | Chaque dimanche à minuit | Scan de sécurité complet (SAST/DAST). |
| 0 8 * * 1-5 | 8h00 du lundi au vendredi | Vérification matinale de l'infrastructure. |
| */30 * * * * | Toutes les 30 minutes | Synchronisation de données ou monitoring. |
Utiliser les variables dans les Schedules
Une fonctionnalité très puissante consiste à ajouter des Variables CI/CD spécifiques au moment de créer le planning. Cela permet au pipeline de savoir qu'il tourne en mode "Planifié" et non en mode "Commit".
# Exemple dans le .gitlab-ci.yml
backup_job:
stage: deploy
script:
- echo "Démarrage de la sauvegarde..."
- ./scripts/backup.sh
rules:
# Ce job ne s'exécute QUE si le pipeline est déclenché par un Schedule
- if: $CI_PIPELINE_SOURCE == "schedule"
Le conseil du SysAdmin
Évitez de planifier tous vos pipelines à l'heure pile (ex: 00:00). Si vous avez 50 projets, vos Runners seront saturés au même moment. Décalez-les de quelques minutes (ex: 00:05, 00:12) pour lisser la charge sur vos serveurs.
Intégration avec Kubernetes
Pour qu'une application passe de GitLab à votre serveur, il faut que les deux communiquent. Historiquement, GitLab utilisait des clés SSH pour "forcer" la porte du serveur de l'extérieur. C'était complexe et dangereux pour la sécurité.
Aujourd'hui, on utilise l'Agent GitLab. Imaginez-le comme un agent de sécurité que vous embauchez pour travailler à l'intérieur de votre serveur.
- Connexion sortante (Pull) : Les portes de votre serveur restent fermées de l'extérieur. C'est l'agent qui, de l'intérieur, ouvre un tunnel sécurisé vers GitLab pour demander : "Y a-t-il du nouveau code à déployer ?".
- Surveillance continue : Grâce à ce tunnel, GitLab sait en permanence si votre serveur fonctionne correctement.
Le manuel d'instructions (Le Code)
Pour que tout fonctionne, vous devez créer un seul fichier de configuration dans un dépôt central (le dépôt Infrastructure). C'est le "cerveau" de l'agent.
entreprise/infrastructure/.gitlab/agents/mon-agent/config.yaml
# 1. Liste d'invités (Mode Manuel / CI-CD)
# On autorise les pipelines des autres dépôts à passer par ce pont.
user_access:
projects:
- id: entreprise/frontend
- id: entreprise/api
# 2. Pilote automatique (Mode Automatique / GitOps)
# On ordonne à l'agent de surveiller lui-même ce dépôt.
gitops:
manifest_projects:
- id: entreprise/infrastructure
paths:
- glob: '/kubernetes/*.yaml'
Pourquoi cette structure avec 3 dépôts ?
- Le dépôt Infrastructure : C'est le Propriétaire. Il possède le fichier de config et le jeton secret. Il sert de pont unique pour toute l'entreprise.
- Les dépôts Frontend & API : Ce sont les Utilisateurs. Ils n'ont pas besoin de configurer d'agent ni de gérer de jeton. Ils utilisent simplement le pont ouvert par l'Infrastructure via leur pipeline .gitlab-ci.yml.
Comment l'agent accède-t-il à tout ça sans mot de passe partout ?
Tout repose sur la hiérarchie GitLab : tant que vos projets sont dans le même groupe, GitLab sert d'arbitre. L'agent utilise son identité unique pour prouver à GitLab qu'il a le droit de lire le code du Backend ou d'accepter les ordres du Frontend.
Générer le badge d'accès (L'Interface)
Votre fichier est poussé sur GitLab. Le système détecte maintenant que l'agent "mon-agent" existe. Il faut lui créer son "passeport" (le Jeton/Token) pour qu'il puisse sortir du serveur et appeler GitLab.
- Allez dans le dépôt Infrastructure (uniquement celui-là).
- Dans le menu de gauche, accédez à Operate > Kubernetes clusters.
- Cliquez sur Connect a cluster.
- Un Jeton secret unique est généré.
Règle de sécurité absolue
Ce jeton ne s'affichera qu'une seule fois. Copiez-le temporairement. Ne l'écrivez jamais dans votre code source.
Sécurité centralisée
Ce jeton est le seul et l'unique pour toute votre infrastructure. Vous n'avez pas besoin de créer de jetons dans les dépôts Frontend ou API. C'est ce jeton que vous installerez sur votre serveur Kubernetes pour que le tunnel global s'ouvre.
Installer l'Agent sur le serveur (L'Infrastructure)
Nous avons le manuel (Étape 1) et le mot de passe (Étape 2). Il faut maintenant installer le petit programme "Agent" sur votre vrai serveur Kubernetes. On utilise l'outil helm depuis le terminal de votre serveur.
helm repo add gitlab https://charts.gitlab.io
helm repo update
helm upgrade --install mon-agent gitlab/gitlab-agent \
--set config.token=VOTRE_JETON_SECRET \
--set kasAddress=wss://kas.gitlab.com
Ces commandes téléchargent l'agent GitLab et l'installent sur votre serveur en lui fournissant le mot de passe et l'adresse web pour établir le tunnel sécurisé.
Utiliser le Tunnel (Deux méthodes au choix)
Le tunnel est ouvert (statut vert dans GitLab). C'est ici que la confusion survient souvent : vous avez maintenant deux façons d'envoyer votre application sur le serveur. Vous devez choisir celle qui convient à votre projet.
Méthode A : Le Pipeline Classique (CI/CD)
C'est la méthode manuelle et standard. Vous écrivez un script dans votre fichier .gitlab-ci.yml. Le pipeline s'exécute, se connecte au tunnel et donne les ordres au serveur.
deploy_to_k8s:
stage: deploy
image:
name: bitnami/kubectl:latest
entrypoint: [""]
script:
- kubectl config use-context entreprise/infrastructure:mon-agent
- kubectl apply -f deployment.yaml
- kubectl rollout status deployment/mon-app
Le job active la connexion au tunnel de l'agent, envoie le fichier de déploiement au serveur, puis vérifie que l'application a bien démarré.
Méthode B : Le Pilote Automatique (GitOps)
C'est la méthode moderne. Vous supprimez le job de déploiement de votre pipeline. Grâce au bloc gitops défini à l'étape précédente, l'agent se débrouille tout seul. Dès que vous modifiez un fichier YAML dans GitLab, l'agent le détecte et met à jour le serveur instantanément, garantissant que le serveur est toujours une copie conforme de votre code.
Conclusion
La maîtrise des Environnements et des accès SSH transforme votre simple script de test en une usine de production robuste. En automatisant vos déploiements, vous éliminez l'erreur humaine et garantissez une disponibilité maximale de vos services.
Espace commentaire
Écrire un commentaire
Rejoignez la discussion
Vous devez être connecté pour poster un message.
22 commentaires
L'installation de l'agent avec
helmme sort une erreur de certificat surkas.gitlab.com.Vérifie que ton cluster a bien accès à internet et que tu n'as pas de proxy qui bloque le trafic WebSocket. L'agent a besoin d'une connexion persistante via
wss://.Carrément. Ajoute tes variables lors de la création du planning dans l'interface GitLab. Tu peux ensuite les tester avec
$CI_PIPELINE_SOURCE == "schedule".Peut-on utiliser des variables dans les
Schedulespour changer la destination du build ?C'est parce que l'empreinte de ton serveur a changé. Nettoie ton
known_hostsou force la mise à jour viassh-keyscandans ton pipeline.J'ai un warning sur mon runner : "WARNING: Remote host identification has changed". Je fais quoi ?
Oui, ED25519 est bien plus performant et surtout plus court. Pour de la CI/CD, c'est le standard actuel.
Le
ssh-keygen -t ed25519est vraiment plus rapide que le RSA ?Oui, tu fais un saut de ligne et tu colles la seconde clé. C'est du standard SSH.
Est-ce qu'on peut mettre plusieurs clés publiques dans
authorized_keys?Utilise le flag
--deletedans ta commandersync. Ça synchronise parfaitement ton répertoire local avec le serveur :Ok bien vu, c'était ça. Par contre, pour le
rsync, comment je gère les fichiers supprimés sur le serveur cible ?Vérifie ton
config.yamldans le dépôt infrastructure. As-tu bien ajouté ton projet frontend dans la listeuser_access? Sans ça, l'agent rejette la requête.Je galère avec l'Agent Kubernetes. Le tunnel est bien ouvert, mais mon
kubectl applyéchoue avec un accès refusé.Vire la ligne, mais c'est à ne jamais faire en prod sauf si tu aimes jouer avec le feu.
Question sur le
when: manual. Si je veux forcer le déploiement sans clic, je vire juste la ligne ou il y a une autre option ?Utilise bien le type File pour ta variable. Si tu la mets en texte brut, les sauts de ligne sautent et la clé est corrompue. Voici le bloc à utiliser pour le fix :
Top, ça marche. Par contre pour le
SSH_PRIVATE_KEY, j'ai des erreurs de formatage. GitLab me rejette la clé.Ajoute
mkdir -p ~/.sshavant de manipuler tes clés. Si le dossier n'existe pas,ssh-keyscanne pourra jamais écrire dansknown_hosts.Même avec l'installation, j'ai une erreur de permission sur le dossier
~/.ssh. Une idée ?C'est normal, ton image doit inclure les outils de base. Vérifie bien que tu as installé
openssh-clientdans tonbefore_scriptcomme indiqué dans l'article.J'ai un souci avec mon déploiement SSH. Mon pipeline échoue sur le
ssh-keyscan. Il me dit que la commande est introuvable alors que j'utilise l'image de base.