Calcul et mise à l'échelle automatique - Amazon EKS

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.

Calcul et mise à l'échelle automatique

En tant que développeur, vous évaluerez les besoins en ressources de votre application, par exemple en termes de processeur et de mémoire, mais si vous ne les ajustez pas continuellement, elles risquent de devenir obsolètes, ce qui peut augmenter vos coûts et détériorer les performances et la fiabilité. Il est plus important d'ajuster en permanence les besoins en ressources d'une application que de les satisfaire correctement du premier coup.

Les meilleures pratiques mentionnées ci-dessous vous aideront à créer et à exploiter des charges de travail sensibles aux coûts qui permettent d'obtenir des résultats commerciaux tout en minimisant les coûts et en permettant à votre organisation de maximiser son retour sur investissement. Voici un ordre d'importance élevé pour optimiser les coûts de calcul de votre cluster :

  1. Dimensionnez correctement les charges de travail

  2. Réduction de la capacité inutilisée

  3. Optimisez les types de capacité de calcul (par exemple Spot) et les accélérateurs (par exemple GPUs)

Dimensionnez correctement vos charges de travail

Dans la plupart des clusters EKS, l'essentiel des coûts provient des EC2 instances utilisées pour exécuter vos charges de travail conteneurisées. Vous ne serez pas en mesure de dimensionner correctement vos ressources informatiques sans connaître vos exigences en matière de charges de travail. C'est pourquoi il est essentiel que vous utilisiez les demandes et les limites appropriées et que vous modifiiez ces paramètres si nécessaire. En outre, les dépendances, telles que la taille de l'instance et la sélection du stockage, peuvent affecter les performances de la charge de travail, ce qui peut avoir diverses conséquences imprévues sur les coûts et la fiabilité.

Les demandes doivent correspondre à l'utilisation réelle. Si les demandes d'un conteneur sont trop élevées, la capacité sera inutilisée, ce qui représente un facteur important dans le coût total du cluster. Chaque conteneur d'un pod, par exemple l'application et les sidecars, doit avoir ses propres demandes et limites définies pour garantir que les limites globales des pods sont aussi précises que possible.

Utilisez des outils tels que Goldilocks, KRR et Kubecost pour estimer les demandes de ressources et les limites pour vos conteneurs. En fonction de la nature des applications, des exigences en matière de performances/coûts et de leur complexité, vous devez déterminer quels indicateurs sont les meilleurs pour évoluer, à quel moment les performances de votre application se dégradent (point de saturation) et comment ajuster les demandes et les limites en conséquence. Veuillez vous référer à la section Taille correcte de l'application pour obtenir de plus amples informations à ce sujet.

Nous vous recommandons d'utiliser le Horizontal Pod Autoscaler (HPA) pour contrôler le nombre de répliques de votre application à exécuter, le Vertical Pod Autoscaler (VPA) pour ajuster le nombre de demandes et les limites dont votre application a besoin par réplique, et un autoscaler de nœuds tel que Karpenter ou Cluster Autoscaler pour ajuster en permanence le nombre total de nœuds de votre cluster. Les techniques d'optimisation des coûts utilisant Karpenter et Cluster Autoscaler sont décrites dans une section ultérieure de ce document.

Le Vertical Pod Autoscaler peut ajuster les demandes et les limites attribuées aux conteneurs afin que les charges de travail s'exécutent de manière optimale. Vous devez exécuter le VPA en mode audit afin qu'il n'apporte pas automatiquement de modifications et ne redémarre pas vos pods. Il proposera des modifications en fonction des indicateurs observés. Toute modification affectant les charges de travail de production doit d'abord être examinée et testée dans un environnement hors production, car elle peut avoir un impact sur la fiabilité et les performances de votre application.

Réduire la consommation

