En augmentation MTBF - Disponibilité et au-delà : comprendre et améliorer la résilience des systèmes distribués sur AWS

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

En augmentation MTBF

Le dernier élément pour améliorer la disponibilité consiste à augmenter leMTBF. Cela peut s'appliquer à la fois au logiciel et aux AWS services utilisés pour l'exécuter.

Élargir le système distribué MTBF

L'un des moyens d'augmenter MTBF est de réduire les défauts du logiciel. Il existe plusieurs méthodes pour le faire. Les clients peuvent utiliser des outils tels qu'Amazon CodeGuru Reviewer pour détecter et corriger les erreurs courantes. Vous devez également effectuer des révisions complètes du code par les pairs, des tests unitaires, des tests d'intégration, des tests de régression et des tests de charge sur le logiciel avant son déploiement en production. L'augmentation de la couverture du code dans les tests permettra de garantir que même les chemins d'exécution de code peu courants sont testés.

Le déploiement de modifications mineures peut également aider à éviter des résultats inattendus en réduisant la complexité des modifications. Chaque activité permet d'identifier et de corriger les défauts avant qu'ils ne puissent être invoqués.

Une autre approche pour prévenir les défaillances consiste à effectuer des tests réguliers. La mise en œuvre d'un programme d'ingénierie du chaos peut vous aider à tester les défaillances de votre charge de travail, à valider les procédures de reprise et à identifier et corriger les modes de défaillance avant qu'ils ne surviennent en production. Les clients peuvent utiliser le simulateur d'injection de AWS défauts dans le cadre de leur ensemble d'outils d'expérimentation d'ingénierie du chaos.

La tolérance aux pannes est un autre moyen de prévenir les défaillances dans un système distribué. Les modules rapides, les nouvelles tentatives avec retard et instabilité exponentiels, les transactions et l'idempotencie sont autant de techniques qui contribuent à rendre les charges de travail tolérantes aux pannes.

Les transactions sont un groupe d'opérations qui respectent les ACID propriétés. Ce sont les suivants :

  • Atomicité — Soit toutes les actions se produisent, soit aucune d'entre elles ne se produira.

  • Cohérence — Chaque transaction laisse la charge de travail dans un état valide.

  • Isolation — Les transactions effectuées simultanément laissent la charge de travail dans le même état que si elles avaient été effectuées de manière séquentielle.

  • Durabilité — Une fois qu'une transaction est validée, tous ses effets sont préservés, même en cas de défaillance de la charge de travail.

Les nouvelles tentatives avec retard et instabilité exponentiels vous permettent de surmonter les défaillances transitoires causées par des Heisenbugs, une surcharge ou d'autres conditions. Lorsque les transactions sont idempotentes, elles peuvent être réessayées plusieurs fois sans effets secondaires.

