Sparen Sie bei AWS Kubernetes Cloud-Kosten

Eine Übersetzung des Artikels wurde vor dem Start des Kubernetes-basierten Infrastructure Platform- Kurses vorbereitet .








Wie kann ich bei der Arbeit mit Kubernetes Cloud-Kosten sparen? Es gibt keine einheitliche richtige Lösung, aber dieser Artikel enthält verschiedene Tools, mit denen Sie Ressourcen effizienter verwalten und Cloud-Computing-Kosten senken können.



Ich habe diesen Artikel mit Blick auf Kubernetes für AWS geschrieben, aber er wird (fast) genauso für andere Cloud-Anbieter gelten. Ich gehe davon aus, dass für Ihre Cluster bereits eine automatische Skalierung ( Cluster-Autoscaler ) konfiguriert ist . Durch das Entfernen von Ressourcen und das Verringern Ihrer Bereitstellung werden Sie nur dann gerettet, wenn dadurch auch Ihre Flotte von Arbeitsknoten (EC2-Instanzen) reduziert wird.



Dieser Artikel behandelt:





Nicht verwendete Ressourcen bereinigen



In einer schnelllebigen Umgebung zu arbeiten ist großartig. Wir wollen, dass sich technische Organisationen beschleunigen . Eine schnellere Softwarebereitstellung bedeutet auch mehr PR-Bereitstellungen, Vorschauumgebungen, Prototypen und Analyselösungen. Alles auf Kubernetes bereitgestellt. Wer hat Zeit, Testbereitstellungen manuell zu bereinigen? Es ist leicht zu vergessen, ein einwöchiges Experiment zu löschen. Die Cloud-Rechnung wird irgendwann wachsen, weil wir vergessen haben, zu schließen:










(Henning Jacobs:

Leben:

(zitiert) Corey Quinn:

Mythos: Ihr AWS-Konto ist eine Funktion der Anzahl Ihrer Benutzer.

Fakt: Ihr AWS-Konto ist eine Funktion der Anzahl Ihrer Ingenieure.



Ivan Kurnosov (als Antwort):

Wirkliche Tatsache: Ihr AWS-Konto ist eine Funktion, die von der Anzahl der Dinge abhängt, die Sie vergessen haben, zu deaktivieren / löschen.)





Kubernetes Janitor (kube-janitor) hilft beim Aufräumen Ihres Clusters. Die Hausmeisterkonfiguration ist sowohl für den globalen als auch für den lokalen Gebrauch flexibel:



  • Allgemeine Regeln für den gesamten Cluster können die maximale Lebensdauer (Time-to-Live, TTL) für PR- / Testbereitstellungen definieren.
  • Einzelne Ressourcen können beispielsweise mit janitor / ttl kommentiert werden, um Spikes / Prototypen nach 7 Tagen automatisch zu entfernen.


Allgemeine Regeln sind in der YAML-Datei definiert. Sein Pfad wird über den Parameter --rules-filean kube-janitor übergeben. Hier ist ein Beispiel für eine Regel, nach der alle Namespaces -pr-in einem Namen nach zwei Tagen entfernt werden:



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


Das folgende Beispiel regelt die Verwendung des Anwendungsetiketts auf den Pods Deployment und StatefulSet für alle neuen Deployments / StatefulSet im Jahr 2020, ermöglicht jedoch gleichzeitig die einwöchige Ausführung von Tests ohne dieses Etikett:



- 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


Ausführen einer zeitlich begrenzten Demo für 30 Minuten in dem Cluster, in dem kube-janitor ausgeführt wird:



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


Eine weitere Quelle für steigende Kosten sind persistente Volumina (AWS EBS). Durch das Löschen eines Kubernetes StatefulSet werden seine persistenten Volumes (PVCs - PersistentVolumeClaim) nicht gelöscht. Nicht genutzte 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 Reinigen nicht verwendeter PVCs. Mit dieser Regel werden beispielsweise alle PVCs entfernt, die nicht vom Pod montiert sind und von StatefulSet oder CronJob nicht referenziert werden:



#   PVC,         StatefulSets
- id: remove-unused-pvcs
  resources:
  - persistentvolumeclaims
  jmespath: "_context.pvc_is_not_mounted && _context.pvc_is_not_referenced"
  ttl: 24h


Mit Kubernetes Janitor können Sie Ihren Cluster sauber halten und die langsam wachsenden Kosten für Cloud Computing vermeiden. Anweisungen zur Bereitstellung und Konfiguration finden Sie in der README-Datei von kube-janitor .



Reduzierung der Skalierung außerhalb der Geschäftszeiten



Test- und Staging-Systeme müssen normalerweise nur während der Geschäftszeiten betrieben werden. Einige Produktionsanwendungen, wie z. B. Backoffice- / Verwaltungstools, erfordern ebenfalls nur eine begrenzte Verfügbarkeit und können nachts ausgeschaltet werden.



