Hoe bespaar je op cloudkosten als je met Kubernetes werkt? Er bestaat niet één juiste oplossing, maar in dit artikel worden verschillende tools beschreven waarmee u uw resources effectiever kunt beheren en de kosten voor cloud computing kunt verlagen.
Ik heb dit artikel geschreven met Kubernetes voor AWS in gedachten, maar het zal (bijna) precies hetzelfde gelden voor andere cloudproviders. Ik ga ervan uit dat voor uw cluster(s) automatisch schalen al is geconfigureerd (cluster-autoscaler). Het verwijderen van resources en het terugschalen van uw implementatie bespaart u alleen geld als het ook uw vloot van werkknooppunten (EC2-instanties) verkleint.
Verminder de schaalvergroting tijdens niet-werkuren (Kube-downscaler)
met behulp van horizontale automatische schaling (HPA),
vermindering van buitensporige reserveringen van hulpbronnen (kube-resource-rapport, VPA)
met behulp van Spot-instanties
Ongebruikte bronnen opruimen
Werken in een snelle omgeving is geweldig. Wij willen technologieorganisaties versneld. Snellere softwarelevering betekent ook meer PR-implementaties, preview-omgevingen, prototypes en analyseoplossingen. Alles wordt ingezet op Kubernetes. Wie heeft de tijd om testimplementaties handmatig op te schonen? Het is gemakkelijk om het verwijderen van een experiment van een week oud te vergeten. De cloudrekening zal uiteindelijk stijgen vanwege iets dat we zijn vergeten af te sluiten:
(Henning Jacobs:
Zhiza:
(citaten) Corey Quinn:
Mythe: uw AWS-account is een functie van het aantal gebruikers dat u heeft.
Feit: uw AWS-score is een functie van het aantal engineers dat u heeft.
Ivan Koernosov (in antwoord):
Echt feit: uw AWS-score is een functie van het aantal dingen dat u bent vergeten uit te schakelen/verwijderen.)
Kubernetes-conciërge (kube-janitor) helpt bij het opschonen van uw cluster. De conciërgeconfiguratie is flexibel voor zowel mondiaal als lokaal gebruik:
Regels voor het hele cluster kunnen de maximale time-to-live (TTL) voor PR-/testimplementaties definiëren.
Individuele bronnen kunnen worden geannoteerd met conciërge/ttl, om bijvoorbeeld de piek/prototype automatisch na 7 dagen te verwijderen.
Algemene regels worden gedefinieerd in het YAML-bestand. Het pad wordt door de parameter doorgegeven --rules-file in kube-conciërge. Hier is een voorbeeldregel waarmee u alle naamruimten kunt verwijderen -pr- in de naam na twee dagen:
Het volgende voorbeeld regelt het gebruik van het applicatielabel op de Deployment- en StatefulSet-pods voor alle nieuwe Deployments/StatefulSets in 2020, maar staat tegelijkertijd de uitvoering van tests toe zonder dit label gedurende een week:
- 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
Voer een tijdelijke demo van 30 minuten uit op een cluster waarop kube-janitor wordt uitgevoerd:
kubectl run nginx-demo --image=nginx
kubectl annotate deploy nginx-demo janitor/ttl=30m
Een andere bron van stijgende kosten zijn persistente volumes (AWS EBS). Als u een Kubernetes StatefulSet verwijdert, worden de persistente volumes ervan (PVC - PersistentVolumeClaim) niet verwijderd. Ongebruikte EBS-volumes kunnen gemakkelijk leiden tot kosten van honderden dollars per maand. Kubernetes Janitor heeft een functie om ongebruikte PVC's op te ruimen. Deze regel verwijdert bijvoorbeeld alle PVC's die niet door een module zijn gemonteerd en waarnaar niet wordt verwezen door een StatefulSet of 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 u helpen uw cluster schoon te houden en te voorkomen dat de kosten voor cloud computing zich langzaam opstapelen. Voor implementatie- en configuratie-instructies volgt u README kube-conciërge.
Verminder schaalvergroting tijdens niet-werkuren
Test- en faseringssystemen zijn doorgaans alleen nodig voor gebruik tijdens kantooruren. Sommige productietoepassingen, zoals backoffice-/beheertools, vereisen ook slechts een beperkte beschikbaarheid en kunnen van de ene op de andere dag worden uitgeschakeld.
Kubernetes-downscaler (kube-downscaler) stelt gebruikers en operators in staat het systeem buiten werktijd terug te schalen. Implementaties en StatefulSets kunnen worden geschaald naar nulreplica's. CronJobs kan worden opgeschort. Kubernetes Downscaler wordt geconfigureerd voor een heel cluster, een of meer naamruimten of individuele bronnen. U kunt de “inactieve tijd” of, omgekeerd, de “werktijd” instellen. Om bijvoorbeeld de schaalvergroting tijdens de nacht en het weekend zoveel mogelijk te beperken:
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 is een grafiek voor het schalen van clusterwerkknooppunten in het weekend:
Het terugschalen van ~13 naar 4 worker-nodes maakt zeker een merkbaar verschil in uw AWS-factuur.
Maar wat als ik moet werken tijdens de "downtime" van het cluster? Bepaalde implementaties kunnen permanent worden uitgesloten van schalen door de annotatie downscaler/exclude: true toe te voegen. Implementaties kunnen tijdelijk worden uitgesloten met behulp van de annotatie downscaler/uitsluiten tot met een absolute tijdstempel in de notatie JJJJ-MM-DD HH:MM (UTC). Indien nodig kan het hele cluster worden teruggeschaald door een pod met de annotatie te implementeren downscaler/force-uptime, bijvoorbeeld door nginx blank te starten:
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
Zien README kube-downscaler, als u geïnteresseerd bent in implementatie-instructies en aanvullende opties.
Gebruik horizontale automatische schaling
Veel applicaties/diensten hebben te maken met een dynamisch laadpatroon: soms zijn hun modules inactief, en soms werken ze op volle capaciteit. Het exploiteren van een permanente vloot van pods om de maximale piekbelasting op te vangen is niet economisch. Kubernetes ondersteunt horizontaal automatisch schalen voor een resource HorizontalPodAutoscaler (HPA). CPU-gebruik is vaak een goede indicator voor schaalvergroting:
Zalando heeft een component gemaakt om eenvoudig aangepaste statistieken te koppelen voor schaalvergroting: Kube Metrics-adapter (kube-metrics-adapter) is een generieke metrische adapter voor Kubernetes die aangepaste en externe metrische gegevens kan verzamelen en weergeven voor het horizontaal automatisch schalen van pods. Het ondersteunt schaling op basis van Prometheus-statistieken, SQS-wachtrijen en andere instellingen. Als u uw implementatie bijvoorbeeld wilt schalen naar een aangepaste statistiek die door de toepassing zelf wordt vertegenwoordigd als JSON in /metrics, gebruikt u het volgende:
Het configureren van horizontale automatische schaling met HPA zou een van de standaardacties moeten zijn om de efficiëntie voor staatloze services te verbeteren. Spotify heeft een presentatie met hun ervaringen en aanbevelingen voor HPA: schaal uw implementaties, niet uw portemonnee.
Verminder de overboeking van resources
Kubernetes-workloads bepalen hun CPU-/geheugenbehoeften via ‘resourceverzoeken’. CPU-bronnen worden gemeten in virtuele kernen of vaker in “millicores”, bijvoorbeeld 500m impliceert 50% vCPU. Geheugenbronnen worden gemeten in bytes en er kunnen algemene achtervoegsels worden gebruikt, zoals 500Mi, wat 500 megabytes betekent. Resourceaanvragen 'vergrendelen' de capaciteit op werkknooppunten, wat betekent dat een pod met een CPU-verzoek van 1000 m op een knooppunt met 4 vCPU's slechts 3 vCPU's beschikbaar laat voor andere pods. [1]
Slack (overschotreserve) is het verschil tussen de gevraagde bronnen en het daadwerkelijke gebruik. Een pod die bijvoorbeeld 2 GiB geheugen vraagt maar slechts 200 MiB gebruikt, heeft ~1,8 GiB "overtollig" geheugen. Overschot kost geld. Je kunt grofweg schatten dat 1 GiB redundant geheugen ~$10 per maand kost. [2]
Kubernetes-bronrapport (kube-resource-report) geeft overtollige reserves weer en kan u helpen het besparingspotentieel te bepalen:
Kubernetes-bronrapport toont het teveel geaggregeerd per toepassing en bevel. Hierdoor kunt u plaatsen vinden waar de vraag naar hulpbronnen kan worden verminderd. Het gegenereerde HTML-rapport biedt slechts een momentopname van het bronnengebruik. U moet naar het CPU-/geheugengebruik in de loop van de tijd kijken om te bepalen of er voldoende bronnen zijn aangevraagd. Hier is een Grafana-grafiek voor een "typische" CPU-zware service: alle pods gebruiken aanzienlijk minder dan de 3 gevraagde CPU-kernen:
Door het CPU-verzoek terug te brengen van 3000 m naar ~400 m, komen bronnen vrij voor andere werklasten en kan het cluster kleiner worden.
Maar willen we echt dat mensen waarden in YAML-bestanden veranderen? Nee, machines kunnen het veel beter! Kubernetes Verticale Pod Autoscaler (VPA) doet precies dat: past resourceverzoeken en -beperkingen aan op basis van de werklast. Hier is een voorbeeldgrafiek van Prometheus CPU-verzoeken (dunne blauwe lijn), aangepast door VPA in de loop van de tijd:
boterbloem van Fairwind is een tool die voor elke implementatie in een naamruimte een VPA creëert en vervolgens een VPA-aanbeveling op het dashboard weergeeft. Het kan ontwikkelaars helpen bij het instellen van de juiste CPU-/geheugenverzoeken voor hun applicaties:
Last but not least kunnen de AWS EC2-kosten worden verlaagd door Spot-instanties te gebruiken als Kubernetes-werkknooppunten [3]. Spot-exemplaren zijn beschikbaar met een korting van maximaal 90% vergeleken met On-Demand-prijzen. Het uitvoeren van Kubernetes op EC2 Spot is een goede combinatie: u moet verschillende instantietypen opgeven voor een hogere beschikbaarheid, wat betekent dat u een groter knooppunt kunt krijgen voor dezelfde of een lagere prijs, en dat de grotere capaciteit kan worden gebruikt door gecontaineriseerde Kubernetes-workloads.
Hoe voer ik Kubernetes uit op EC2 Spot? Er zijn verschillende opties: gebruik een service van derden zoals SpotInst (nu "Spot" genoemd, vraag me niet waarom), of voeg eenvoudigweg een Spot AutoScalingGroup (ASG) toe aan uw cluster. Hier is bijvoorbeeld een CloudFormation-fragment voor een "capaciteitsgeoptimaliseerde" Spot ASG met meerdere instantietypen:
Wat zijn uw best practices om cloudkosten op Kubernetes te besparen? Laat het mij weten via Twitter (@try_except_).
[1] In feite zullen minder dan 3 vCPU's bruikbaar blijven omdat de doorvoer van het knooppunt wordt verminderd door gereserveerde systeembronnen. Kubernetes maakt onderscheid tussen fysieke knooppuntcapaciteit en ‘ingerichte’ bronnen (Knooppunt toewijsbaar).
[2] Rekenvoorbeeld: één m5.large instance met 8 GiB geheugen kost ~$84 per maand (eu-central-1, On-Demand), d.w.z. het blokkeren van 1/8 knooppunt kost ongeveer ~$10/maand.
[3] Er zijn nog veel meer manieren om uw EC2-factuur te verlagen, zoals Gereserveerde Instances, Spaarplan, enz. - Ik zal deze onderwerpen hier niet behandelen, maar u moet er zeker naar kijken!