Come accedere alle risorse del Pod Kubernetes

Come accedere alle risorse del Pod KubernetesIl Reward di Tohad

All'inizio del lavoro con Kubernetes, di solito si dimentica di configurare le risorse dei container. In questa fase, è sufficiente assicurarsi che l'immagine Docker funzioni e che possa essere distribuita nel cluster Kubernetes.

Ma in seguito, l'applicazione deve essere distribuita in un cluster di produzione insieme ad altre applicazioni. Per questo, è necessario allocare risorse per il container e assicurarsi che siano sufficienti per avviare e far funzionare l'applicazione, senza che si verifichino problemi con le altre applicazioni in esecuzione.

Team Kubernetes aaS di Mail.ru ho tradotto un articolo sulle risorse dei container (CPU & MEM), le richieste e i limiti delle risorse. Scoprirete quali vantaggi offrono queste impostazioni e cosa accade se non vengono configurate.

Risorse di calcolo

Abbiamo due tipi di risorse con le seguenti unità:

  • Processore centrale (CPU) — core;
  • Memoria (MEM) — byte.

Le risorse sono specificate per ogni container. Nel seguente file YAML di Pod, vedrete la sezione delle risorse che contiene le risorse richieste e quelle limite:

  • Risorse richieste del Pod = somma delle risorse richieste di tutti i container;
  • Risorse limite del Pod = somma delle risorse limite di tutti i container.

apiVersion: v1
kind: Pod
metadata:
  name: backend-pod-name
  labels:
    application: backend
spec:
  containers:
    — name: main-container
      image: my-backend
      tag: v1
      ports:
      — containerPort: 8080
      resources:
        requests:
          cpu: 0.2 # CPU RICHIESTO: 200m core
          memory: "1Gi" # MEM RICHIESTO: 1Gi
        limits:
          cpu: 1 # USO MASSIMO CPU: 1 core
          memory: "1Gi" # USO MASSIMO MEM:  1Gi
    — name: other-container
      image: other-app
      tag: v1
      ports:
      — containerPort: 8000
      resources:
        requests:
          cpu: "200m" # CPU RICHIESTO: 200m core
          memory: "0.5Gi" # MEM RICHIESTO: 0.5Gi
        limits:
          cpu: 1 # USO MASSIMO CPU: 1 core
          memory: "1Gi" # USO MASSIMO MEM:  1Gi

Esempio di risorse richieste e limiti

Campo resources.requested dallo specifica del Pod — uno degli elementi utilizzati per cercare il nodo corretto. Su di esso si può pianificare il deployment del Pod. Come si trova il nodo appropriato?

Kubernetes è composto da diversi componenti, inclusi un nodo principale o master-node (Kubernetes Control Plane). Nel master-node ci sono diversi processi: kube-apiserver, kube-controller-manager e kube-scheduler.

Il processo kube-scheduler si occupa di esaminare i nuovi pod creati e di cercare i nodi di lavoro compatibili con tutte le richieste dei pod, inclusi i requisiti relativi alle risorse richieste. L'elenco dei nodi trovati da kube-scheduler è ordinato per punteggio. Il Pod viene pianificato sul nodo con il punteggio più alto.

Come accedere alle risorse del Pod KubernetesDove verrà collocato il Pod viola?

Nell'immagine, si può vedere che kube-scheduler deve pianificare un nuovo Pod viola. Il cluster Kubernetes contiene due nodi: A e B. Come si può notare, kube-scheduler non può pianificare il Pod sul nodo A — le risorse disponibili (non richieste) non soddisfano le esigenze del Pod viola. Infatti, l'1 GiB di memoria richiesto dal Pod viola non può essere allocato sul nodo A, poiché la memoria disponibile è di 0,5 GiB. Tuttavia, il nodo B ha risorse sufficienti. Di conseguenza, kube-scheduler decide che la destinazione per il Pod viola è il nodo B.