Le meilleur moyen d'économiser de l'argent est de fournir moins de ressources. L'un des moyens d'y parvenir consiste à ajuster les charges de travail en fonction de leurs exigences actuelles. Vous devez commencer tout effort d'optimisation des coûts en vous assurant que vos charges de travail répondent à leurs exigences et évoluent de manière dynamique. Cela nécessitera d'obtenir des métriques à partir de vos applications et de définir des configurations telles que PodDisruptionBudgetsPod Readiness Gates pour garantir que votre application peut évoluer dynamiquement à la hausse et à la baisse en toute sécurité. Il est important de noter qu'une restriction PodDisruptionBudgets peut empêcher Cluster Autoscaler et Karpenter de réduire les nœuds, étant donné que Cluster Autoscaler et Karpenter respectent tous les deux. PodDisruptionBudgets La valeur « minAvailable » dans le PodDisruptionBudget doit toujours être inférieure au nombre de pods dans le déploiement et vous devez garder une bonne mémoire tampon entre les deux, par exemple dans un déploiement de 6 pods où vous souhaitez qu'un minimum de 4 pods fonctionnent en permanence, réglez le « minAvailable » sur 4. PodDisruptionBidget Cela permettra à Cluster Autoscaler et Karpenter de vider et d'expulser en toute sécurité les pods des nœuds sous-utilisés lors d'un événement de réduction des nœuds. Reportez-vous au document FAQ de Cluster Autoscaler.

L'Horizontal Pod Autoscaler est un autoscaler de charge de travail flexible qui peut ajuster le nombre de répliques nécessaires pour répondre aux exigences de performance et de fiabilité de votre application. Il dispose d'un modèle flexible permettant de définir quand augmenter ou diminuer en fonction de diverses mesures telles que le processeur, la mémoire ou de mesures personnalisées, telles que la profondeur de la file d'attente, le nombre de connexions à un pod, etc.

Le serveur de métriques Kubernetes permet une mise à l'échelle en réponse à des indicateurs intégrés tels que l'utilisation du processeur et de la mémoire, mais si vous souhaitez effectuer une mise à l'échelle en fonction d'autres indicateurs, tels que la profondeur des files d'attente Amazon CloudWatch ou SQS, vous devez envisager des projets de mise à l'échelle automatique pilotés par des événements tels que KEDA. Reportez-vous à ce billet de blog pour savoir comment utiliser KEDA avec CloudWatch les métriques. Si vous n'êtes pas certain des indicateurs à surveiller et sur lesquels vous baser, consultez les meilleures pratiques en matière de surveillance des indicateurs importants.

La réduction de la consommation de charge de travail crée une capacité excédentaire dans un cluster et, avec une configuration d'autoscaling appropriée, vous pouvez automatiquement réduire le nombre de nœuds et réduire vos dépenses totales. Nous vous recommandons de ne pas essayer d'optimiser la capacité de calcul manuellement. Le planificateur Kubernetes et les autoscalers de nœuds ont été conçus pour gérer ce processus à votre place.

Réduction de la capacité inutilisée

Une fois que vous avez déterminé la taille appropriée pour les applications, réduisant ainsi le nombre de demandes excédentaires, vous pouvez commencer à réduire la capacité de calcul allouée. Vous devriez être en mesure de le faire de manière dynamique si vous avez pris le temps de dimensionner correctement vos charges de travail dans les sections ci-dessus. Deux autoscalers de nœuds principaux sont utilisés avec Kubernetes dans AWS.

Karpenter et Cluster Autoscaler

Karpenter et Kubernetes Cluster Autoscaler augmenteront le nombre de nœuds de votre cluster en fonction de la création ou de la suppression de pods et de l'évolution des exigences de calcul. L'objectif principal des deux est le même, mais Karpenter adopte une approche différente pour le provisionnement et le déprovisionnement de la gestion des nœuds, ce qui peut contribuer à réduire les coûts et à optimiser l'utilisation à l'échelle du cluster.

À mesure que la taille des clusters augmente et que la variété des charges de travail augmente, il devient de plus en plus difficile de préconfigurer les groupes de nœuds et les instances. Tout comme pour les demandes de charge de travail, il est important de définir une base de référence initiale et de l'ajuster en permanence selon les besoins.

Si vous utilisez Cluster Autoscaler, il respectera les valeurs « minimum » et « maximum » de chaque groupe Auto Scaling (ASG) et ajustera uniquement la valeur « souhaitée ». Il est important de faire attention lorsque vous définissez ces valeurs pour l'ASG sous-jacent, car Cluster Autoscaler ne sera pas en mesure de réduire un ASG au-delà de son nombre « minimum ». Définissez le nombre « souhaité » comme le nombre de nœuds dont vous avez besoin pendant les heures normales de bureau et le nombre « minimum » comme le nombre de nœuds dont vous avez besoin en dehors des heures de bureau. Reportez-vous au document FAQ de Cluster Autoscaler.

