Sparen Sie Kubernetes-Cloud-Kosten auf AWS

Die Übersetzung des Artikels wurde am Vorabend des Kursbeginns erstellt „Infrastrukturplattform auf Basis von Kubernetes“.

Sparen Sie Kubernetes-Cloud-Kosten auf AWS

Wie kann man bei der Arbeit mit Kubernetes Cloud-Kosten sparen? Es gibt keine einzige richtige Lösung, aber dieser Artikel beschreibt mehrere Tools, die Ihnen helfen können, Ihre Ressourcen effektiver zu verwalten und Ihre Cloud-Computing-Kosten zu senken.

Ich habe diesen Artikel mit Blick auf Kubernetes für AWS geschrieben, aber er gilt (fast) genauso für andere Cloud-Anbieter. Ich gehe davon aus, dass für Ihre Cluster bereits Autoscaling konfiguriert ist (Cluster-Autoscaler). Durch die Entfernung von Ressourcen und die Verkleinerung Ihrer Bereitstellung können Sie nur dann Geld sparen, wenn dadurch auch Ihre Flotte an Worker-Knoten (EC2-Instanzen) reduziert wird.

Dieser Artikel behandelt:

  • Aufräumen ungenutzter Ressourcen (Kube-Hausmeister)
  • Reduzieren Sie die Skalierung während der arbeitsfreien Zeit (Kube-Downscaler)
  • mit horizontaler automatischer Skalierung (HPA),
  • Reduzierung übermäßiger Ressourcenreservierung (Kube-Ressourcenbericht, VPA)
  • Verwendung von Spot-Instanzen

Aufräumen ungenutzter Ressourcen

Es ist großartig, in einem schnelllebigen Umfeld zu arbeiten. Wir wollen Technologieorganisationen beschleunigt. Eine schnellere Softwarebereitstellung bedeutet auch mehr PR-Bereitstellungen, Vorschauumgebungen, Prototypen und Analyselösungen. Alles wird auf Kubernetes bereitgestellt. Wer hat die Zeit, Testbereitstellungen manuell zu bereinigen? Es kann leicht passieren, dass man vergisst, ein einwöchiges Experiment zu löschen. Die Cloud-Rechnung wird am Ende steigen, weil wir vergessen haben, sie abzuschließen:

Sparen Sie Kubernetes-Cloud-Kosten auf AWS

(Henning Jacobs:
Zhiza:
(Zitate) Corey Quinn:
Mythos: Ihr AWS-Konto hängt von der Anzahl Ihrer Benutzer ab.
Tatsache: Ihr AWS-Score ist eine Funktion der Anzahl Ihrer Ingenieure.

Ivan Kurnosov (als Antwort):
Echte Tatsache: Ihr AWS-Score ist eine Funktion der Anzahl der Dinge, die Sie vergessen haben zu deaktivieren/löschen.)

Kubernetes-Hausmeister (kube-janitor) hilft beim Aufräumen Ihres Clusters. Die Janitor-Konfiguration ist flexibel für den globalen und lokalen Einsatz:

  • Clusterweite Regeln können die maximale Lebensdauer (TTL) für PR-/Testbereitstellungen definieren.
  • Einzelne Ressourcen können mit janitor/ttl annotiert werden, um beispielsweise den Spike/Prototyp nach 7 Tagen automatisch zu entfernen.

Allgemeine Regeln sind in der YAML-Datei definiert. Sein Pfad wird durch den Parameter übergeben --rules-file in Kube-Hausmeister. Hier ist eine Beispielregel zum Entfernen aller Namespaces -pr- im Namen nach zwei Tagen:

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

Das folgende Beispiel regelt die Verwendung des Anwendungslabels auf den Deployment- und StatefulSet-Pods für alle neuen Deployments/StatefulSets im Jahr 2020, ermöglicht aber gleichzeitig die Durchführung von Tests ohne dieses Label für eine Woche:

- 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

Führen Sie eine zeitlich begrenzte Demo für 30 Minuten auf einem Cluster aus, auf dem kube-janitor ausgeführt wird:

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

