Modèles d'applications évolutives et résilientes

Last reviewed 2024-03-19 UTC

Ce document présente des modèles et des pratiques permettant de créer des applications résilientes et évolutives, deux objectifs essentiels pour nombre d'architectures modernes. Une application bien conçue doit évoluer à la hausse ou à la baisse en fonction de l'augmentation et de la diminution de la demande, et être suffisamment résiliente pour résister aux interruptions de service. Le développement et l'exploitation d'applications répondant à ces exigences nécessitent une planification et une conception minutieuses.

Évolutivité : adaptation de la capacité en fonction de la demande

L'évolutivité est une mesure permettant d'évaluer la capacité d'un système à gérer différentes tâches en ajoutant ou en supprimant des ressources du système. Par exemple, une application Web évolutive est une application qui fonctionne bien, que ce soit avec un ou plusieurs utilisateurs, et qui est capable de gérer les pics et baisses de trafic de manière optimale.

La flexibilité d'ajuster les ressources consommées par une application est un facteur stratégique déterminant pour migrer vers le cloud. Avec une conception appropriée, vous pouvez réduire les coûts en supprimant les ressources sous-utilisées, sans compromettre les performances et l'expérience utilisateur. Vous pouvez également assurer une bonne expérience utilisateur lors des pics de trafic en ajoutant davantage de ressources. Ainsi, votre application ne consomme que les ressources nécessaires pour répondre à la demande.

Google Cloud fournit des produits et des fonctionnalités pour vous aider à créer des applications évolutives et efficaces :

  • Les autoscalers intégrés aux machines virtuelles Compute Engine et aux clusters Google Kubernetes Engine (GKE) vous permettent d'augmenter ou de réduire la consommation des ressources en fonction des métriques que vous définissez.
  • La plate-forme sans serveur de Google Cloud fournit des services gérés de calcul et de base de données qui évoluent rapidement de zéro requête à un volume de requêtes élevé, et vous ne payez que ce que vous utilisez.
  • Les produits de base de données, tels que BigQuery, Spanner et Bigtable peuvent offrir des performances constantes sur des données de très grande taille.
  • Cloud Monitoring met à votre disposition des métriques pour vos applications et votre infrastructure. Vous pouvez ainsi prendre des décisions en termes de scaling en vous appuyant sur les données.

Résilience : conception permettant de supporter les défaillances

Une application résiliente est une application qui continue à fonctionner malgré les défaillances des composants du système. La résilience nécessite une planification à tous les niveaux de l'architecture. Elle influe sur l'organisation de l'infrastructure et du réseau, ainsi que sur la conception de l'application et du stockage de données. La résilience s'étend également aux personnes et aux cultures.

Il est difficile de développer et d'exploiter des applications résilientes. Cela est particulièrement vrai pour les applications distribuées, qui peuvent contenir plusieurs couches d'infrastructure, de réseaux et de services. Des erreurs et des pannes peuvent se produire. L'amélioration de la résilience de votre application est donc un défi constant. Vous pouvez améliorer la capacité de votre application à supporter les défaillances à l'aide d'une planification minutieuse. Avec des processus et une culture organisationnelle appropriés, vous pouvez également tirer des leçons des défaillances pour accroître davantage la résilience de votre application.

Google Cloud fournit des outils et des services pour vous aider à créer des applications résilientes à disponibilité élevée :

  • Les services Google Cloud sont disponibles dans plusieurs régions et zones du monde, ce qui vous permet de déployer votre application en répondant au mieux à vos objectifs de disponibilité.
  • Les groupes d'instances Compute Engine et les clusters GKE peuvent être répartis et gérés entre les zones disponibles d'une région.
  • Les disques persistants régionaux Compute Engine sont répliqués de manière synchrone dans les zones d'une même région.
  • Google Cloud propose différentes options d'équilibrage de charge pour gérer le trafic de votre application, y compris l'équilibrage de charge au niveau mondial permettant d'acheminer le trafic vers la région opérationnelle la plus proche de vos utilisateurs.
  • La plate-forme sans serveur de Google Cloud fournit des produits de calcul et de base de données gérés, dotés d'une fonctionnalité de redondance intégrée et d'équilibrage de charge.
  • Google Cloud est compatible avec les solutions de CI/CD via des outils natifs et des intégrations aux technologies Open Source pour vous aider à automatiser la conception et le déploiement de vos applications.
  • Cloud Monitoring met à votre disposition des métriques pour vos applications et votre infrastructure. Vous pouvez ainsi prendre des décisions à partir de données concernant les performances et l'état de vos applications.

Facteurs et contraintes

Plusieurs exigences et motivations peuvent influer sur l'amélioration de l'évolutivité et de la résilience de votre application. Vous pouvez également être soumis à certaines contraintes limitant votre capacité à remplir vos objectifs d'évolutivité et de résilience. L'importance relative de ces exigences et contraintes varie en fonction du type d'application, du profil de vos utilisateurs, ainsi que de l'envergure et de la maturité de votre organisation.

Facteurs

Pour vous aider à hiérarchiser vos besoins, prenez en compte les facteurs des différentes parties de votre organisation.

Facteurs commerciaux

Les entreprises sont soumises à un certain nombre de facteurs stratégiques, y compris les suivants :

  • Optimiser les coûts et la consommation des ressources
  • Minimiser les temps d'arrêt de l'application
  • S'assurer que la demande des utilisateurs peut être satisfaite pendant les périodes de forte utilisation
  • Améliorer la qualité et la disponibilité du service
  • Garantir la continuité de l'expérience utilisateur et de la confiance en cas d'interruption de service
  • Augmenter la flexibilité et l'agilité pour répondre aux nouvelles exigences du marché

Facteurs de développement

Le développement dans l'entreprise est tributaire des facteurs suivants :

  • Diminuer le temps consacré à l'analyse des défaillances
  • Augmenter le temps consacré au développement de nouvelles fonctionnalités
  • Minimiser les tâches laborieuses par le biais de l'automatisation
  • Développer des applications basées sur les derniers modèles et pratiques du secteur