Expandeur de priorité Cluster Autoscaler

Le Kubernetes Cluster Autoscaler fonctionne en redimensionnant des groupes de nœuds (appelés groupes de nœuds) vers le haut ou vers le bas au fur et à mesure que les applications augmentent ou diminuent. Si vous ne dimensionnez pas les charges de travail de manière dynamique, le Cluster Autoscaler ne vous aidera pas à économiser de l'argent. Le Cluster Autoscaler nécessite qu'un administrateur du cluster crée des groupes de nœuds à l'avance pour que les charges de travail soient consommées. Les groupes de nœuds doivent être configurés pour utiliser des instances ayant le même « profil », c'est-à-dire à peu près la même quantité de processeur et de mémoire.

Vous pouvez avoir plusieurs groupes de nœuds et le Cluster Autoscaler peut être configuré pour définir des niveaux de dimensionnement prioritaires. Chaque groupe de nœuds peut contenir des nœuds de tailles différentes. Les groupes de nœuds peuvent avoir différents types de capacité et l'extenseur de priorité peut d'abord être utilisé pour dimensionner des groupes moins coûteux.

Vous trouverez ci-dessous un exemple d'extrait de configuration de cluster qui utilise un ConfigMap` pour prioriser la capacité réservée avant d'utiliser des instances à la demande. Vous pouvez utiliser la même technique pour prioriser les instances Graviton ou Spot par rapport aux autres types.

apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-cluster managedNodeGroups: - name: managed-ondemand minSize: 1 maxSize: 7 instanceType: m5.xlarge - name: managed-reserved minSize: 2 maxSize: 10 instanceType: c5.2xlarge
apiVersion: v1 kind: ConfigMap metadata: name: cluster-autoscaler-priority-expander namespace: kube-system data: priorities: |- 10: - .*ondemand.* 50: - .*reserved.*

L'utilisation de groupes de nœuds peut aider les ressources de calcul sous-jacentes à faire ce que l'on attend par défaut, par exemple en répartissant les nœuds AZs, mais toutes les charges de travail n'ont pas les mêmes exigences ou attentes. Il est donc préférable de laisser les applications déclarer leurs besoins de manière explicite. Pour plus d'informations sur Cluster Autoscaler, consultez la section des meilleures pratiques.

Déplanificateur

Le Cluster Autoscaler peut ajouter et supprimer de la capacité des nœuds d'un cluster en fonction de la nécessité de planifier de nouveaux pods ou de la sous-utilisation de nœuds. Il ne prend pas en compte de manière globale le placement des pods une fois qu'ils ont été planifiés sur un nœud. Si vous utilisez le Cluster Autoscaler, vous devez également consulter le déplanificateur Kubernetes pour éviter de gaspiller de la capacité dans votre cluster.

Si vous avez 10 nœuds dans un cluster et que chaque nœud est utilisé à 60 %, vous n'utilisez pas 40 % de la capacité allouée dans le cluster. Avec le Cluster Autoscaler, vous pouvez définir le seuil d'utilisation par nœud à 60 %, mais cela n'essaiera de réduire qu'un seul nœud lorsque l'utilisation est tombée en dessous de 60 %.

Avec le déplanificateur, il peut examiner la capacité et l'utilisation du cluster une fois que les pods ont été planifiés ou que des nœuds ont été ajoutés au cluster. Il tente de maintenir la capacité totale du cluster au-dessus d'un seuil spécifié. Il peut également supprimer des pods en fonction de l'altération des nœuds ou de nouveaux nœuds qui rejoignent le cluster pour s'assurer que les pods fonctionnent dans leur environnement informatique optimal. Notez que le déplanificateur ne planifie pas le remplacement des pods expulsés mais s'appuie sur le planificateur par défaut pour cela.

Consolidation de Karpenter

