In genere, c'è sempre la necessità di fornire un pool dedicato di risorse a un'applicazione per il suo corretto e stabile funzionamento. Ma cosa succede se sulla stessa infrastruttura operano più applicazioni contemporaneamente? Come garantire risorse minime necessarie a ciascuna di esse? Quali modalità esistono per limitare il consumo di risorse? Come distribuire adeguatamente il carico tra i nodi? Come garantire il funzionamento del meccanismo di scalabilità orizzontale in caso di aumento del carico sulle applicazioni?

Bisogna innanzitutto chiarire quali sono i principali tipi di risorse esistenti nel sistema: si tratta ovviamente del tempo di CPU e della memoria RAM. Nei manifesti k8s, questi tipi di risorse vengono misurati nelle seguenti unità:
- CPU — in core
- RAM — in byte
Inoltre, per ciascuna risorsa è possibile impostare due tipi di requisiti — requests e limits. Requests — descrive i requisiti minimi per le risorse libere del nodo per avviare un contenitore (e del pod in generale), mentre limits stabilisce un limite rigido alle risorse disponibili per il contenitore.
È importante capire che nel manifesto non è necessario definire esplicitamente entrambi i tipi, e il comportamento sarà il seguente:
- Se è stato specificato solo il limite per una risorsa, le richieste per questa risorsa assumono automaticamente il valore del limite (può essere verificato richiamando la descrizione dell'entità). Cioè, in effetti, l'operatività del contenitore sarà limitata alla stessa quantità di risorse che richiede per il suo avvio.
- Se per la risorsa è stata specificata solo la richiesta, non vengono impostati limiti superiori su questa risorsa: cioè, il contenitore è limitato solo dalle risorse del nodo stesso.
Esiste anche la possibilità di gestire le risorse non solo a livello di singolo contenitore, ma anche a livello di namespace utilizzando le seguenti entità:
- LimitRange — descrive la politica di limitazione a livello di contenitore/pod nel ns e serve per definire i limiti predefiniti per il contenitore/pod, oltre a prevenire la creazione di contenitori/pod decisamente sovradimensionati (o viceversa), limitando il loro numero e determinando la possibile differenza di valori tra limits e requests.
- ResourceQuotas — descrivono la politica di limitazione in generale per tutti i container in ns e viene utilizzata, di norma, per distinguere le risorse tra gli ambienti (utile quando gli ambienti non sono severamente separati a livello di nodi)
Di seguito sono riportati esempi di manifesti in cui vengono stabiliti limiti sulle risorse:
A livello di un singolo container:
containers: - name: app-nginx image: nginx resources: requests: memory: 1Gi limits: cpu: 200mCioè, in questo caso, per avviare un container con nginx sono necessari almeno 1G di RAM e 0.2 CPU disponibili nel nodo, mentre al massimo il container può utilizzare 0.2 CPU e tutta la RAM disponibile nel nodo.
A livello di un intero ns:
apiVersion: v1 kind: ResourceQuota metadata: name: nxs-test spec: hard: requests.cpu: 300m requests.memory: 1Gi limits.cpu: 700m limits.memory: 2GiCioè, la somma di tutte le richieste dei container nel ns predefinito non può superare 300m per la CPU e 1G per la RAM, mentre la somma di tutti i limiti non può superare 700m per la CPU e 2G per la RAM.
Limitazioni predefinite per i container in ns:
apiVersion: v1 kind: LimitRange metadata: name: nxs-limit-per-container spec: limits: - type: Container defaultRequest: cpu: 100m memory: 1Gi default: cpu: 1 memory: 2Gi min: cpu: 50m memory: 500Mi max: cpu: 2 memory: 4GiCioè, nel namespace predefinito, per tutti i container verrà impostato un limite di richiesta di 100m per la CPU e 1G per la RAM, e un limite di 1 CPU e 2G. Inoltre, è stato stabilito un limite sui valori possibili in richiesta / limite per la CPU (50m < x < 2) e RAM (500M < x < 4G).
Limitazioni a livello di pod ns:
apiVersion: v1 kind: LimitRange metadata: name: nxs-limit-pod spec: limits: - type: Pod max: cpu: 4 memory: 1GiCioè, per ogni pod nel ns predefinito sarà impostato un limite di 4 vCPU e 1G.
Ora vorremmo parlare dei vantaggi che l'impostazione di queste limitazioni può offrirci.
Meccanismo di bilanciamento del carico tra i nodi
Come è noto, la distribuzione dei pod tra i nodi è gestita da un componente k8s chiamato scheduler, che funziona secondo un determinato algoritmo. Questo algoritmo, nella scelta del nodo ottimale per l'avvio, passa attraverso due fasi:
- Filtraggio
- Ranking
Cioè, secondo la politica descritta, inizialmente vengono selezionati i nodi sui quali è possibile avviare il pod basandosi su un insieme di predicates (incluso il controllo se il nodo dispone di risorse sufficienti per avviare il pod — PodFitsResources), e poi, per ciascuno di questi nodi, secondo priorities vengono accumulati punti (incluso, più risorse libere ha il nodo, più punti vengono assegnati - LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) e viene attivato sul nodo con il maggior numero di punti (se più nodi soddisfano questa condizione, viene scelto casualmente uno di essi).
Va compreso che il scheduler, nella valutazione delle risorse disponibili del nodo, si basa sui dati memorizzati in etcd - cioè sulla somma delle risorse richieste/limitate di ogni pod in esecuzione su questo nodo, ma non sul consumo effettivo delle risorse. Queste informazioni possono essere ottenute dall'output del comando kubectl describe node $NODE, per esempio:
# kubectl describe nodes nxs-k8s-s1
..
Non-terminated Pods: (9 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
ingress-nginx nginx-ingress-controller-754b85bf44-qkt2t 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d
kube-system kube-flannel-26bl4 150m (0%) 300m (1%) 64M (0%) 500M (1%) 233d
kube-system kube-proxy-exporter-cb629 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d
kube-system kube-proxy-x9fsc 0 (0%) 0 (0%) 0 (0%) 0 (0%) 233d
kube-system nginx-proxy-k8s-worker-s1 25m (0%) 300m (1%) 32M (0%) 512M (1%) 233d
nxs-monitoring alertmanager-main-1 100m (0%) 100m (0%) 425Mi (1%) 25Mi (0%) 233d
nxs-logging filebeat-lmsmp 100m (0%) 0 (0%) 100Mi (0%) 200Mi (0%) 233d
nxs-monitoring node-exporter-v4gdq 112m (0%) 122m (0%) 200Mi (0%) 220Mi (0%) 233d
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 487m (3%) 822m (5%)
memory 15856217600 (2%) 749976320 (3%)
ephemeral-storage 0 (0%) 0 (0%)Qui vediamo tutti i pod in esecuzione su un nodo specifico, così come le risorse richieste da ciascun pod. Ecco come appaiono i log del scheduler durante l'avvio del pod cronjob-cron-events-1573793820-xt6q9 (queste informazioni nei log del scheduler appariranno impostando il livello di registrazione al 10° livello negli argomenti del comando di avvio -v=10):
log
I1115 07:57:21.637791 1 scheduling_queue.go:908] In procinto di provare a programmare il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9
I1115 07:57:21.637804 1 scheduler.go:453] Tentativo di programmare il pod: nxs-stage/cronjob-cron-events-1573793820-xt6q9
I1115 07:57:21.638285 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s5 consentito, il nodo sta eseguendo solo 16 su 110 pod.
I1115 07:57:21.638300 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s6 consentito, il nodo sta eseguendo solo 20 su 110 pod.
I1115 07:57:21.638322 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s3 consentito, il nodo sta eseguendo solo 20 su 110 pod.
I1115 07:57:21.638322 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s4 consentito, il nodo sta eseguendo solo 17 su 110 pod.
I1115 07:57:21.638334 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s10 consentito, il nodo sta eseguendo solo 16 su 110 pod.
I1115 07:57:21.638365 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s12 consentito, il nodo sta eseguendo solo 9 su 110 pod.
I1115 07:57:21.638334 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s11 consentito, il nodo sta eseguendo solo 11 su 110 pod.
I1115 07:57:21.638385 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s1 consentito, il nodo sta eseguendo solo 19 su 110 pod.
I1115 07:57:21.638402 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s2 consentito, il nodo sta eseguendo solo 21 su 110 pod.
I1115 07:57:21.638383 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s9 consentito, il nodo sta eseguendo solo 16 su 110 pod.
I1115 07:57:21.638335 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s8 consentito, il nodo sta eseguendo solo 18 su 110 pod.
I1115 07:57:21.638408 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s13 consentito, il nodo sta eseguendo solo 8 su 110 pod.
I1115 07:57:21.638478 1 predicates.go:1369] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s10 consentito, le condizioni di anti-affinità dei pod esistenti sono soddisfatte.
I1115 07:57:21.638505 1 predicates.go:1369] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s8 consentito, le condizioni di anti-affinità dei pod esistenti sono soddisfatte.
I1115 07:57:21.638577 1 predicates.go:1369] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s9 consentito, le condizioni di anti-affinità dei pod esistenti sono soddisfatte.
I1115 07:57:21.638583 1 predicates.go:829] Programma il pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 sul nodo nxs-k8s-s7 consentito, il nodo sta eseguendo solo 25 su 110 pod.
I1115 07:57:21.638932 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Bilanciamento allocazione risorse, capacità 39900 millicores 66620178432 byte di memoria, richiesta totale 2343 millicores 9640186880 byte di memoria, punteggio 9
I1115 07:57:21.638946 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Allocazione risorse minima, capacità 39900 millicores 66620178432 byte di memoria, richiesta totale 2343 millicores 9640186880 byte di memoria, punteggio 8
I1115 07:57:21.638961 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Bilanciamento allocazione risorse, capacità 39900 millicores 66620170240 byte di memoria, richiesta totale 4107 millicores 11307422720 byte di memoria, punteggio 9
I1115 07:57:21.638971 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Bilanciamento allocazione risorse, capacità 39900 millicores 66620178432 byte di memoria, richiesta totale 5847 millicores 24333637120 byte di memoria, punteggio 7
I1115 07:57:21.638975 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Allocazione risorse minima, capacità 39900 millicores 66620170240 byte di memoria, richiesta totale 4107 millicores 11307422720 byte di memoria, punteggio 8
I1115 07:57:21.638990 1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Allocazione risorse minima, capacità 39900 millicores 66620178432 byte di memoria, richiesta totale 5847 millicores 24333637120 byte di memoria, punteggio 7
I1115 07:57:21.639022 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: Priorità di tolleranza di taint, Punteggio: (10)
I1115 07:57:21.639030 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: Priorità di tolleranza di taint, Punteggio: (10)
I1115 07:57:21.639034 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: Priorità di tolleranza di taint, Punteggio: (10)
I1115 07:57:21.639041 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: Priorità di affinità nodo, Punteggio: (0)
I1115 07:57:21.639053 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: Priorità di affinità nodo, Punteggio: (0)
I1115 07:57:21.639059 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: Priorità di affinità nodo, Punteggio: (0)
I1115 07:57:21.639061 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Priorità di affinità inter-pod, Punteggio: (0)
I1115 07:57:21.639063 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: Priorità di distribuzione selettiva, Punteggio: (10)
I1115 07:57:21.639073 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Priorità di affinità inter-pod, Punteggio: (0)
I1115 07:57:21.639077 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: Priorità di distribuzione selettiva, Punteggio: (10)
I1115 07:57:21.639085 1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Priorità di affinità inter-pod, Punteggio: (0)
I1115 07:57:21.639088 1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: Priorità di distribuzione selettiva, Punteggio: (10)
I1115 07:57:21.639103 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: Priorità di distribuzione selettiva, Punteggio: (10)
I1115 07:57:21.639109 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: Priorità di distribuzione selettiva, Punteggio: (10)
I1115 07:57:21.639114 1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: Priorità di distribuzione selettiva, Punteggio: (10)
I1115 07:57:21.639127 1 generic_scheduler.go:781] Host nxs-k8s-s10 -> Punteggio 100037
I1115 07:57:21.639150 1 generic_scheduler.go:781] Host nxs-k8s-s8 -> Punteggio 100034
I1115 07:57:21.639154 1 generic_scheduler.go:781] Host nxs-k8s-s9 -> Punteggio 100037
I1115 07:57:21.639267 1 scheduler_binder.go:269] AssumePodVolumes per pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", nodo "nxs-k8s-s10"
I1115 07:57:21.639286 1 scheduler_binder.go:279] AssumePodVolumes per pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", nodo "nxs-k8s-s10": tutte le PVC sono legate e non c'è nulla da fare
I1115 07:57:21.639333 1 factory.go:733] Tentativo di legare cronjob-cron-events-1573793820-xt6q9 a nxs-k8s-s10Qui vediamo che inizialmente il scheduler esegue un filtraggio e crea un elenco di 3 nodi sui quali è possibile avviare (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Successivamente, calcola i punteggi in base a diversi parametri (inclusi BalancedResourceAllocation, LeastResourceAllocation) per ciascuno di questi nodi al fine di determinare il nodo più adatto. Alla fine, si pianifica sul nodo con il punteggio più alto (qui due nodi hanno lo stesso punteggio di 100037, quindi viene scelta una di esse a caso — nxs-k8s-s10).
Conclusione: se nel nodo sono in esecuzione pod per i quali non sono state impostate restrizioni, per k8s (dal punto di vista del consumo delle risorse) questo equivarrà a considerare che su questo nodo tali pod siano assenti. Pertanto, se avete, per esempio, un pod con un processo molto esigente (ad esempio, wowza) e per esso non sono state definite restrizioni, può verificarsi una situazione in cui questo pod consuma tutte le risorse del nodo, ma per k8s questo nodo risulta non sovraccarico e riceverà lo stesso punteggio in fase di classificazione (a livello di punteggi di risorse disponibili) di un nodo su cui non ci sono pod attivi, il che può portare a una distribuzione incoerente del carico tra i nodi.
Espulsione del pod
Come è noto, a ogni pod viene assegnata una delle 3 classi QoS:
- garantita — viene assegnata quando per ogni contenitore nel pod sono stati definiti request e limit per la memoria e la CPU, e questi valori devono coincidere
- burstable — almeno un contenitore nel pod ha request e limit, con request < limit
- best effort — quando nessun contenitore nel pod è limitato nelle risorse
Pertanto, quando nel nodo si verifica una carenza di risorse (disco, memoria), kubelet inizia a classificare ed espellere i pod secondo un determinato algoritmo, che tiene conto della priorità del pod e della sua classe QoS. Ad esempio, per quanto riguarda la RAM, i punteggi vengono assegnati sulla base della classe QoS secondo il seguente principio:
- Guaranteed: -998
- BestEffort: 1000
- Burstable: min(max(2, 1000 — (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)
Cioè, a parità di priorità, kubelet espellerà in prima battuta i pod con classe QoS best effort.
Conclusione: se desiderate ridurre la probabilità di espulsione di un pod necessario dal nodo in caso di carenza di risorse, dovete anche assicurarvi di definire request/limit per esso, oltre alla priorità.
Meccanismo di autoscaling orizzontale dei pod dell'applicazione (HPA)
Quando si tratta di aumentare e diminuire automaticamente il numero di pod in base all'utilizzo delle risorse (sistema — CPU/RAM o utente — rps), può aiutare un'entità k8s come HPA (Horizontal Pod Autoscaler). Il cui algoritmo è il seguente:
- Si determinano le letture attuali della risorsa monitorata (currentMetricValue)
- Si definiscono i valori desiderati per la risorsa (desiredMetricValue), che per le risorse di sistema vengono impostati tramite request
- Si determina l'attuale numero di repliche (currentReplicas)
- Si calcola il numero desiderato di repliche (desiredReplicas) con la seguente formula
desiredReplicas = [ currentReplicas * ( currentMetricValue / desiredMetricValue )]
In questo caso non ci sarà scaling quando il rapporto (currentMetricValue / desiredMetricValue) è vicino a 1 (e la tolleranza può essere impostata da noi, per impostazione predefinita è 0.1).
Esaminiamo il funzionamento dell'HPA con l'esempio dell'applicazione app-test (descritta come Deployment), dove è necessario modificare il numero di repliche in base al consumo della CPU:
Manifesto dell'applicazione
kind: Deployment apiVersion: apps/v1beta2 metadata: name: app-test spec: selector: matchLabels: app: app-test replicas: 2 template: metadata: labels: app: app-test spec: containers: - name: nginx image: registry.nixys.ru/generic-images/nginx imagePullPolicy: Always resources: requests: cpu: 60m ports: - name: http containerPort: 80 - name: nginx-exporter image: nginx/nginx-prometheus-exporter resources: requests: cpu: 30m ports: - name: nginx-exporter containerPort: 9113 args: - -nginx.scrape-uri - http://127.0.0.1:80/nginx-statusCioè, vediamo che il pod con l'applicazione viene inizialmente avviato in due esemplari, ognuno dei quali contiene due contenitori nginx e nginx-exporter, per ciascuno dei quali è stato impostato requests per la CPU.
Manifesto HPA
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: app-test-hpa spec: maxReplicas: 10 minReplicas: 2 scaleTargetRef: apiVersion: extensions/v1beta1 kind: Deployment name: app-test metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 30Cioè, abbiamo creato un HPA che monitorerà il Deployment app-test e regolerà il numero di pod con l'applicazione in base all'indicatore della CPU (ci aspettiamo che il pod dovrebbe consumare il 30% della CPU richiesta), con il numero di repliche che rimane tra 2 e 10.
Ora consideriamo il meccanismo di funzionamento dell'HPA se si applica un carico a uno dei pod:
# kubectl top pod NAME CPU(cores) MEMORY(bytes) app-test-78559f8f44-pgs58 101m 243Mi app-test-78559f8f44-cj4jz 4m 240Mi
In sintesi, abbiamo il seguente:
- Il valore desiderato (desiredMetricValue) — secondo le impostazioni di hpa è pari al 30%
- Il valore attuale (currentMetricValue) — per il calcolo, il controller-manager calcola la media del consumo delle risorse in %, ossia sostanzialmente esegue quanto segue:
- Ottiene i valori assoluti delle metriche dei pod dal metric-server, ossia 101m e 4m
- Calcola il valore assoluto medio, cioè (101m + 4m) / 2 = 53m
- Ottiene il valore assoluto per il consumo desiderato delle risorse (per questo si sommano le richieste di tutti i container) 60m + 30m = 90m
- Calcola la percentuale media di utilizzo della CPU rispetto alle richieste del pod, cioè 53m / 90m * 100% = 59%
Ora abbiamo tutto il necessario per determinare se è necessario modificare il numero di repliche, per questo calcoliamo il rapporto:
ratio = 59% / 30% = 1.96
Cioè, il numero di repliche deve essere aumentato di circa 2 volte e quindi essere [2 * 1.96] = 4.
Conclusione: Come si può notare, affinché questo meccanismo funzioni, una condizione necessaria è anche la presenza di richieste per tutti i container nel pod osservato.
Meccanismo di autoscaling orizzontale dei nodi (Cluster Autoscaler)
Per ridurre l'impatto negativo sul sistema durante i picchi di carico, avere un hpa configurato può essere insufficiente. Ad esempio, secondo le impostazioni dell'hpa, il controller manager decide che il numero di repliche deve aumentare di 2 volte, ma nei nodi non ci sono risorse disponibili per avviare un tale numero di pod (cioè il nodo non può fornire le risorse richieste dalle richieste del pod) e questi pod passano allo stato Pending.
In questo caso, se il provider ha un corrispondente IaaS/PaaS (ad esempio, GKE/GCE, AKS, EKS, ecc.), uno strumento come Node Autoscalerci può aiutare. Permette di impostare un numero massimo e minimo di nodi nel cluster e regolare automaticamente il numero attuale di nodi (richiedendo all'API del provider cloud l'ordine/rimozione di un nodo), quando si osserva una mancanza di risorse nel cluster e i pod non possono essere pianificati (si trovano in stato Pending).
Conclusione: Per avere la possibilità di autoscaling dei nodi, è necessario impostare le richieste nei container dei pod, affinché k8s possa valutare correttamente il carico dei nodi e segnalare di conseguenza che non ci sono risorse nel cluster per avviare un ulteriore pod.
Conclusione
È importante notare che impostare limiti sulle risorse del contenitore non è un prerequisito per l'avvio riuscito dell'applicazione, tuttavia è consigliabile farlo per i seguenti motivi:
- Per un funzionamento più preciso dello scheduler nella distribuzione del carico tra i nodi k8s
- Per ridurre la probabilità che si verifichi un evento di 'espulsione del pod'
- Per il funzionamento dell'auto-scaling orizzontale dei pod dell'applicazione (HPA)
- Per il funzionamento dell'auto-scaling orizzontale dei nodi (Cluster Autoscaling) da parte dei fornitori di cloud
Leggi anche altri articoli nel nostro blog:
Fonte: habr.com
