Catégories
Astuces et Design

Exécution efficace d'instances ponctuelles avec Amazon EKS

Depuis que nous avons commencé à travailler sur HEY, l'une des choses dont j'ai été le plus grand partisan était de conserver autant que possible l'infrastructure de calcul côté application sur des instances ponctuelles (traitement des tâches frontales et asynchrones; à l'exclusion de la base de données, Redis et Elasticsearch). À la suite de nos deux premières semaines d'exécution de l'application avec une charge de trafic de production réelle, nous sommes assis à environ 90% de notre calcul exécuté sur des instances ponctuelles.

Surtout autour du lancement d'un nouveau produit, vous ne savez généralement pas à quoi ressembleront le trafic et les niveaux de charge, ce qui rend les achats d'instances réservées ou les plans d'épargne une proposition risquée. Les instances ponctuelles nous donnent la possibilité d'obtenir le calcul dont nous avons besoin à un prix encore plus élevé qu'un taux de RI ou de plan d'épargne d'un an, sans le même engagement. Combinez le prix avec une intégration transparente avec des groupes de mise à l'échelle automatique et cela en fait une évidence pour la plupart de nos charges de travail.

Le gros problème avec les instances ponctuelles? AWS peut vous les reprendre avec un préavis de deux minutes.

Charges de travail adaptées au site

Le choix d'exécuter la majeure partie de vos charges de travail sur place ne fonctionne bien que si ces charges de travail peuvent gérer être démolies et recréées facilement (dans notre cas, via les modules Kubernetes). Mais que signifie «facilement»? Pour nous, cela signifie sans provoquer d'exceptions (face au client ou en interne) ou d'échecs de travail.

Pour HEY, nous pouvons nous en sortir en exécutant l'intégralité de la pile frontale (OpenResty, Puma) et la majeure partie de nos tâches d'arrière-plan asynchrones (Resque) sur place.

Charges de travail durables

Qu'est-ce qui ne convient pas bien aux instances ponctuelles? Pour HEY, nous avons trouvé trois catégories principales: les travaux de longue durée, les instances Redis pour les déploiements de succursales et tout ce qui nécessite un volume persistant (comme certains éléments du pipeline de messagerie). Nous plaçons ces cas spéciaux sur ce que nous appelons le groupe de nœuds «durable» qui utilise des instances régulières à la demande (et probablement des IR ou des plans d'épargne à l'avenir).

Jetons un œil à chacun:

  • Les travaux qui ont la possibilité de s'exécuter pendant plus d'une minute et demie à deux minutes sont un basculement automatique vers le groupe de nœuds durable. Actuellement, pour HEY, il s'agit uniquement d'exportations de compte.
  • Redis est un composant d'infrastructure principal pour HEY. Nous l'utilisons pour un tas de choses – voir la mise en cache, Resque, le stockage d'informations sur le pipeline de courrier entrant, etc. afin de ne pas marcher les uns sur les autres (l'utilisation de la fonction de bases de données Redis ne fonctionne pas tout à fait ici). Pendant un certain temps, nous avons essayé d'exécuter ces instances Redis sur place, mais bah, le bruit de surveillance et la rupture aléatoire des pods Redis qui vont et viennent, puis l'application se connecte au pod en lecture seule et lève des exceptions…. c'était trop. La solution: les retirer des instances ponctuelles. (cela n'affecte que la version bêta / intermédiaire – ces environnements utilisent un graphique Redis Helm vendu que nous exécutons dans le cluster, la production utilise Elasticache)
  • Nous avons réussi à exécuter beaucoup de choses qui nécessitent des PVC dans Kubernetes. Heck, pendant plusieurs mois, nous avons exécuté l'ensemble des clusters Elasticsearch pour Basecamp 2 et 3 sur Kubernetes sans aucun problème majeur. Mais cela ne signifie pas que je le recommanderais, et surtout je ne le recommande pas lors de l'utilisation d'instances ponctuelles. Un problème récurrent que nous avons vu était qu'un nœud avec un pod utilisant un PVC serait récupéré et que ce pod n'aurait pas de nœud pour se lancer dans le même AZ que le PVC existant. Kubernetes adore ça le montre via une erreur d'affinité de volume et il a souvent fallu un nettoyage manuel pour redémarrer les pods. Lancer les dés sur devoir intervenir chaque fois qu'une remise en état ponctuelle se produit ne vaut pas la peine pour notre équipe.

Faire les bons choix

gestionnaire de terminaison de nœud

