La traduzione dell'articolo è stata preparata in vista dell'inizio del corso .

Come risparmiare sui costi del cloud lavorando con Kubernetes? Non esiste una soluzione unica, ma in questo articolo vengono descritti alcuni strumenti che possono aiutarti a gestire le risorse in modo più efficiente e ridurre le spese per il cloud computing.
Ho scritto questo articolo con un focus su Kubernetes per AWS, ma sarà applicabile (quasi) esattamente allo stesso modo anche per altri fornitori di servizi cloud. Presumo che il tuo cluster sia già configurato per il ridimensionamento automatico (). La rimozione delle risorse e la riduzione della scala del deployment consentiranno di risparmiare solo se questo ridurrà anche il numero dei nodi di lavoro (istanze EC2).
In questo articolo verranno discussi:
- la pulizia delle risorse non utilizzate ()
- riduzione della scala durante il tempo non lavorativo ()
- uso dell'autoscaling orizzontale (HPA),
- riduzione del sovraccarico delle risorse (, VPA)
- uso delle istanze Spot
Pulizia delle risorse non utilizzate
Lavorare in un ambiente in rapida evoluzione è fantastico. Vogliamo che le organizzazioni tecniche . Una consegna di software più rapida significa anche un numero maggiore di deployment PR, ambienti di anteprima, prototipi e soluzioni analitiche. Tutto distribuito su Kubernetes. Chi ha tempo per pulire manualmente i deployment di test? È facile dimenticare di rimuovere un esperimento di settimane fa. La bolletta del cloud alla fine crescerà a causa delle risorse dimenticate:

(Henning Jacobs:
Svara:
(citando) Corey Quinn:
Mito: La tua bolletta AWS dipende dal numero dei tuoi utenti.
Fatto: La tua bolletta AWS dipende dal numero dei tuoi ingegneri.
Ivan Kurnossov (in risposta):
Fatto reale: La tua bolletta AWS dipende dal numero delle cose che hai dimenticato di spegnere/rimuovere.)
(kube-janitor) aiuta a ripulire il tuo cluster. La configurazione del janitor è flessibile sia per l'uso globale che locale:
- Regole generali per l'intero cluster possono definire un tempo massimo di vita (TTL – time-to-live) per i deployment PR/test.
- Specifici risorse possono essere annotate con janitor/ttl, ad esempio, per la rimozione automatica di spike/prototipi dopo 7 giorni.
Le regole generali sono definite in un file YAML. Il suo percorso viene passato tramite il parametro --rules-file a kube-janitor. Ecco un esempio di regole per rimuovere tutti gli spazi dei nomi con -pr- nel nome dopo due giorni:
- id: cleanup-resources-from-pull-requests
resources:
- namespaces
jmespath: "contains(metadata.name, '-pr-')"
ttl: 2dIl seguente esempio disciplina l'uso dell'etichetta application sui pod Deployment e StatefulSet per tutti i nuovi Deployments/StatefulSet nel 2020, ma consente nel contempo di eseguire test senza questa etichetta per una settimana:
- id: require-application-label
# rimuovere deployments e statefulsets senza etichetta "application"
resources:
- deployments
- statefulsets
# vedi http://jmespath.org/specification.html
jmespath: "!(spec.template.metadata.labels.application) && metadata.creationTimestamp > '2020-01-01'"
ttl: 7dEsecuzione di una demo a tempo limitato per 30 minuti in un cluster dove è in funzione kube-janitor:
kubectl run nginx-demo --image=nginx
kubectl annotate deploy nginx-demo janitor/ttl=30mUn'altra fonte di crescenti costi sono i volumi persistenti (AWS EBS). Quando si elimina uno StatefulSet di Kubernetes, non vengono rimossi i suoi volumi persistenti (PVC – PersistentVolumeClaim). Volumi EBS non utilizzati possono facilmente portare a costi di centinaia di dollari al mese. Kubernetes Janitor ha una funzionalità per pulire PVC non utilizzati. Ad esempio, questa regola eliminerà tutti i PVC che non sono montati da un modulo e non sono referenziati da uno StatefulSet o CronJob:
# удалить все PVC, которые не смонтированы и на которые не ссылаются StatefulSets
- id: remove-unused-pvcs
resources:
- persistentvolumeclaims
jmespath: "_context.pvc_is_not_mounted && _context.pvc_is_not_referenced"
ttl: 24hKubernetes Janitor può aiutarti a mantenere il tuo cluster "pulito" e prevenire costi di cloud computing che si accumulano lentamente. Per le istruzioni su come implementare e configurare, seguire nel .
Riduzione della scala durante il tempo non lavorativo
Sistemi di test e intermediari di solito sono richiesti soltanto durante il tempo lavorativo. Alcune applicazioni di produzione, come back-office / strumenti per amministratori, richiedono anche solo una disponibilità limitata e possono essere spenti durante la notte.
(kube-downscaler) consente agli utenti e agli operatori di ridurre la scala del sistema durante il tempo non lavorativo. I Deployments e StatefulSets possono essere scalati fino a zero repliche. I CronJobs possono essere sospesi. Kubernetes Downscaler è configurato per l'intero cluster, uno o più spazi dei nomi o singole risorse. Può essere impostato per il "tempo di inattività" o, al contrario, per il "tempo di operatività". Ad esempio, per ridurre al minimo la scala durante la notte e nei fine settimana:
image: hjacobs/kube-downscaler:20.4.3
args:
- --interval=30
# non disattivare i componenti dell'infrastruttura
- --exclude-namespaces=kube-system,infra
# non disattivare kube-downscaler e mantenere Postgres Operator per gestire i database esclusi
- --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-timeEcco il grafico di scalabilità dei nodi del cluster nei fine settimana:

Ridurre la scala da ~13 a 4 nodi di lavoro fa sicuramente una grande differenza nella fattura di AWS.
Ma cosa succede se devo lavorare durante il 'tempo di inattività' del cluster? Alcuni deployment possono essere esclusi dalla scalabilità in modo permanente aggiungendo l'annotazione downscaler/exclude: true. I deployment possono essere temporaneamente esclusi utilizzando l'annotazione downscaler/exclude-until con un timestamp assoluto nel formato AAAA-MM-GG HH:MM (UTC). Se necessario, l'intero cluster può essere ridimensionato tornando a un deployment con l'annotazione downscaler/force-uptime, ad esempio, eseguendo un pod nginx come modello:
kubectl run scale-up --image=nginx
kubectl annotate deploy scale-up janitor/ttl=1h # rimuovere il deployment dopo un'ora
kubectl annotate pod $(kubectl get pod -l run=scale-up -o jsonpath="{.items[0].metadata.name}") downscaler/force-uptime=trueVedi , se sei interessato a istruzioni di deployment e opzioni aggiuntive.
Utilizza l'autoscaling orizzontale
Molte applicazioni/servizi affrontano schemi di carico dinamici: a volte i loro componenti sono inattivi, mentre altre volte funzionano a pieno regime. Mantenere un parco costante di pod per gestire il massimo carico di picco non è economico. Kubernetes supporta l'autoscaling orizzontale tramite la risorsa (HPA). L'uso della CPU è spesso un buon indicatore per la scalabilità:
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: UtilizationZalando ha creato un componente per la facile integrazione di metriche personalizzate per la scalabilità: (kube-metrics-adapter) è un adattatore di metriche universale per Kubernetes, che può raccogliere e servire metriche personalizzate ed esterne per l'autoscaling orizzontale dei pod. Supporta la scalabilità sulla base di metriche Prometheus, code SQS e altre impostazioni. Ad esempio, per scalare un deployment a una metrica personalizzata fornita dall'applicazione stessa in formato JSON in /metrics usa:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
annotations:
# metric-config.../
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: AverageValueConfigurare l'autoscaling orizzontale con HPA dovrebbe essere una delle azioni predefinite per migliorare l'efficienza per i servizi stateless. Spotify ha una presentazione con la loro esperienza e raccomandazioni per HPA: .
Ridurre il sovraccarico delle risorse
Le workload di Kubernetes definiscono le loro esigenze di CPU/memoria tramite 'richieste di risorse' (resource requests). Le risorse CPU sono misurate in core virtuali o più frequentemente in 'millicores' (millicores), ad esempio, 500m implica 50% di vCPU. Le risorse di memoria sono misurate in byte e si possono utilizzare suffissi comuni, come 500Mi, che indica 500 megabyte. Le richieste di risorse 'bloccano' la quantità sui nodi di lavoro, quindi un modulo con una richiesta di CPU di 1000m su un nodo con 4 vCPU lascerà solo 3 vCPU disponibili per altri moduli.
Slack (sovraccarico) è la differenza tra le risorse richieste e l'uso reale. Ad esempio, un pod che richiede 2 GiB di memoria, ma utilizza solo 200 MiB, ha ~ 1,8 GiB di 'memoria sovraccarica'. Il sovraccarico costa denaro. Si può stimare che 1 GiB di memoria sovraccarica costi ~ 10 dollari al mese.
(kube-resource-report) visualizza i surplus di risorse e può aiutarti a identificare le opportunità di risparmio:

mostra un eccesso aggregato dall'applicazione e dal team. Questo permette di identificare aree in cui le richieste di risorse possono essere ridotte. Il report HTML generato fornisce solo uno snapshot dell'utilizzo delle risorse. Dovreste osservare l'utilizzo della CPU/memoria nel tempo per determinare le richieste di risorse adeguate. Ecco un diagramma di Grafana per un servizio "tipico" con elevato carico CPU: tutti i pod utilizzano significativamente meno di 3 core CPU richiesti:

Ridurre la richiesta CPU da 3000m a ~400m libera risorse per altri carichi di lavoro e consente di ridurre il cluster.
"L'utilizzo medio della CPU delle istanze EC2 oscilla spesso tra percentuali a una cifra", . Mentre per EC2 , modificare alcune richieste di risorse Kubernetes nel file YAML è facile e può portare a enormi risparmi.
Ma vogliamo davvero che le persone modifichino i valori nei file YAML? No, le macchine possono farlo molto meglio! Kubernetes VPA (Vertical Pod Autoscaler) si occupa proprio di questo: adatta le richieste di risorse e i limiti in base al carico di lavoro. Ecco un esempio di grafico delle richieste di CPU di Prometheus (linea blu sottile), adattate dal VPA nel tempo:

per i componenti dell'infrastruttura. Anche le applicazioni non critiche possono utilizzare il VPA.
di Fairwind è uno strumento che crea un VPA per ogni distribuzione nello spazio dei nomi e poi visualizza il consiglio VPA sulla sua dashboard. Può aiutare gli sviluppatori a impostare le corrette richieste di CPU/memoria per le loro applicazioni:

Ho scritto un breve nel 2019, e recentemente nel .
Utilizzo delle istanze EC2 Spot
Infine, non meno importante, i costi di AWS EC2 possono essere ridotti utilizzando le istanze Spot come nodi di lavoro Kubernetes. Le istanze Spot sono disponibili con sconti fino al 90% rispetto ai prezzi on-demand. Lanciare Kubernetes su EC2 Spot è una buona combinazione: è necessario specificare diversi tipi di istanze per una maggiore disponibilità, quindi puoi ottenere un nodo più grande allo stesso prezzo o a un prezzo più basso e la capacità aggiuntiva può essere utilizzata dalle carichi di lavoro container Kubernetes.
Come avviare Kubernetes su EC2 Spot? Ci sono diverse opzioni: utilizzare un servizio di terze parti come SpotInst (ora si chiama "Spot", non chiedetemi perché) o semplicemente aggiungere un AutoScalingGroup (ASG) Spot al vostro cluster. Per esempio, ecco un frammento di CloudFormation per un ASG Spot "ottimizzato per la capacità" con diversi tipi di istanze:
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"Alcuni appunti sull'uso delle Spot con Kubernetes:
- È necessario gestire le interruzioni delle Spot, ad esempio tramite lo scarico dei nodi all'arresto dell'istanza.
- Zalando utilizza l'autoscaling del cluster ufficiale con priorità dei pool nodi
- I nodi Spot ad accettare "registrazioni" dei carichi di lavoro da eseguire su Spot.
Riepilogo
Spero che troviate utili alcuni degli strumenti presentati per ridurre il vostro costo per il cloud. Potete trovare gran parte del contenuto dell'articolo anche nel .
Quali sono le vostre migliori pratiche per risparmiare sui costi del cloud in Kubernetes? Fatecelo sapere su .
In effetti, meno di 3 vCPU saranno utilizzabili, poiché la capacità del nodo diminuisce a causa delle risorse di sistema riservate. Kubernetes distingue tra la capacità fisica del nodo e le risorse "allocabili" ().
Esempio di calcolo: un'istanza m5.large con 8 GiB di memoria costa circa ~84 dollari al mese (eu-central-1, On-Demand), ossia bloccare 1/8 del nodo costa circa ~10 dollari al mese.
Ci sono molte altre modalità per ridurre il vostro conto EC2, come le istanze riservate, i piani di risparmio, ecc. — non discuterò questi argomenti qui, ma dovete sicuramente informavi su di essi!
Fonte: habr.com
