Spar på Kubernetes skykostnader på AWS

Oversettelsen av artikkelen ble utarbeidet like før kursstart "Infrastrukturplattform basert på Kubernetes".

Spar på Kubernetes skykostnader på AWS

Hvordan spare skykostnader når du jobber med Kubernetes? Det er ingen enkelt riktig løsning, men denne artikkelen beskriver flere verktøy som kan hjelpe deg med å administrere ressursene dine mer effektivt og redusere kostnadene for skydatabehandling.

Jeg skrev denne artikkelen med Kubernetes for AWS i tankene, men den vil gjelde (nesten) nøyaktig på samme måte for andre skyleverandører. Jeg antar at klyngene dine allerede har konfigurert automatisk skalering (cluster-autoscaler). Fjerning av ressurser og nedskalering av distribusjonen vil bare spare deg for penger hvis det også reduserer flåten av arbeidernoder (EC2-forekomster).

Denne artikkelen vil dekke:

Rydde opp i ubrukte ressurser

Å jobbe i et hektisk miljø er flott. Vi vil ha teknologiske organisasjoner akselerert. Raskere programvarelevering betyr også flere PR-distribusjoner, forhåndsvisningsmiljøer, prototyper og analyseløsninger. Alt er distribuert på Kubernetes. Hvem har tid til å rydde opp i testdistribusjoner manuelt? Det er lett å glemme å slette et ukegammelt eksperiment. Skyregningen vil ende opp på grunn av noe vi glemte å stenge:

Spar på Kubernetes skykostnader på AWS

(Henning Jacobs:
Zhiza:
(sitater) Corey Quinn:
Myte: AWS-kontoen din er en funksjon av antall brukere du har.
Fakta: Din AWS-poengsum er en funksjon av antall ingeniører du har.

Ivan Kurnosov (som svar):
Virkelig faktum: AWS-poengsummen din er en funksjon av antall ting du har glemt å deaktivere/slette.)

Kubernetes vaktmester (kube-janitor) hjelper til med å rydde opp i klyngen din. Vaktmesterkonfigurasjonen er fleksibel for både global og lokal bruk:

  • Regler for hele klyngen kan definere maksimal tid til å leve (TTL) for PR/test-distribusjoner.
  • Individuelle ressurser kan merkes med vaktmester/ttl, for eksempel for å automatisk fjerne piggen/prototypen etter 7 dager.

Generelle regler er definert i YAML-filen. Banen går gjennom parameteren --rules-file i kube-vaktmester. Her er en eksempelregel for å fjerne alle navneområder med -pr- i navnet etter to dager:

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

Følgende eksempel regulerer bruken av applikasjonsetiketten på Deployment- og StatefulSet-podene for alle nye Deployments/StatefulSets i 2020, men tillater samtidig utføring av tester uten denne etiketten i en uke:

- 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

Kjør en tidsbegrenset demo i 30 minutter på en klynge som kjører kube-janitor:

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

En annen kilde til økende kostnader er vedvarende volumer (AWS EBS). Sletting av et Kubernetes StatefulSet sletter ikke dets vedvarende volumer (PVC - PersistentVolumeClaim). Ubrukte EBS-volumer kan lett resultere i kostnader på hundrevis av dollar per måned. Kubernetes Janitor har en funksjon for å rydde opp i ubrukte PVC-er. For eksempel vil denne regelen fjerne alle PVC-er som ikke er montert av en modul og som ikke er referert til av et StatefulSet eller CronJob:

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

Kubernetes Janitor kan hjelpe deg med å holde klyngen din ren og forhindre at kostnader for nettsky-databehandling langsomt hoper seg opp. Følg instruksjoner for distribusjon og konfigurasjon README kube-vaktmester.

Reduser skalering i ikke-arbeidstid

Test- og iscenesettelsessystemer er vanligvis pålagt å fungere bare i arbeidstiden. Noen produksjonsapplikasjoner, for eksempel backoffice/admin-verktøy, krever også bare begrenset tilgjengelighet og kan bli deaktivert over natten.