Si nous prenons en compte l'effet d'un Heisenbug sur une configuration matérielle tolérante aux pannes, nous ne nous inquiétons guère, car la probabilité que le Heisenbug apparaisse à la fois sur le sous-système principal et sur le sous-système redondant est infiniment faible. (Voir Jim Gray, « Pourquoi les ordinateurs s'arrêtent-ils et que peut-on faire pour y remédier ? », juin 1985, Rapport technique de Tandem 85.7.) Dans les systèmes distribués, nous voulons obtenir les mêmes résultats avec nos logiciels.

Lorsqu'un Heisenbug est invoqué, il est impératif que le logiciel détecte rapidement l'opération incorrecte et échoue afin de pouvoir réessayer. Ceci est réalisé grâce à une programmation défensive et à la validation des entrées, des résultats intermédiaires et des sorties. De plus, les processus sont isolés et ne partagent aucun état avec les autres processus.

Cette approche modulaire garantit que l'ampleur de l'impact en cas de panne est limitée. Les processus échouent indépendamment. Lorsqu'un processus échoue, le logiciel doit utiliser des « paires de processus » pour recommencer le travail, ce qui signifie qu'un nouveau processus peut assumer le travail d'un processus défaillant. Pour maintenir la fiabilité et l'intégrité de la charge de travail, chaque opération doit être traitée comme une ACID transaction.

Cela permet à un processus d'échouer sans altérer l'état de la charge de travail en annulant la transaction et en annulant les modifications apportées. Cela permet au processus de restauration de réessayer la transaction à partir d'un état dont le fonctionnement a été vérifié et de redémarrer correctement. C'est ainsi que le logiciel peut être tolérant aux pannes face aux Heisenbugs.

Cependant, vous ne devez pas viser à rendre le logiciel tolérant aux bohrbugs. Ces défauts doivent être détectés et corrigés avant que la charge de travail n'entre en production, car aucun niveau de redondance ne permettra d'obtenir un résultat correct. (Voir Jim Gray, « Pourquoi les ordinateurs s'arrêtent-ils et que peut-on faire pour y remédier ? », juin 1985, Rapport technique de Tandem 85.7.)

La dernière méthode d'augmentation MTBF consiste à réduire la portée de l'impact d'une défaillance. L'utilisation de l'isolation des pannes par modularisation pour créer des conteneurs de défaillances est un moyen principal d'y parvenir, comme indiqué précédemment dans Tolérance aux pannes et isolation des pannes. La réduction du taux de défaillance améliore la disponibilité. AWS utilise des techniques telles que la division des services en plans de contrôle et en plans de données, l'indépendance des zones de disponibilité (AZI), l'isolation régionale, les architectures basées sur les cellules et le shuffle-sharding pour isoler les pannes. Ce sont également des modèles qui peuvent également être utilisés par les AWS clients.

Par exemple, examinons un scénario dans lequel une charge de travail plaçait les clients dans différents conteneurs de défaillances de son infrastructure desservant au plus 5 % du total des clients. L'un de ces conteneurs d'erreurs connaît un événement qui augmente la latence au-delà du délai d'expiration du client pour 10 % des demandes. Lors de cet événement, pour 95 % des clients, le service était disponible à 100 %. Pour les 5 % restants, le service semblait être disponible à 90 %. Cela se traduit par une disponibilité de 1 − (5 % o f c u s t o m e r s × 10 % o f t h e i r r e q u e s t s) = 99,5 % au lieu de 10 % des demandes échouées pour 100 % des clients (soit une disponibilité de 90 %).

Règle 11

L'isolation des défaillances réduit la portée de l'impact et augmente la charge MTBF de travail en réduisant le taux de défaillance global.

Dépendance croissante MTBF

La première méthode pour augmenter votre AWS dépendance MTBF consiste à utiliser l'isolation des pannes. De nombreux AWS services offrent un certain niveau d'isolation au niveau de l'AZ, ce qui signifie qu'une panne dans un AZ n'affecte pas le service dans un AZ différent.

L'utilisation d'EC2instances redondantes dans plusieurs instances AZs augmente la disponibilité des sous-systèmes. AZIfournit une capacité d'épargne au sein d'une seule région, ce qui vous permet d'augmenter la disponibilité de vos AZI services.

Cependant, tous les AWS services ne fonctionnent pas au niveau AZ. Beaucoup d'autres offrent un isolement régional. Dans ce cas, lorsque la disponibilité prévue du service régional ne prend pas en charge la disponibilité globale requise pour votre charge de travail, vous pouvez envisager une approche multirégionale. Chaque région propose une instanciation isolée du service, ce qui équivaut à du sparing.

Il existe différents services qui facilitent la création d'un service multirégional. Par exemple :

Ce document n'aborde pas les stratégies de création de charges de travail multirégionales, mais vous devez évaluer les avantages de disponibilité des architectures multirégionales avec les coûts supplémentaires, la complexité et les pratiques opérationnelles nécessaires pour atteindre les objectifs de disponibilité souhaités.

La méthode suivante pour augmenter la dépendance MTBF consiste à concevoir votre charge de travail de manière à ce qu'elle soit statiquement stable. Par exemple, vous avez une charge de travail qui fournit des informations sur les produits. Lorsque vos clients font une demande pour un produit, votre service adresse une demande à un service de métadonnées externe pour récupérer les détails du produit. Votre charge de travail renvoie ensuite toutes ces informations à l'utilisateur.

Toutefois, si le service de métadonnées n'est pas disponible, les demandes de vos clients échouent. Au lieu de cela, vous pouvez extraire ou transférer de manière asynchrone les métadonnées localement vers votre service afin de les utiliser pour répondre aux demandes. Cela élimine l'appel synchrone au service de métadonnées depuis votre chemin critique.

En outre, étant donné que votre service est toujours disponible même lorsque le service de métadonnées ne l'est pas, vous pouvez le supprimer en tant que dépendance dans votre calcul de disponibilité. Cet exemple repose sur l'hypothèse selon laquelle les métadonnées ne changent pas fréquemment et qu'il vaut mieux servir des métadonnées périmées que l'échec de la demande. Un autre exemple similaire est celui de Serve-Stale, DNS qui permet de conserver les données dans le cache au-delà de TTL leur expiration et de les utiliser pour les réponses lorsqu'une réponse actualisée n'est pas facilement disponible.

La dernière méthode pour augmenter la dépendance MTBF consiste à réduire la portée de l'impact d'une défaillance. Comme indiqué précédemment, l'échec n'est pas un événement binaire, il existe des degrés de défaillance. C'est l'effet de la modularisation ; l'échec est limité aux demandes ou aux utilisateurs desservis par ce conteneur.

Cela permet de réduire le nombre de défaillances lors d'un événement, ce qui augmente en fin de compte la disponibilité de la charge de travail globale en limitant l'étendue de l'impact.

Réduire les sources d'impact communes

En 1985, Jim Gray a découvert, lors d'une étude menée par Tandem Computers, que les défaillances étaient principalement dues à deux facteurs : le logiciel et les opérations. (Voir Jim Gray, « Pourquoi les ordinateurs s'arrêtent-ils et que peut-on faire pour y remédier ? », juin 1985, Rapport technique de Tandem 85.7.) Même 36 ans plus tard, cela continue d'être vrai. Malgré les avancées technologiques, il n'existe pas de solution facile à ces problèmes, et les principales causes de défaillance n'ont pas changé. La résolution des défaillances logicielles a été abordée au début de cette section. L'accent sera donc mis ici sur les opérations et la réduction de la fréquence des défaillances.

Stabilité par rapport aux fonctionnalités

Si nous nous référons au graphique des taux d'échec du logiciel et du matériel dans la sectionDisponibilité du système distribué, nous pouvons remarquer que des défauts sont ajoutés dans chaque version logicielle. Cela signifie que toute modification de la charge de travail augmente le risque de défaillance. Ces modifications concernent généralement de nouvelles fonctionnalités, ce qui constitue un corollaire. Des charges de travail à disponibilité plus élevée favoriseront la stabilité par rapport aux nouvelles fonctionnalités. Ainsi, l'un des moyens les plus simples d'améliorer la disponibilité consiste à déployer moins souvent ou à proposer moins de fonctionnalités. Les charges de travail qui sont déployées plus fréquemment seront intrinsèquement moins disponibles que celles qui ne le sont pas. Cependant, les charges de travail qui n'ajoutent pas de fonctionnalités ne répondent pas à la demande des clients et peuvent devenir moins utiles au fil du temps.

Alors, comment continuer à innover et à publier des fonctionnalités en toute sécurité ? La réponse est la standardisation. Quelle est la bonne méthode de déploiement ? Comment commandez-vous des déploiements ? Quelles sont les normes de test ? Combien de temps attendez-vous entre les étapes ? Vos tests unitaires couvrent-ils une partie suffisante du code logiciel ? La normalisation répondra à ces questions et évitera les problèmes causés par des facteurs tels que l'absence de tests de charge, le fait de sauter des étapes de déploiement ou un déploiement trop rapide sur un trop grand nombre d'hôtes.

La façon dont vous implémentez la standardisation passe par l'automatisation. Cela réduit les risques d'erreurs humaines et permet aux ordinateurs de faire ce pour quoi ils sont doués, c'est-à-dire faire toujours la même chose de la même manière. La façon dont vous combinez standardisation et automatisation consiste à définir des objectifs. Des objectifs tels que l'absence de modifications manuelles, l'accès à l'hôte uniquement par le biais de systèmes d'autorisation conditionnelsAPI, l'écriture de tests de charge pour chacun, etc. L'excellence opérationnelle est une norme culturelle qui peut nécessiter des changements substantiels. L'établissement et le suivi des performances par rapport à un objectif contribuent à susciter un changement culturel qui aura un impact important sur la disponibilité de la charge de travail. Le pilier AWS Well-Architected Operational Excellence fournit des meilleures pratiques complètes pour l'excellence opérationnelle.

Sécurité des opérateurs

L'autre facteur majeur qui contribue aux événements opérationnels qui entraînent des défaillances sont les personnes. Les humains commettent des erreurs. Ils peuvent utiliser des informations d'identification incorrectes, saisir la mauvaise commande, appuyer sur Entrée trop tôt ou manquer une étape critique. Toute action manuelle entraîne systématiquement des erreurs, ce qui entraîne un échec.

L'une des principales causes des erreurs des opérateurs réside dans les interfaces utilisateur confuses, peu intuitives ou incohérentes. Jim Gray a également noté dans son étude de 1985 que « les interfaces qui demandent des informations à l'opérateur ou lui demandent d'exécuter une fonction doivent être simples, cohérentes et tolérantes aux pannes de l'opérateur ». (Voir Jim Gray, « Pourquoi les ordinateurs s'arrêtent-ils et que peut-on faire pour y remédier ? », juin 1985, Rapport technique de Tandem 85.7.) Cette idée est toujours vraie aujourd'hui. Au cours des trente dernières années, il existe de nombreux exemples dans l'industrie où une interface utilisateur confuse ou complexe, l'absence de confirmation ou d'instructions, ou même simplement un langage humain peu convivial ont incité un opérateur à faire le mauvais choix.

Règle 12

Permettez aux opérateurs de prendre facilement les bonnes décisions.

Prévenir les surcharges

Le dernier contributeur commun à l'impact est constitué par vos clients, les véritables utilisateurs de votre charge de travail. Les charges de travail réussies ont tendance à s'habituer, dans une large mesure, mais cette utilisation dépasse parfois la capacité d'évolution de la charge de travail. De nombreuses choses peuvent se produire : les disques peuvent être saturés, les pools de threads peuvent être épuisés, la bande passante réseau peut être saturée ou les limites de connexion à la base de données peuvent être atteintes.

Il n'existe pas de méthode infaillible pour les éliminer, mais une surveillance proactive de la capacité et de l'utilisation par le biais de métriques Operational Health fournira des alertes précoces lorsque de telles défaillances pourraient survenir. Des techniques telles que le délestage, les disjoncteurs et les nouvelles tentatives avec recul et instabilité exponentiels peuvent aider à minimiser l'impact et à augmenter le taux de réussite, mais ces situations constituent tout de même un échec. La mise à l'échelle automatisée basée sur les indicateurs de santé opérationnelle peut aider à réduire la fréquence des pannes dues à une surcharge, mais risque de ne pas être en mesure de répondre assez rapidement aux changements d'utilisation.

Si vous devez garantir la disponibilité continue de la capacité pour les clients, vous devez faire des compromis en termes de disponibilité et de coût. L'un des moyens de garantir que le manque de capacité n'entraîne pas d'indisponibilité est de fournir un quota à chaque client et de veiller à ce que la capacité de votre charge de travail soit adaptée à 100 % des quotas alloués. Lorsque les clients dépassent leur quota, ils sont limités, ce qui n'est pas un échec et n'est pas pris en compte dans la disponibilité. Vous devrez également suivre de près votre clientèle et prévoir son utilisation future afin de maintenir une capacité suffisante. Cela garantit que votre charge de travail n'est pas entraînée par des scénarios de défaillance en raison d'une consommation excessive par vos clients.

Par exemple, examinons une charge de travail qui fournit un service de stockage. Chaque serveur de la charge de travail peut prendre en charge 100 téléchargements par seconde, les clients disposent d'un quota de 200 téléchargements par seconde, et il y a 500 clients. Pour pouvoir prendre en charge ce volume de clients, le service doit fournir une capacité de 100 000 téléchargements par seconde, ce qui nécessite 1 000 serveurs. Si un client dépasse son quota, il est limité, ce qui garantit une capacité suffisante pour tous les autres clients. Il s'agit d'un exemple simple d'une façon d'éviter la surcharge sans rejeter les unités de travail.