Facteurs opérationnels

Il convient également de prendre en compte les exigences opérationnelles suivantes :

  • Réduire la fréquence des pannes nécessitant une intervention humaine
  • Augmenter la capacité à résoudre automatiquement les pannes
  • Minimiser les tâches laborieuses par le biais de l'automatisation
  • Minimiser l'impact de la défaillance d'un composant particulier

Contraintes

Des contraintes peuvent limiter votre capacité à améliorer l'évolutivité et la résilience de votre application. Assurez-vous que vos décisions de conception n'introduisent pas de contraintes ou n'y contribuent pas :

  • Dépendances matérielles ou logicielles difficiles à faire évoluer
  • Dépendances matérielles ou logicielles difficiles à exploiter dans une configuration de haute disponibilité
  • Dépendances entre les applications
  • Restrictions de licence
  • Manque de compétences ou d'expérience des équipes chargées du développement et des opérations
  • Résistance à l'automatisation au sein de l'organisation

Modèles et pratiques

Le reste de ce document définit les modèles et pratiques permettant de développer des applications résilientes et évolutives. Ces modèles ont une incidence sur l'ensemble du cycle de vie de votre application, y compris la conception de l'infrastructure, l'architecture de l'application, les options de stockage, les processus de déploiement et la culture organisationnelle.

Trois thèmes se distinguent dans ces modèles :

  • Automatisation. Le développement d'applications évolutives et résilientes nécessite une automatisation. L'automatisation du provisionnement de l'infrastructure, des tests et des déploiements d'applications permet d'améliorer la cohérence et la rapidité, ainsi que de limiter les erreurs humaines.
  • Couplage faible. Traiter votre système sous forme de collection de composants faiblement couplés et indépendants vous apporte flexibilité et résilience. L'indépendance englobe la répartition physique des ressources, l'architecture de l'application et la conception du stockage.
  • Conception basée sur les données. Il est essentiel de collecter des métriques pour comprendre le comportement de votre application. Les décisions permettant de déterminer à quel moment faire évoluer votre application ou d'identifier un service non opérationnel doivent être basées sur les données. Vous devez attacher une importance particulière aux métriques et aux journaux.

Automatiser le provisionnement de l'infrastructure

La création d'une infrastructure immuable par le biais de l'automatisation vous permet d'améliorer la cohérence de vos environnements et d'augmenter le taux de réussite de vos déploiements.

Gérer l'infrastructure comme du code

L'Infrastructure as code (IaC) est une technique qui vous encourage à traiter le provisionnement et la configuration de votre infrastructure de la même manière que vous gérez le code d'application. La logique de provisionnement et de configuration est stockée dans un dépôt source de façon à la rendre visible. Elle peut également comporter des versions gérées et être contrôlée. Comme elle se trouve dans un dépôt de code, vous pouvez tirer profit des pipelines d'intégration continue et de déploiement continu (CI/CD), de sorte que toutes les modifications apportées à votre configuration puissent être testées et déployées automatiquement.

En supprimant les étapes manuelles du provisionnement de votre infrastructure, l'IaC permet de limiter les erreurs humaines, ainsi que d'améliorer la cohérence et la reproductibilité des applications et des environnements. De cette manière, vous pouvez augmenter la résilience de vos applications.

Cloud Deployment Manager vous permet d'automatiser la création et la gestion des ressources Google Cloud à l'aide de modèles flexibles. Config Connector vous permet également de gérer vos ressources à l'aide des techniques et des workflows Kubernetes. Google Cloud est également compatible avec des outils IaC tiers, tels que Terraform, Chef et Puppet.

Créer une infrastructure immuable

L'infrastructure immuable est une philosophie qui s'appuie sur les avantages de l'Infrastructure as Code. L'infrastructure immuable exige qu'aucune modification ne soit apportée aux ressources après leur déploiement. Lorsqu'il est nécessaire de procéder à la mise à jour d'une machine virtuelle, d'un cluster Kubernetes ou d'une règle de pare-feu, vous pouvez mettre à jour la configuration de la ressource dans le dépôt source. Une fois les modifications testées et validées, vous pouvez redéployer complètement la ressource à l'aide de la nouvelle configuration. En d'autres termes, vous recréez les ressources au lieu de les ajuster.

L'infrastructure immuable permet de rendre les déploiements et les rollbacks plus prévisibles. Elle résout également les problèmes courants des infrastructures mutables, tels que les écarts de configuration et les serveurs en flocon. En optant pour une infrastructure immuable, vous améliorez donc davantage la cohérence et la fiabilité de vos environnements.

Concevoir pour la haute disponibilité

La disponibilité est une mesure de la fraction de temps pendant laquelle un service est utilisable. La disponibilité est souvent utilisée comme indicateur clé de l'état général du service. Les architectures hautement disponibles visent à maximiser la disponibilité du service, généralement via le déploiement redondant de composants. Autrement dit, la haute disponibilité implique généralement la distribution des ressources de calcul, l'équilibrage de charge et la réplication des données.

Répartir physiquement les ressources

Les services Google Cloud sont disponibles partout dans le monde. Ces emplacements sont organisés en régions et en zones. La manière dont vous déployez votre application dans ces régions et zones affecte la disponibilité, la latence et d'autres propriétés de votre application. Pour en savoir plus, consultez les Bonnes pratiques pour la sélection des régions Compute Engine.

La redondance correspond à la duplication des composants d'un système dans le but d'augmenter sa disponibilité. Dans Google Cloud, la redondance est généralement obtenue en déployant votre application ou votre service dans plusieurs zones, voire dans plusieurs régions. Si un service existe dans plusieurs zones ou régions, il résiste mieux aux interruptions de service dans une zone ou une région particulière. Bien que Google Cloud s'efforce de prévenir de telles perturbations, certains événements restent imprévisibles et il est préférable de s'y préparer.