Ora sappiamo come le risorse richieste influenzano la scelta del nodo per l'esecuzione del Pod. Ma come influiscono le risorse limite?

Le risorse limite sono un confine che CPU/MEM non può oltrepassare. Tuttavia, le risorse CPU sono flessibili, quindi i container che raggiungono i valori limite per CPU non porteranno alla terminazione del Pod. Invece, verrà attivato il throttling della CPU. Se viene raggiunto il limite d'uso della MEM, il container verrà arrestato per OOM-Killer e riavviato, se consentito dalla configurazione RestartPolicy.

Risorse richieste e limiti in dettaglio

Come accedere alle risorse del Pod KubernetesCollegamento delle risorse tra Docker e Kubernetes

Il modo migliore per spiegare come funzionano le risorse richieste e i limiti è rappresentare il collegamento tra Kubernetes e Docker. Nell'immagine sopra puoi vedere come sono collegati i campi di Kubernetes e i flag di avvio di Docker.

Memoria: richiesta e limite

containers:
...
 resources:
   requests:
     memory: "0.5Gi"
   limits:
     memory: "1Gi"

Come accennato in precedenza, la memoria è misurata in byte. Basandosi su documentazione di Kubernetes, possiamo specificare la memoria in forma numerica. Di solito è un intero, ad esempio 2678 — cioè 2678 byte. È possibile utilizzare anche i suffissi G e Gi, è importante ricordare che non sono equivalenti. Il primo è decimale, mentre il secondo è binario. Come esempio, citato nella documentazione di k8s: 128974848, 129e6, 129M, 123Mi — sono praticamente equivalenti.

Parametro Kubernetes limits.memory corrisponde al flag --memory di Docker. Nel caso di request.memory il puntatore per Docker è assente, poiché Docker non utilizza questo campo. Puoi chiederti se sia davvero necessario? Sì, lo è. Come ho già detto, il campo è importante per Kubernetes. Sulla base delle informazioni contenute in esso, kube-scheduler decide su quale nodo pianificare il Pod.

Cosa succede se si imposta una richiesta di memoria insufficiente?

Se il contenitore raggiunge i limiti della memoria richiesta, il Pod viene messo in un gruppo di Pod che vengono arrestati in caso di mancanza di memoria nel nodo.

Cosa succede se si imposta un limite di memoria troppo basso?

Se il contenitore supera il limite di memoria, verrà terminato per OOM-Killed. E verrà riavviato, se possibile, in base a RestartPolicy, dove il valore predefinito è Always.

Cosa succede se non viene specificata la memoria richiesta?

Kubernetes prenderà il limite e lo imposterà come valore predefinito.

Cosa può succedere se non viene specificata la memoria limite?

Il container non ha limiti, può utilizzare quanta più memoria desidera. Se inizia a utilizzare tutta la memoria disponibile del nodo, verrà terminato da OOM. Successivamente, il container verrà riavviato, se possibile, in base a RestartPolicy.

Cosa succede se non si specificano limiti di memoria?

Questo è il peggior scenario: il pianificatore non sa quante risorse richiede il container e ciò può causare gravi problemi sul nodo. In questo caso, sarebbe utile avere limiti predefiniti nello spazio dei nomi (impostati tramite LimitRange). Non ci sono limiti predefiniti: il Pod non ha restrizioni, può utilizzare quanta più memoria desidera.

Se la memoria richiesta è superiore a quella che il nodo può offrire, il Pod non verrà pianificato. È importante ricordare che Requests.memory non è un valore minimo. È una descrizione della quantità di memoria necessaria per il funzionamento continuo del container.

Di solito si consiglia di impostare lo stesso valore per request.memory e limit.memory. In questo modo Kubernetes non pianificherà il Pod su un nodo che ha abbastanza memoria per avviare il Pod, ma non abbastanza per farlo funzionare. Ricordate: durante la pianificazione del Pod, Kubernetes considera solo requests.memory, e limits.memory non considera.

CPU: richiesta e limite