Mit Kubernetes Downscaler (kube-downscaler) können Benutzer und Bediener das System außerhalb der Geschäftszeiten verkleinern. Bereitstellungen und StatefulSets können auf null Replikate skaliert werden. CronJobs können ausgesetzt werden. Kubernetes Downscaler ist für den gesamten Cluster, einen oder mehrere Namespaces oder einzelne Ressourcen konfiguriert. Sie können entweder die Leerlaufzeit oder die Betriebszeit einstellen. Zum Beispiel, um die Skalierung während der Nacht und am Wochenende zu minimieren:



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 der Cluster-Worker-Knoten über das Wochenende: Die







Verkleinerung von ~ 13 auf 4 Worker-Knoten macht auf der AWS-Rechnung sicherlich einen erheblichen Unterschied.



Was aber, wenn ich während der „Ausfallzeit“ des Clusters arbeiten muss? Bestimmte Bereitstellungen können dauerhaft von der Skalierung ausgeschlossen werden, indem der Annotation Downscaler / exclude: true hinzugefügt wird. Bereitstellungen können mithilfe der Annotation "Downscaler / Ausschluss bis" mit einem absoluten Zeitstempel im Format JJJJ-MM-TT HH: MM (UTC) vorübergehend ausgeschlossen werden. Bei Bedarf kann der gesamte Cluster durch Bereitstellen eines mit Anmerkungen versehenen Pods verkleinert werden downscaler/force-uptime, z. B. durch Ausführen von nginx dummy:



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


Weitere Informationen finden Sie unter README kube-downscaler, wenn Sie an Bereitstellungsanweisungen und zusätzlichen Optionen interessiert sind.



Verwenden Sie die horizontale automatische Skalierung



Viele Anwendungen / Dienste arbeiten mit einem dynamischen Ladeschema: Manchmal sind ihre Module inaktiv und manchmal werden sie mit voller Kapazität ausgeführt. Es ist nicht wirtschaftlich, mit einer konstanten Flotte von Herden zu arbeiten, um die maximale Spitzenlast zu bewältigen. Kubernetes unterstützt die horizontale automatische Skalierung über die HorizontalPodAutoscaler (HPA) -Ressource . Die CPU-Auslastung ist häufig eine gute Messgröße 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, mit der benutzerdefinierte Metriken für die Skalierung einfach verbunden werden können: Der Kube Metrics Adapter (Kube-Metrics-Adapter) ist ein universeller Metrikadapter für Kubernetes, mit dem benutzerdefinierte und externe Metriken für die horizontale automatische Skalierung von Pods erfasst und bereitgestellt werden können. Es unterstützt die Skalierung basierend auf Prometheus-Metriken, SQS-Warteschlangen und anderen Anpassungen. Verwenden Sie beispielsweise Folgendes, um Ihre Bereitstellung für eine benutzerdefinierte Metrik zu skalieren, die von der Anwendung selbst als JSON in /metrics dargestellt wird.



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


Das Einrichten der horizontalen automatischen Skalierung mit HPA sollte eine der Standardaktionen sein, um die Leistung für zustandslose Dienste zu verbessern. Spotify bietet eine Präsentation mit ihren Erfahrungen und Best Practices für HPA: Skalieren Sie Ihre Bereitstellungen und nicht Ihre Brieftasche .



Reduzierte redundante Ressourcenreservierung



Kubernetes-Workloads bestimmen ihren CPU- / Speicherbedarf durch "Ressourcenanforderungen". CPU-Ressourcen werden in virtuellen Kernen oder häufiger in "Millicores" gemessen. 500 m bedeuten beispielsweise 50% vCPU. Speicherressourcen werden in Bytes gemessen, und Sie können die üblichen Suffixe verwenden, z. B. 500Mi, dh 500 Megabyte. Ressourcenanforderungen "sperren" die Kapazität auf Arbeitsknoten, dh ein Modul mit einer CPU-Anforderung von 1000 m auf einem Knoten mit 4 vCPUs lässt nur 3 vCPUs für andere Module verfügbar. [1]



Durchhang (überschüssige Reserve)- Dies ist der Unterschied zwischen den angeforderten Ressourcen und der tatsächlichen Verwendung. Zum Beispiel hat ein Pod, der 2 GiB Speicher anfordert, aber nur 200 MiB verwendet, ~ 1,8 GiB "überschüssigen" Speicher. Überschuss kostet Geld. Es kann grob geschätzt werden, dass 1 GiB überschüssiger Speicher ~ 10 USD pro Monat kostet. [2] Der



Kubernetes-Ressourcenbericht (kube-resource-report) zeigt überschüssige Reserven an und kann Ihnen bei der Ermittlung potenzieller Einsparungen helfen:







Kubernetes Resource Reportzeigt einen Überschuss, der nach Anwendung und Team aggregiert ist. Auf diese Weise können Sie Orte finden, an denen der Ressourcenbedarf reduziert werden kann. Der generierte HTML-Bericht bietet nur eine Momentaufnahme der Ressourcennutzung. Sie sollten sich die CPU- / Speicherauslastung im Laufe der Zeit ansehen, um geeignete Ressourcenanforderungen zu ermitteln. Hier ist ein Grafana-Diagramm für einen "typischen" Dienst mit hoher CPU-Auslastung: Alle Pods verwenden deutlich weniger als 3 angeforderte CPU-Kerne: Durch







Reduzieren der CPU-Anforderung von 3000 m auf ~ 400 m werden Ressourcen für andere Workloads frei und der Cluster kann verkleinert werden.



„Die durchschnittliche CPU-Auslastung von EC2-Instanzen schwankt häufig im einstelligen Prozentbereich“, schreibt Corey Quinn . Während für EC2 die Schätzung der richtigen Größe eine schlechte Entscheidung sein kannDas Ändern einiger Kubernetes-Ressourcenanforderungen in einer YAML-Datei ist einfach und kann enorme Einsparungen bringen.



Aber wollen wir wirklich, dass Leute Werte in YAML-Dateien ändern? Nein, Autos können es viel besser! Kubernetes Vertical Pod Autoscaler (VPA) macht genau das: Passt Ressourcenanforderungen und Einschränkungen an die Arbeitslast an. Hier ist ein Beispiel für ein Prometheus-CPU-Abfragediagramm (dünne blaue Linie), das von VPA im Laufe der Zeit angepasst wurde:







Zalando verwendet VPA in allen seinen Clustern für Infrastrukturkomponenten. Nicht kritische Anwendungen können auch VPA verwenden.



Goldlöckchenby Fairwind ist ein Tool, das für jede Bereitstellung in einem Namespace einen VPA erstellt und dann die VPA-Empfehlung in seinem Dashboard anzeigt. Es kann Entwicklern helfen, die richtigen Prozessor- / Speicheranforderungen für ihre Anwendungen zu ermitteln:







Ich habe 2019 einen kleinen Blog-Beitrag über VPA geschrieben , und VPA wurde kürzlich in der CNCF-Endbenutzer-Community diskutiert .



Verwenden von EC2-Spotinstanzen



Last but not least können die AWS EC2-Kosten durch die Verwendung von Spot-Instanzen als Kubernetes-Arbeitsknoten gesenkt werden [3] . Spot-Instanzen sind bei Bedarf mit bis zu 90% Rabatt auf die Preise erhältlich. Das Ausführen von Kubernetes unter EC2 Spot ist eine gute Kombination: Sie müssen mehrere verschiedene Instanztypen angeben, um eine höhere Verfügbarkeit zu erzielen. Dies bedeutet, dass Sie einen größeren Knoten zum gleichen oder niedrigeren Preis erhalten können und die erhöhte Kapazität von containerisierten Kubernetes-Workloads verwendet werden kann.



Wie führe ich Kubernetes auf EC2 Spot aus? Es gibt verschiedene Möglichkeiten: Verwenden Sie einen Drittanbieter-Service wie SpotInst (jetzt "Spot" genannt, fragen Sie mich nicht warum) oder fügen Sie einfach die Spot AutoScalingGroup (ASG) zu Ihrem Cluster hinzu. Hier ist beispielsweise ein CloudFormation-Snippet für ein "kapazitätsoptimiertes" 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-Vervollständigungen verarbeiten, indem Sie beispielsweise einen Knoten an einem Instanzstopp entleeren
  • Zalando gabelte die offizielle automatische Skalierung des Clusters mit den Prioritäten des Knotenpools
  • Spot-Knoten können gezwungen werden , Workload-Registrierungen zu akzeptieren, um auf Spot ausgeführt zu werden


Zusammenfassung



Ich hoffe, Sie finden einige der hier vorgestellten Tools hilfreich, um Ihre Cloud-Computing-Rechnung zu senken. Sie finden den größten Teil des Inhalts auch in meinem YouTube-Vortrag und meinen Folien zu DevOps Gathering 2019 .



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






[1] Tatsächlich bleiben weniger als 3 virtuelle CPUs verwendbar, da der Durchsatz des Knotens aufgrund reservierter Systemressourcen verringert wird. Kubernetes unterscheidet zwischen physischer Knotenkapazität und "zugewiesenen" Ressourcen ( Node Allocatable ).



[2] Berechnungsbeispiel: Eine Kopie von m5.large mit 8 GiB Speicher kostet ~ 84 USD pro Monat (eu-central-1, On-Demand), d. H. Das Blockieren mit 1/8 Knoten beträgt ungefähr 10 US-Dollar pro Monat.



[3] Es gibt noch viele weitere Möglichkeiten, Ihr EC2-Konto zu reduzieren, z. B. Reservierte Instanzen, Sparplan usw. - Ich werde diese Themen hier nicht behandeln, aber Sie sollten sich auf jeden Fall darüber informieren!






Erfahren Sie mehr über den Kurs.







All Articles