Fondamentaux du CI/CD¶
Anatomie d'un pipeline¶
Un pipeline CI/CD est une sequence d'étapes automatisees declenchee par un événement (push, tag, merge request). Chaque étape produit un résultat qui alimente la suivante.
graph LR
Trigger --> Build --> Test --> Scan --> Package --> Deploy
Deploy --> Production
Package --> Registre["Registre (Harbor)"]
Scan --> Rapport_sec["Rapport securite (Trivy)"]
Test --> Rapport_test["Rapport tests + couverture"]
Build --> Artefact["Artefact compile"]
Trigger --> Evenement["Push / Tag / Merge<br/>Cron / Webhook"] Étapes détaillées¶
| Étape | Objectif | Outils typiques | Artefact produit |
|---|---|---|---|
| Trigger | Déclencher le pipeline | Webhook Git, cron, dispatch manuel | Événement |
| Build | Compiler le code, construire l'image | go build, npm, Containerfile | Binaire, image OCI |
| Test | Valider le comportement (unit, integration) | pytest, go test, Jest | Rapport de tests |
| Scan | Détecter vulnerabilites et defauts de qualité | Trivy, SonarQube, hadolint | Rapport de sécurité |
| Package | Pousser l'artefact dans un registre | podman push, helm package | Image taguee dans Harbor |
| Deploy | Déployer sur l'environnement cible | Flux v2 sync, kubectl apply | Application en production |
Pipeline-as-Code¶
Le pipeline est defini dans un fichier YAML versionne dans le dépôt. Chaque modification du pipeline suit le même workflow que le code : review, merge, historique.
Fichier de workflow Gitea Actions¶
# .gitea/workflows/ci.yaml
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: make build
- name: Test
run: make test
- name: Scan
run: trivy fs --exit-code 1 .
Avantages du pipeline-as-code¶
| Avantage | Description |
|---|---|
| Versionnement | Le pipeline évolue avec le code, chaque changement est trace |
| Reproductibilite | Le même commit produit toujours le même pipeline |
| Review | Les modifications du pipeline passent par le même processus de review |
| Self-service | Les développeurs modifient leur pipeline sans dépendre d'un admin CI |
| Disaster recovery | Le pipeline est restaure avec le dépôt — pas de configuration orpheline |
Runners, agents et workers¶
Le runner est le composant qui execute les étapes du pipeline. Il reçoit les jobs du serveur CI, execute les commandes dans un environnement isole et renvoie les résultats.
Architecture runner¶
graph LR
CI["Serveur CI<br/>(Gitea)<br/><br/>File de jobs<br/>Resultats<br/>Artefacts"] <-->|gRPC| R1["Runner #1<br/>(act runner)<br/>Conteneur ephemere"]
CI <-->|gRPC| R2["Runner #2<br/>(act runner)<br/>VM persistante"] Ephemere vs persistant¶
| Caractéristique | Runner ephemere | Runner persistant |
|---|---|---|
| Cycle de vie | Cree pour un job, detruit apres | Demarre une fois, traite plusieurs jobs |
| Isolation | Forte (chaque job = environnement neuf) | Faible (risque de pollution entre jobs) |
| Performance | Temps de demarrage à chaque job | Pas de demarrage, cache reutilise |
| Sécurité | Pas de residus de secrets entre jobs | Risque de fuite de secrets entre jobs |
| Cas d'usage | Production, pipelines sensibles | Dev, builds lourds avec cache |
Recommandation
Privilegier les runners ephemeres en production. Le coût de demarrage (~10s pour un conteneur) est negligeable face au gain en isolation et en sécurité.
Passage d'artefacts entre étapes¶
Les étapes d'un pipeline doivent partager des artefacts (binaires compiles, rapports de tests, images). Plusieurs mécanismes existent :
| Mécanisme | Description | Exemple |
|---|---|---|
| Cache | Répertoires persistants entre runs (dependencies) | ~/.cache/go-build, node_modules |
| Artifacts | Fichiers uploades par un job, telecharges par un autre | Binaire compile, rapport HTML |
| Registre OCI | Image poussee dans Harbor, tiree par le déploiement | harbor.example.com/app:v1.2.3 |
| Volume partage | Volume monte dans tous les conteneurs du même job | Workspace du job |
# Exemple : partage d'artefacts entre jobs
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make build
- uses: actions/upload-artifact@v4
with:
name: binary
path: ./bin/app
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: binary
- run: ./deploy.sh
Injection de secrets¶
Les secrets (tokens, credentials, cles) ne doivent jamais apparaître dans le code du pipeline. Ils sont injectes a l'execution.
Méthodes d'injection¶
| Méthode | Source | Sécurité | Exemple |
|---|---|---|---|
| Variables CI | UI du serveur CI | Moyenne | ${{ secrets.REGISTRY_PASSWORD }} |
| Vault injection | HashiCorp Vault | Forte | vault kv get secret/ci/registry |
| Fichier monte | Secret Kubernetes | Forte | /run/secrets/registry_password |
| OIDC token exchange | IdP (Keycloak) | Forte | Token ephemere sans secret statique |
Regles absolues
- Ne jamais logger un secret (désactiver
set -xautour des commandes sensibles) - Ne jamais passer un secret en argument de commande (visible dans
/proc) - Utiliser des tokens ephemeres plutôt que des credentials statiques
- Rotationner les secrets régulièrement (90 jours maximum)
Stratégies de déploiement¶
Le déploiement est l'étape la plus critique. Plusieurs stratégies permettent de limiter l'impact d'une régression.
Comparaison des stratégies¶
| Stratégie | Principe | Risque | Rollback | Coût infra |
|---|---|---|---|---|
| Rolling | Remplacement progressif des instances | Moyen | Redeploy ancien | x1 |
| Blue/Green | Deux environnements, bascule instantanee | Faible | Rebascule | x2 |
| Canary | Petit pourcentage du trafic vers la nouvelle version | Tres faible | Retrait du canary | x1 + epsilon |
| Recreate | Arrêt total, redeploy | Eleve (downtime) | Redeploy ancien | x1 |
Rolling update¶
graph TD
T0["Temps 0 : v1 v1 v1 v1"]
T1["Temps 1 : <b>v2</b> v1 v1 v1 — une instance remplacee"]
T2["Temps 2 : <b>v2 v2</b> v1 v1"]
T3["Temps 3 : <b>v2 v2 v2</b> v1"]
T4["Temps 4 : <b>v2 v2 v2 v2</b> — deploiement termine"]
T0 --> T1 --> T2 --> T3 --> T4 Blue/Green¶
graph LR
subgraph Avant bascule
T1["Traffic"] -->|100%| Blue1["Blue (v1) — actif"]
Green1["Green (v2) — pret, pas de trafic"]
end
subgraph Apres bascule
T2["Traffic"] -->|100%| Green2["Green (v2) — actif"]
Blue2["Blue (v1) — standby"]
end Canary¶
graph LR
Traffic["Traffic"]
Traffic -->|95%| Stable["Stable v1"]
Traffic -->|5%| Canary["Canary v2<br/>observation des metriques"] Modèle GitOps¶
GitOps est un paradigme de déploiement ou l'état desire de l'infrastructure est declare dans un dépôt Git. Un opérateur (Flux v2) reconcilie en permanence l'état reel du cluster avec l'état declare.
Principes fondamentaux¶
| Principe | Description |
|---|---|
| Declaratif | L'état desire est décrit dans des manifestes (YAML, Helm, Kustomize) |
| Versionne | Git est la source de vérité unique |
| Automatise | Les changements sont appliques automatiquement par l'opérateur |
| Observable | L'opérateur détecte et signale les derivations (drift) |
Boucle de reconciliation¶
graph LR
Git["Depot Git
etat desire
manifests/
app/deployment.yaml"] --> FluxV2["Flux v2
operateur
Compare desired
vs actual
Sync si diff"]
FluxV2 --> K8s["Cluster K8s
etat reel
Pods, Services,
ConfigMaps..."]
FluxV2 --> Drift{"Drift detecte ?"}
Drift --> Sync["Sync automatique
ou alerte"] Pull vs Push deployment¶
| Modèle | Sens du flux | Sécurité | Exemple |
|---|---|---|---|
| Push | Le CI pousse vers le cluster | Le CI a des credentials du cluster | kubectl apply |
| Pull | L'opérateur tire depuis Git | Le cluster tire, pas de credentials CI | Flux v2 sync |
Recommandation GitOps
Le modèle pull est plus securise : le cluster n'expose pas d'API au CI, et les credentials du cluster ne sortent jamais du cluster. C'est le modèle natif de Flux v2.
Recapitulatif¶
| Concept | Point cle |
|---|---|
| Pipeline-as-code | Le pipeline vit dans le dépôt, versionne et reviewable |
| Runners ephemeres | Un conteneur par job pour l'isolation maximale |
| Artefacts | Upload/download entre jobs, images OCI pour le déploiement |
| Secrets | Injection depuis Vault, jamais en clair dans le pipeline |
| Déploiement | Rolling pour la simplicité, Blue/Green ou Canary pour la sécurité |
| GitOps | Git = source de vérité, Flux v2 = reconciliation automatique |