containers:
...
 resources:
   requests:
     cpu: 1
   limits:
     cpu: "1200m"

Con il CPU è tutto un po' più complicato. Tornando all'immagine della relazione tra Kubernetes e Docker, si può notare che request.cpu corrisponde a --cpu-shares, mentre limit.cpu corrisponde al flag cpus in Docker.

La CPU richiesta da Kubernetes viene moltiplicata per 1024 — la proporzione dei cicli della CPU. Se desideri richiedere 1 core completo, devi aggiungere cpu: 1, come mostrato sopra.

La richiesta di un core completo (proporzione = 1024) non significa che il tuo contenitore lo riceverà. Se il tuo computer host ha solo un core e utilizzi più di un contenitore, tutti i contenitori devono condividere la CPU disponibile tra di loro. Come avviene questo? Diamo un'occhiata all'immagine.

Come accedere alle risorse del Pod Kubernetes
Richiesta CPU — sistema con un core

Immaginiamo di avere un sistema host con un core, su cui sono in esecuzione i contenitori. Mamma (Kubernetes) ha cotto una torta (CPU) e vuole condividerla tra i bambini (contenitori). Tre bambini vogliono un'intera torta (proporzione = 1024), un altro bambino ne vuole metà (512). Mamma vuole essere giusta e fa un semplice calcolo.

# Сколько пирогов хотят дети?
# 3 ребенка хотят по целому пирогу и еще один хочет половину пирога
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
# Выражение получается так:
3 (ребенка/контейнера) * 1 (целый пирог/полное ядро) + 1 (ребенок/контейнер) * 0.5 (половина пирога/половина ядра)
# Сколько пирогов испечено?
availableCakesNumber = 1
# Сколько пирога (максимально) дети реально могут получить?
newMaxRequest = 1 / 3.5 =~ 28%

Secondo i calcoli, tre bambini riceveranno il 28% di un core, e non un core intero. Al quarto bambino andrà il 14% di un core completo, e non la metà. Ma tutto sarà diverso se hai un sistema multicore.

Come accedere alle risorse del Pod Kubernetes
Richiesta CPU — sistema multicore (4)

Nell'immagine sopra, si vede che tre bambini vogliono un intero dolce, mentre uno desidera la metà. Poiché la mamma ha preparato quattro dolci, ciascuno dei suoi figli riceverà quanto desidera. In un sistema multicore, le risorse della CPU sono distribuite su tutti i core disponibili. Se un contenitore è limitato a meno di un core CPU completo, può comunque utilizzarlo al 100%.

I calcoli sopra riportati sono semplificati per far comprendere come la CPU venga distribuita tra i contenitori. Naturalmente, oltre ai contenitori stessi, ci sono altri processi che utilizzano anche le risorse della CPU. Quando i processi in un contenitore sono inattivi, altri possono utilizzare le sue risorse. CPU: "200m" corrisponde a CPU: 0,2, che significa circa il 20% di un core.

Ora parliamo di limit.cpu. La CPU limitata da Kubernetes viene moltiplicata per 100. Il risultato è la quantità di tempo che il contenitore può utilizzare ogni 100 µs (cpu-period).

limit.cpu corrisponde al flag Docker --cpus. Questa è una nuova combinazione di vecchi --cpu-period e --cpu-quota. Impostandolo, indichiamo quante risorse CPU il contenitore può utilizzare al massimo prima che inizi il throttling:

  • cpus — combinazione cpu-period e cpu-quota. cpus = 1.5 è equivalente a impostare cpu-period = 100000 e cpu-quota = 150000;
  • cpu-period — periodo del pianificatore CPU CFS, di default 100 microsecondi;
  • cpu-quota — numero di microsecondi dentro cpu-period, a cui il contenitore è limitato.

Cosa succede se si imposta una richiesta di CPU insufficiente?

Se il contenitore ha bisogno di più di quanto impostato, ruberà CPU ad altri processi.

Cosa succede se si imposta un limite di CPU insufficiente?