Les groupes d'instances gérés Compute Engine vous permettent de répartir les instances de machines virtuelles sur plusieurs zones d'une même région et de les gérer en tant qu'unité logique. Google Cloud propose également des disques persistants régionaux pour répliquer automatiquement vos données dans deux zones d'une même région.

Vous pouvez également améliorer la disponibilité et la résilience des applications déployées sur GKE en créant des clusters régionaux. Un cluster régional répartit les composants, les nœuds et les pods du plan de contrôle GKE sur plusieurs zones d'une même région. Comme les composants du plan de contrôle sont répartis, vous pouvez continuer à accéder au plan de contrôle du cluster, même en cas de panne impliquant une ou plusieurs zones (mais pas toutes).

Favoriser les services gérés

Plutôt que d'installer, de maintenir à jour et d'exploiter de manière indépendante chaque partie d'une pile d'applications, vous pouvez utiliser des services gérés pour consommer des parties de la pile d'applications en tant que services. Par exemple, plutôt que d'installer et de gérer une base de données MySQL sur des machines virtuelles (VM), vous pouvez utiliser une base de données MySQL fournie par Cloud SQL. Vous bénéficiez alors d'un contrat de niveau de service garantissant une certaine disponibilité. Vous pouvez compter sur Google Cloud pour gérer la réplication des données, les sauvegardes et l'infrastructure sous-jacente. Les services gérés vous permettent de consacrer moins de temps à la gestion de l'infrastructure, et davantage à l'amélioration de la fiabilité de votre application.

De nombreux services de calcul, de base de données et de stockage Google Cloud offrent une fonctionnalité de redondance intégrée, qui peut vous aider à atteindre vos objectifs de disponibilité. La plupart de ces services proposent un modèle régional, ce qui signifie que l'infrastructure qui exécute votre application est située dans une région spécifique et gérée par Google pour être disponible de manière redondante dans toutes les zones de cette région. Si une zone devient indisponible, votre application ou vos données sont automatiquement diffusées depuis une autre zone de la région.

Certains services de base de données et de stockage offrent également une disponibilité multirégionale, ce qui signifie que l'infrastructure qui exécute votre application est située dans plusieurs régions. Les services multirégionaux peuvent tolérer la perte d'une région entière, mais généralement au prix d'une latence plus élevée.

Équilibrage de charge à chaque niveau

L'équilibrage de charge vous permet de répartir le trafic sur des groupes de ressources. Vous vous assurez ainsi que les ressources individuelles ne sont pas surchargées et que les autres restent inactives. La plupart des équilibreurs de charge fournissent également des fonctionnalités de vérification d'état permettant de vérifier que le trafic n'est pas acheminé vers des ressources non opérationnelles ou indisponibles.

Google Cloud propose plusieurs options d'équilibrage de charge. Si votre application s'exécute sur Compute Engine ou GKE, vous pouvez choisir le type d'équilibreur de charge le plus approprié en fonction du type, de la source et d'autres aspects du trafic. Pour en savoir plus, consultez la présentation de l'équilibrage de charge et la présentation de la mise en réseau de GKE.

Certains services gérés Google Cloud, tels qu'App Engine et Cloud Run, équilibrent également la charge du trafic de manière automatique.

Il est courant d'équilibrer la charge des requêtes reçues de sources externes, telles que les clients Web ou mobiles. Toutefois, vous pouvez accroître la résilience et la flexibilité de votre application en utilisant des équilibreurs de charge entre ses différents services ou niveaux. Google Cloud fournit un équilibrage de charge interne de couche 4 et de couche 7 à cet effet.

Le schéma suivant présente un équilibreur de charge externe répartissant le trafic global entre deux régions, us-central1 et asia-east1. Il présente également un équilibrage de charge interne répartissant le trafic du niveau Web sur le niveau interne de chaque région.

Répartition du trafic global entre les régions

Surveiller votre infrastructure et vos applications

Avant de décider comment améliorer la résilience et l'évolutivité de votre application, vous devez comprendre son comportement. Vous pouvez détecter les problèmes potentiels avant qu'ils ne provoquent une panne en accédant à un ensemble complet de métriques et de séries temporelles pertinentes sur les performances et l'état de votre application. Elles peuvent également vous aider à diagnostiquer et à résoudre une panne le cas échéant. Le chapitre Surveillance des systèmes distribués du livre SRE de Google fournit un bon aperçu de certaines approches de surveillance.

En plus de fournir des informations sur l'état de l'application, les métriques peuvent également être utilisées pour contrôler le comportement de l'autoscaling des services.

Cloud Monitoring est l'outil de surveillance intégré de Google Cloud. Cloud Monitoring ingère des événements, des métriques et des métadonnées, et génère des tendances via des tableaux de bord et des alertes. La plupart des services Google Cloud envoient automatiquement des métriques à Cloud Monitoring. Google Cloud accepte également de nombreuses sources tierces. Cloud Monitoring peut servir de backend pour les outils de surveillance Open Source populaires, en examinant votre application à l'aide d'une vue centralisée.

Surveiller à tous les niveaux

Vous pouvez obtenir un aperçu complet de l'état et du comportement de votre application en collectant des métriques à différents niveaux de l'architecture.

Surveillance de l'infrastructure

La surveillance au niveau de l'infrastructure présente l'état et les performances de référence de votre application. Cette approche de surveillance enregistre des informations, telles que la charge du processeur, l'utilisation de la mémoire et le nombre d'octets écrits sur le disque. Ces métriques peuvent indiquer qu'une machine est surchargée ou qu'elle ne fonctionne pas comme prévu.

En plus de la collecte automatique de métriques, Cloud Monitoring fournit un agent que vous pouvez installer pour obtenir des informations plus détaillées à partir des VM Compute Engine, y compris d'applications tierces s'exécutant sur ces machines.