Karpenter adopte une approche « sans groupe » pour la gestion des nœuds. Cette approche est plus flexible pour différents types de charges de travail et nécessite moins de configuration initiale pour les administrateurs de clusters. Au lieu de prédéfinir des groupes et de dimensionner chaque groupe en fonction des besoins des charges de travail, Karpenter utilise des fournisseurs et des modèles de nœuds pour définir de manière générale le type d' EC2 instances pouvant être créées et les paramètres relatifs aux instances au fur et à mesure de leur création.

Le bin packing est une pratique qui consiste à utiliser une plus grande partie des ressources de l'instance en répartissant davantage de charges de travail sur un nombre réduit d'instances de taille optimale. Bien que cela contribue à réduire vos coûts de calcul en provisionnant uniquement les ressources utilisées par vos charges de travail, cela comporte un compromis. Le démarrage de nouvelles charges de travail peut prendre plus de temps car de la capacité doit être ajoutée au cluster, en particulier lors d'événements de grande envergure. Tenez compte de l'équilibre entre l'optimisation des coûts, les performances et la disponibilité lors de la configuration de l'emballage en bacs.

Karpenter peut effectuer une surveillance continue et un binpack afin d'améliorer l'utilisation des ressources des instances et de réduire vos coûts de calcul. Karpenter peut également sélectionner un nœud de travail plus rentable pour votre charge de travail. Cela peut être réalisé en activant l'indicateur « consolidation » sur true dans le fournisseur (exemple d'extrait de code ci-dessous). L'exemple ci-dessous montre un exemple de fournisseur qui permet la consolidation. Au moment de la rédaction de ce guide, Karpenter ne remplacera pas une instance Spot en cours d'exécution par une instance Spot moins chère. Pour plus de détails sur la consolidation de Karpenter, consultez ce blog.

apiVersion: karpenter.sh/v1 kind: Provisioner metadata: name: enable-binpacking spec: consolidation: enabled: true

Pour les charges de travail susceptibles de ne pas être interruptibles, par exemple les tâches par lots de longue durée sans point de contrôle, pensez à annoter les pods avec l'annotation. do-not-evict En refusant l'expulsion des modules, vous dites à Karpenter qu'il ne doit pas supprimer volontairement les nœuds contenant ce module. Toutefois, si un do-not-evict pod est ajouté à un nœud alors que celui-ci se vide, les pods restants seront tout de même expulsés, mais ce pod bloquera la terminaison jusqu'à ce qu'il soit retiré. Dans les deux cas, le nœud sera bouclé pour empêcher que des travaux supplémentaires ne soient planifiés sur le nœud. Vous trouverez ci-dessous un exemple montrant comment définir l'annotation :

8"" linenumbering="unnumbered">apiVersion: v1 kind: Pod metadata: name: label-demo labels: environment: production annotations: + "karpenter.sh/do-not-evict": "true" spec: containers: * name: nginx image: nginx ports: ** containerPort: 80

Supprimez les nœuds sous-utilisés en ajustant les paramètres du Cluster Autoscaler

L'utilisation des nœuds est définie comme la somme des ressources demandées divisée par la capacité. Par défaut, scale-down-utilization-threshold il est défini sur 50 %. Ce paramètre peut être utilisé conjointement avec etscale-down-unneeded-time, qui détermine la durée pendant laquelle un nœud doit être inutile avant de pouvoir être réduit. La valeur par défaut est de 10 minutes. Les pods toujours en cours d'exécution sur un nœud réduit seront planifiés sur d'autres nœuds par kube-scheduler. L'ajustement de ces paramètres peut aider à supprimer les nœuds sous-utilisés, mais il est important de tester d'abord ces valeurs afin de ne pas forcer le cluster à se réduire prématurément.

Vous pouvez empêcher la réduction de la taille en veillant à ce que les pods dont l'expulsion coûte cher soient protégés par une étiquette reconnue par le Cluster Autoscaler. Pour ce faire, assurez-vous que les pods dont l'expulsion coûte cher comportent l'annotationcluster-autoscaler.kubernetes.io/safe-to-evict=false. Voici un exemple de fichier yaml pour définir l'annotation :

8"" linenumbering="unnumbered">apiVersion: v1 kind: Pod metadata: name: label-demo labels: environment: production annotations: + "cluster-autoscaler.kubernetes.io/safe-to-evict": "false" spec: containers: * name: nginx image: nginx ports: ** containerPort: 80