Projet Orion - Industrialisation d'une chaîne DevOps de bout en bout
De l'audit des pratiques Dev/Ops à une plateforme CI/CD automatisée, sécurisée et observable
Contexte
Dans le cadre du projet Orion, j'ai accompagné la transformation d'un processus de livraison largement manuel vers une chaîne DevOps automatisée.
Le projet a commencé par un audit des pratiques des équipes de développement et d'exploitation, mettant notamment en évidence l'absence de pipeline CI/CD, les déploiements manuels, une détection trop tardive des vulnérabilités et une dépendance à un registre Docker externe. À partir de ces constats, j'ai défini puis mis en œuvre une architecture permettant d'automatiser progressivement l'ensemble du cycle :
Le projet a ensuite évolué vers une infrastructure AWS EKS, entièrement provisionnée par Terraform, configurée par Ansible et déployée avec Helm, avec une stack de supervision Prometheus/Loki/Grafana et le suivi automatisé des métriques DORA.
🎯 Mes objectifs
- Automatiser le cycle de livraison de l'application.
- Réduire les interventions manuelles entre les équipes Dev et Ops.
- Introduire des contrôles de qualité et de sécurité directement dans la CI.
- Rendre l'infrastructure reproductible grâce à l'IaC.
- Fiabiliser les déploiements et prévoir leur récupération en cas d'échec.
- Mettre en place une véritable observabilité de la plateforme.
- Mesurer la performance du processus avec les métriques DORA.
Les grandes étapes du projet
Audit et définition de la stratégie DevOps
La première étape a consisté à comprendre comment les équipes travaillaient réellement, plutôt que de commencer directement par la technique.
L'audit des équipes Dev et Ops a permis d'identifier plusieurs points de friction :
- absence de CI/CD automatisée ;
- génération et transmission manuelles des images Docker ;
- déploiement manuel ;
- analyse de sécurité effectuée trop tard dans le cycle ;
- absence d'analyse statique du code ;
- dépendance à DockerHub ;
- risques liés à la concentration des connaissances sur quelques personnes.
À partir de ces constats, j'ai réalisé une veille technologique et une analyse comparative afin de sélectionner les outils adaptés aux contraintes du projet. GitLab CI, SonarQube, Trivy et GitLab Container Registry ont notamment été retenus.
Choix important : privilégier une chaîne relativement simple et intégrée à GitLab plutôt que multiplier les composants.
Construction du pipeline CI/CD
J'ai ensuite construit la première chaîne CI/CD autour de GitLab CI.
Le pipeline automatise progressivement :
Le versionnement a été automatisé avec Semantic Release, permettant de déduire la nouvelle version à partir des Conventional Commits, de créer les tags, le changelog et la release GitLab.
Les images frontend, backend et standalone sont ensuite construites et publiées dans le GitLab Container Registry.
Intégration de la qualité et de la sécurité dans la CI
J'ai intégré deux niveaux de contrôle complémentaires.
SonarQube / SonarCloud
Analyse du code frontend Angular et backend Java afin de détecter les problèmes de qualité, les vulnérabilités et la dette technique.
J'ai également corrigé le système de couverture de tests :
- JaCoCo côté backend ;
- LCOV côté frontend ;
- transmission des rapports entre les jobs GitLab ;
- intégration des résultats dans SonarCloud.
La refonte backend a ensuite permis d'obtenir environ 94 % de couverture d'instructions JaCoCo.
Trivy
Trivy a été positionné immédiatement après la construction des images Docker, avant leur publication.
Ce positionnement permet de bloquer le pipeline lorsqu'une vulnérabilité critique est détectée.
Le mécanisme a notamment permis d'identifier plusieurs CVE critiques dans Tomcat et de les corriger avant publication.
Conteneurisation et migration vers Kubernetes
Après la première industrialisation CI/CD, le projet a évolué vers une infrastructure Kubernetes réelle.
J'ai conservé un Dockerfile multi-stage permettant de construire les différentes applications et ajouté un environnement Docker Compose pour valider localement le fonctionnement frontend/backend avant déploiement.
Puis j'ai fait évoluer l'architecture vers :
Les premières ressources Kubernetes ont été créées sous forme de manifests afin de valider le fonctionnement de l'application.
J'ai ensuite transformé ces manifests en Chart Helm paramétrable, notamment pour gérer les versions d'images, le nombre de replicas et les ressources Kubernetes.
Infrastructure as Code avec Terraform et Ansible
L'infrastructure cible a été déployée sur AWS EKS.
Terraform
Terraform est responsable de la création de l'infrastructure AWS :
- VPC ;
- sous-réseaux publics et privés ;
- cluster EKS ;
- node group ;
- ressources IAM ;
- composants nécessaires au cluster.
L'état Terraform a ensuite été migré d'un stockage local vers un backend S3 distant avec verrouillage, afin de rendre l'utilisation de Terraform compatible avec la CI/CD.
Ansible
Ansible intervient pour les opérations de configuration du cluster, notamment :
- création du namespace applicatif ;
- création du secret permettant l'accès au registry ;
- configuration de composants Kubernetes nécessaires au fonctionnement de la plateforme.
Les tâches sont conçues pour être idempotentes.
Automatisation complète de l'infrastructure dans GitLab
Une fois Terraform et Ansible stabilisés localement, je les ai intégrés au pipeline.
Le workflow devient alors :
Un choix important a été fait ici : Terraform Apply reste manuel.
L'objectif est de conserver un garde-fou humain avant toute modification réelle de l'infrastructure AWS, notamment parce que certaines opérations peuvent entraîner des coûts.
Fiabilisation et rollback automatique
Le déploiement ne se limite pas à lancer un nouveau conteneur.
J'ai mis en place un mécanisme permettant de :
- Mémoriser la dernière version fonctionnelle.
- Déployer la nouvelle version.
- Effectuer un health check.
- Attendre la disponibilité réelle de l'application.
- Restaurer automatiquement la version précédente en cas d'échec.
- Faire échouer le pipeline afin que l'incident reste visible.
Le mécanisme a été testé avec différents scénarios d'échec, notamment une version inexistante et un health check volontairement défaillant. Le rollback a effectivement restauré la version précédente.
Refonte de l'architecture backend
Le projet ne s'est finalement pas limité à l'infrastructure.
L'analyse du backend a révélé une architecture basée directement sur Spring Data REST, exposant les repositories JPA au client.
J'ai donc réalisé une refonte vers une architecture en couches :
avec :
- DTOs ;
- validation ;
- gestion centralisée des exceptions ;
- configuration CORS ;
- services métier ;
- tests repository ;
- tests services avec Mockito ;
- tests controllers avec @WebMvcTest.
Cette refonte a également permis de corriger plusieurs problèmes de conception et de sécurité identifiés lors de la revue de code.
Monitoring et observabilité
Pour superviser la plateforme, j'ai choisi une stack PLG : Prometheus + Loki + Grafana, plutôt qu'ELK.
Ce choix était volontaire : le cluster EKS utilise de petites instances t3.small, et Elasticsearch aurait représenté une charge mémoire trop importante pour les ressources disponibles.
La stack permet de centraliser :
- les métriques avec Prometheus ;
- les logs avec Loki ;
- la visualisation avec Grafana ;
- les métriques Kubernetes avec kube-state-metrics et node-exporter.
Mise en place des métriques DORA
J'ai automatisé le calcul des quatre métriques DORA :
- Deployment Frequency
- Lead Time for Changes
- Change Failure Rate
- Mean Time to Restore / MTTR
Un script Python interroge l'API GitLab, calcule les indicateurs sur une fenêtre glissante et pousse les résultats vers Prometheus Pushgateway.
Ces données sont ensuite visualisées dans un dashboard Grafana dédié.
J'ai également pris en compte les biais de mesure liés au fonctionnement du projet et notamment aux périodes où l'infrastructure était volontairement détruite entre deux sessions.
Durcissement de la sécurité
Une partie importante du projet a consisté à ne pas considérer les premières solutions comme définitives.
Par exemple, l'utilisateur IAM utilisé initialement par Terraform disposait d'AdministratorAccess.
J'ai finalement construit une policy IAM scoped adaptée aux ressources réellement utilisées par Terraform, puis supprimé les permissions trop larges.
La policy a été validée par un cycle réel de terraform destroy / terraform apply, permettant de confirmer que l'infrastructure pouvait être recréée avec les permissions restreintes.
Cette démarche est intéressante à valoriser car elle montre une évolution :
« ça fonctionne » , pour allers vers, « ça fonctionne de manière maîtrisée et sécurisée ».
Résolution d'incidents et amélioration continue
Le projet a également été un travail de diagnostic permanent.
Plusieurs problèmes réels ont été rencontrés puis résolus :
- permissions IAM AWS ;
- versions Kubernetes/EKS arrivées en fin de support ;
- authentification au GitLab Container Registry ;
- problèmes de configuration Helm ;
- pods en ImagePullBackOff ;
- Grafana en CrashLoopBackOff ;
- problèmes de ServiceMonitor Prometheus ;
- erreurs de pipeline GitLab ;
- gestion des credentials ;
- perte puis reconstruction du dashboard DORA.
Ces incidents ont été traités avec une démarche systématique :
C'est probablement l'un des aspects les plus représentatifs de ma démarche DevOps sur ce projet.
Architecture finale
Le résultat peut être résumé par ce flux :
┌──────────────────────┐
│ GitLab │
│ Source + CI/CD │
└──────────┬───────────┘
│
Semantic Release
│
┌──────────┴───────────┐
│ │
Tests SonarQube
│ │
└──────────┬───────────┘
│
Build
│
Trivy
│
▼
GitLab Container Registry
│
▼
Terraform / AWS EKS
│
Ansible
│
Helm
│
┌──────────┴───────────┐
│ │
Frontend Backend
│ │
└──────────┬───────────┘
│
Monitoring / Logs
│
┌──────────┼──────────────┐
│ │ │
Prometheus Loki Grafana
│
DORA