Surveillance de l'application

Nous vous recommandons de recueillir des métriques au niveau de l'application. Par exemple, vous pourriez avoir besoin d'évaluer le temps nécessaire pour exécuter une requête particulière ou pour effectuer une séquence d'appels de service associée. Vous pouvez vous-même définir ces métriques au niveau de l'application. Elles collectent des informations que les métriques Cloud Monitoring intégrées ne peuvent pas obtenir. Les métriques au niveau de l'application peuvent capturer des conditions agrégées qui reflètent plus fidèlement les workflows principaux. Elles peuvent également déceler des problèmes que les métriques au niveau de l'infrastructure de bas niveau ne peuvent pas identifier.

Nous vous recommandons également de capturer les métriques au niveau de votre application à l'aide d'OpenTelemetry. OpenTelemetry fournit une norme ouverte unique pour les données de télémétrie. Utilisez OpenTelemetry pour collecter et exporter des données à partir de votre application et de votre infrastructure cloud-first. Vous pouvez ensuite surveiller et analyser les données de télémétrie exportées.

Surveillance des services

Il est important de surveiller les interactions entre les différents services et composants des applications distribuées basées sur des microservices. Ces métriques peuvent vous aider à diagnostiquer des problèmes, tels qu'une augmentation du nombre d'erreurs ou de la latence entre les services.

Istio est un outil Open Source qui fournit des informations et un contrôle opérationnel sur le réseau de microservices. Istio génère une télémétrie détaillée pour toutes les communications entre les services. Il peut être configuré pour envoyer des métriques à Cloud Monitoring.

Surveillance de bout en bout

La surveillance de bout en bout, également appelée surveillance par boîte noire, teste le comportement visible de l'extérieur, tel qu'un utilisateur le perçoit. Elle vérifie si l'utilisateur est en mesure d'effectuer des actions critiques dans les limites des seuils que vous avez définis. Cette surveillance à faible précision peut détecter des erreurs ou une latence qu'une surveillance plus précise ne pourrait pas identifier. Elle présente également la disponibilité telle qu'elle est perçue par l'utilisateur.

Exposer l'état des applications

Un système à disponibilité élevée doit être en mesure d'identifier les parties du système qui sont opérationnelles et qui fonctionnent correctement. Si certaines ressources ne semblent pas opérationnelles, le système peut envoyer des requêtes ailleurs. En règle générale, les vérifications d'état impliquent l'extraction de données d'un point de terminaison pour déterminer l'état d'un service.

La vérification d'état fait partie des principales responsabilités d'un équilibreur de charge. Lorsque vous associez un équilibreur de charge à un groupe d'instances de machines virtuelles, vous définissez également une vérification d'état. Celle-ci détermine comment l'équilibreur de charge communique avec les machines virtuelles afin d'évaluer si des instances particulières doivent continuer à recevoir du trafic. Les vérifications d'état d'un équilibreur de charge peuvent également être utilisées pour l'autoréparation des groupes d'instances, de manière à ce que les machines non opérationnelles soient recréées. Si vous exécutez GKE et que vous équilibrez la charge du trafic externe via une ressource d'entrée, GKE crée automatiquement les vérifications d'état appropriées pour l'équilibreur de charge.

Kubernetes est compatible avec les vérifications d'activité et d'aptitude. Ces vérifications aident l'outil d'orchestration de Kubernetes à décider comment gérer les pods et les requêtes au sein de votre cluster. Si votre application est déployée sur Kubernetes, il est recommandé d'exposer son état aux vérifications par le biais de points de terminaison appropriés.

Établir des métriques clés

La surveillance et la vérification d'état fournissent des métriques sur le comportement et l'état de votre application. L'étape suivante consiste à analyser ces métriques pour déterminer celles qui sont les plus descriptives ou les plus efficaces. Les métriques clés varient en fonction de la plate-forme sur laquelle l'application est déployée et des tâches effectuées par l'application.

Il est peu probable que vous trouviez une seule métrique indiquant que votre application nécessite un scaling ou qu'un service particulier n'est pas opérationnel. Il s'agit souvent d'une combinaison de facteurs qui, ensemble, indiquent un certain ensemble de conditions. Cloud Monitoring vous permet de créer des métriques personnalisées pour faciliter la capture de ces conditions. Le livre sur l'ingénierie SRE de Google préconise de surveiller un système visible par l'utilisateur à l'aide de quatre signaux clés : la latence, le trafic, les erreurs et la saturation.

Tenez également compte de la tolérance aux anomalies. L'utilisation d'une valeur moyenne ou médiane pour mesurer l'état ou les performances n'est peut-être pas la meilleure solution, car ces mesures peuvent cacher de profonds déséquilibres. Il est donc important de tenir compte de la répartition d'une métrique. Le 99e centile peut être une mesure plus informative que la moyenne.

Définir des objectifs de niveau de service (SLO)

Vous pouvez utiliser les métriques collectées par votre système de surveillance pour définir des objectifs de niveau de service (SLO, Service Level Objective). Les SLO spécifient un niveau cible de performances ou de fiabilité pour votre service. Les SLO sont un élément essentiel des pratiques d'ingénierie SRE. Ils sont décrits en détail dans le chapitre consacré aux objectifs de niveau de service dans le livre sur l'ingénierie SRE, ainsi que dans celui dédié à la mise en œuvre des SLO dans le manuel d'ingénierie SRE.

Vous pouvez utiliser la surveillance des services pour définir des SLO en fonction des métriques de Cloud Monitoring. Vous pouvez créer des règles d'alerte sur les SLO pour vous indiquer si vous risquez d'en enfreindre un.

Stocker les métriques

Les métriques de votre système de surveillance sont utiles à court terme pour faciliter les vérifications d'état en temps réel ou étudier les problèmes récents. Cloud Monitoring conserve vos métriques pendant plusieurs semaines afin de répondre au mieux à ces cas d'utilisation.

