Optimisation de la mise à l'échelle automatique du service Amazon ECS - Amazon Elastic Container Service

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.

Optimisation de la mise à l'échelle automatique du service Amazon ECS

Un service Amazon ECS est un ensemble géré de tâches. Chaque service est associé à une définition de tâche, à un nombre de tâches souhaité et à une stratégie de placement facultative. Le dimensionnement automatique du service Amazon ECS est mis en œuvre via le service Application Auto Scaling. Application Auto Scaling utilise CloudWatch les métriques comme source pour le dimensionnement des métriques. Il utilise également des CloudWatch alarmes pour définir des seuils indiquant quand il faut étendre ou dédimensionner votre service. Vous fournissez les seuils de mise à l'échelle, soit en définissant une cible métrique, appelée échelle de suivi des cibles, soit en spécifiant des seuils, appelés mise à l'échelle par étapes. Une fois qu'Application Auto Scaling est configurée, elle calcule en permanence le nombre de tâches souhaité pour le service. Il indique également à Amazon ECS lorsque le nombre de tâches souhaité doit changer, soit en le redimensionnant, soit en le redimensionnant.

Pour utiliser efficacement le dimensionnement automatique des services, vous devez choisir une métrique de dimensionnement appropriée.

Une application doit être étendue si l'on prévoit que la demande sera supérieure à la capacité actuelle. À l'inverse, une application peut être étendue pour réduire les coûts lorsque les ressources dépassent la demande.

Identifier une métrique

Pour effectuer une mise à l'échelle efficace, il est essentiel d'identifier une métrique indiquant l'utilisation ou la saturation. Cette métrique doit présenter les propriétés suivantes pour être utile à la mise à l'échelle.

  • La métrique doit être corrélée à la demande. Lorsque les ressources sont maintenues stables, mais que la demande change, la valeur métrique doit également changer. La métrique doit augmenter ou diminuer lorsque la demande augmente ou diminue.

  • La valeur métrique doit évoluer proportionnellement à la capacité. Lorsque la demande reste constante, l'ajout de ressources supplémentaires doit entraîner une modification proportionnelle de la valeur de la métrique. Ainsi, le doublement du nombre de tâches devrait entraîner une diminution de 50 % de la métrique.

Le meilleur moyen d'identifier une métrique d'utilisation consiste à effectuer des tests de charge dans un environnement de pré-production tel qu'un environnement intermédiaire. Les solutions de test de charge commerciales et open source sont largement disponibles. Ces solutions peuvent généralement générer une charge synthétique ou simuler le trafic utilisateur réel.

Pour démarrer le processus de test de charge, créez des tableaux de bord pour les indicateurs d'utilisation de votre application. Ces indicateurs incluent l'utilisation du processeur, l'utilisation de la mémoire, les opérations d'E/S, la profondeur de la file d'attente d'E/S et le débit du réseau. Vous pouvez collecter ces statistiques avec un service tel que Container Insights. Pour plus d’informations, consultez Surveillez les conteneurs Amazon ECS à l'aide de Container Insights. Au cours de ce processus, assurez-vous de collecter et de tracer des mesures relatives aux temps de réponse ou aux taux d'achèvement des travaux de votre application.

Commencez par une petite demande ou un taux d'insertion professionnelle. Maintenez ce taux constant pendant plusieurs minutes pour permettre à votre application de s'échauffer. Ensuite, augmentez lentement le taux et maintenez-le stable pendant quelques minutes. Répétez ce cycle en augmentant le taux à chaque fois jusqu'à ce que les délais de réponse ou de traitement de votre application soient trop lents pour atteindre vos objectifs de niveau de service (SLO).

Lors du test de charge, examinez chacune des mesures d'utilisation. Les indicateurs qui augmentent en fonction de la charge sont les meilleurs candidats pour vous servir de meilleurs indicateurs d'utilisation.

