
Sommaire
Votre organisation a décidé d’adopter une plateforme Cloud ? C’est l’occasion rêvée pour envisager un move to cloud global du système d’information. Parmi les stratégies des 7 R (rehost, relocate, replatform, refactor, repurchase, retire, retain), la priorité a été donnée au replatforming avec Kubernetes.
Depuis une décennie, Kubernetes est la solution phare pour orchestrer les conteneurs, abstraire les fournisseurs cloud et moderniser les infrastructures. Son adoption massive dans l’écosystème DevOps en fait une compétence incontournable. Il suffit d’échanger avec quelques ingénieurs DevOps : la conteneurisation et l’orchestration sont devenues des prérequis.
Mais faire tourner une application legacy sur Kubernetes est-il vraiment si simple ? Quelles sont les contraintes techniques à anticiper ? Cet article explore les défis liés à la conteneurisation et vous aide à identifier les applications qui poseront problème.
Conteneuriser une application legacy : simple… en apparence
Créer une image de conteneur est une opération accessible. Grâce à un fichier Dockerfile
ou à des commandes Podman, vous embarquez binaires, dépendances et métadonnées dans une image exécutable. Vous pouvez ensuite faire tourner vos conteneurs via Docker, Docker Compose, ou Podman.
L'intérêt principal réside dans :
- L’adoption de standards de packaging (Dockerfile, registre d’images, politique de tags).
- Une portabilité accrue de l’exécution.
- Une gestion facilitée via
systemd
pour l’automatisation des redémarrages.
Vous avez conteneurisé votre application legacy ! Facile si la liste des dépendances est claire. Fastidieux en l’absence de documentation avec source de vérité, une machine virtuelle installée manuellement il y a plus de 5 ans…
Orchestration avec Kubernetes : là où les choses se corsent
Quand il s’agit de passer en production sur des dizaines de nœuds, l’enjeu devient l’orchestration des conteneurs à grande échelle. Kubernetes ne se contente pas d’exécuter des conteneurs. Il les gère, surveille, redémarre, met à l’échelle, et les replanifie en fonction de l’état du cluster. Cette puissance s’accompagne d’une contrainte majeure : l’éphémérité des pods… le fameux pet versus cattle ou encore Everything fails all the time de Werner Vogels. Auparavant, vous aviez une couche de virtualisation très avancée qui permettait de garantir la disponibilité d’une machine virtuelle. Vous pouviez effectuer une live migration pour déplacer une VM entre nœuds physiques, ou encore vous appuyer sur les mécanismes de haute disponibilité sous-jacents.
Avec Kubernetes :
- Les nœuds sont mis à jour régulièrement (3 versions/an).
- Les pods peuvent être supprimés à tout moment. D’où la nécessité de supporter plusieurs réplicas répartis sur différentes instances.
- Le démarrage de pods n’est pas une anomalie. C’est un non-événement qui se doit être automatique, rapide et fiable.
Votre application est-elle prête pour ce changement de paradigme ? Voici les points à maîtriser.
1. Maîtriser la taille de l’image conteneur
Les images trop volumineuses sont à proscrire :
- Temps de téléchargement excessif sur les nœuds, avec une surcharge sur le registre d’images comme l’infrastructure réseau.
- Occupation disque inutile et donc un coût de stockage additionnel.
- Surface d’attaque plus grande puisque le risque d’embarquer des vulnérabilités est plus élevé avec un grand nombre de librairies.
Quelques repères :
- ✅ < 100 Mo : idéal (Go, Rust).
- ⚠️ 100-500 Mo : acceptable (Python, Node.js).
- 🚨 > 1 Go : à optimiser d’urgence.
Cet article complet illustre de manière claire les différentes stratégies que vous pouvez mettre en œuvre : des images distroless, aux outils de minification, en passant par le build multi stage.
2. Maîtriser le temps de démarrage
Un démarrage rapide est essentiel en environnement cloud-native :
- 📍 Utilisez les probes Kubernetes (startupProbe, readinessProbe, livenessProbe) pour surveiller les états.
- 🔥 Objectif : démarrage < 1 minute.
- 🚨 Au-delà de 5 minutes : refactoring indispensable.
3. Définir un profil de ressources adapté
Kubernetes arrive avec une promesse de mutualisation des nœuds d’exécution. Pour cela, les valeurs requests
et limits
guident le scheduler Kubernetes. Déterminer le bon paramétrage peut se heurter aux cas suivants :
- ⚙️ Démarrage intensif : certaines applications, comme les monolithes Java, consomment beaucoup de mémoire ou CPU au démarrage pour ensuite se stabiliser sur des valeurs plus basses en fonctionnement nominal. Généralement un surdimensionnement des ressources lié au démarrage est mis en œuvre.
- 🧠 Gestion de mémoire non bornée : certains binaires ne gèrent pas de manière simple la limitation de mémoire. Pour éviter les risques de OOM (Out of Memory), après quelques cheveux arrachés, vous arriverez à la conclusion qu’il faut surdimensionner les pods, voire dédier des nœuds pour ne porter qu’un seul pod.
- 🔁 Batch : il est commun de voir des applications legacy qui embarquent des exécutions de jobs programmés. Si le traitement des batchs est compris dans le profil ressources défini pour Kubernetes tout ira bien. A défaut, l’exécution de batchs donnera lieu à des Out Of Memory qui apparaîtront ponctuellement.
🎯 Solution :
- Le composant Vertical Pod Autoscaler peut vous aider sur un cluster de test à qualifier les bonnes valeurs.
- Dimensionner correctement les nœuds du cluster. Un service qui tournait correctement sur une VM 16 VCPU / 32 Go RAM aura vraisemblablement besoin d’autant de ressources une fois conteneurisé.
4. Gérer la persistance des données
Le principe de Kubernetes : stateless by design.
Mais dans le monde legacy, on retrouve :
- Des bases embarquées (MySQL, Oracle…).
- Des sessions utilisateur en mémoire.
- Des fichiers de cache ou de log critiques.
🎯 Solution :
- Externalisez les états sur des volumes persistants (PVC).
- Ou utilisez des services managés (DBaaS, cache as a service…).
Kubernetes n’est pas magique : il faut préparer vos applications
Pour qu’une application soit réellement compatible Kubernetes, elle doit :
- ✅ Être réplicable (stateless ou avec gestion d’état externalisée).
- ✅ Avoir une image légère.
- ✅ Démarrer rapidement.
- ✅ Utiliser des sondes pour signaler son état.
- ✅ Définir des ressources CPU/mémoire réalistes.
Les applications legacy ne remplissent généralement pas tous ces critères. Le passage de la VM au pod nécessite un effort d’ingénierie.
Mais ce travail est aussi une opportunité de modernisation progressive du SI.
Conclusion
Kubernetes se destine avant tout aux applications dites cloud native. L’acceptation d'arrêt de pod est sans doute le principe le plus emblématique du cloud native. Il en découle que les caractéristiques des applications compatibles Kubernetes sont :
- la capacité à s’exécuter dans plusieurs réplicas en parallèles
- un démarrage rapide qui suppose
- une taille d’image mesurée
- une maîtrise du temps de démarrage et des sondes (probes)
- une gestion de ressources CPU et mémoire
- un découplage entre les données et l’exécution
La conteneurisation d’applications legacy sur Kubernetes est faisable, mais implique un changement de paradigme fort. De l’image Docker à la gestion de l’état, en passant par l’allocation des ressources, chaque point demande une attention particulière. Au-delà des contraintes liées aux démarrages des pods que nous avons abordées, la question des logs et de l’observabilité impose des modifications spécifiques.
Toutefois, Kubernetes peut également servir de base solide pour faire tourner des applications legacy, avec en dernier recours l’isolation des workloads sur des nœuds dédiés. Cela ouvre la voie à une modernisation progressive du SI sans devoir tout refactoriser dès le départ.
Enfin, pour faciliter l’adoption de Kubernetes et réduire la complexité des migrations, les Platform Engineering teams jouent un rôle clé. En intégrant des pratiques comme l'automatisation des déploiements, la gestion des pipelines CI/CD et l'intégration continue, elles permettront de rendre l’adoption de Kubernetes plus simple et plus fluide pour les équipes de développement et d’exploitation.