Histoire de déploiement qui a tout touché

Histoire de déploiement qui a tout touché
Ennemis de la réalité par 12f-2

Fin avril, alors que les White Walkers assiégeaient Winterfell, quelque chose de plus intéressant nous est arrivé, nous avons fait un déploiement inhabituel. En principe, nous lançons constamment de nouvelles fonctionnalités en production (comme tout le monde). Mais celui-ci n'était pas comme les autres. Son ampleur était telle que toute erreur potentielle que nous pourrions commettre affecterait tous nos services et utilisateurs. En conséquence, nous avons tout déroulé conformément au plan, à la période d'arrêt prévue et annoncée, sans conséquences pour la vente. L'article explique comment nous y sommes parvenus et comment ceux qui le souhaitent peuvent le répéter à la maison.

Je ne vais pas décrire maintenant les solutions architecturales et techniques que nous avons adoptées, ni raconter comment tout cela fonctionne. Ce sont plutôt des notes en marge sur le déroulement d'un des déploiements les plus difficiles, que j'ai pu observer et dans lequel j'ai été directement impliqué. Je ne prétends pas à l'exhaustivité ou aux détails techniques, peut-être apparaîtront-ils dans un autre article.

Contexte + quelle est cette fonctionnalité

Nous construisons une plateforme cloud Solutions Cloud Mail.ru (MCS), où je travaille en tant que CTO. Et maintenant - il est temps de vous connecter à notre plateforme IAM (Identity and Access Management), qui fournit une gestion unifiée de tous les comptes d'utilisateurs, utilisateurs, mots de passe, rôles, services et plus encore. Pourquoi est-il nécessaire dans le cloud est une question évidente : toutes les informations des utilisateurs y sont stockées.

Habituellement, de telles choses commencent à se construire au tout début de tout projet. Mais MCS s'est historiquement développé un peu différemment. MCS a été construit en deux parties :

  • Openstack avec son propre module d'autorisation Keystone,
  • Hotbox (stockage S3) basé sur le projet Cloud Mail.ru,

autour duquel de nouveaux services sont alors apparus.

En fait, il s'agissait de deux types d'autorisation différents. De plus, nous avons utilisé certains développements Mail.ru distincts, par exemple, le stockage de mot de passe partagé Mail.ru, ainsi qu'un connecteur openid auto-écrit, grâce auquel SSO (autorisation de passage) a été fourni dans le panneau Horizon de virtuel machines (interface utilisateur native OpenStack).

Faire de l'IAM pour nous signifiait tout combiner en un seul système, entièrement nôtre. En même temps, ne perdre aucune fonctionnalité en cours de route, pour créer une réserve pour l'avenir, qui nous permettra de l'affiner en toute transparence sans refactoriser, et de le mettre à l'échelle en fonctionnalité. De plus, au début, les utilisateurs avaient un modèle de rôle pour accéder aux services (RBAC central, contrôle d'accès basé sur les rôles) et quelques autres petites choses.

La tâche s'est avérée non triviale : python et perl, plusieurs backends, des services écrits indépendamment, plusieurs équipes de développement et administrateurs. Et le plus important - des milliers d'utilisateurs en direct sur le système de production de combat. Tout cela devait être écrit et, surtout, déployé sans faire de victimes.

Qu'allons-nous déployer

Si c'est très difficile, quelque part dans 4 mois, nous avons préparé ce qui suit :

  • Nous avons créé plusieurs nouveaux démons qui agrégeaient des fonctions qui fonctionnaient auparavant dans différentes parties de l'infrastructure. Le reste des services s'est vu attribuer un nouveau backend sous la forme de ces démons.
  • Nous avons écrit notre propre stockage central de mots de passe et de clés, disponible pour tous nos services, qui peut être librement modifié selon nos besoins.
  • Nous avons écrit 4 nouveaux backends pour Keystone à partir de zéro (utilisateurs, projets, rôles, attributions de rôles), qui, en fait, ont remplacé sa base, et maintenant il agit comme un référentiel unique pour nos mots de passe utilisateur.
  • Nous avons appris à tous nos services Openstack à accéder à un service de politique tiers pour leurs politiques au lieu de lire ces politiques localement à partir de chaque serveur (oui, c'est comme ça qu'Openstack fonctionne par défaut !)

Une refonte aussi importante nécessite des modifications importantes, complexes et, surtout, synchrones dans plusieurs systèmes, écrites par différentes équipes de développement. Après assemblage, l'ensemble du système devrait fonctionner.

Comment déployer de tels changements et ne pas tout gâcher ? Tout d'abord, nous avons décidé de jeter un coup d'œil vers l'avenir.

Stratégie de déploiement

  • Il serait possible de déployer en plusieurs étapes, mais cela multiplierait par trois le temps de développement. De plus, pendant un certain temps, nous aurions une désynchronisation complète des données dans les bases de données. Je devrais écrire mes propres outils de synchronisation et vivre longtemps avec plusieurs magasins de données. Et cela crée une grande variété de risques.
  • Tout ce qui pouvait être préparé de manière transparente pour l'utilisateur était fait à l'avance. Cela a pris 2 mois.
  • Nous nous sommes permis des temps d'arrêt de plusieurs heures - uniquement sur les opérations des utilisateurs pour créer et modifier des ressources.
  • Le temps d'arrêt n'était pas valide pour que toutes les ressources déjà créées fonctionnent. Nous avons prévu que pendant le déploiement, les ressources devraient fonctionner sans temps d'arrêt et affecter les clients.
  • Pour réduire l'impact sur nos clients en cas de problème, nous avons décidé de déployer le dimanche soir. Moins de clients gèrent des machines virtuelles la nuit.
  • Nous avons averti tous nos clients que la gestion des services ne sera pas disponible pendant la période de déploiement.

Retraite : qu'est-ce que le déploiement ?

<attention, philosophie>

Chaque spécialiste informatique peut facilement répondre à ce qu'est un déploiement. Vous mettez CI/CD, et tout est automatiquement livré à la prod. 🙂

Bien sûr, c'est vrai. Mais la difficulté est qu'avec les outils modernes d'automatisation de la livraison de code, la compréhension du déploiement lui-même est perdue. Comment oubliez-vous l'invention épique de la roue, en regardant les transports modernes. Tout est tellement automatisé que le déploiement s'effectue souvent sans avoir une vue d'ensemble.

Et toute l'image est comme ça. Le déploiement comprend quatre aspects principaux :

  1. Livraison du code, y compris la modification des données. Par exemple, leurs migrations.
  2. L'annulation du code est la possibilité de revenir en arrière si quelque chose ne va pas. Par exemple, via la création de sauvegardes.
  3. Heure de chaque opération de déploiement/restauration. Il est nécessaire de comprendre le timing de toute opération des deux premiers points.
  4. Fonctionnalité affectée. Il est nécessaire d'évaluer à la fois les effets positifs attendus et les effets négatifs possibles.

Tous ces aspects doivent être pris en compte pour un déploiement réussi. Habituellement, seul le premier, au mieux le deuxième point est évalué, puis le déploiement est considéré comme réussi. Mais les troisième et quatrième sont encore plus importants. Quel utilisateur aimerait que le déploiement prenne 3 heures au lieu d'une minute ? Ou si quelque chose de superflu est affecté lors du déploiement ? Ou l'indisponibilité d'un service entraînera-t-elle des conséquences imprévisibles ?

Acte 1..n, préparation à la libération

Au début, je pensais décrire brièvement nos réunions : toute l'équipe, ses parties, des tas de discussions en points café, des disputes, des tests, des brainstorms. Ensuite, j'ai pensé que ce serait redondant. Quatre mois de développement consistent toujours en cela, surtout lorsque vous écrivez non pas quelque chose qui peut être livré en permanence, mais une grande fonctionnalité pour un système en direct. Ce qui touche tous les services, mais rien ne devrait changer pour les utilisateurs, hormis "un bouton dans l'interface web".

Notre compréhension de la façon de déployer a changé à chaque nouvelle réunion, et de manière assez significative. Par exemple, nous allions mettre à jour toute notre base de données de facturation. Mais nous avons compté le temps et réalisé qu'il était impossible de le faire dans un délai raisonnable pour le déploiement. Nous avons pris près d'une semaine supplémentaire pour partitionner et archiver la base de données de facturation. Et lorsque la vitesse de déploiement attendue ne convenait pas même après cela, ils ont commandé du matériel supplémentaire plus puissant, où ils ont traîné toute la base. Ce n'est pas que nous ne voulions pas le faire plus tôt, mais le besoin actuel de déploiement ne nous laissait aucune option.

Lorsque l'un de nous a douté que le déploiement puisse affecter la disponibilité de nos machines virtuelles, nous avons passé une semaine à tester, expérimenter, analyser le code et avons clairement compris que cela ne se produirait pas dans notre production, et même les personnes les plus sceptiques ont accepté avec ça.

Entre-temps, les gars du support technique ont mené leurs propres expériences indépendantes afin d'écrire des instructions aux clients sur les méthodes de connexion, qui étaient censées changer après le déploiement. Ils ont travaillé sur l'UX de l'utilisateur, préparé des instructions et fourni des conseils personnalisés.

Nous avons automatisé toutes les opérations de déploiement qui étaient possibles. Toute opération était scénarisée, même la plus simple, des tests étaient exécutés en permanence. Ils se sont disputés sur la meilleure façon de désactiver le service - abaissez le démon ou bloquez l'accès au service avec un pare-feu. Nous avons créé une liste de contrôle des équipes pour chaque étape du déploiement, en la mettant constamment à jour. Nous avons dessiné et constamment mis à jour le diagramme de Gantt pour tous les travaux de déploiement, avec des délais.

Et alors ...

Acte final, avant le déploiement

… il est temps de se déployer.

Comme on dit, une œuvre d'art ne peut pas être achevée, seulement finie de travailler dessus. Il est nécessaire de faire un effort de volonté, en réalisant que vous ne trouverez pas tout, mais en pensant que vous avez fait toutes les hypothèses raisonnables, prévu tous les cas possibles, fermé tous les bogues critiques et que tous les participants ont fait de leur mieux. Plus on déploie de code, plus il est difficile de s'en convaincre (d'ailleurs, tout le monde comprend qu'il est impossible de tout prévoir).

Nous avons pris la décision que nous étions prêts à déployer lorsque nous nous sommes assurés que nous avions fait tout notre possible pour éliminer tous les risques pour nos utilisateurs associés aux effets inattendus et aux temps d'arrêt. Autrement dit, tout peut mal tourner, sauf :

  1. L'effet de l'infrastructure utilisateur (sacrée pour nous, la plus précieuse),
  2. Fonctionnalité : L'utilisation de notre service après le déploiement doit être la même qu'avant.

Dérouler

Histoire de déploiement qui a tout touché
Deux rouleaux, 8 n'interfèrent pas

Nous prenons les temps d'arrêt pour toutes les demandes des utilisateurs dans les 7 heures. À l'heure actuelle, nous avons à la fois un plan de déploiement et un plan de restauration.

  • Le trajet en lui-même dure environ 3 heures.
  • 2 heures pour tester.
  • 2 heures est une marge pour une éventuelle annulation des modifications.

Un diagramme de Gantt a été compilé pour chaque action, combien de temps cela prend, ce qui se passe séquentiellement, ce qui est fait en parallèle.

Histoire de déploiement qui a tout touché
Un morceau d'un diagramme de Gantt déroulant, l'une des premières versions (sans exécution parallèle). L'outil de synchronisation le plus précieux

Tous les participants ont un rôle défini dans le déploiement, quelles tâches ils effectuent, de quoi ils sont responsables. Nous essayons d'amener chaque étape à l'automatisme, de la déployer, de la faire reculer, de recueillir les commentaires et de la relancer.

Chronique

Ainsi, 15 personnes sont venues travailler le dimanche 29 avril, à 10 heures. En plus des participants clés, certains sont venus juste pour soutenir l'équipe, pour laquelle un merci spécial à eux.

Par ailleurs, il convient de mentionner que notre testeur clé est en vacances. Déployer sans tester est impossible, nous travaillons sur des options. Une collègue accepte de nous tester depuis les vacances, ce dont elle est immensément reconnaissante de la part de toute l'équipe.

00:00. Arrêt
Nous arrêtons les demandes des utilisateurs, accrochons une plaque signalétique, disent-ils, un travail technique. La surveillance hurle, mais tout est régulier. Nous vérifions que rien n'est tombé, sauf ce qui aurait dû l'être. Et nous commençons à travailler sur la migration.

Chacun a un plan de déploiement imprimé point par point, chacun sait qui fait quoi et à quel moment. Après chaque action, nous vérifions les timings que nous ne les dépassons pas, et tout se passe comme prévu. Ceux qui ne participent pas directement au déploiement au stade actuel se préparent en lançant un jouet en ligne (Xonotic, type 3 wacks) pour ne pas déranger les collègues. 🙂

02:00. deployé
Une agréable surprise - nous terminons le déploiement une heure plus tôt, grâce à l'optimisation de nos bases de données et de nos scripts de migration. Le cri universel, « déployé ! Toutes les nouvelles fonctionnalités sont en production, mais nous ne les voyons que dans l'interface. Tout le monde passe en mode test, trie en piles et commence à voir ce qui s'est passé à la fin.

Ça n'a pas très bien marché, on le comprend au bout de 10 minutes, quand rien n'est connecté et ne marche pas dans les projets des membres de l'équipe. Synchronisation rapide, exprimer nos problèmes, définir des priorités, se diviser en équipes et déboguer.

02h30. Deux gros problèmes contre quatre yeux
Nous trouvons deux gros problèmes. Nous nous sommes rendus compte que les clients ne verraient pas certains services connectés, et qu'il y aurait des problèmes avec les comptes partenaires. Les deux sont liés à l'imperfection des scripts de migration pour certains cas extrêmes. Je dois le réparer maintenant.

Nous écrivons des demandes qui corrigent cela, au moins à 4 yeux. Nous le roulons en pré-production pour nous assurer qu'ils fonctionnent et ne cassent rien. Vous pouvez rouler plus loin. En parallèle, nos tests d'intégration habituels sont exécutés, ce qui révèle quelques problèmes supplémentaires. Tous sont petits, mais doivent également être réparés.

03h00. -2 problèmes +2 problèmes
Deux gros problèmes précédents sont corrigés, presque tous les petits aussi. Tous les chômeurs dans les correctifs travaillent activement dans leurs comptes et signalent ce qu'ils trouvent. On priorise, distribue par équipes, laisse le non critique pour le matin.

Nous relançons les tests, ils révèlent deux nouveaux gros problèmes. Toutes les stratégies de service n'étant pas arrivées correctement, certaines demandes d'utilisateurs échouent à l'autorisation. Plus un nouveau problème avec les comptes partenaires. Nous nous précipitons pour regarder.

03h20. synchronisation d'urgence
Un nouveau problème résolu. Pour le second, nous organisons une synchronisation d'urgence. Nous comprenons ce qui se passe : le correctif précédent a résolu un problème, mais en a créé un autre. Nous prenons une pause pour comprendre comment le faire correctement et sans conséquences.

03h30. six yeux
Nous savons quel doit être l'état final de la base pour que tout soit bon pour tous les partenaires. On rédige une demande à 6 yeux, on la roule sur la pré-production, on la teste, on la roule sur la production.

04h00. Tout fonctionne
Tous les tests ont réussi, aucun problème critique n'est visible. De temps en temps dans l'équipe quelque chose ne marche pas pour quelqu'un, on répond vite. La plupart du temps c'est une fausse alerte. Mais parfois, quelque chose n'a pas atteint, une page séparée ne fonctionne pas quelque part. Nous nous asseyons, réparons, réparons, réparons. Une équipe distincte lance la dernière grande fonctionnalité - la facturation.

04h30. point de non retour
Le point de non-retour approche, c'est-à-dire le moment où, si nous commençons à reculer, nous ne respecterons pas le temps d'arrêt qui nous est accordé. Il y a des problèmes avec la facturation, qui sait et enregistre tout, mais ne veut obstinément pas radier l'argent des clients. Il y a plusieurs bugs sur des pages, des actions, des statuts séparés. La fonctionnalité principale fonctionne, tous les tests réussissent. Nous décidons que le déploiement a eu lieu, nous ne reculerons pas.

06h00. Ouvert à tous dans l'interface utilisateur
Les bogues sont corrigés. Certains qui n'affectent pas les utilisateurs sont laissés pour plus tard. Nous ouvrons l'interface à tout le monde. Nous continuons à évoquer la facturation excessive, nous attendons les commentaires des utilisateurs et les résultats de la surveillance.

07h00. Problèmes de chargement d'API
Il devient clair que nous avons planifié la charge sur notre API et testé de manière un peu incorrecte cette charge, ce qui n'a pas permis d'identifier le problème. En conséquence, ≈5 % des requêtes échouent. Nous nous mobilisons, nous cherchons une raison.

Facturation persistante, trop ne veut pas travailler. Nous décidons de le reporter à plus tard afin de faire des changements dans le calme. Autrement dit, toutes les ressources qu'il contient sont accumulées, mais les radiations des clients ne passent pas. Bien sûr, c'est un problème, mais comparé au déploiement général, cela ne semble pas important.

08h00. Corriger l'API
Ils ont déployé un correctif pour la charge, les échecs ont disparu. Nous commençons à rentrer à la maison.

10h00. Tous
Tout est fixé. C'est silencieux dans la surveillance et chez les clients, l'équipe s'endort petit à petit. La facturation reste, nous la rétablirons demain.

Puis, au cours de la journée, des déploiements ont corrigé les journaux, les notifications, les codes de retour et la personnalisation pour certains de nos clients.

Alors, le déploiement a été réussi ! Cela pourrait bien sûr être mieux, mais nous avons tiré des conclusions sur ce qui nous manquait pour atteindre la perfection.

En tout

En 2 mois de préparation active, 43 tâches ont été réalisées au moment du déploiement, d'une durée de quelques heures à plusieurs jours.

Pendant le déploiement :

  • démons nouveaux et modifiés - 5 pièces, remplaçant 2 monolithes;
  • changements à l'intérieur des bases de données - nos 6 bases de données contenant des données utilisateur ont été affectées, le déchargement a été effectué de trois anciennes bases de données vers une nouvelle ;
  • frontend entièrement refait;
  • quantité de code téléchargé — 33 3 lignes de nouveau code, ≈ 5 XNUMX lignes de code dans les tests, ≈ XNUMX XNUMX lignes de code de migration ;
  • toutes les données sont intactes, pas une seule machine virtuelle du client n'a été affectée. 🙂

Les bonnes pratiques pour un bon déploiement

Nous avons été guidés par eux dans cette situation difficile. Mais, d'une manière générale, il est utile de les observer lors de tout déploiement. Mais plus le déploiement est difficile, plus leur rôle est important.

  1. La première chose à faire est de comprendre comment le déploiement peut ou affectera les utilisateurs. Y aura-t-il un temps d'arrêt? Si oui, alors temps d'arrêt de quoi ? Comment cela affectera-t-il les utilisateurs ? Quels sont les meilleurs et les pires scénarios possibles ? Et couvrir les risques.
  2. Planifiez tout. A chaque étape, vous devez comprendre tous les aspects du déploiement :
    • livraison de codes ;
    • restauration de code ;
    • le temps de chaque opération;
    • fonctionnalité affectée.
  3. Jouez des scénarios jusqu'à ce que toutes les étapes du déploiement, ainsi que les risques associés à chacune d'entre elles, deviennent clairs. En cas de doute sur quelque chose, vous pouvez faire une pause et examiner séparément l'étape douteuse.
  4. Chaque étape peut et doit être améliorée si elle aide nos utilisateurs. Par exemple, cela réduira les temps d'arrêt ou supprimera certains risques.
  5. Les tests de restauration sont beaucoup plus importants que les tests de livraison de code. Il est nécessaire de vérifier qu'à la suite d'une restauration, le système reviendra à son état d'origine, confirmez-le par des tests.
  6. Tout ce qui peut être automatisé doit être automatisé. Tout ce qui ne peut pas être automatisé doit être écrit à l'avance sur une feuille de triche.
  7. Fixez les critères de réussite. Quelles fonctionnalités doivent être disponibles et à quelle heure ? Si ce n'est pas le cas, exécutez le plan de restauration.
  8. Et surtout, les gens. Chacun doit être conscient de ce qu'il fait, pourquoi et ce qui dépend de ses actions dans le processus de déploiement.

Et si en une phrase, alors avec une bonne planification et élaboration, vous pouvez déployer tout ce que vous voulez sans conséquences pour la vente. Même quelque chose qui affecte tous vos services dans la vente.

Source: habr.com

Ajouter un commentaire