Identifiez ensuite la ressource qui atteint la saturation. Dans le même temps, examinez également les indicateurs d'utilisation pour voir lequel s'aplatit le premier à un niveau élevé ou atteint un pic puis fait planter votre application en premier. Par exemple, si l'utilisation du processeur passe de 0 % à 70 à 80 % à mesure que vous ajoutez de la charge, puis qu'elle reste à ce niveau une fois la charge ajoutée encore plus importante, on peut affirmer sans risque de se tromper que le processeur est saturé. Selon l'architecture du processeur, il se peut qu'il n'atteigne jamais 100 %. Supposons, par exemple, que l'utilisation de la mémoire augmente à mesure que vous ajoutez de la charge, puis que votre application se bloque soudainement lorsqu'elle atteint la limite de mémoire de la tâche ou de l'instance Amazon EC2. Dans ce cas, il est probable que la mémoire ait été entièrement consommée. Plusieurs ressources peuvent être consommées par votre application. Choisissez donc la métrique qui représente la ressource qui s'épuise en premier.

Enfin, réessayez de tester la charge après avoir doublé le nombre de tâches ou d'instances Amazon EC2. Supposons que l'indicateur clé augmente ou diminue de moitié par rapport au taux précédent. Si tel est le cas, la métrique est proportionnelle à la capacité. Il s'agit d'un bon indicateur d'utilisation pour le dimensionnement automatique.

Examinons maintenant ce scénario hypothétique. Supposons que vous testiez le chargement d'une application et que vous constatiez que l'utilisation du processeur atteint finalement 80 % à 100 demandes par seconde. Lorsqu'une charge supplémentaire est ajoutée, l'utilisation du processeur n'augmente plus. Cependant, cela ralentit la réponse de votre application. Ensuite, vous exécutez à nouveau le test de charge, en doublant le nombre de tâches tout en maintenant le taux à sa valeur maximale précédente. Si vous constatez que l'utilisation moyenne du processeur tombe à environ 40 %, l'utilisation moyenne du processeur est un bon candidat pour une métrique de mise à l'échelle. En revanche, si l'utilisation du processeur reste à 80 % après l'augmentation du nombre de tâches, l'utilisation moyenne du processeur n'est pas un bon indicateur de mise à l'échelle. Dans ce cas, des recherches supplémentaires sont nécessaires pour trouver une métrique appropriée.

Modèles d'application et propriétés de mise à l'échelle courants

Des logiciels de toutes sortes sont exécutés AWS. De nombreuses charges de travail sont développées en interne, tandis que d'autres sont basées sur des logiciels open source populaires. Quelle que soit leur origine, nous avons observé certains modèles de conception courants pour les services. La manière de procéder à une mise à l'échelle efficace dépend en grande partie du modèle.

Le serveur efficace lié au processeur

Le serveur efficace lié au processeur n'utilise pratiquement aucune ressource autre que le processeur et le débit du réseau. Chaque demande peut être traitée par l'application seule. Les demandes ne dépendent pas d'autres services tels que les bases de données. L'application peut gérer des centaines de milliers de demandes simultanées et peut utiliser efficacement plusieurs processeurs pour ce faire. Chaque demande est traitée soit par un thread dédié avec une faible surcharge de mémoire, soit par une boucle d'événements asynchrone qui s'exécute sur chaque processeur qui traite les demandes. Chaque réplique de l'application est également capable de traiter une demande. La seule ressource susceptible d'être épuisée avant le processeur est la bande passante réseau. Dans les services liés au processeur, l'utilisation de la mémoire, même au débit maximal, ne représente qu'une fraction des ressources disponibles.

Ce type d'application convient à la mise à l'échelle automatique basée sur le processeur. L'application bénéficie d'une flexibilité maximale en termes de mise à l'échelle. Il peut être redimensionné verticalement en lui fournissant des instances Amazon EC2 plus grandes ou des vCPU Fargate. De plus, il peut également être redimensionné horizontalement en ajoutant d'autres répliques. L'ajout de répliques supplémentaires, ou le doublement de la taille de l'instance, réduit de moitié l'utilisation moyenne du processeur par rapport à la capacité.

Si vous utilisez la capacité Amazon EC2 pour cette application, pensez à la placer sur des instances optimisées pour le calcul, telles que la famille or. c5 c6g

Le serveur économe en mémoire

Le serveur limité à la mémoire efficace alloue une quantité importante de mémoire par requête. En cas de simultanéité maximale, mais pas nécessairement de débit, la mémoire est épuisée avant que les ressources du processeur ne soient épuisées. La mémoire associée à une demande est libérée lorsque celle-ci prend fin. Des demandes supplémentaires peuvent être acceptées dans la limite de la mémoire disponible.

Ce type d'application convient à la mise à l'échelle automatique basée sur la mémoire. L'application bénéficie d'une flexibilité maximale en termes de mise à l'échelle. Il peut être redimensionné à la fois verticalement en lui fournissant des ressources de mémoire Amazon EC2 ou Fargate plus importantes. De plus, il peut également être redimensionné horizontalement en ajoutant d'autres répliques. L'ajout de répliques supplémentaires ou le doublement de la taille de l'instance peut réduire de moitié l'utilisation moyenne de la mémoire par rapport à la capacité.

Si vous utilisez la capacité Amazon EC2 pour cette application, pensez à la placer sur des instances optimisées pour la mémoire, telles que la famille or. r5 r6g

Certaines applications limitées en mémoire ne libèrent pas la mémoire associée à une demande lorsqu'elle se termine, de sorte qu'une réduction de la simultanéité n'entraîne pas une réduction de la mémoire utilisée. Pour cela, nous vous déconseillons d'utiliser le dimensionnement basé sur la mémoire.

Le serveur basé sur les travailleurs

Le serveur basé sur les travailleurs traite une demande pour chaque thread de travail individuel l'une après l'autre. Les threads de travail peuvent être des threads légers, tels que des threads POSIX. Il peut également s'agir de threads plus lourds, tels que des processus UNIX. Quel que soit le thread, l'application peut toujours prendre en charge une simultanéité maximale. En général, la limite de simultanéité est définie proportionnellement aux ressources de mémoire disponibles. Si la limite de simultanéité est atteinte, des demandes supplémentaires sont placées dans une file d'attente de backlog. Si la file d'attente du backlog est débordée, les demandes entrantes supplémentaires sont immédiatement rejetées. Les applications courantes qui correspondent à ce modèle incluent le serveur Web Apache et Gunicorn.

La simultanéité des demandes est généralement le meilleur indicateur pour dimensionner cette application. Étant donné qu'il existe une limite de simultanéité pour chaque réplique, il est important de procéder à une mise à l'échelle avant que la limite moyenne ne soit atteinte.

Le meilleur moyen d'obtenir des mesures de simultanéité des demandes est de demander à votre application de les communiquer à CloudWatch. Chaque réplique de votre application peut publier le nombre de demandes simultanées sous forme de métrique personnalisée à une fréquence élevée. Nous recommandons de régler la fréquence au moins une fois par minute. Une fois que plusieurs rapports ont été collectés, vous pouvez utiliser la simultanéité moyenne comme mesure de mise à l'échelle. Cette métrique est calculée en divisant la simultanéité totale par le nombre de répliques. Par exemple, si la simultanéité totale est de 1 000 et que le nombre de répliques est de 10, la simultanéité moyenne est de 100.

Si votre application se trouve derrière un Application Load Balancer, vous pouvez également utiliser la ActiveConnectionCount métrique de l'équilibreur de charge comme facteur dans la métrique de dimensionnement. La ActiveConnectionCount métrique doit être divisée par le nombre de répliques pour obtenir une valeur moyenne. La valeur moyenne doit être utilisée pour la mise à l'échelle, par opposition à la valeur de comptage brute.

Pour que cette conception fonctionne au mieux, l'écart type de latence de réponse doit être faible à de faibles taux de requêtes. Nous recommandons que, pendant les périodes de faible demande, la plupart des demandes reçoivent une réponse dans un court laps de temps, et il n'y a pas beaucoup de demandes dont le délai de réponse est nettement supérieur à la moyenne. Le temps de réponse moyen doit être proche du 95e percentile. Dans le cas contraire, des dépassements de files d'attente pourraient en résulter. Cela entraîne des erreurs. Nous vous recommandons de fournir des répliques supplémentaires si nécessaire pour atténuer le risque de débordement.

Le serveur en attente

