Architectures cloud-native et industrialisation

cicd cloud-native devops docker kubernetes

Extrait du mémoire de Master 2 Cybersécurité et Cloud de Holali David GAVI — Partie 1/3.

1.1 Évolution des architectures logicielles

L’histoire des architectures logicielles est celle d’une quête permanente vers plus de modularité, de scalabilité et de résilience. Durant les années 2000, l’architecture monolithique dominait : une seule base de code, un seul déploiement, une seule base de données. Ce modèle, décrit par Richardson (2018) comme « le point de départ naturel de tout projet », présente l’avantage de la simplicité mais atteint rapidement ses limites face à la croissance.

L’émergence des architectures orientées services (SOA) dans les années 2005-2010 a introduit la notion de décomposition fonctionnelle. Cependant, comme le soulignent Newman (2021) et Fowler (2014), la SOA souffrait d’une complexité excessive liée aux Enterprise Service Bus (ESB), aux protocoles SOAP et aux schémas WSDL. Le couplage fort entre services via l’ESB central constituait un point de défaillance unique (Single Point of Failure).

La rupture survient avec les microservices, popularisés par les retours d’expérience de Netflix, Amazon et Spotify à partir de 2012. Fowler et Lewis (2014) définissent cette approche comme « un style architectural où une application est composée de petits services autonomes, communiquant via des mécanismes légers, typiquement des API HTTP/REST ». Chaque service possède sa propre base de données (pattern Database per Service), son propre cycle de déploiement et peut être développé dans un langage différent.

L’architecture cloud-native, formalisée par la Cloud Native Computing Foundation (CNCF), va plus loin en intégrant nativement les principes de conteneurisation, d’orchestration dynamique, de mesh de services et d’immutabilité de l’infrastructure. Selon le rapport CNCF (2024), 96% des organisations utilisent ou évaluent Kubernetes, et 79% exécutent des conteneurs en production.

La méthodologie Twelve-Factor App, proposée par Wiggins (2012) chez Heroku, établit les fondements des applications cloud-native : codebase unique en contrôle de version, dépendances explicites, configuration par variables d’environnement, services backing interchangeables, séparation build/release/run, processus stateless, port binding, concurrence par le modèle de processus, disposabilité avec démarrage rapide et arrêt gracieux, parité dev/prod, logs comme flux d’événements, et processus d’administration ponctuels.

1.2 Conteneurisation et Docker

La conteneurisation représente un changement de paradigme dans le déploiement logiciel. Contrairement à la virtualisation traditionnelle qui émule un système d’exploitation complet via un hyperviseur (VMware, Hyper-V, KVM), les conteneurs partagent le noyau du système hôte en s’appuyant sur les namespaces et les cgroups du noyau Linux (Merkel, 2014).

Les namespaces Linux (PID, Network, Mount, UTS, IPC, User) assurent l’isolation des processus : chaque conteneur dispose de sa propre vue du système. Les cgroups (control groups) limitent et comptabilisent les ressources (CPU, mémoire, I/O disque, réseau) consommées par chaque conteneur. Cette combinaison offre une isolation quasi équivalente à la virtualisation pour une fraction du coût en ressources.

Docker, créé par Solomon Hykes en 2013 chez dotCloud, a démocratisé la conteneurisation en fournissant une interface utilisateur accessible et un écosystème complet. L’innovation clé de Docker est le concept de layer filesystem basé sur UnionFS (puis OverlayFS) : chaque instruction du Dockerfile crée une couche en lecture seule, empilée sur les précédentes. Seule la couche supérieure est accessible en écriture. Ce mécanisme permet un partage efficace des couches de base entre conteneurs et un cache intelligent lors des builds.

Le Dockerfile décrit de manière déclarative la construction d’une image :

  • FROM — Image de base (ex: eclipse-temurin:21-jre-alpine)
  • COPY / ADD — Ajout de fichiers dans l’image
  • RUN — Exécution de commandes (installation de dépendances)
  • EXPOSE — Documentation des ports écoutés
  • CMD / ENTRYPOINT — Commande par défaut au démarrage

Les bonnes pratiques de conteneurisation, telles que documentées par Hightower et al. (2019), incluent le multi-stage build pour réduire la taille des images, l’utilisation d’images de base minimales (Alpine, Distroless), l’exécution en utilisateur non-root, et le scan de vulnérabilités via des outils comme Trivy (Aqua Security) ou Docker Scout. Google recommande l’usage d’images Distroless qui ne contiennent que l’application et ses dépendances runtime, sans shell ni utilitaires système, réduisant drastiquement la surface d’attaque (Google, 2023).

L’Open Container Initiative (OCI), fondée en 2015 sous l’égide de la Linux Foundation, standardise les formats d’images et les runtimes de conteneurs. Cette standardisation a permis l’émergence d’alternatives à Docker comme containerd, CRI-O et Podman. Depuis Kubernetes 1.24, le support direct de Docker (dockershim) a été retiré au profit de l’interface CRI (Container Runtime Interface) standardisée.

1.3 Orchestration Kubernetes

Kubernetes (K8s), initialement développé par Google sur la base de son système interne Borg (Burns et al., 2016), est devenu le standard d’orchestration de conteneurs. Open-sourcé en 2014 et confié à la CNCF en 2016, Kubernetes gère le déploiement, la mise à l’échelle et l’exploitation d’applications conteneurisées.

L’architecture de Kubernetes repose sur un control plane et des worker nodes :

  • kube-apiserver — Point d’entrée unique (API RESTful) pour toutes les opérations, avec authentification, autorisation (RBAC) et admission control
  • etcd — Base de données clé-valeur distribuée (algorithme Raft) stockant l’état du cluster. Ongaro et Ousterhout (2014) démontrent que Raft offre des garanties de cohérence forte essentielles pour un système d’orchestration
  • kube-scheduler — Assigne les Pods aux nœuds selon les contraintes de ressources, d’affinité/anti-affinité et les topologies
  • kube-controller-manager — Boucles de réconciliation (Deployment, ReplicaSet, StatefulSet, DaemonSet) qui convergent l’état réel vers l’état désiré
  • kubelet — Agent sur chaque nœud, responsable du cycle de vie des Pods via le CRI
  • kube-proxy — Gestion du réseau interne (iptables/IPVS) pour le routage des Services

Le modèle déclaratif de Kubernetes, exprimé en YAML ou JSON, incarne le principe de desired state management : l’opérateur déclare l’état souhaité (3 réplicas d’un service, avec 512 Mo de RAM maximum), et les contrôleurs assurent en permanence la convergence. Ce modèle, emprunté à la théorie du contrôle automatique, garantit une auto-réparation (self-healing) : si un Pod crashe, le ReplicaSet en crée un nouveau automatiquement.

Les Custom Resource Definitions (CRD) et le pattern Operator, formalisé par Dobies et Wood (2022), permettent d’étendre Kubernetes avec une logique métier spécifique. Des opérateurs comme le Prometheus Operator, Cert-Manager ou les opérateurs de bases de données (PostgreSQL, MongoDB) encapsulent l’expertise opérationnelle dans du code.

1.4 Helm et packaging applicatif

Le déploiement d’applications sur Kubernetes implique la gestion de nombreux manifests YAML interdépendants : Deployments, Services, ConfigMaps, Secrets, Ingress, HorizontalPodAutoscaler, etc. Pour une application typique, cela représente facilement 10 à 20 fichiers de configuration. Helm, le gestionnaire de packages de Kubernetes, résout ce problème en introduisant le concept de Chart (CNCF, 2023).

Un Chart Helm est une collection de fichiers organisés selon une structure conventionnelle :

  • Chart.yaml — Métadonnées (nom, version, dépendances)
  • values.yaml — Valeurs par défaut configurables
  • templates/ — Manifests Kubernetes avec templating Go
  • charts/ — Sous-charts (dépendances)

Le moteur de templating Go ({{ .Values.replicas }}, {{ include "helper" . }}) permet de paramétrer chaque aspect du déploiement. Un même Chart peut ainsi être déployé en développement avec 1 réplica et 256 Mo de RAM, et en production avec 5 réplicas, 2 Go de RAM, des Network Policies et du monitoring, simplement en changeant le fichier values.yaml.

Helm introduit également la notion de release : chaque installation d’un Chart dans un cluster crée une release versionnée. L’historique des releases permet des rollbacks instantanés (helm rollback <release> <revision>). Les Hooks Helm (pre-install, post-install, pre-upgrade, post-upgrade, pre-delete) permettent d’exécuter des actions à des moments précis du cycle de vie, comme les migrations de base de données avant un upgrade.

Les Chart Repositories (Artifact Hub, registres OCI) centralisent la distribution. La tendance actuelle, comme le souligne Sayfan (2021), est au stockage des Charts dans des registres OCI (Harbor, GitHub Container Registry) plutôt que dans des dépôts HTTP classiques, unifiant ainsi la gestion des images de conteneurs et des Charts dans un même registre.

1.5 Infrastructure as Code et CI/CD

L’Infrastructure as Code (IaC) applique les pratiques du développement logiciel (versioning, revue de code, tests, automatisation) à la gestion de l’infrastructure. Morris (2020) distingue deux approches fondamentales :

  • Approche déclarative — L’opérateur décrit l’état final souhaité, et l’outil détermine les actions nécessaires pour y parvenir (Terraform/OpenTofu, CloudFormation, Pulumi)
  • Approche impérative — L’opérateur décrit les étapes à exécuter séquentiellement (Ansible, scripts Shell). Ansible se positionne en réalité à mi-chemin, avec des modules idempotents qui convergent vers un état désiré

Terraform, créé par HashiCorp en 2014, utilise le langage HCL (HashiCorp Configuration Language) pour décrire l’infrastructure de manière déclarative. Son concept central est le state file, un fichier JSON qui maintient la correspondance entre les ressources déclarées dans le code et les ressources réelles dans le cloud. Le cycle plan → apply → destroy offre une prévisibilité totale des changements. Depuis le fork OpenTofu (Linux Foundation, 2023), le débat sur la licence BSL a accéléré l’innovation dans l’écosystème IaC (Brikman, 2024).

La CI/CD (Continuous Integration / Continuous Delivery) automatise le cycle de vie complet du logiciel, du commit au déploiement en production. Humble et Farley (2010), dans leur ouvrage fondateur Continuous Delivery, définissent un pipeline de livraison comme une suite de validations automatisées qui garantissent qu’un artefact est déployable à tout moment.

Un pipeline CI/CD moderne pour une application cloud-native inclut typiquement :

  • Build — Compilation, résolution des dépendances
  • Tests unitaires et d’intégration — Exécution automatique avec couverture minimale
  • Analyse statique — SonarQube, ESLint, linting IaC (tflint, checkov)
  • Build d’image — Construction de l’image Docker avec tag sémantique
  • Scan de sécurité — Analyse de vulnérabilités (Trivy, Snyk) et conformité (OPA/Gatekeeper)
  • Push vers le registre — Publication de l’image dans un registre (Harbor, ECR, GCR)
  • Déploiement — Mise à jour via Helm, Kustomize ou GitOps (ArgoCD, Flux)
  • Tests de fumée — Vérification post-déploiement (health checks, tests E2E)

Le paradigme GitOps, formalisé par Weaveworks (Limoncelli et al., 2020), pousse cette logique plus loin : Git devient la source unique de vérité pour l’état de l’infrastructure et des applications. ArgoCD ou Flux surveillent un dépôt Git et synchronisent automatiquement le cluster Kubernetes. Tout changement passe par une Pull Request, offrant un audit trail complet et un mécanisme de rollback naturel via git revert.

Références

  • Brikman, Y. (2024). Terraform: Up & Running, 3rd Edition. O’Reilly Media.
  • Burns, B., Grant, B., Oppenheimer, D., Brewer, E. & Wilkes, J. (2016). « Borg, Omega, and Kubernetes ». ACM Queue, 14(1), 70-93.
  • CNCF (2024). Cloud Native Survey 2024. Cloud Native Computing Foundation.
  • Dobies, J. & Wood, J. (2022). Kubernetes Operators. O’Reilly Media.
  • Fowler, M. & Lewis, J. (2014). « Microservices: a definition of this new architectural term ». martinfowler.com.
  • Google (2023). « Distroless Container Images ». GitHub — GoogleContainerTools/distroless.
  • Hightower, K., Burns, B. & Beda, J. (2019). Kubernetes: Up and Running, 2nd Edition. O’Reilly Media.
  • Humble, J. & Farley, D. (2010). Continuous Delivery. Addison-Wesley.
  • Merkel, D. (2014). « Docker: Lightweight Linux Containers for Consistent Development and Deployment ». Linux Journal, 2014(239).
  • Morris, K. (2020). Infrastructure as Code, 2nd Edition. O’Reilly Media.
  • Newman, S. (2021). Building Microservices, 2nd Edition. O’Reilly Media.
  • Ongaro, D. & Ousterhout, J. (2014). « In Search of an Understandable Consensus Algorithm ». USENIX ATC ’14.
  • Richardson, C. (2018). Microservices Patterns. Manning Publications.
  • Sayfan, G. (2021). Mastering Kubernetes, 3rd Edition. Packt Publishing.
  • Wiggins, A. (2012). « The Twelve-Factor App ». 12factor.net.
Share: Partager :