La pièce la plus importante du puzzle spot-with-Kubernetes est sans doute le gestionnaire de terminaison de noeud aws. Il s'exécute en tant que DaemonSet et surveille en permanence le service de métadonnées EC2 pour voir si le nœud actuel a reçu des notifications de terminaison ponctuelle (ou des notifications de maintenance planifiée). S'il en trouve un, il (tentera) de supprimer avec élégance les pods en cours d'exécution afin que Kubernetes puisse les planifier ailleurs sans impact sur l'utilisateur.

cluster-autoscaler

cluster-autoscaler n'a pas besoin de nombreuses modifications pour s'exécuter avec un groupe de mise à l'échelle automatique ponctuel. Dans la mesure où nous parlons de garantir que les comportements de terminaison d'instance sont bien gérés, vous devez savoir à quel point nous avons souffert pour que le rééquilibrage ASG soit géré correctement. Lors du rééquilibrage, nous verrions des nœuds qui viennent de mourir et l'ALB continuerait à leur envoyer du trafic via kube-proxy car aucun avertissement à kubelet n'était sur le point de disparaître. aws-node-terminaison-handler ne peut pas gérer le rééquilibrage actuellement, mais je pense que les groupes de nœuds gérés par EKS le font – au détriment de la non-prise en charge des instances ponctuelles. Un projet appelé lifecycle-manager s'est avéré essentiel pour nous dans la gestion du rééquilibrage avec facilité (même si nous avons fini par désactiver le rééquilibrage tous ensemble 😬).

Types et tailles d'instances

Il est sage de faire vos propres tests et de déterminer comment vos charges de travail consomment les ressources CPU et mémoire et choisissez vos types et tailles d'instance EC2 en conséquence. Les ASG ponctuels sont plus utiles lorsque le planificateur ASG peut choisir parmi de nombreux types et tailles d'instances différentes pour répondre à vos demandes ponctuelles. Sans répartir cette charge sur plusieurs types (ou tailles), vous courez le risque d'être affecté par des événements de capacité où AWS ne peut pas répondre à votre demande ponctuelle.

En fait, cela nous est arrivé plus tôt dans l'année lorsque la demande au comptant a monté en flèche. Nous avons rencontré des problèmes avec l'ASG nous disant qu'il n'y avait pas de capacité ponctuelle pour répondre à notre demande, et lorsque les choses ont été satisfaites, il n'était pas rare que ces instances soient récupérées quelques minutes plus tard. Le taux de désabonnement était intenable à ce rythme. Le correctif pour nous était de fonctionner avec d'autres types et tailles d'instances.

Nos charges de travail fonctionnent mieux avec les instances de la série C, nous le savons, c'est donc ce que nous utilisons. Cependant, si vous pouvez vous en sortir en utilisant des instances de série M ou T, faites-le (elles ont des demandes de CPU / mémoire comparables sur toute la plage de taille et vous tirez facilement de m5, m5d, m5n, etc. pour ajouter plus de variabilité à votre emplacement demandes).

Un gotcha: cluster-autoscaler n'aime vraiment pas les ASG à instances mixtes où les demandes de CPU et de mémoire ne sont pas les mêmes entre les types de nœuds disponibles. Il peut vous laisser dans une position où il pense que l'ASG a des nœuds 8c / 16g tandis que l'ASG a réellement répondu à une demande en utilisant un nœud 4c / 8g – maintenant les calculs de cluster-autoscaler sur le nombre d'instances dont il a besoin pour l'ensemble de pods non programmables est incorrect . Il y a une section à ce sujet dans la documentation du cluster-autoscaler, mais le tl; dr est que si vous souhaitez utiliser différents types d'instances, assurez-vous que les spécifications sont généralement les mêmes.

Zones et régions de disponibilité

La disponibilité et le prix des instances ponctuelles varient considérablement d'une zone à l'autre et d'une région à l'autre. Prenons cet exemple d'instances ponctuelles c5.2xlarge dans us-east-1:

c5.2xlarge, us-east-1 – avec la permission de spotcost.com

Surtout depuis le début du mois de juin, il existe une disparité folle dans les prix au comptant entre les AZ des États-Unis-1! Si vous planifiez uniquement en us1-az2, vous payez une prime de 18% par rapport à us1-az1. Si votre ASG est configuré pour s'étendre sur des AZ, cela est automatiquement pris en compte lors du traitement des demandes ponctuelles et AWS essaiera de placer vos instances dans des AZ moins chères si possible (sauf si vous avez modifié l'option de priorité de planification).