Toutefois, il peut également être intéressant de stocker vos métriques de surveillance pour une analyse à plus long terme. L'accès à un enregistrement historique peut vous aider à adopter une approche basée sur les données pour affiner l'architecture de votre application. Vous pouvez utiliser les données collectées pendant et après une panne pour identifier les goulots d'étranglement et les interdépendances dans vos applications. Vous pouvez également créer et valider des tests pertinents à l'aide de ces données.

Les données de l'historique permettent également de vérifier si votre application répond aux objectifs commerciaux au cours de périodes clés. Par exemple, les données peuvent vous aider à analyser le scaling de votre application lors d'événements promotionnels à trafic élevé au cours des derniers trimestres, voire d'années.

Pour en savoir plus sur l'exportation et le stockage des métriques, consultez la page Exportation de métriques Cloud Monitoring.

Déterminer le profil de scaling

Vous souhaitez que votre application atteigne ses objectifs en termes d'expérience utilisateur et de performances sans surprovisionner les ressources.

Le schéma suivant représente le profil de scaling d'une application de manière simplifiée. L'application conserve un niveau de ressources de base et utilise l'autoscaling pour évoluer en fonction de la demande.

Profil de scaling d'une application

Équilibrer les coûts et l'expérience utilisateur

Prendre la décision de faire évoluer votre application dépend essentiellement de l'équilibrage des coûts et de l'expérience utilisateur. Vous devez déterminer le niveau de performances minimal acceptable et, éventuellement, définir un plafond. Ces seuils varient d'une application à l'autre, et éventuellement pour différents composants ou services au sein d'une même application.

Par exemple, une application Web ou mobile destinée aux consommateurs doit fixer des objectifs stricts en termes de latence. Une étude montre que même de légers retards peuvent avoir un impact négatif sur la façon dont les utilisateurs perçoivent votre application, entraînant une baisse des conversions et des inscriptions. Par conséquent, il est important de s'assurer que votre application dispose d'une capacité de diffusion suffisante pour répondre rapidement aux requêtes des utilisateurs. Dans ce cas, les coûts plus élevés liés à l'exécution d'un plus grand nombre de serveurs Web peuvent être justifiés.

Le rapport coût-performances peut être différent pour une application interne qui n'est pas critique pour l'activité, car ses utilisateurs sont susceptibles d'être plus tolérants aux petits retards. Par conséquent, votre profil de scaling peut être moins agressif. Dans ce cas, il peut s'avérer plus judicieux de limiter les coûts que d'optimiser l'expérience utilisateur.

Définir des ressources de référence

Un autre élément clé de votre profil de scaling est le choix d'un ensemble minimal de ressources appropriées.

Les machines virtuelles Compute Engine ou les clusters GKE nécessitent généralement un certain temps pour effectuer le scaling à la hausse, car de nouveaux nœuds doivent être créés et initialisés. Par conséquent, il peut être nécessaire de maintenir un ensemble minimal de ressources, même en l'absence de trafic. Là encore, l'étendue des ressources de référence dépend du type d'application et du profil du trafic.

À l'inverse, les technologies sans serveur telles qu'App Engine, Cloud Functions et Cloud Run sont conçues pour effectuer le scaling à zéro instance, démarrer et évoluer rapidement, même lors du démarrage à froid de l'instance. Selon le type d'application et le profil du trafic, ces technologies peuvent offrir de bonnes performances pour certaines parties de votre application.

Configurer l'autoscaling

L'autoscaling vous aide à effectuer le scaling automatique des ressources de calcul consommées par votre application. L'autoscaling se produit généralement en cas de dépassement de métriques ou lorsque des conditions sont remplies. Par exemple, si la latence des requêtes vers votre niveau Web commence à dépasser une certaine valeur, vous pouvez ajouter automatiquement des machines pour augmenter la capacité de diffusion.

De nombreux produits de calcul Google Cloud offrent des fonctionnalités d'autoscaling. Les services gérés sans serveur tels que Cloud Run, Cloud Functions et App Engine sont conçus pour évoluer rapidement. Ces services proposent souvent des options de configuration pour limiter ou influencer le comportement de l'autoscaling, mais en général, une grande partie de celui-ci est dissimulé à l'opérateur.

Compute Engine et GKE fournissent davantage d'options pour contrôler le comportement du scaling. Avec Compute Engine, vous pouvez effectuer le scaling en fonction de différentes entrées, y compris les métriques personnalisées de Cloud Monitoring et la capacité de diffusion de l'équilibreur de charge. Vous pouvez définir des limites minimale et maximale pour le comportement du scaling, ainsi qu'une règle d'autoscaling comportant plusieurs signaux pour gérer différents scénarios. Comme avec GKE, vous pouvez configurer l'autoscaler du cluster pour ajouter ou supprimer des nœuds en fonction des métriques de la charge de travail ou du pod, ou des métriques externes au cluster.

Nous vous recommandons de configurer le comportement de l'autoscaling en fonction des principales métriques de l'application, de votre profil de coût et du niveau minimal de ressources que vous avez défini.

Réduire le délai de démarrage

Pour que le scaling soit efficace, il doit se produire assez rapidement pour gérer l'augmentation de la charge. Cela est particulièrement vrai lorsque vous ajoutez de la capacité de calcul ou de diffusion.

Utiliser des images préconçues

Si votre application s'exécute sur des VM Compute Engine, vous devrez probablement installer un logiciel et configurer les instances pour exécuter votre application. Bien que vous puissiez configurer de nouvelles instances à l'aide de scripts de démarrage, un moyen plus efficace consiste à créer une image personnalisée. Une image personnalisée est un disque de démarrage que vous avez défini avec le logiciel et la configuration spécifiques à l'application.

Pour en savoir plus sur la gestion des images, consultez l'article Bonnes pratiques pour la gestion des images.