Le serveur en attente effectue un certain traitement pour chaque demande, mais son fonctionnement dépend fortement d'un ou de plusieurs services en aval. Les applications de conteneurs font souvent un usage intensif des services en aval tels que les bases de données et autres services d'API. La réponse de ces services peut prendre un certain temps, en particulier dans les scénarios de haute capacité ou de concurrence élevée. En effet, ces applications ont tendance à utiliser peu de ressources du processeur et à utiliser leur simultanéité maximale en termes de mémoire disponible.

Le service d'attente convient soit au modèle de serveur limité à la mémoire, soit au modèle de serveur basé sur le travailleur, selon la conception de l'application. Si la simultanéité de l'application est limitée uniquement par la mémoire, l'utilisation moyenne de la mémoire doit être utilisée comme mesure de mise à l'échelle. Si la simultanéité de l'application est basée sur une limite de travail, la simultanéité moyenne doit être utilisée comme mesure de mise à l'échelle.

Le serveur basé sur Java

Si votre serveur basé sur Java dépend du processeur et s'adapte proportionnellement aux ressources du processeur, il convient peut-être au modèle de serveur efficace lié au processeur. Si tel est le cas, l'utilisation moyenne du processeur peut être appropriée comme mesure de mise à l'échelle. Cependant, de nombreuses applications Java ne sont pas liées au processeur, ce qui les rend difficiles à adapter.

Pour de meilleures performances, nous vous recommandons d'allouer autant de mémoire que possible au segment de machine virtuelle Java (JVM). Les versions récentes de la JVM, y compris la mise à jour 191 ou ultérieure de Java 8, définissent automatiquement la taille du tas aussi grande que possible pour tenir dans le conteneur. Cela signifie qu'en Java, l'utilisation de la mémoire est rarement proportionnelle à l'utilisation des applications. À mesure que le taux de demandes et la simultanéité augmentent, l'utilisation de la mémoire reste constante. Pour cette raison, nous ne recommandons pas de dimensionner les serveurs Java en fonction de l'utilisation de la mémoire. Au lieu de cela, nous recommandons généralement une mise à l'échelle en fonction de l'utilisation du processeur.

Dans certains cas, les serveurs basés sur Java sont épuisés avant d'épuiser le processeur. Si votre application risque de s'épuiser en cas de forte simultanéité, le nombre moyen de connexions constitue le meilleur indicateur de mise à l'échelle. Si votre application est susceptible de s'épuiser en tas à haut débit, le taux de requêtes moyen est le meilleur indicateur de mise à l'échelle.

Serveurs utilisant d'autres environnements d'exécution collectés

De nombreuses applications serveur sont basées sur des environnements d'exécution qui collectent les déchets, tels que .NET et Ruby. Ces applications serveur peuvent correspondre à l'un des modèles décrits précédemment. Cependant, comme pour Java, nous ne recommandons pas de dimensionner ces applications en fonction de la mémoire, car l'utilisation moyenne de la mémoire observée n'est souvent pas corrélée au débit ou à la simultanéité.

Pour ces applications, nous vous recommandons de dimensionner l'utilisation du processeur si l'application est liée au processeur. Dans le cas contraire, nous vous recommandons d'effectuer une mise à l'échelle en fonction du débit moyen ou de la simultanéité moyenne, en fonction des résultats de vos tests de charge.

Processeurs de tâches

De nombreuses charges de travail impliquent un traitement de tâches asynchrone. Il s'agit notamment des applications qui ne reçoivent pas de demandes en temps réel, mais qui s'abonnent à une file d'attente pour recevoir des offres d'emploi. Pour ces types d'applications, la mesure de dimensionnement appropriée est presque toujours la profondeur de la file d'attente. La croissance des files d'attente indique que le travail en attente dépasse la capacité de traitement, tandis qu'une file d'attente vide indique qu'il y a plus de capacité que de travail à effectuer.

AWS les services de messagerie, tels qu'Amazon SQS et Amazon Kinesis Data Streams, fournissent des CloudWatch métriques qui peuvent être utilisées pour le dimensionnement. Pour Amazon SQS, ApproximateNumberOfMessagesVisible c'est le meilleur indicateur. Pour Kinesis Data Streams, pensez à utiliser MillisBehindLatest la métrique publiée par la Kinesis Client Library (KCL). Cette métrique doit être moyennée pour tous les consommateurs avant de l'utiliser à des fins de mise à l'échelle.