Contexte. Kiddoo est un projet académique réalisé en 2026 dans le cadre d’une simulation professionnelle encadrée. Il s’agit d’une API REST de mise en relation pour des services de garde d’enfants. Cet article documente l’architecture et les pratiques mises en œuvre ; il ne présente pas la plateforme comme un service commercial en production.
Le problème : livrer sans dépendre d’actions manuelles
Le point de départ était une API Rust composée de plusieurs services. La difficulté n’était pas seulement de la faire démarrer : il fallait pouvoir vérifier une modification, la packager, la faire progresser entre environnements et confirmer son état après le déploiement.
J’ai donc traité la livraison comme une chaîne cohérente plutôt que comme une succession de commandes :
- une modification doit être testée dans un environnement propre ;
- l’artefact déployé doit être identifié par une image versionnée ;
- chaque environnement doit déclarer explicitement la version attendue ;
- Kubernetes doit converger vers cet état sans intervention manuelle ;
- l’équipe doit pouvoir constater rapidement qu’un service est disponible, lent ou en erreur.
Cette approche réduit les écarts entre postes, améliore la traçabilité et prépare un retour arrière propre lorsqu’une version ne se comporte pas comme prévu.
Architecture applicative et responsabilités
Le dépôt applicatif est un workspace Rust. Il regroupe une bibliothèque database et trois services :
api-gateway, point d’entrée des requêtes ;identity-proxy, responsable des échanges liés à l’authentification ;orchestrator, destiné à coordonner certains traitements métier.
PostgreSQL est utilisé pour la persistance. Cette séparation des responsabilités rend les services plus faciles à tester et à conteneuriser, mais elle impose aussi des contrats réseau et une gestion explicite de la configuration.
Client
│
▼
api-gateway ───► identity-proxy
│
├────────────► orchestrator
│
└────────────► PostgreSQL

Vue d’ensemble de l’architecture Kiddoo et de ses composants de déploiement.
Le conteneur n’embarque ni identifiants ni paramètres propres à un environnement. Ports, URL internes et paramètres non sensibles sont injectés au démarrage ; les secrets suivent un mécanisme séparé. Cette distinction évite de reconstruire une image à chaque environnement et diminue le risque d’exposer un mot de passe dans Git ou dans les journaux.
Première barrière : une CI qui vérifie l’application dans un environnement jetable
GitHub Actions fournit un contexte Linux propre à chaque exécution. Le workflow lance un service postgres:17-alpine, attend son état de santé avec pg_isready, puis transmet aux tests l’URL de connexion appropriée.
Les vérifications couvrent le workspace complet :
cargo test --workspace --verbose
cargo fmt --check
cargo clippy -- -D warnings
cargo build --release
Tester le workspace plutôt qu’un seul binaire est important : une modification dans la bibliothèque de persistance peut affecter plusieurs services. Des tests d’intégration ont également été prévus pour les routes essentielles, notamment /health, /login et /me.
Les hooks pre-commit complètent la CI côté développeur. Ils détectent plus tôt les problèmes de formatage, certaines erreurs de syntaxe et l’ajout accidentel de fichiers sensibles. Ils ne remplacent pas la CI : ils raccourcissent simplement la boucle de retour avant le push.
Conteneuriser sans recréer les problèmes de la machine locale
Chaque service applicatif possède son Dockerfile. Docker Compose permet de lancer localement les composants nécessaires, avec un réseau interne et une configuration commune. La passerelle est le point exposé ; le proxy d’identité et PostgreSQL restent sur le réseau applicatif.
Un détail a été particulièrement important : dans un conteneur, localhost désigne le conteneur lui-même. Les appels inter-services utilisent donc les noms de services Compose, par exemple identity-proxy, plutôt qu’une adresse IP fixe ou localhost.
La donnée reste hors du cycle de vie d’un conteneur applicatif. Ainsi, remplacer une image par une version plus récente ne doit pas entraîner la perte de la base. Cette règle prépare aussi le passage entre PostgreSQL en test et RDS PostgreSQL dans un environnement AWS.
GitOps : faire de Git la source de vérité du déploiement
La chaîne de livraison sépare l’application de sa déclaration de déploiement :
- GitHub Actions valide et produit une image identifiée.
- L’image est publiée dans GitHub Container Registry.
- Le tag de l’image attendu est mis à jour dans la configuration de l’environnement cible.
- Argo CD détecte le changement Git et synchronise Kubernetes.
Kustomize évite de copier l’ensemble des manifests : une base commune porte la configuration partagée, tandis que des overlays adaptent les paramètres de développement, de préproduction et de production. Cette séparation donne un rôle clair aux environnements : intégrer vite, qualifier dans des conditions proches de la production, puis promouvoir une version stable.
Commit → CI → image GHCR:version
│
▼
overlay Kustomize de l'environnement
│
▼
dépôt Git (état désiré)
│
▼
Argo CD → cluster Kubernetes