Eine weitere Quelle steigender Kosten sind persistente Volumina (AWS EBS). Durch das Löschen eines Kubernetes StatefulSet werden seine persistenten Volumes (PVC – PersistentVolumeClaim) nicht gelöscht. Ungenutzte EBS-Volumina können leicht zu Kosten in Höhe von Hunderten von Dollar pro Monat führen. Kubernetes Janitor verfügt über eine Funktion zum Bereinigen nicht verwendeter PVCs. Diese Regel entfernt beispielsweise alle PVCs, die nicht von einem Modul gemountet sind und auf die nicht von einem StatefulSet oder CronJob verwiesen wird:

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

Kubernetes Janitor kann Ihnen helfen, Ihren Cluster sauber zu halten und zu verhindern, dass sich die Cloud-Computing-Kosten langsam anhäufen. Anweisungen zur Bereitstellung und Konfiguration finden Sie hier README kube-janitor.

Reduzieren Sie die Skalierung während der arbeitsfreien Zeit

Test- und Stagingsysteme sind in der Regel nur während der Geschäftszeiten für den Betrieb erforderlich. Einige Produktionsanwendungen, wie z. B. Backoffice-/Verwaltungstools, erfordern ebenfalls nur eine begrenzte Verfügbarkeit und können über Nacht deaktiviert werden.

Kubernetes-Downscaler (kube-downscaler) ermöglicht Benutzern und Betreibern, das System außerhalb der Arbeitszeiten zu verkleinern. Bereitstellungen und StatefulSets können auf null Replikate skaliert werden. CronJobs können ausgesetzt werden. Kubernetes Downscaler wird für einen gesamten Cluster, einen oder mehrere Namespaces oder einzelne Ressourcen konfiguriert. Sie können entweder „Leerlaufzeit“ oder umgekehrt „Arbeitszeit“ einstellen. Um beispielsweise die Skalierung nachts und am Wochenende so weit wie möglich zu reduzieren:

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

Hier ist ein Diagramm zur Skalierung von Cluster-Worker-Knoten an Wochenenden:

Sparen Sie Kubernetes-Cloud-Kosten auf AWS

Die Skalierung von ca. 13 auf 4 Worker-Knoten macht sicherlich einen spürbaren Unterschied in Ihrer AWS-Rechnung.

Was aber, wenn ich während der „Ausfallzeit“ des Clusters arbeiten muss? Bestimmte Bereitstellungen können dauerhaft von der Skalierung ausgeschlossen werden, indem die Annotation „downscaler/exclude: true“ hinzugefügt wird. Bereitstellungen können mithilfe der Downscaler/exclude-until-Annotation mit einem absoluten Zeitstempel im Format JJJJ-MM-TT HH:MM (UTC) vorübergehend ausgeschlossen werden. Bei Bedarf kann der gesamte Cluster verkleinert werden, indem ein Pod mit der Annotation bereitgestellt wird downscaler/force-uptime, zum Beispiel durch den Start von 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

sehen README kube-downscaler, wenn Sie an Bereitstellungsanweisungen und zusätzlichen Optionen interessiert sind.

Verwenden Sie horizontale Autoskalierung

Viele Anwendungen/Dienste unterliegen einem dynamischen Lademuster: Manchmal sind ihre Module im Leerlauf, manchmal arbeiten sie mit voller Kapazität. Der Betrieb einer permanenten Pod-Flotte zur Bewältigung der maximalen Spitzenlast ist nicht wirtschaftlich. Kubernetes unterstützt die horizontale automatische Skalierung über eine Ressource hinweg HorizontalPodAutoscaler (HPA). Die CPU-Auslastung ist oft ein guter Indikator für die Skalierung:

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 hat eine Komponente erstellt, um benutzerdefinierte Metriken für die Skalierung einfach zu verbinden: Kube-Metrik-Adapter (kube-metrics-adapter) ist ein generischer Metrikadapter für Kubernetes, der benutzerdefinierte und externe Metriken für die horizontale automatische Skalierung von Pods sammeln und bereitstellen kann. Es unterstützt die Skalierung basierend auf Prometheus-Metriken, SQS-Warteschlangen und anderen Einstellungen. Um beispielsweise Ihre Bereitstellung auf eine benutzerdefinierte Metrik zu skalieren, die von der Anwendung selbst als JSON in /metrics dargestellt wird, verwenden Sie Folgendes:

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

