J'essaie de réaliser des déploiements sans temps d'arrêt afin de pouvoir déployer moins pendant les heures creuses et plus pendant les heures "plus lentes" - ou à tout moment, en théorie.
Ma configuration actuelle, quelque peu simplifiée:
Mon processus de déploiement actuel:
Cela conduit à une petite durée d'indisponibilité chaque mois - environ 30 minutes. Je le fais pendant les heures creuses, donc ce n'est pas un gros problème - mais c'est quelque chose que j'aimerais éviter.
De plus, il n'y a aucun moyen de vraiment revenir en arrière. Je ne fais généralement pas de restauration de scripts DB - seulement des scripts de mise à niveau.
J'adorerais pouvoir mettre à niveau un serveur Web à la fois. Retirez le serveur Web A de l'équilibreur de charge, mettez-le à niveau, remettez-le en ligne, puis répétez l'opération pour le serveur Web B.
Le problème est la base de données. Chaque version de mon logiciel devra s'exécuter sur une version différente de la base de données - je suis donc en quelque sorte "bloqué".
Une solution actuelle que j'envisage est d'adopter les règles suivantes:
Bien que cela semble un peu extrême - je pense que cela résout le problème. Chaque version de l'application atteindra la base de données sans interruption. Le code attend certains résultats des vues/procédures stockées - et cela maintient ce "contrat" valide. Le problème est - il suinte simplement bâclé. Je sais que je peux nettoyer les anciennes procédures stockées après le déploiement de l'application pendant un certain temps, mais cela semble juste sale. En outre - cela dépend de tous les développeurs qui suivent ces règles, ce qui se produira principalement, mais j'imagine que quelqu'un fera une erreur.
Il s'agit d'une approche très pragmatique des mises à niveau logicielles basées sur une base de données. Il a été décrit par Martin Fowler et Pramod Sadalage en 2003 et rédigé par la suite dans Refactoring Databases: Evolutionary Database Design .
Je peux voir ce que vous voulez dire lorsque vous dites que cela semble bâclé, mais lorsque cela est fait intentionnellement et avec prévoyance, et en prenant le temps de refactoriser les structures inutilisées de la base de code et de la base de données lorsqu'elles ne sont manifestement plus utilisées, c'est beaucoup plus robuste que des solutions plus simples basées sur des scripts de mise à niveau et de restauration.
Le "temps d'arrêt zéro" n'est qu'une des nombreuses raisons possibles de ce type d'approche. Garder un modèle de données rétrocompatible de cette façon vous aide à faire face à de nombreux problèmes différents:
si vous avez beaucoup de progiciels accédant à votre base de données, vous n'aurez pas à tous les vérifier si un changement de schéma les affecte (dans les grandes organisations avec plusieurs équipes écrivant des programmes accédant tous à la même base de données, les changements de schéma peuvent devenir très difficiles)
si vous le devez, vous pouvez consulter une ancienne version de l'un de vos programmes et elle s'exécutera probablement contre une base de données plus récente (tant que vous ne vous attendez pas à ce que l'ancien programme gère correctement les nouvelles colonnes)
l'importation/exportation de données archivées dans la version actuelle de la base de données est beaucoup plus facile
Voici une règle supplémentaire pour votre liste
(cela garantit que même les programmes plus anciens qui ne connaissent pas les nouvelles colonnes ne casseront rien lorsqu'ils créent de nouveaux enregistrements dans votre base de données).
Bien sûr, cette approche a un réel inconvénient: la qualité de votre modèle de données peut se dégrader avec le temps. Et si vous avez un contrôle total sur toutes les applications accédant à votre base de données, et que vous pouvez facilement refactoriser toutes ces applications lorsque vous, par exemple, allez renommer une colonne, alors vous pourriez envisager de refactoriser les choses de manière plus propre.
Cela varie d'un déploiement à l'autre.
Bien sûr, vous ne pouvez jamais supprimer un tableau ou une colonne. Vous ne pourriez jamais rien changer à la compatibilité de l'interface. Vous pouvez toujours ajouter une couche d'abstraction. Mais alors vous devez versionner cette abstraction et la version le versioning.
La question que vous devez vous poser est la suivante: chaque version modifie-t-elle le schéma de manière à ce qu'il ne soit pas rétrocompatible?
Si très peu de versions modifient le schéma de cette manière, le problème de base de données est alors muet. Effectuez simplement un déploiement continu des serveurs d'applications.
Les deux choses que j'ai vues aider le plus avec un déploiement à temps d'arrêt minimal sont:
Espérons que le reste de vos déploiements puisse être enregistré pour les fenêtres de maintenance.
Autres idées pouvant aider à gérer les quelques déploiements qui nécessitent des temps d'arrêt:
Vous pourriez potentiellement le faire comme ça pour un peu d'effort supplémentaire.
Naturellement, les mises à jour Web auraient besoin de nouvelles entrées de configuration pour pointer vers le nouveau schéma Db. Le problème est que si vous publiez une fois par mois et que c'est une petite équipe, combien de modifications de base de données effectuez-vous qui ne sont pas rétrocompatibles? Si vous pouvez contrôler cela en testant, vous pouvez opter pour un déploiement automatisé sans temps d'arrêt ou, au pire, seulement 5 minutes de temps d'arrêt.