Poiché la risorsa CPU è regolabile, si attiverà il throttling.

Cosa succede se non si specifica una richiesta di CPU?

Come nel caso della memoria, il valore della richiesta è uguale al limite.

Cosa succede se non si specifica un limite di CPU?

Il contenitore utilizzerà tanta CPU quanta ne ha bisogno. Se nel namespace è definita una politica CPU predefinita (LimitRange), questo limite verrà utilizzato anche per il contenitore.

Cosa succede se non si specifica né richiesta né limite di CPU?

Come nel caso della memoria, questa è la situazione peggiore. Il pianificatore non sa quante risorse sono necessarie per il tuo container e questo può causare seri problemi sul nodo. Per evitarlo, è necessario impostare limiti predefiniti per i namespace (LimitRange).

Ricorda: se richiedi più CPU di quanta ne possano fornire i nodi, il Pod non verrà pianificato. Requests.cpu — non è un valore minimo, ma un valore sufficiente per avviare il Pod e farlo funzionare senza problemi. Se l'applicazione non esegue calcoli complessi, la cosa migliore da fare è impostare request.cpu <= 1 e avviare tante repliche quante necessarie.

La quantità ideale di risorse richieste o limite delle risorse

Abbiamo appreso riguardo al limite delle risorse computazionali. Ora è il momento di rispondere alla domanda: «Quante risorse sono necessarie affinché il mio Pod esegua l'applicazione senza problemi? Qual è la quantità ideale?».

Sfortunatamente, non ci sono risposte definitive a queste domande. Se non si sa come funziona la propria applicazione, quanta CPU o memoria richiede, la cosa migliore da fare è fornire molte risorse di memoria e CPU, e poi eseguire test di prestazione.

Oltre ai test di prestazioni, monitora il comportamento dell'applicazione durante la settimana. Se dai grafici risulta che la tua applicazione consuma meno risorse di quelle richieste, puoi diminuire la quantità di CPU o memoria richiesta.

Per esempio, guarda questo dashboard Grafana. Mostra la differenza tra le risorse richieste o il limite delle risorse e l'attuale utilizzo delle risorse.

Conclusione

La richiesta e il limite delle risorse aiutano a mantenere operativo il cluster Kubernetes. Una corretta configurazione dei limiti riduce al minimo i costi e mantiene costantemente le applicazioni in funzionamento.

In sintesi, ci sono alcuni punti da tenere a mente:

  1. Le risorse richieste sono la configurazione considerata durante l'avvio (quando Kubernetes pianifica la collocazione dell'applicazione). Al contrario, il limite delle risorse è importante durante il funzionamento — quando l'applicazione è già in esecuzione su un nodo.
  2. Rispetto alla memoria, la CPU è una risorsa regolabile. In caso di carenza di CPU, il tuo Pod non si fermerà, ma si attiverà il meccanismo di throttling.
  3. Le risorse richieste e i limiti delle risorse non sono valori minimi e massimi! Definendo le risorse richieste, garantite che l'applicazione funzioni senza problemi.
  4. È una buona pratica impostare la richiesta di memoria uguale al limite di memoria.
  5. È bene impostare la richiesta di CPU <=1, se l'applicazione non esegue calcoli complessi.
  6. Se richiedete più risorse di quelle disponibili nel nodo, il Pod non sarà mai programmato su quel nodo.
  7. Per determinare la quantità corretta di risorse richieste/livelli di risorse, utilizzate i test di carico e il monitoraggio.

Spero che questo articolo vi aiuti a comprendere il concetto fondamentale di limitazione delle risorse. E sarete in grado di applicare queste conoscenze nel vostro lavoro.

Buona fortuna!

Cosa altro leggere:

  1. Osservabilità SRE: spazi dei nomi e struttura delle metriche.
  2. 90+ strumenti utili per Kubernetes: deployment, gestione, monitoraggio, sicurezza e altro ancora.
  3. Il nostro canale Attorno a Kubernetes su Telegram.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster