À mesure que les entreprises migrent leurs applications vers le cloud, elles doivent trancher entre un simple lift and shift et une refonte de leur architecture pour la rendre cloud-native, terme dont la définition varie. Cet article se concentre sur la seconde approche, et plus précisément sur une technique utile pour migrer des applications vers des conteneurs (Docker, par exemple) et les orchestrer avec Kubernetes.

Source : iStockPhoto
Le défi du bootstrapping
L'une des promesses du DevOps et des migrations cloud, c'est d'alléger les opérations traditionnelles en automatisant les processus manuels. La nature déclarative de Kubernetes, qui garantit automatiquement l'état souhaité de vos applications, est particulièrement puissante. Pour autant, certaines applications nécessitent parfois des étapes de bootstrapping avant de pouvoir s'exécuter correctement, ou doivent être démarrées dans un ordre précis pour gérer leurs dépendances vis-à-vis d'autres systèmes comme des files d'attente ou des bases de données.
Pour qu'une application démarre dans de bonnes conditions, on pourrait la réécrire avec une logique de réessai sur mesure jusqu'à réunir les conditions optimales, mais cela risque de retarder la migration. Une alternative, qui évite toute réécriture de code, consiste à créer de petites applications, scripts ou commandes, puis à les ajouter en tant qu'InitContainers.
Cas d'usage potentiels des Init Containers
- Une application blockchain qui doit s'enregistrer auprès de ses pairs
- Une application qui doit récupérer un jeton d'accès auprès d'un fournisseur d'identité
- Des données dynamiques chargées depuis une base de données et mises en cache pour que l'application puisse s'exécuter après son démarrage
- Récupérer des secrets chiffrés depuis un vault et les écrire sur le système de fichiers
- Bloquer le démarrage de l'application tant qu'un autre système n'est pas disponible (file d'attente ou serveur de base de données, par exemple)
Exemple simple avec deux images Busybox
Dans cet exemple, partons du principe qu'une application doit être alimentée dynamiquement avec des données avant son démarrage (comme dans les scénarios évoqués plus haut). On pourrait y parvenir avec un ConfigMap, mais pour illustrer la puissance de cette technique, restez ouvert à tout ce que vous pourriez faire par ailleurs.
- Créer un PersistentVolumeClaim
Il nous faut d'abord un volume de stockage accessible.
Persistent Volume Claim
$ kubectl apply -f test-pvc.yamlpersistentvolumeclaim/test-pvc created
2. Initialiser un fichier YAML de configuration de Deployment
$ kubectl create deployment test-app --image=busybox:1.28.0 -o yaml --dry-run > test-app.yaml
3. Modifier le Deployment pour y ajouter le volume ainsi que l'Init Container, comme suit
Deployment avec Init Container
Vous remarquerez que dans ce fichier, nous avons ajouté le volume, puis une seconde image Busybox dans l'initContainer. Cela pourrait être n'importe quelle image, mais pour cet exemple, je voulais simplement écrire du contenu dans un fichier sur le système de fichiers monté ; ainsi, lorsque l'application démarre avec l'autre image Busybox, elle accède au fichier et en lit le contenu.
4. Lancer le Deployment et surveiller les logs
# deploy app
$ kubectl apply -f test-app.yamldeployment.apps/test-app configured# monitor logs
$ kubectl logs -f deployment/test-appFile content: Hello, World!
Si vous voyez File content: Hello, World!, c'est que tout a fonctionné. À partir de cet exemple basique, vous pouvez ensuite personnaliser votre application en remplaçant l'image du conteneur principal, et ajouter autant d'init containers que nécessaire pour que votre application démarre avec tout ce dont elle a besoin. L'atout de cette technique : automatiser le déploiement de vos applications sans avoir à écrire de logique complexe de réessai ou de gestion d'erreurs pour traiter les anciennes dépendances manuelles.
Pour en savoir plus sur les Init Containers, consultez la documentation officielle de Kubernetes :