Une fois votre image créée, vous pouvez définir un modèle d'instance. Les modèles d'instances combinent l'image du disque de démarrage, le type de machine et d'autres propriétés de l'instance. Vous pouvez ensuite utiliser un modèle d'instance pour créer des instances de VM individuelles ou un groupe d'instances géré. Les modèles d'instances constituent un moyen pratique d'enregistrer la configuration d'une instance de VM afin de l'utiliser ultérieurement pour créer des instances de VM identiques.

Bien que la création d'images personnalisées et de modèles d'instances puisse augmenter la vitesse de déploiement, elle peut également entraîner des coûts de maintenance supplémentaires en raison de la mise à jour plus fréquente des images. Pour en savoir plus, consultez les documents concernant l'équilibrage de la configuration de l'image et la vitesse de déploiement.

Conteneuriser l'application

Une alternative à la création d'instances de VM personnalisées consiste à conteneuriser votre application. Un conteneur est un package logiciel exécutable, autonome et léger qui inclut tous les éléments nécessaires à l'exécution d'une application : du code, un environnement d'exécution, des outils système, des bibliothèques système et des paramètres. Ces caractéristiques facilitent le transfert, le déploiement et le scaling des applications en conteneur, bien plus que les machines virtuelles. Les conteneurs sont généralement rapides à démarrer. Ils sont donc adaptés aux applications évolutives et résilientes.

Google Cloud propose plusieurs services pour exécuter les conteneurs de votre application. Cloud Run fournit une plate-forme de calcul gérée sans serveur pour héberger vos conteneurs sans état. L'environnement flexible App Engine héberge vos conteneurs dans une infrastructure Platform as a Service (PaaS) gérée. GKE fournit un environnement Kubernetes géré permettant d'héberger et d'organiser vos applications en conteneur. Vous pouvez également exécuter les conteneurs de votre application sur Compute Engine lorsque vous avez besoin d'assurer un contrôle complet sur votre environnement de conteneurs.

Optimiser le démarrage de l'application

En plus de vous assurer que votre infrastructure et votre application peuvent être déployées aussi efficacement que possible, il est important de veiller à ce que votre application soit mise en ligne rapidement.

Les optimisations appropriées pour votre application dépendent de ses caractéristiques et de la plate-forme d'exécution. Il est important de procéder comme suit :

  • Recherchez et supprimez les goulots d'étranglement en profilant les sections critiques de votre application qui sont appelées au démarrage.
  • Diminuez le délai de démarrage initial en mettant en œuvre des techniques comme l'initialisation tardive, en particulier pour les ressources coûteuses.
  • Minimisez les dépendances de l'application qui doivent éventuellement être chargées au démarrage.

Privilégier les architectures modulaires

Vous pouvez accroître la flexibilité de votre application en choisissant des architectures qui permettent aux composants d'être déployés, gérés et mis à l'échelle indépendamment. Ce modèle peut également améliorer la résilience de votre application en supprimant les points de défaillance uniques.

Décomposer l'application en services indépendants

Vous pouvez accroître la flexibilité de votre application en la développant sous forme d'ensemble de services indépendants faiblement couplés. Une conception faiblement couplée permet de lancer et de déployer vos services de manière indépendante. En plus de nombreux autres avantages, cette approche permet à ces services d'utiliser différentes piles technologiques et d'être gérés par plusieurs équipes. Cette approche faiblement couplée est au cœur des modèles d'architectures, tels que les architectures de microservices et orientées services (SOA).

Lorsque vous envisagez de fixer des limites à vos services, il est primordial de prendre en compte les exigences de disponibilité et d'évolutivité. Par exemple, si un composant donné a une exigence de disponibilité ou un profil de scaling différent de vos autres composants, il peut être un bon candidat pour un service autonome.

Opter pour le sans état

Une application ou un service sans état ne conserve pas de données ou d'état persistants. Un modèle sans état vous permet de gérer chaque requête ou interaction avec le service, indépendamment des requêtes précédentes. Ce modèle facilite l'évolutivité et la récupération. Vous pouvez ainsi développer, réduire ou redémarrer le service sans perdre les données requises pour gérer les processus ou les requêtes en cours de transfert. La caractéristique sans état est particulièrement importante lorsque vous utilisez un autoscaler, car les instances, les nœuds ou les pods hébergeant le service peuvent être créés et détruits de manière inattendue.

Il se peut que tous vos services ne soient pas sans état. Dans ce cas, indiquez de façon explicite les services qui nécessitent un état. En distinguant clairement les services sans état et avec état, vous pouvez faciliter l'évolutivité des services sans état tout en adoptant une approche plus réfléchie pour les services avec état.

Gérer la communication entre les services

Un des objectifs d'une architecture de microservices distribuée est de gérer la communication entre les services. Il est probable que les interdépendances des services soient plus nombreuses à mesure que votre réseau de services se développe. Vous ne voulez pas que la défaillance d'un service entraîne celle d'autres services, parfois appelée défaillance en cascade.

Vous pouvez réduire le trafic vers un service surchargé ou défaillant en adoptant des techniques telles qu'un modèle de disjoncteur, des intervalles exponentiels entre les tentatives et une dégradation élégante. Ces modèles augmentent la résilience de votre application soit en facilitant la récupération des services surchargés, soit en gérant consciencieusement l'état des erreurs. Pour en savoir plus, consultez le chapitre Gérer les défaillances en cascade du livre sur l'ingénierie SRE de Google.

L'utilisation d'un maillage de services peut vous aider à gérer le trafic entre vos services distribués. Un maillage de services est un logiciel qui relie les services entre eux et permet de dissocier la logique métier de la mise en réseau. Il offre généralement des fonctionnalités de résilience, telles que de nouvelles tentatives d'exécution des requêtes, des basculements et des disjoncteurs.

Utiliser une base de données et une technologie de stockage appropriées

