De nos jours, beaucoup d’applications ou de services nécessitent des déploiements sans downtime.
L’une des opérations les plus critiques lors d’un déploiement concerne la mise à jour de base de données. Nous allons voir comment nous pouvons nous en sortir avec quelques règles à respecter.
La plupart des applications de nos jours utilisent un mécanisme de load balancing ou un orchestrateur de container.
Lors du déploiement d’une nouvelle version d’une application, le système de déploiement va progressivement basculer les applications en v1 vers la v2.
Dans cette typologie d’architecture, il y a principalement trois problèmes à résoudre :
Une solution que l’on peut qualifier de naïve serait de lancer le script de migration de la base de données avec le démarrage de la première application.
L’idée est de laisser la première application lancer les migrations de bases de données via une librairie type Flyway ou Mongock. Une fois mises à jour les autres instances ne feront rien vu que la base de données sera déjà à jour.
Malheureusement, cette solution pose plusieurs problèmes :
La solution est de laisser le système de déploiement faire le travail en amont du premier déploiement d’application. La migration de base de données sera alors exécutée lors d’une tâche préparatoire. Cela permet de s’assurer qu’il n’est exécuté qu’une fois et le rollback devient alors plus aisé.
Nous voulons ajouter la possibilité à nos utilisateurs d’uploader un avatar. Après l’enregistrement, chaque utilisateur se voit attribuer aléatoirement un avatar auto-généré avec l’option d’uploader le leur. Pour implémenter cela, nous avons besoin d’ajouter une colonne avatar
à notre table Users
.
Pour implémenter cette feature, nous devons côté base de données :
avatar
nullable à la table Users
.avatar
non-nullable.Si nous lançons le script de migration de cette feature, les applications v1 ne pourront plus procéder à l’enregistrement des utilisateurs n’ayant pas de connaissance de la colonne avatar
non-nullable. Toutefois, le problème se résoudra de lui-même avec la bascule des applications v1 en v2 mais dans un contexte de zéro downtime cela n’est pas acceptable.
L’astuce est de diviser en deux phases l’ajout de la colonne avatar
:
avatar
nullable. Cela ne provoquera aucun problème sur l’enregistrement des nouveaux utilisateurs sur la v1. L’application, une fois mise à jour en v2, commencera à populer la valeur pour les nouvelles entrées.avatar
vides. Après cela, la colonne avatar
est mise en non-nullable. À noter que même si des enregistrements a lieu lors de la migration, cela ne posera pas de problème car ce qui a été déployé en Phase 1 initialise déjà des avatars pour les nouveaux utilisateurs.Disons que la fonctionnalité d’avatar n’a pas atteint nos attentes. En effet, la fonctionnalité n’est pas assez populaire et il a été décidé de la retirer. Nous voulons par conséquent retirer la colonne avatar
de la base de données.
Si le script de migration supprime la colonne alors cela va engendrer de gros problèmes. En effet, la migration des applications prenant un certain temps, toute celles qui sont en v1 et qui ont encore la fonctionnalité d’avatar ne fonctionneront plus correctement.
La solution est encore une fois de découper la suppression de la colonne en deux phases :
avatar
nullable. Cela n’aura pas d’impact sur l’application qui tourne actuellement en production. En même temps, cela nous permets de déployer la nouvelle application sans la feature d’avatar.avatar
nulle part et du coup nous pouvons supprimer la colonne.Partons du principe qu’au lieu de stocker le nom des fichiers nous voulons que la feature d’avatar soit capable de gérer les avatars hébergés sur différents domaines. Nous avons donc besoin d’augmenter la taille de la colonne avatar
de 100 caractères à 1000 caractères. Nous souhaitons également renommer la colonne avatar
en avatar_url
pour refléter cette information.
Le script de migration doit :
varchar(100)
à varchar(1000)
.avatar
en avatar_url
.Encore une fois, si nous lançons le script de migration en production tel quel cela va provoquer des problèmes. Les applications v1 ne pourront plus fonctionner correctement du fait du changement de nom ou de type. Le problème perdurera tant que toutes les applications n’auront pas été mises à jour.
La solution est encore une fois de découper la mise à jour en plusieurs étapes :
avatar_url
. Nous ne touchons pas à la colonne avatar
. L’application v2 écrit dans les deux colonnes en même temps.avatar_url
puis rend la colonne non-nullable. L’application n’utilise plus que la colonne avatar_url
en lecture mais continue d’écrire dans les deux colonnes car la colonne avatar
est toujours non-nullable.avatar
. L’application arrête d’écrire des données dans la colonne avatar
.avatar
de la base de données. L’application n’écrivant déjà plus dans la colonne avatar
, aucune modification n’est requise.Concernant les opérations de base de données lourdes, il n’existe pas réellement de méthodes à appliquer mais je peux vous donner quelques astuces.
Apporter des modifications à une base de données sans aucun downtime n’est pas trivial mais avec les bons process il est possible de considérablement améliorer la qualité de vos processus de déploiement.
Si vous rencontrez des difficultés sur ces sujets, n’hésitez pas à me contacter.