Die Konfiguration der horizontalen Autoskalierung mit HPA sollte eine der Standardaktionen sein, um die Effizienz zustandsloser Dienste zu verbessern. Spotify hat eine Präsentation mit ihren Erfahrungen und Empfehlungen für HPA: Skalieren Sie Ihre Bereitstellungen, nicht Ihren Geldbeutel.

Reduzieren Sie die Überbuchung von Ressourcen

Kubernetes-Workloads ermitteln ihren CPU-/Speicherbedarf durch „Ressourcenanfragen“. CPU-Ressourcen werden in virtuellen Kernen oder häufiger in „Millicores“ gemessen, zum Beispiel bedeutet 500 m 50 % vCPU. Speicherressourcen werden in Bytes gemessen und es können gängige Suffixe verwendet werden, z. B. 500Mi, was 500 Megabyte bedeutet. Ressourcenanforderungen „sperren“ die Kapazität auf Worker-Knoten, was bedeutet, dass ein Pod mit einer 1000-m-CPU-Anfrage auf einem Knoten mit 4 vCPUs nur 3 vCPUs für andere Pods verfügbar lässt. [1]

Slack (Überschussreserve) ist die Differenz zwischen angeforderten Ressourcen und tatsächlicher Nutzung. Beispielsweise verfügt ein Pod, der 2 GiB Speicher anfordert, aber nur 200 MiB nutzt, über etwa 1,8 GiB „überschüssigen“ Speicher. Überschüsse kosten Geld. Man kann grob schätzen, dass 1 GiB redundanter Speicher etwa 10 US-Dollar pro Monat kostet. [2]

Kubernetes-Ressourcenbericht (kube-resource-report) zeigt überschüssige Reserven an und kann Ihnen dabei helfen, Einsparpotenziale zu ermitteln:

Sparen Sie Kubernetes-Cloud-Kosten auf AWS

Kubernetes-Ressourcenbericht zeigt den nach Anwendung und Befehl aggregierten Überschuss an. Dadurch können Sie Orte finden, an denen der Ressourcenbedarf reduziert werden kann. Der generierte HTML-Bericht bietet lediglich eine Momentaufnahme der Ressourcennutzung. Sie sollten die CPU-/Speicherauslastung im Laufe der Zeit betrachten, um angemessene Ressourcenanforderungen zu ermitteln. Hier ist ein Grafana-Diagramm für einen „typischen“ CPU-lastigen Dienst: Alle Pods verbrauchen deutlich weniger als die drei angeforderten CPU-Kerne:

Sparen Sie Kubernetes-Cloud-Kosten auf AWS

Durch die Reduzierung der CPU-Anforderung von 3000 m auf ~400 m werden Ressourcen für andere Arbeitslasten frei und der Cluster kann kleiner werden.

„Die durchschnittliche CPU-Auslastung von EC2-Instanzen bewegt sich oft im einstelligen Prozentbereich.“ schreibt Corey Quinn. Während für EC2 Die Schätzung der richtigen Größe kann eine schlechte Entscheidung seinDas Ändern einiger Kubernetes-Ressourcenabfragen in einer YAML-Datei ist einfach und kann enorme Einsparungen bringen.

Aber wollen wir wirklich, dass Leute Werte in YAML-Dateien ändern? Nein, Maschinen können das viel besser! Kubernetes Vertikaler Pod-Autoscaler (VPA) macht genau das: Passt Ressourcenanforderungen und -beschränkungen entsprechend der Arbeitslast an. Hier ist ein Beispieldiagramm der Prometheus-CPU-Anfragen (dünne blaue Linie), die von VPA im Laufe der Zeit angepasst wurden:

Sparen Sie Kubernetes-Cloud-Kosten auf AWS

Zalando nutzt VPA in allen seinen Clustern für Infrastrukturkomponenten. Auch unkritische Anwendungen können VPA nutzen.

Goldlöckchen von Fairwind ist ein Tool, das für jede Bereitstellung in einem Namespace eine VPA erstellt und dann eine VPA-Empfehlung auf seinem Dashboard anzeigt. Es kann Entwicklern dabei helfen, die richtigen CPU-/Speicheranforderungen für ihre Anwendungen festzulegen:

Sparen Sie Kubernetes-Cloud-Kosten auf AWS

Ich habe ein kleines geschrieben Blogbeitrag über VPA im Jahr 2019 und kürzlich in Die CNCF-Endbenutzer-Community diskutierte das VPA-Problem.

Verwendung von EC2-Spot-Instances

Nicht zuletzt können die AWS EC2-Kosten durch die Verwendung von Spot-Instanzen als Kubernetes-Worker-Knoten gesenkt werden [3]. Spot-Instanzen sind mit einem Rabatt von bis zu 90 % im Vergleich zu On-Demand-Preisen erhältlich. Das Ausführen von Kubernetes auf EC2 Spot ist eine gute Kombination: Sie müssen mehrere verschiedene Instanztypen für eine höhere Verfügbarkeit angeben, was bedeutet, dass Sie einen größeren Knoten zum gleichen oder einem niedrigeren Preis erhalten und die erhöhte Kapazität von containerisierten Kubernetes-Workloads genutzt werden kann.

Wie führe ich Kubernetes auf EC2 Spot aus? Es gibt mehrere Möglichkeiten: Verwenden Sie einen Drittanbieterdienst wie SpotInst (jetzt „Spot“ genannt, fragen Sie mich nicht warum) oder fügen Sie einfach eine Spot AutoScalingGroup (ASG) zu Ihrem Cluster hinzu. Hier ist beispielsweise ein CloudFormation-Snippet für eine „kapazitätsoptimierte“ Spot-ASG mit mehreren Instanztypen:

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"

Einige Hinweise zur Verwendung von Spot mit Kubernetes:

  • Sie müssen Spot-Beendigungen handhaben, indem Sie beispielsweise den Knoten zusammenführen, wenn die Instanz gestoppt wird
  • Zalando nutzt Gabel Offizielle Cluster-Autoskalierung mit Knotenpoolprioritäten
  • Erkennen Sie Knoten kann erzwungen werden Akzeptieren Sie „Registrierungen“ von Workloads zur Ausführung in Spot

Zusammenfassung

Ich hoffe, dass Sie einige der vorgestellten Tools hilfreich finden, um Ihre Cloud-Rechnung zu senken. Die meisten Inhalte des Artikels finden Sie auch unter mein Vortrag beim DevOps Gathering 2019 auf YouTube und in Folien.

Was sind Ihre Best Practices, um Cloud-Kosten auf Kubernetes zu sparen? Bitte lassen Sie es mich wissen unter Twitter (@try_exclusive_).

[1] Tatsächlich bleiben weniger als 3 vCPUs nutzbar, da der Durchsatz des Knotens durch reservierte Systemressourcen verringert wird. Kubernetes unterscheidet zwischen physischer Knotenkapazität und „bereitgestellten“ Ressourcen (Knoten zuweisbar).

[2] Berechnungsbeispiel: Eine m5.large-Instanz mit 8 GiB Speicher kostet ~84 $ pro Monat (eu-central-1, On-Demand), d. h. Das Blockieren von 1/8 Knoten kostet ungefähr 10 $/Monat.

[3] Es gibt viele weitere Möglichkeiten, Ihre EC2-Rechnung zu reduzieren, wie z. B. Reserved Instances, Savings Plan usw. – ich werde diese Themen hier nicht behandeln, aber Sie sollten sich auf jeden Fall damit befassen!

Erfahren Sie mehr über den Kurs.

Source: habr.com

Kommentar hinzufügen