Économisez sur les coûts du cloud Kubernetes sur AWS

La traduction de l'article a été préparée à la veille du début du cours "Plateforme d'infrastructure basée sur Kubernetes".

Économisez sur les coûts du cloud Kubernetes sur AWS

Comment économiser sur les coûts du cloud lorsque vous travaillez avec Kubernetes ? Il n'existe pas de solution unique, mais cet article décrit plusieurs outils qui peuvent vous aider à gérer vos ressources plus efficacement et à réduire vos coûts de cloud computing.

J'ai écrit cet article en pensant à Kubernetes pour AWS, mais il s'appliquera (presque) exactement de la même manière aux autres fournisseurs de cloud. Je suppose que la mise à l'échelle automatique est déjà configurée sur votre ou vos clusters (mise à l'échelle automatique de cluster). La suppression de ressources et la réduction de votre déploiement ne vous feront économiser de l'argent que si cela réduit également votre flotte de nœuds de travail (instances EC2).

Cet article couvrira :

  • nettoyer les ressources inutilisées (Kube-concierge)
  • Réduire la mise à l'échelle pendant les heures non travaillées (Kube-downscaler)
  • en utilisant la mise à l'échelle automatique horizontale (HPA),
  • réduction des réservations excessives de ressources (rapport-ressources Kube, APV)
  • utilisation d'instances Spot

Nettoyer les ressources inutilisées

Travailler dans un environnement en évolution rapide est formidable. Nous voulons des organisations technologiques accéléré. Une livraison de logiciels plus rapide signifie également davantage de déploiements de relations publiques, d'environnements de prévisualisation, de prototypes et de solutions d'analyse. Tout est déployé sur Kubernetes. Qui a le temps de nettoyer manuellement les déploiements de tests ? Il est facile d'oublier la suppression d'une expérience vieille d'une semaine. La facture du cloud va finir par augmenter à cause d'un truc qu'on a oublié de fermer :

Économisez sur les coûts du cloud Kubernetes sur AWS

(Henning Jacobs :
Jiza :
(citations) Corey Quinn :
Mythe : votre compte AWS est fonction du nombre d'utilisateurs dont vous disposez.
Fait : votre score AWS est fonction du nombre d'ingénieurs dont vous disposez.

Ivan Kurnossov (en réponse) :
Fait réel : votre score AWS est fonction du nombre d'éléments que vous avez oublié de désactiver/supprimer.)

Concierge Kubernetes (kube-janitor) aide à nettoyer votre cluster. La configuration du concierge est flexible pour une utilisation globale et locale :

  • Les règles à l'échelle du cluster peuvent définir la durée de vie maximale (TTL) pour les déploiements PR/test.
  • Les ressources individuelles peuvent être annotées avec janitor/ttl, par exemple pour supprimer automatiquement le pic/prototype après 7 jours.

Les règles générales sont définies dans le fichier YAML. Son chemin passe par le paramètre --rules-file dans Kube-Janitor. Voici un exemple de règle pour supprimer tous les espaces de noms avec -pr- au nom après deux jours :

- id: cleanup-resources-from-pull-requests
  resources:
    - namespaces
  jmespath: "contains(metadata.name, '-pr-')"
  ttl: 2d

L'exemple suivant régule l'utilisation du label d'application sur les pods Deployment et StatefulSet pour tous les nouveaux Deployments/StatefulSets en 2020, mais permet en même temps l'exécution de tests sans ce label pendant une semaine :

- id: require-application-label
  # удалить deployments и statefulsets без метки "application"
  resources:
    - deployments
    - statefulsets
  # см. http://jmespath.org/specification.html
  jmespath: "!(spec.template.metadata.labels.application) && metadata.creationTimestamp > '2020-01-01'"
  ttl: 7d

Exécutez une démo limitée dans le temps pendant 30 minutes sur un cluster exécutant kube-janitor :

kubectl run nginx-demo --image=nginx
kubectl annotate deploy nginx-demo janitor/ttl=30m

Les volumes persistants (AWS EBS) constituent une autre source d'augmentation des coûts. La suppression d'un Kubernetes StatefulSet ne supprime pas ses volumes persistants (PVC - PersistentVolumeClaim). Les volumes EBS inutilisés peuvent facilement entraîner des coûts de plusieurs centaines de dollars par mois. Kubernetes Janitor dispose d'une fonctionnalité permettant de nettoyer les PVC inutilisés. Par exemple, cette règle supprimera tous les PVC qui ne sont pas montés par un module et qui ne sont pas référencés par un StatefulSet ou un CronJob :

# удалить все PVC, которые не смонтированы и на которые не ссылаются StatefulSets
- id: remove-unused-pvcs
  resources:
  - persistentvolumeclaims
  jmespath: "_context.pvc_is_not_mounted && _context.pvc_is_not_referenced"
  ttl: 24h

Kubernetes Janitor peut vous aider à garder votre cluster propre et à empêcher les coûts du cloud computing de s'accumuler lentement. Pour les instructions de déploiement et de configuration, suivez README Kube-Janitor.

Réduire la mise à l’échelle en dehors des heures de travail

Les systèmes de test et de préparation doivent généralement fonctionner uniquement pendant les heures de bureau. Certaines applications de production, telles que les outils de back-office/d'administration, ne nécessitent également qu'une disponibilité limitée et peuvent être désactivées du jour au lendemain.

Réducteur de mise à l'échelle Kubernetes (kube-downscaler) permet aux utilisateurs et aux opérateurs de réduire le système en dehors des heures de travail. Les déploiements et les StatefulSets peuvent évoluer jusqu'à zéro réplica. Les CronJobs peuvent être suspendus. Kubernetes Downscaler est configuré pour un cluster entier, un ou plusieurs espaces de noms ou des ressources individuelles. Vous pouvez définir soit le « temps d'inactivité », soit, à l'inverse, le « temps de travail ». Par exemple, pour réduire autant que possible la mise à l'échelle pendant les nuits et les week-ends :

image: hjacobs/kube-downscaler:20.4.3
args:
  - --interval=30
  # не отключать компоненты инфраструктуры
  - --exclude-namespaces=kube-system,infra
  # не отключать kube-downscaler, а также оставить Postgres Operator, чтобы исключенными БД можно было управлять
  - --exclude-deployments=kube-downscaler,postgres-operator
  - --default-uptime=Mon-Fri 08:00-20:00 Europe/Berlin
  - --include-resources=deployments,statefulsets,stacks,cronjobs
  - --deployment-time-annotation=deployment-time

Voici un graphique pour la mise à l'échelle des nœuds de travail du cluster le week-end :

Économisez sur les coûts du cloud Kubernetes sur AWS

La réduction d'environ 13 à 4 nœuds de travail fait certainement une différence notable dans votre facture AWS.

Mais que se passe-t-il si je dois travailler pendant les « temps d'arrêt » du cluster ? Certains déploiements peuvent être définitivement exclus de la mise à l’échelle en ajoutant l’annotation downscaler/exclude: true. Les déploiements peuvent être temporairement exclus à l'aide de l'annotation downscaler/exclude-until avec un horodatage absolu au format AAAA-MM-JJ HH:MM (UTC). Si nécessaire, l'ensemble du cluster peut être réduit en déployant un pod avec l'annotation downscaler/force-uptime, par exemple, en lançant nginx blank :

kubectl run scale-up --image=nginx
kubectl annotate deploy scale-up janitor/ttl=1h # удалить развертывание через час
kubectl annotate pod $(kubectl get pod -l run=scale-up -o jsonpath="{.items[0].metadata.name}") downscaler/force-uptime=true

Voir README Kube-downscaler, si vous êtes intéressé par les instructions de déploiement et les options supplémentaires.

Utiliser la mise à l'échelle automatique horizontale

De nombreuses applications/services gèrent un modèle de chargement dynamique : parfois leurs modules sont inactifs, et parfois ils fonctionnent à pleine capacité. L’exploitation d’une flotte permanente de pods pour faire face à une charge de pointe maximale n’est pas économique. Kubernetes prend en charge la mise à l'échelle automatique horizontale sur une ressource HorizontalPodAutoscaler (HPA). L'utilisation du processeur est souvent un bon indicateur de mise à l'échelle :

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        averageUtilization: 100
        type: Utilization

Zalando a créé un composant pour connecter facilement des métriques personnalisées à des fins de mise à l'échelle : Adaptateur de métriques Kube (kube-metrics-adapter) est un adaptateur de métriques générique pour Kubernetes qui peut collecter et servir des métriques personnalisées et externes pour la mise à l'échelle automatique horizontale des pods. Il prend en charge la mise à l'échelle basée sur les métriques Prometheus, les files d'attente SQS et d'autres paramètres. Par exemple, pour adapter votre déploiement à une métrique personnalisée représentée par l'application elle-même sous forme de JSON dans /metrics, utilisez :

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
  annotations:
    # metric-config.<metricType>.<metricName>.<collectorName>/<configKey>
    metric-config.pods.requests-per-second.json-path/json-key: "$.http_server.rps"
    metric-config.pods.requests-per-second.json-path/path: /metrics
    metric-config.pods.requests-per-second.json-path/port: "9090"
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: requests-per-second
      target:
        averageValue: 1k
        type: AverageValue

La configuration de la mise à l'échelle automatique horizontale avec HPA devrait être l'une des actions par défaut pour améliorer l'efficacité des services sans état. Spotify a une présentation avec son expérience et ses recommandations pour HPA : faites évoluer vos déploiements, pas votre portefeuille.

Réduire la surréservation des ressources

Les charges de travail Kubernetes déterminent leurs besoins en CPU/mémoire via des « demandes de ressources ». Les ressources CPU sont mesurées en cœurs virtuels ou plus communément en « millicores », par exemple 500 Mo implique 50 % de vCPU. Les ressources mémoire sont mesurées en octets et des suffixes courants peuvent être utilisés, tels que 500Mi, ce qui signifie 500 mégaoctets. Les demandes de ressources « verrouillent » la capacité sur les nœuds de travail, ce qui signifie qu'un pod avec une demande de CPU de 1000 4 m sur un nœud avec 3 vCPU ne laissera que XNUMX vCPU disponibles pour les autres pods.

Slack (réserve excédentaire) est la différence entre les ressources demandées et l’utilisation réelle. Par exemple, un pod qui demande 2 Gio de mémoire mais n'en utilise que 200 Mio possède environ 1,8 Gio de mémoire « excédentaire ». L’excès coûte de l’argent. On peut estimer approximativement que 1 Gio de mémoire redondante coûte environ 10 $ par mois.

Rapport sur les ressources Kubernetes (kube-resource-report) affiche les réserves excédentaires et peut vous aider à déterminer le potentiel d'économies :

Économisez sur les coûts du cloud Kubernetes sur AWS

Rapport sur les ressources Kubernetes montre l'excédent agrégé par application et commande. Cela vous permet de trouver des endroits où les demandes en ressources peuvent être réduites. Le rapport HTML généré fournit uniquement un instantané de l'utilisation des ressources. Vous devez examiner l'utilisation du processeur/de la mémoire au fil du temps pour déterminer les demandes de ressources adéquates. Voici un graphique Grafana pour un service "typique" gourmand en CPU : tous les pods utilisent beaucoup moins que les 3 cœurs de processeur demandés :

Économisez sur les coûts du cloud Kubernetes sur AWS

La réduction de la demande de CPU de 3000 400 m à environ XNUMX m libère des ressources pour d'autres charges de travail et permet au cluster d'être plus petit.

« L'utilisation moyenne du processeur des instances EC2 oscille souvent dans une fourchette de pourcentage à un chiffre » écrit Corey Quinn. Alors que pour EC2 estimer la bonne taille peut être une mauvaise décisionModifier certaines requêtes de ressources Kubernetes dans un fichier YAML est simple et peut générer d'énormes économies.

Mais voulons-nous vraiment que les gens changent les valeurs dans les fichiers YAML ? Non, les machines peuvent faire bien mieux ! Kubernetes Autoscaler de pods verticaux (VPA) fait exactement cela : adapte les demandes et contraintes de ressources en fonction de la charge de travail. Voici un exemple de graphique des requêtes CPU Prometheus (fine ligne bleue) adaptées par VPA au fil du temps :

Économisez sur les coûts du cloud Kubernetes sur AWS

Zalando utilise le VPA dans tous ses clusters pour les composants d’infrastructure. Les applications non critiques peuvent également utiliser VPA.

boucle d'or de Fairwind est un outil qui crée un VPA pour chaque déploiement dans un espace de noms, puis affiche une recommandation VPA sur son tableau de bord. Il peut aider les développeurs à définir les demandes correctes de CPU/mémoire pour leurs applications :

Économisez sur les coûts du cloud Kubernetes sur AWS

j'ai écrit un petit article de blog sur l'APV en 2019, et récemment en La communauté des utilisateurs finaux de la CNCF a discuté du problème du VPA.

Utilisation des instances ponctuelles EC2

Enfin, les coûts d'AWS EC2 peuvent être réduits en utilisant des instances Spot comme nœuds de travail Kubernetes. . Les instances Spot sont disponibles avec une remise allant jusqu'à 90 % par rapport aux prix à la demande. Exécuter Kubernetes sur EC2 Spot est une bonne combinaison : vous devez spécifier plusieurs types d'instances différents pour une plus grande disponibilité, ce qui signifie que vous pouvez obtenir un nœud plus grand pour le même prix ou moins, et que la capacité accrue peut être utilisée par les charges de travail Kubernetes conteneurisées.

Comment exécuter Kubernetes sur EC2 Spot ? Il existe plusieurs options : utiliser un service tiers comme SpotInst (maintenant appelé "Spot", ne me demandez pas pourquoi), ou simplement ajouter un Spot AutoScalingGroup (ASG) à votre cluster. Par exemple, voici un extrait CloudFormation pour un Spot ASG « à capacité optimisée » avec plusieurs types d'instances :

MySpotAutoScalingGroup:
 Properties:
   HealthCheckGracePeriod: 300
   HealthCheckType: EC2
   MixedInstancesPolicy:
     InstancesDistribution:
       OnDemandPercentageAboveBaseCapacity: 0
       SpotAllocationStrategy: capacity-optimized
     LaunchTemplate:
       LaunchTemplateSpecification:
         LaunchTemplateId: !Ref LaunchTemplate
         Version: !GetAtt LaunchTemplate.LatestVersionNumber
       Overrides:
         - InstanceType: "m4.2xlarge"
         - InstanceType: "m4.4xlarge"
         - InstanceType: "m5.2xlarge"
         - InstanceType: "m5.4xlarge"
         - InstanceType: "r4.2xlarge"
         - InstanceType: "r4.4xlarge"
   LaunchTemplate:
     LaunchTemplateId: !Ref LaunchTemplate
     Version: !GetAtt LaunchTemplate.LatestVersionNumber
   MinSize: 0
   MaxSize: 100
   Tags:
   - Key: k8s.io/cluster-autoscaler/node-template/label/aws.amazon.com/spot
     PropagateAtLaunch: true
     Value: "true"

Quelques remarques sur l'utilisation de Spot avec Kubernetes :

  • Vous devez gérer les terminaisons Spot, par exemple en fusionnant le nœud lorsque l'instance est arrêtée
  • Zalando utilise fourchette mise à l'échelle automatique officielle du cluster avec les priorités du pool de nœuds
  • Nœuds de repérage peut être forcé accepter les « enregistrements » des charges de travail à exécuter dans Spot

Résumé

J'espère que vous trouverez certains des outils présentés utiles pour réduire votre facture cloud. Vous pouvez également trouver la plupart du contenu de l'article sur mon discours au DevOps Gathering 2019 sur YouTube et dans les diapositives.

Quelles sont vos bonnes pratiques pour économiser les coûts du cloud sur Kubernetes ? S'il vous plaît laissez-moi savoir à Twitter (@try_sauf_).

En fait, moins de 3 vCPU resteront utilisables car le débit du nœud est réduit par les ressources système réservées. Kubernetes fait la distinction entre la capacité du nœud physique et les ressources « provisionnées » (Nœud attribuable).

Exemple de calcul : une instance m5.large avec 8 Gio de mémoire coûte environ 84 $ par mois (eu-central-1, On-Demand), soit le blocage de 1/8 de nœud coûte environ ~ 10 $/mois.

Il existe de nombreuses autres façons de réduire votre facture EC2, telles que les instances réservées, le plan d'épargne, etc. - Je n'aborderai pas ces sujets ici, mais vous devriez absolument les examiner !

En savoir plus sur le cours.

Source: habr.com

Ajouter un commentaire