Certaines bases de données et certains types de stockage sont difficiles à faire évoluer et à rendre résilients. Assurez-vous que vos choix concernant la base de données ne limitent pas la disponibilité et l'évolutivité de votre application.

Évaluer les besoins de la base de données

Le modèle de conception de l'application en tant qu'ensemble de services indépendants s'étend également aux bases de données et au stockage. Il peut s'avérer judicieux de choisir différents types de stockage pour plusieurs parties de votre application de sorte que les espaces de stockage soient hétérogènes.

Souvent, les applications traditionnelles fonctionnent exclusivement avec des bases de données relationnelles. Les bases de données relationnelles offrent des fonctionnalités utiles, telles que les transactions, la cohérence forte, l'intégrité référentielle et l'interrogation complexe des tables. Les fonctionnalités des bases de données relationnelles sont donc parfaitement adaptées à de nombreuses fonctionnalités d'application courantes. Cependant, les bases de données relationnelles présentent également certaines contraintes. Elles sont généralement difficiles à faire évoluer et nécessitent une gestion minutieuse de la configuration de haute disponibilité. Une base de données relationnelle n'est peut-être pas le meilleur choix pour l'ensemble des besoins de votre base de données.

Les bases de données non relationnelles, souvent appelées "bases de données NoSQL", reposent sur une approche différente. Bien que les détails varient selon les produits, les bases de données NoSQL sacrifient généralement certaines fonctionnalités des bases de données relationnelles au profit d'une disponibilité et d'une évolutivité accrues. Selon le théorème CAP, les bases de données NoSQL mettent souvent l'accent sur la disponibilité au détriment de la cohérence.

La pertinence d'une base de données NoSQL dépend souvent du degré de cohérence requis. Si le modèle de données d'un service particulier ne nécessite pas toutes les fonctionnalités d'un SGBDR et peut être conçu pour être cohérent à terme, opter pour une base de données NoSQL peut offrir une disponibilité et une évolutivité accrues.

Dans le domaine de la gestion des données, les bases de données relationnelles et non relationnelles sont souvent considérées comme des technologies complémentaires et non concurrentes. En utilisant ces deux types de bases de données de manière stratégique, les entreprises peuvent exploiter leurs atouts respectifs pour obtenir des résultats optimaux en matière de stockage, de récupération et d'analyse des données.

En plus d'une gamme de bases de données relationnelles et NoSQL, Google Cloud intègre également Spanner, une base de données à cohérence forte, hautement disponible et distribuée à l'échelle mondiale compatible avec SQL. Pour en savoir plus sur le choix d'une base de données appropriée dans Google Cloud, consultez la page Bases de données Google Cloud.

Mettre en œuvre la mise en cache

L'objectif principal d'un cache est d'optimiser la récupération des données en limitant l'accès à la couche de stockage sous-jacente plus lente.

La mise en cache améliore l'évolutivité en limitant la dépendance au stockage sur disque. Étant donné que les requêtes peuvent être traitées à partir de la mémoire, la latence des requêtes envoyées à la couche de stockage est réduite, ce qui permet généralement à votre service de gérer davantage de requêtes. De plus, la mise en cache peut réduire la charge sur les services en aval de votre application, en particulier les bases de données, ce qui permet aux autres composants qui interagissent avec ce service d'évoluer plus facilement ou pas du tout.

La mise en cache peut également augmenter la résilience à l'aide de techniques comme la dégradation élégante. Si la couche de stockage sous-jacente est surchargée ou indisponible, le cache peut continuer à gérer les requêtes. Même si les données renvoyées par le cache peuvent être incomplètes ou ne pas être à jour, cela peut être acceptable pour certains scénarios.

Memorystore pour Redis fournit un service entièrement géré, alimenté par le datastore en mémoire Redis. Memorystore pour Redis fournit un accès de faible latence et un débit élevé pour les données très consultées. Il peut être déployé dans une configuration de haute disponibilité incluant la réplication interzone et le basculement automatique.

Moderniser les processus et la culture de développement

DevOps peut être considéré comme une vaste collection de processus, de culture et d'outils permettant d'augmenter l'agilité et de réduire le temps de production des applications et des fonctionnalités, en levant le cloisonnement entre les équipes de développement et d'exploitation. L'objectif des techniques DevOps est d'améliorer la qualité et la fiabilité des logiciels.

Ce document n'aborde pas DevOps de manière détaillée, mais certains aspects essentiels liés à l'amélioration de la fiabilité et de la résilience de votre application sont décrits dans les sections suivantes. Pour en savoir plus, consultez la page DevOps de Google Cloud.

Concevoir pour la testabilité

Le test automatisé est un élément clé des pratiques modernes de livraison de logiciels. La capacité à exécuter un ensemble complet de tests unitaires, d'intégration et système est essentielle pour vérifier que votre application se comporte comme prévu et qu'elle peut passer à l'étape suivante du cycle de déploiement. La testabilité est un critère de conception clé pour votre application.

Nous vous recommandons de privilégier les tests unitaires pour la majeure partie de vos tests, car ils sont rapides à exécuter et généralement simples à gérer. Nous vous recommandons également d'automatiser l'intégration de niveau supérieur et les tests système. Ces tests sont considérablement simplifiés si vous appliquez des techniques d'Infrastructure as Code, car des environnements et des ressources de test dédiés peuvent être créés à la demande, puis supprimés une fois les tests terminés.

À mesure que le pourcentage de votre codebase couvert par les tests augmente, vous réduisez les incertitudes et la diminution potentielle de la fiabilité de chaque modification du code. En optant pour une couverture de test adéquate, vous pouvez apporter davantage de modifications avant que la fiabilité ne passe en dessous d'un niveau acceptable.

Les tests automatisés font partie intégrante de l'intégration continue. L'exécution d'un ensemble complet de tests automatisés sur chaque commit de code permet d'obtenir un retour rapide sur les modifications, améliorant ainsi la qualité et la fiabilité de votre logiciel. Les outils natifs de Google Cloud comme Cloud Build et les outils tiers tels que Jenkins vous aident à mettre en œuvre l'intégration continue.