Mais ce ne sont pas seulement les zones de disponibilité où il existe de réelles disparités de prix. Entre les différentes régions, les différences de prix peuvent être encore plus fortes. Prenez us-east-1 et us-east-2 – deux régions où les prix du calcul sont généralement les mêmes pour les réservations à la demande. Dans us-east-2, les demandes ponctuelles pour les instances c5.2xlarge vont actuellement de 40 à 50% moins cher que la même chose dans us-east-1:

c5.2xlarge, us-east-2 – avec la permission de spotcost.com

Ce sont des économies importantes à grande échelle. Bien sûr, il existe d'autres obligations pour fonctionner dans d'autres régions – tous les services que vous utilisez sont-ils pris en charge, pouvez-vous accéder à d'autres infrastructures dont vous disposez, etc. (et il est également possible que le fait de déménager dans une autre région à lui seul ne fasse tout simplement pas sens pour vous, c'est tout à fait bien!).

Mise à niveau

Le simple fait de faire du calcul sur place n'est pas l'objectif final, et nous pouvons emprunter plusieurs voies pour continuer à améliorer notre infrastructure de calcul afin de placer les ressources de manière optimale, à la fois du point de vue des coûts et pour garder les choses proches de la fin. utilisateur.

  • (court terme) L'utilisation de l'autoscaler à pod horizontal pour mettre à l'échelle automatiquement les répliques de déploiement compte comme du trafic vers la plate-forme qui fluctue régulièrement. Lorsqu'il est combiné avec un cluster autoscaler, Kubernetes (avec beaucoup de confiance de votre équipe opérationnelle… ..) peut prendre en charge la mise à l'échelle automatique de votre infrastructure en fonction de l'utilisation du processeur, de la latence des demandes, du nombre de demandes, etc. HEY commence déjà à modèle de trafic standard où l'utilisation est la plus élevée pendant les heures de travail aux États-Unis, puis diminue considérablement pendant la nuit et le week-end. Ce sont des moments parfaits pour réduire l'application à une taille de déploiement plus petite. Le calcul frontal n'est pas le principal facteur de coût pour HEY (qui tombe dans une infrastructure de stockage de données persistante comme Aurora et Elasticache), mais la mise à l'échelle quelque chose vers le bas quand vous le pouvez est mieux que de ne rien faire du tout.
  • (long terme) Calcul shunté entre les régions et les zones géographiques en fonction des prix au comptant. Ce n'est probablement pas une chose à laquelle une entreprise de la taille de Basecamp doit penser, mais être en mesure de shunter le trafic vers différentes régions et zones géographiques en fonction des coûts de calcul et de la disponibilité est un objectif de rêve. C'est délicat car nous devons également tenir compte de l'emplacement de nos backends de données. Peut-être que vous exécutez déjà une configuration active / active / active avec trois régions du monde et pouvez progressivement déplacer vos opérations de mise à l'échelle dans les différentes régions à mesure que différentes parties du monde commencent à se réveiller et à utiliser votre application. Vous utilisez peut-être simplement une configuration active / active plus simple, mais calculez les prix ou la disponibilité dans la région A commencez à montrer des signes de problèmes, vous pouvez facilement passer à la région B.

Conclusion

Les instances ponctuelles peuvent être un excellent outil pour gérer les dépenses tout en obtenant les ressources de calcul dont vous avez besoin, mais elles comportent des défis supplémentaires dont vous devez rester conscient. Suivre cette voie n'est pas une décision unique – en particulier avec une application qui connaît un développement actif, vous devez être attentif à la modification de l'utilisation des ressources et des flux de travail pour vous assurer que les terminaisons ponctuelles ne nuisent pas à vos charges de travail et à vos clients, et que les changements dans les fonctionnalités principales du spot (comme les prix et la disponibilité) ne vous affectent pas.

La bonne nouvelle est que si le spot s'avère négatif pour vous, le passage à la demande est un changement unique dans votre configuration de groupe à mise à l'échelle automatique, puis relancez progressivement vos instances existantes.


Si vous êtes intéressé par HEY, consultez hey.com et découvrez notre point de vue sur le courrier électronique.

Blake est administrateur système principal au sein de l'équipe des opérations de Basecamp. Il passe la plupart de son temps à travailler avec Kubernetes et AWS, dans une certaine mesure. Lorsqu'il n'est pas plongé dans YAML, il fait du VTT. Si vous avez des questions, envoyez-les sur Twitter – @ t3rabytes.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *