paint-brush
Comment expédier en toute sécurité les modifications à la productionby@israel_hlc
16,459
16,459

Comment expédier en toute sécurité les modifications à la production

10m2023/10/24
Read on Terminal Reader

Nous connaissons tous le principe, n'est-ce pas ? Après avoir fini de travailler sur un changement de code et [espérons-le] de le tester sur notre machine locale, nous poussons ensuite le changement à l'étape suivante du cycle. Les tests locaux sont très biaisés, et idéalement, nous aimerions valider le changement dans un environnement plus stable (et ne pas suivre uniquement le point de vue de l'ingénieur qui a implémenté le changement).
featured image - Comment expédier en toute sécurité les modifications à la production
undefined HackerNoon profile picture

Nous connaissons tous le principe, n'est-ce pas ? Après avoir fini de travailler sur un changement de code et (espérons-le) de le tester sur notre machine locale, nous poussons ensuite le changement à l'étape suivante du cycle. Les tests locaux sont très biaisés, et idéalement, nous aimerions valider le changement dans un environnement plus stable (et aussi ne pas suivre uniquement le point de vue venant de l'ingénieur qui a implémenté le changement).


Une étape suivante semble ici très naturelle : pousser les modifications vers un environnement de test fiable et demander à des partenaires (AQ, PM, autres ingénieurs) de l'aider à la validation avant de déplacer les modifications. Cela serait suivi d'une correction de bogues et d'une revalidation jusqu'à ce que nous pensons que c'est assez bon pour passer en production. Super!


Cependant, dans la plupart des contextes, cela ne se produit tout simplement pas. Cela peut être dû à diverses raisons, mais quelle qu'en soit la raison, la conséquence est que nous devons souvent promouvoir des modifications sur les serveurs de production avant qu'ils ne soient suffisamment testés ou validés.


Le problème est… Et si quelque chose se casse ? En fait, comment détecter les problèmes plus tôt ? Bonne nouvelle : il est possible d'adopter certains outils et pratiques pour faire des tests et de la validation en production non seulement une pratique sûre pour vous et votre entreprise, mais peut-être même une bonne idée.

La référence : les métriques

Avant de passer aux tests en production, nous devons parler de métriques : nous en avons besoin pour valider que le changement que nous expédions produit l'effet souhaité, ne provoque pas d'effets secondaires indésirables, que le produit est toujours stable, etc. Sans bien -mesures établies, nous sommes fondamentalement aveugles lors du déploiement des changements. Nous ferons référence aux métriques dans de nombreux sujets de l'article. Examinons donc deux types différents de métriques dont nous devrions être conscients.

Mesures commerciales

Les mesures liées à l'entreprise telles que les KPI, les objectifs et le comportement des utilisateurs doivent être surveillées après la mise en œuvre des modifications afin d'évaluer l'impact. Avant tout changement, identifiez les métriques qui devraient être affectées. Les mesures de garde-fou, qui indiquent ce qui ne devrait pas changer, sont tout aussi importantes. Des changements imprévus dans ces garde-fous peuvent signifier des problèmes avec le nouveau changement, nécessitant un examen.

Paramètres techniques

Une fois les indicateurs commerciaux définis, il est également important de comprendre les indicateurs techniques. Ces éléments sont fondamentaux pour garantir que les systèmes restent sains à mesure que des changements sont introduits au fil du temps. Nous parlons ici de stabilité du système, de taux d'erreur, de volume, de contraintes de capacité de la machine, etc.


De bonnes mesures techniques sont également utiles pour expliquer les problèmes observés dans les mesures commerciales ou pour trouver rapidement la cause première des régressions. Par exemple, disons que nous observons que les utilisateurs s'engagent beaucoup moins avec une fonctionnalité particulière après le déploiement de la dernière version. Une augmentation des délais d'attente des requêtes ou des taux d'erreur pourrait rapidement indiquer quels services/points de terminaison sont à l'origine du problème.

Surveillance

Nous avons des métriques business et techniques bien définies, tant mieux ! Maintenant, il faut les surveiller. Il existe de nombreuses façons de procéder, mais une première étape courante consiste à créer des tableaux de bord qui suivent les mesures au fil du temps, facilitant ainsi la détection des pics inhabituels. C'est encore mieux si le tableau de bord permet un filtrage rapide des données en fonction de segments spécifiques qui peuvent être particulièrement pertinents pour l'entreprise. La surveillance active des tableaux de bord est un bon moyen de visualiser rapidement les effets qu'un nouveau changement a introduit dans le système. Certaines entreprises considèrent la surveillance active comme si importante qu'elles mettent même en place des équipes de surveillance 24h/24 et 7j/7 pour détecter et résoudre les problèmes le plus tôt possible.


Un autre bon moyen de surveiller les métriques consiste à utiliser la détection et les alertes automatiques. Pour les indicateurs clés, les alertes peuvent fournir une notification en temps réel lorsque quelque chose ne va pas. Disons que nous commençons à déployer une fonctionnalité et que quelques minutes après le démarrage du processus, nous recevons une alerte indiquant que le taux d'erreur augmente au-dessus d'un seuil spécifique. Cette notification précoce peut nous empêcher de propager le changement plus loin en production et nous épargner bien des problèmes !


Enfin, il est important d'être conscient de la quantité d'informations dont nous avons besoin et dans quelles circonstances. Même si les tableaux de bord sont très utiles pour fournir un aperçu visuel des performances du produit et du système, l’ajout de 1 000 graphiques différents va apporter plus de confusion que de clarté. De même, si nous recevons 1 000 alertes par jour, il est impossible d’enquêter et d’agir en conséquence, et elles finiront par être ignorées.

Atterrissage plus sûr

Métriques définies, suivi en place, super ! Examinons maintenant quelques outils et stratégies pour nous aider à éviter les problèmes, à les détecter plus tôt et à minimiser les impacts sur la production. En fonction de la configuration de l'environnement de production, certaines d'entre elles seront plus difficiles à mettre en œuvre que d'autres, et n'auront peut-être même pas beaucoup de sens une fois combinées. Cependant, chaque élément ici pourrait nous aider à nous rapprocher d’un environnement de production sûr et stable.

Tests automatisés

Les tests automatisés, souvent mis de côté lorsque les projets échouent, peuvent accélérer le développement et rendre les modifications de la production plus sûres et plus rapides. Plus les problèmes sont détectés tôt, plus vite ils peuvent être résolus, réduisant ainsi le temps global consacré au processus. Le processus consistant à annuler les modifications, à les corriger et à les repousser est généralement très stressant et peut faire perdre un temps précieux.


Viser une couverture de tests à 100 % avec des tests unitaires, d'intégration et de bout en bout peut être idéaliste pour la plupart des projets. Au lieu de cela, priorisez les tests en fonction de l’effort par rapport aux avantages. Les métriques peuvent guider cela : couvrir les fonctionnalités de base de l'entreprise est probablement plus crucial que les fonctionnalités de niche à moindre impact, n'est-ce pas ? Commencez par les fonctionnalités de base, en les développant à mesure que le système évolue.


Le processus de publication en production doit inclure l'exécution de la suite de tests avant le déploiement en production. Les échecs des tests devraient interrompre la publication, évitant ainsi les problèmes de production. Il est préférable de retarder la sortie d'une fonctionnalité plutôt que de découvrir le lendemain qu'elle fonctionne totalement dysfonctionnement.

Nourriture pour chiens

Le Dogfooding est le processus de publication d'une fonctionnalité pour des tests internes avant qu'elle n'atteigne les utilisateurs finaux. Lors du dogfooding, la fonctionnalité est rendue disponible en production, mais uniquement aux utilisateurs internes (employés, membres de l'équipe, etc.). De cette façon, nous pouvons tester et valider si la nouvelle fonctionnalité fonctionne comme prévu, en utilisant des données de production réelles, sans impacter les utilisateurs externes.


Il existe différentes stratégies pour le dogfooding. Pour un aperçu simplifié, nous pourrions les regrouper en deux groupes plus grands :

  1. Dogfooding avec artefact complet : Ceci est courant, par exemple, sur les applications iOS/Android, où nous avons des outils intégrés pour publier une nouvelle version de l'application pour des utilisateurs spécifiques, puis rendre cette même version disponible pour le grand public dans les magasins.
  2. Alimentation sélective pour chiens : Parfois, il n'est pas possible (ni même souhaité) de dogfooder l'ensemble de l'artefact, mais nous pouvons toujours autoriser le dogfooding en fonction des informations spécifiques de l'utilisateur. Disons, par exemple, que nous sommes capables d'identifier les salariés en croisant certaines données. L'application pourrait alors être configurée pour activer/désactiver une fonctionnalité particulière en vérifiant ces données et en dirigeant l'utilisateur vers le comportement souhaité. L’application contient alors les deux fonctionnalités, mais seuls certains utilisateurs seraient concernés par le nouveau changement. Nous reviendrons sur certains de ces concepts dans les prochaines rubriques.

Sortie des Canaries

La version Canary est un processus de publication dans lequel, au lieu de déployer les modifications en production sur tous les serveurs en même temps, la modification est mise à la disposition d'un petit sous-ensemble d'entre eux et surveillée pendant un certain temps. Ce n'est qu'après avoir certifié que le changement est stable qu'il est ensuite transféré vers l'environnement de production.


Sortie des Canaries


Il s’agit de l’un des outils les plus puissants pour tester de nouvelles fonctionnalités et des changements risqués, réduisant ainsi les risques de panne en production. En testant le changement sur un groupe d'utilisateurs, nous pouvons arrêter/annuler le processus de déploiement si un problème est détecté, évitant ainsi l'impact sur la plupart des utilisateurs.

Déploiement bleu vert

Blue Green Deployment, une pratique DevOps, vise à éviter les temps d'arrêt en utilisant deux clusters de serveurs (bleu et vert) et en basculant le trafic de production entre eux. Lors du déploiement de la fonctionnalité, les modifications sont publiées sur un ensemble (vert) tout en gardant l'autre (bleu) inchangé. Si des problèmes surviennent, le trafic peut être rapidement renvoyé vers les serveurs Blue, car ils continuaient à fonctionner avec la version précédente.


Déploiement #Bleu Vert

Le déploiement Blue Green est souvent comparé à la version Canary dont nous avons discuté plus tôt. Nous n'entrerons pas dans les détails de cette discussion, mais il est important de le mentionner pour nous aider à décider quels outils sont les plus adaptés à notre travail.

Arrêtez les commutateurs et les bascules de fonctionnalités

Les commutateurs d'arrêt ne sont pas créés dans le contexte du génie logiciel, et la meilleure façon de comprendre leur utilisation est de revenir sur l'intention et la conception d'origine. Dans les machines utilisées dans l'industrie, les coupe-circuit sont des mécanismes de sécurité qui les éteignent le plus rapidement possible grâce à une interaction très simple (généralement un simple bouton ou un interrupteur marche/arrêt). Ils existent pour les situations d'urgence, pour éviter qu'un incident (dysfonctionnement d'une machine par exemple) n'en provoque un autre encore plus grave (blessures ou décès).


En génie logiciel, les kill switch ont un objectif similaire : nous acceptons de perdre (ou de supprimer) une fonctionnalité particulière pour tenter de maintenir le système opérationnel. L'implémentation est, à un niveau élevé, une vérification de condition (voir l'extrait de code ci-dessous), généralement ajoutée au point d'entrée d'une modification ou d'une fonctionnalité particulière.


 if (feature_is_enabled('feature_x')) {xNewBehaviour();} else {xOldBehaviour();}


Disons, par exemple, que nous effectuons une migration vers une nouvelle API tierce. Tout va bien dans les tests, stable dans la version Canary, puis le changement est déployé à 100 % en production. Après un certain temps, la nouvelle API commence à avoir du mal avec le volume et les requêtes commencent à échouer (vous vous souvenez des mesures techniques ?). Grâce à un kill switch, les requêtes API peuvent être instantanément rétablies à l'ancienne API, et nous n'avons pas besoin de revenir à une version précédente ni de fournir rapidement un correctif.


Techniquement parlant, les kill switchs sont en fait un cas d'utilisation particulier des bascules de fonctionnalités (alias drapeaux de fonctionnalités). Alors que nous abordons le sujet, il convient de mentionner un autre grand avantage des bascules de fonctionnalités : permettre le développement basé sur le tronc. Grâce aux bascules de fonctionnalités, le nouveau code peut être poussé en toute sécurité vers la production, même s'il est incomplet ou pas encore testé.

Garder les anciens comportements accessibles

Le code illustré ci-dessus a probablement amené certains d'entre nous à se demander s'il s'agissait réellement d'un bon modèle, avec des comportements anciens et nouveaux vivant simultanément dans l'application. Je conviens que ce n'est probablement pas l'état final que nous souhaitons pour notre base de code, sinon chaque morceau de code finirait par être entouré de clauses if/else, rendant le code illisible en un rien de temps.


Cependant, nous ne devrions pas toujours nous précipiter pour supprimer l'ancien comportement. Oui, il est très tentant de nettoyer le code dès qu'il cesse d'être utilisé et d'éviter les dettes techniques. Mais c'est aussi bien de le laisser là pendant un certain temps sous une bascule de fonctionnalité. Parfois, cela peut prendre un certain temps jusqu'à ce que la nouvelle fonctionnalité soit stabilisée, et disposer d'une option de sauvegarde est un mécanisme sûr au cas où nous aurions besoin d'y revenir, même si ce n'est que pour une courte période.


Le cycle de vie de chaque version est différent et c'est une bonne pratique de savoir quand c'est le bon moment pour se débarrasser de l'ancien code. Garder le code propre et réduire les frais de maintenance évitera la situation inverse dans laquelle, bien que la fonctionnalité soit désactivée dans le code, elle est probablement cassée étant donné le temps écoulé depuis sa désactivation.

Tests d'ombre

L’une de mes techniques préférées pour implémenter des modifications plus sûres est connue sous le nom de test fantôme ou mode ombre. Cela consiste à exécuter à la fois des comportements anciens et nouveaux pour comparer les résultats, mais en désactivant certains des nouveaux effets secondaires du comportement, le cas échéant. Jetons un coup d'œil à cet exemple simple :


 int sum(int a, int b) {int currentResult = currentMathLib.sum(a, b);int newResult = newMathLib.sum(a, b);logDivergences(a, b, currentResult, newResult);return currentResult;}void logSumDivergences(int a, int b, int currentResult, int newResult) {if (currentResult != newResult) {logger.warn(      'Divergence detected when executing {0} + {1}: {2} != {3}',a, b, currentResult, newResult);}}


Bien que les deux opérations de somme soient exécutées, la nouvelle n’est utilisée que pour comparer et enregistrer les divergences. Cette technique est particulièrement utile pour surveiller les changements complexes du système et nous nous attendons à une certaine parité entre les anciens et les nouveaux comportements. Un autre cas d'utilisation intéressant est lorsque nous devons apporter des modifications à des produits avec lesquels nous ne sommes pas très familiers, ou lorsque nous ne savons pas bien quels cas extrêmes peuvent être affectés par le changement prévu.


Dans des scénarios plus complexes, nous devrons peut-être désactiver certains effets secondaires avant d'activer les tests fantômes. Par exemple, disons que nous implémentons une nouvelle API backend pour inscrire les utilisateurs et les enregistrer dans la base de données, en renvoyant l'ID utilisateur. Nous pourrions même avoir une base de données fantôme en place pour exécuter le processus complet, mais ce n'est certainement pas une bonne idée d'envoyer deux fois l'e-mail « Inscription réussie », un pour chaque API backend. Toujours dans le même exemple, nous aurions besoin d’une logique de comparaison plus approfondie, car la simple comparaison des identifiants utilisateur renvoyés ne serait pas très utile.


Enfin, il est important de comprendre ce qui doit être surveillé et testé, et quels critères seront appliqués si la parité n'est pas atteinte. Dans certains scénarios critiques, nous devrons répéter les tests fantômes jusqu'à ce que les résultats soient exactement les mêmes. Dans d'autres, il peut être acceptable d'avoir un certain pourcentage de divergence lorsque la nouvelle mise en œuvre offre des avantages supplémentaires qui compensent la perte.

Journaux

Même avec des mesures de protection solides, les systèmes peuvent faiblir. Lorsque cela se produit, nous devons être capables de comprendre ce qui se passe, avec le niveau de détail approprié, sinon il peut être extrêmement difficile de trouver une solution efficace. C'est ici que les journaux viennent sauver la situation.


Même si la journalisation n'est pas un concept nouveau et qu'il existe de nombreuses solutions faciles à mettre en œuvre, il est difficile de garantir l'efficacité des journaux. Souvent, les journaux sont peu clairs, trop complexes, manquants ou inondés d'entrées non pertinentes, ce qui rend le dépannage difficile. Cependant, les journaux ne servent pas uniquement à résoudre les problèmes. Une journalisation appropriée aide à vérifier l’efficacité des nouvelles fonctionnalités et des modifications. En échantillonnant les entrées du journal, on peut retracer les parcours des utilisateurs et confirmer que les systèmes fonctionnent comme prévu.

Dernières pensées

Envoyer le code en production est parfois dangereux, mais nous disposons de nombreuses stratégies pour rendre le processus beaucoup plus sûr. Même si nous identifions un problème, il est également important de savoir ce qui est acceptable ou non. Tous les échecs ne doivent pas nécessairement entraîner un retour en arrière. Que se passe-t-il si nous essayons de corriger une faille de sécurité grave ou de nous conformer à une nouvelle réglementation ? Il est très important d’avoir des critères clairs et de comprendre à quel point le changement est critique pour déterminer quand abandonner ou poursuivre en cas de problème. Pour revenir au début, les principaux indicateurs sont là pour nous aider dans le processus de décision.


Bon atterrissage à tous !