Flux GitOps : un changement dans Git est synchronisé par Argo CD avec le cluster Kubernetes.
Le bénéfice principal est l’auditabilité : la version demandée et son historique sont visibles dans Git. En cas de régression, revenir à une déclaration connue est plus explicite et plus contrôlable qu’une modification directe du cluster.
Le socle AWS : Infrastructure as Code et défense en profondeur
Le projet comprend aussi une infrastructure AWS conçue avec Terraform. Son organisation modulaire sépare le réseau, le serveur EC2, la base RDS PostgreSQL et les environnements dev, staging et prod. Un backend S3 conserve l’état Terraform à distance afin de ne pas dépendre d’un fichier local unique.
Après le provisionnement, Ansible configure le système. AWS Systems Manager permet d’amorcer ce travail sans dépendre d’un SSH ouvert lors de la phase initiale. Les contrôles de sécurité appliqués sont les suivants :
- VPC et sous-réseaux séparant les composants ;
- groupes de sécurité n’autorisant que les flux nécessaires ;
- RDS non public, accessible depuis le groupe de sécurité applicatif ;
- chiffrement des volumes EBS et du stockage RDS ;
- Secrets Manager et Ansible Vault pour dissocier secrets et dépôt ;
- Cloudflare Tunnel pour exposer un service sans ouvrir directement son port applicatif ;
- durcissement SSH après le provisionnement, avec pare-feu et restrictions d’accès.
L’objectif n’est pas de prétendre qu’un composant suffit à sécuriser l’ensemble, mais de réduire la surface d’attaque à plusieurs niveaux : identité, réseau, données, secrets et administration.
Observer après le déploiement
Un déploiement réussi n’est pas seulement un déploiement dont les ressources sont créées. Il faut confirmer que les services peuvent répondre et que leurs ressources restent saines dans le temps.
Kubernetes utilise des sondes de disponibilité et de bon fonctionnement pour déterminer si un pod peut recevoir du trafic ou doit être redémarré. Prometheus collecte ensuite les indicateurs exposés par les services et la plateforme ; Grafana les rend lisibles dans des tableaux de bord.
Les indicateurs retenus répondent à des questions opérationnelles concrètes :
- le service est-il disponible ?
- le taux d’erreur ou le temps de réponse augmente-t-il ?
- CPU et mémoire approchent-ils de la saturation ?
- un pod redémarre-t-il de manière répétée ?
- les échecs liés à l’authentification signalent-ils une anomalie ?
Des règles d’alerte sont prévues pour ces situations. Elles ne remplacent pas l’analyse humaine, mais réduisent le délai entre l’apparition d’un symptôme et son investigation à partir des métriques et des logs.
Ce que je retiens
La valeur de cette réalisation vient surtout des liens entre les briques. Les tests deviennent utiles parce qu’ils bloquent une image défectueuse ; l’image est utile parce qu’elle est versionnée ; GitOps est utile parce que l’état demandé est lisible ; la supervision est utile parce qu’elle vérifie la conséquence réelle du déploiement.
Le projet m’a permis de pratiquer les compromis d’une chaîne DevOps complète : garder les environnements cohérents sans les confondre, automatiser sans perdre de contrôle, isoler les secrets, et prévoir l’exploitation dès la conception.