Kubernetes Downscaler (kube-downscaler) lar brukere og operatører skalere ned systemet i ikke-arbeidstid. Utrullinger og StatefulSets kan skaleres til null replikaer. CronJobs kan bli suspendert. Kubernetes Downscaler er konfigurert for en hel klynge, ett eller flere navneområder eller individuelle ressurser. Du kan stille inn enten "tomgang" eller omvendt "arbeidstid". For eksempel for å redusere skalering så mye som mulig i løpet av netter og helger:

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

Her er en graf for skalering av klyngearbeidernoder i helgene:

Spar på Kubernetes skykostnader på AWS

Nedskalering fra ~13 til 4 arbeidernoder gjør absolutt en merkbar forskjell i AWS-regningen din.

Men hva om jeg trenger å jobbe under "nedetid" i klyngen? Enkelte distribusjoner kan ekskluderes permanent fra skalering ved å legge til nedskalering/ekskluder: sann annotering. Implementeringer kan midlertidig ekskluderes ved å bruke nedskalering/ekskluder-inntil-kommentaren med et absolutt tidsstempel i formatet ÅÅÅÅ-MM-DD TT:MM (UTC). Om nødvendig kan hele klyngen skaleres tilbake ved å distribuere en pod med merknaden downscaler/force-uptime, for eksempel ved å starte 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

se README kube-downscaler, hvis du er interessert i distribusjonsinstruksjoner og tilleggsalternativer.

Bruk horisontal autoskalering

Mange applikasjoner/tjenester håndterer et dynamisk lastemønster: noen ganger er modulene deres inaktive, og noen ganger fungerer de med full kapasitet. Å drive en permanent flåte av pods for å takle maksimal toppbelastning er ikke økonomisk. Kubernetes støtter horisontal automatisk skalering på tvers av en ressurs HorizontalPodAutoscaler (HPA). CPU-bruk er ofte en god indikator for skalering:

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 har laget en komponent for enkelt å koble til egendefinerte beregninger for skalering: Kube Metrics Adapter (kube-metrics-adapter) er en generisk metrikkadapter for Kubernetes som kan samle inn og betjene tilpassede og eksterne beregninger for horisontal autoskalering av pods. Den støtter skalering basert på Prometheus-målinger, SQS-køer og andre innstillinger. For å skalere distribusjonen til en egendefinert beregning representert av selve applikasjonen som JSON i /metrics, bruk for eksempel:

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

Konfigurering av horisontal autoskalering med HPA bør være en av standardhandlingene for å forbedre effektiviteten for statsløse tjenester. Spotify har en presentasjon med deres erfaringer og anbefalinger for HPA: skaler distribusjonene dine, ikke lommeboken.

Reduser ressursoverbooking

Kubernetes-arbeidsbelastninger bestemmer deres CPU-/minnebehov gjennom «ressursforespørsler». CPU-ressurser måles i virtuelle kjerner eller mer vanlig i "millicores", for eksempel innebærer 500m 50 % vCPU. Minneressurser måles i byte, og vanlige suffikser kan brukes, for eksempel 500Mi, som betyr 500 megabyte. Ressurs forespørsler om å "låse" kapasitet på arbeidernoder, noe som betyr at en pod med en 1000m CPU-forespørsel på en node med 4 vCPUer vil la bare 3 vCPUer være tilgjengelige for andre pods. [1]

Slakk (overflødig reserve) er forskjellen mellom forespurte ressurser og faktisk bruk. For eksempel, en pod som ber om 2 GiB minne, men bare bruker 200 MiB, har ~1,8 GiB "overflødig" minne. Overskudd koster penger. Man kan grovt anslå at 1 GiB redundant minne koster ~$10 per måned. [2]

Kubernetes ressursrapport (kube-resource-report) viser overskuddsreserver og kan hjelpe deg med å bestemme sparepotensialet:

Spar på Kubernetes skykostnader på AWS

Kubernetes ressursrapport viser overskuddet aggregert etter applikasjon og kommando. Dette lar deg finne steder hvor ressursbehovet kan reduseres. Den genererte HTML-rapporten gir bare et øyeblikksbilde av ressursbruken. Du bør se på CPU/minnebruk over tid for å finne tilstrekkelige ressursforespørsler. Her er et Grafana-diagram for en "typisk" CPU-tung tjeneste: alle pods bruker betydelig mindre enn de tre forespurte CPU-kjernene:

Spar på Kubernetes skykostnader på AWS

Å redusere CPU-forespørselen fra 3000m til ~400m frigjør ressurser for andre arbeidsbelastninger og gjør at klyngen blir mindre.

"Gjennomsnittlig CPU-bruk av EC2-forekomster svever ofte i det ensifrede prosentområdet," skriver Corey Quinn. Mens for EC2 å estimere riktig størrelse kan være en dårlig avgjørelseDet er enkelt å endre noen Kubernetes-ressursspørringer i en YAML-fil og kan gi store besparelser.

Men vil vi virkelig at folk skal endre verdier i YAML-filer? Nei, maskiner kan gjøre det mye bedre! Kubernetes Vertical Pod Autoscaler (VPA) gjør nettopp det: tilpasser ressursforespørsler og begrensninger i henhold til arbeidsmengden. Her er en eksempelgraf over Prometheus CPU-forespørsler (tynn blå linje) tilpasset av VPA over tid:

Spar på Kubernetes skykostnader på AWS

Zalando bruker VPA i alle sine klynger for infrastrukturkomponenter. Ikke-kritiske applikasjoner kan også bruke VPA.

Goldilocks fra Fairwind er et verktøy som oppretter en VPA for hver distribusjon i et navneområde og deretter viser en VPA-anbefaling på dashbordet. Det kan hjelpe utviklere med å angi de riktige CPU-/minneforespørslene for applikasjonene deres:

Spar på Kubernetes skykostnader på AWS

Jeg skrev en liten blogginnlegg om VPA i 2019, og nylig i CNCF-sluttbrukerfellesskapet diskuterte VPA-problemet.

Bruke EC2 Spot-forekomster

Sist men ikke minst kan AWS EC2-kostnadene reduseres ved å bruke Spot-instanser som Kubernetes-arbeidernoder [3]. Spot-forekomster er tilgjengelig med en rabatt på opptil 90 % sammenlignet med On-Demand-priser. Å kjøre Kubernetes på EC2 Spot er en god kombinasjon: du må spesifisere flere forskjellige instanstyper for høyere tilgjengelighet, noe som betyr at du kan få en større node for samme eller lavere pris, og den økte kapasiteten kan brukes av containeriserte Kubernetes-arbeidsbelastninger.

Hvordan kjører jeg Kubernetes på EC2 Spot? Det er flere alternativer: bruk en tredjepartstjeneste som SpotInst (nå kalt "Spot", ikke spør meg hvorfor), eller bare legg til en Spot AutoScalingGroup (ASG) til klyngen din. For eksempel, her er en CloudFormation-kodebit for en "kapasitetsoptimalisert" Spot ASG med flere forekomsttyper:

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"

Noen merknader om bruk av Spot med Kubernetes:

  • Du må håndtere Spot-avslutninger, for eksempel ved å slå sammen noden når instansen stoppes
  • Zalando bruker gaffel offisiell klyngeautoskalering med nodepoolprioriteter
  • Spot noder kan tvinges godta "registreringer" av arbeidsbelastninger som skal kjøres i Spot

Oppsummering

Jeg håper du finner noen av verktøyene som presenteres nyttige for å redusere skyregningen din. Du finner det meste av artikkelens innhold også på foredraget mitt på DevOps Gathering 2019 på YouTube og i lysbilder.

Hva er dine beste fremgangsmåter for å spare skykostnader på Kubernetes? Gi meg beskjed kl Twitter (@try_except_).

[1] Faktisk vil mindre enn 3 vCPUer forbli brukbare ettersom nodens gjennomstrømning reduseres av reserverte systemressurser. Kubernetes skiller mellom fysisk nodekapasitet og "forsynte" ressurser (Node allokerbar).

[2] Regneeksempel: én m5.stor instans med 8 GiB minne er ~$84 ​​per måned (eu-central-1, On-Demand), dvs. blokkering av 1/8 node er omtrent ~$10/måned.

[3] Det er mange flere måter å redusere EC2-regningen på, for eksempel reserverte forekomster, spareplan osv. - Jeg vil ikke dekke disse emnene her, men du bør definitivt se nærmere på dem!

Lær mer om kurset.

Kilde: www.habr.com

Legg til en kommentar