Automatisez vos déploiements

L'intégration continue et l'automatisation complète des tests garantissent la stabilité de votre logiciel. Une fois mises en œuvre, la prochaine étape consiste à automatiser le déploiement de votre application. Le niveau d'automatisation du déploiement varie en fonction de la maturité de votre organisation.

Il est essentiel de choisir une stratégie de déploiement appropriée afin de minimiser les risques associés au déploiement d'un nouveau logiciel. En appliquant une stratégie adaptée, vous pouvez progressivement accroître l'exposition des nouvelles versions à un public plus large, tout en vérifiant le comportement tout au long du processus. Vous pouvez également définir des dispositions claires pour le rollback en cas de problème.

Adopter des pratiques SRE pour faire face aux défaillances

Pour les applications distribuées fonctionnant à grande échelle, il est courant de rencontrer un certain degré de défaillance dans un ou plusieurs composants. Si vous vous conformez aux modèles décrits dans ce document, votre application pourra mieux gérer les perturbations dues à une version logicielle défectueuse, à l'arrêt inattendu des machines virtuelles ou même à une panne d'infrastructure affectant une zone entière.

Cependant, même avec une conception d'application minutieuse, vous rencontrez inévitablement des événements inattendus qui nécessitent une intervention humaine. Si vous mettez en place des processus structurés pour gérer ces événements, vous pouvez considérablement réduire leur impact et les résoudre plus rapidement. De plus, l'examen des causes et des réponses à l'événement vous permet de protéger votre application contre des événements futurs similaires.

L'implémentation de processus solides de gestion des incidents et la réalisation de rapports d'incidents sont les principes clés de SRE. Même si l'ensemble des pratiques de Google SRE ne peuvent pas être mises en œuvre dans votre organisation, vous pouvez améliorer la résilience de votre application en n'appliquant que certaines d'entre elles. Les annexes du livre sur l'ingénierie SRE contiennent des modèles qui peuvent vous aider à élaborer vos processus.

Valider et examiner l'architecture

Le comportement des utilisateurs, les profils de trafic et même les priorités commerciales peuvent changer à mesure que votre application évolue. De même, d'autres services ou infrastructures dont votre application dépend peuvent évoluer. Par conséquent, il est important de tester et de valider régulièrement la résilience et l'évolutivité de votre application.

Tester la résilience

Il est essentiel de vérifier que votre application réagit aux défaillances comme vous le souhaitez. Le meilleur moyen d'éviter les défaillances est de les documenter et d'en tirer des leçons.

La simulation et la documentation des défaillances sont complexes. En plus de vérifier le comportement de votre application ou de votre service, vous devez également vous assurer que les alertes attendues et les métriques appropriées sont générées. Nous vous recommandons de suivre une approche structurée, dans laquelle vous documentez les défaillances simples avant de les signaler.

Par exemple, vous pouvez valider et documenter le comportement à chaque étape en procédant comme suit :

  • Documenter les défaillances intermittentes
  • Bloquer l'accès aux dépendances du service
  • Bloquer toutes les communications réseau
  • Arrêter les hôtes

Pour en savoir plus, regardez la vidéo Breaking your systems to make them unbreakable (Faire planter vos systèmes pour les rendre résistants) de la conférence Google Cloud Next 2019.

Si vous utilisez un maillage de services comme Istio pour gérer les services de votre application, vous pouvez injecter des pannes au niveau de la couche d'application au lieu de détruire les pods ou les machines, ou corrompre les paquets au niveau de la couche TCP. Vous pouvez introduire des retards pour simuler la latence du réseau ou un système surchargé en amont. Vous pouvez également mettre en place des abandons, qui imitent des défaillances dans les systèmes en amont.

Tester le comportement du scaling

Nous vous recommandons d'utiliser des tests automatiques non fonctionnels pour vérifier que votre application évolue comme prévu. Cette vérification est souvent associée à des tests de performances ou de charge. Vous pouvez utiliser des outils simples tels que hey pour envoyer la charge à une application Web. Pour obtenir un exemple plus détaillé qui montre comment effectuer des tests de charge sur un point de terminaison REST, consultez la page Tests de charge distribués à l'aide de Google Kubernetes Engine.

Une approche courante consiste à s'assurer que les métriques principales respectent les niveaux attendus pour différentes charges. Par exemple, si vous testez l'évolutivité de votre niveau Web, vous pouvez mesurer la latence moyenne des requêtes pour les pics de requêtes des utilisateurs. De même, pour une fonctionnalité de traitement backend, vous pouvez évaluer le temps de traitement moyen des tâches lorsque leur nombre augmente soudainement.

Vous souhaitez par ailleurs que vos tests estiment le nombre de ressources créées pour gérer la charge de test dans la plage prévue. Par exemple, vos tests peuvent vérifier que le nombre de VM créées pour gérer certaines tâches de backend ne dépasse pas une certaine valeur.

Il est également important de tester les cas spéciaux. Quel est le comportement de votre application ou de votre service lorsque les limites maximales de scaling sont atteintes ? Que se passe-t-il si votre service évolue à la baisse et que la charge augmente de nouveau soudainement ?

Toujours avoir un œil sur l'architecture

Le monde de la technologie évolue rapidement, et cela vaut tout particulièrement pour le cloud. Des produits et des fonctionnalités sont lancés fréquemment, de nouveaux modèles apparaissent, et les demandes de vos utilisateurs et des personnes impliquées en interne ne cessent d'augmenter.

Vous devez toujours trouver des moyens d'affiner, de simplifier et d'améliorer l'architecture de vos applications, comme décrit dans l'article de blog Principes de l'architecture cloud native. Les systèmes logiciels sont vivants et doivent s'adapter à l'évolution de vos priorités.

Étape suivante