
Hai mai notato che, scrivendo la definizione minima di un Pod, compare un warning che ti segnala l’assenza del campo resources
?

One or more containers do not have resources - this can cause noisy neighbor issues
Cosa significa esattamente quel messaggio? Facciamo un passo indietro e partiamo dalle basi.
Cos’è un Pod?
Come possiamo leggere dalla documentazione un Pod è la più piccola unità eseguibile in Kubernetes. Può contenere uno o più container che condividono alcune risorse di sistema, come il networking e lo storage.
Per creare un Pod con la configurazione minima ti basta definire il nome, almeno un container e l’immagine da utilizzare. Con kubectl si può fare direttamente con: kubectl run --image=nginx nginx
Pod schedulato! Ma… senza specificare quante risorse potrà usare.
Le risorse di un Pod
Nel campo resources
si può definire quanto un container richiede e quale sarà il limite massimo delle risorse che potrà usare:
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr
image: vish/stress
resources:
limits:
cpu: "1"
requests:
cpu: "0.5"
Code language: JavaScript (javascript)
In questo esempio:
requests
definisce la quantità minima di risorse necessarie per schedulare il Pod.limits
rappresenta il massimo che il container potrà utilizzare.
Se le risorse richieste (requests
) non sono disponibili, il Pod resterà in stato Pending e non verrà schedulato. Se invece viene schedulato e consuma più di quanto indicato in limits
, il container potrà essere penalizzato o terminato, a seconda del tipo di risorsa.
Nel nostro esempio il container chiede 0.5 CPU e può usarne al massimo 1. Ma che succede se omettiamo completamente il campo resources
? In quel caso, il container potrebbe teoricamente prendersi tutte le risorse del nodo: CPU, memoria, tutto. Ed è qui che entra in gioco il problema del noisy neighbor: un container rumoroso che si prende tutto per sé, rallentando o bloccando gli altri Pod, proprio come un vicino che mette la musica a tutto volume.
Come possiamo prevenire questo comportamento?
LimitRange e ResourceQuota
Kubernetes ci viene in soccorso con due risorse utilissime: LimitRange e ResourceQuota. Entrambe funzionano a livello di Namespace.
LimitRange
Con un LimitRange
si possono:
- Definire valori di default, che verranno applicati ai Pod/container che non specificano risorse.
- Impostare valori minimi e massimi.
I LimitRange ci permettono di definire dei valori di default, e anche dei valori minimi e massimi. Quando un container viene schedulato senza risorse il LimitRanger admission controller* provvederà ad applicare i default predefiniti. Nel caso in cui invece le risorse fossero definite allora provvederà semplicemente a verificare che rientrino nei valori stabiliti.
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-resource-constraint
spec:
limits:
- default:
cpu: 500m
defaultRequest:
cpu: 500m
max:
cpu: "1"
min:
cpu: 100m
type: Container
Code language: JavaScript (javascript)
⚠️ Nota: il LimitRange
funziona grazie all’admission controller LimitRanger
, che intercetta le richieste in ingresso. Quindi si applica solo ai nuovi Pod, non a quelli già schedulati.
ResourceQuota
Le ResourceQuota invece permettono di definire dei limiti totali per l’intero Namespace: CPU, memoria, numero di Pod, storage, ecc. È come mettere un tetto massimo al consumo complessivo. Puoi anche filtrare le risorse da conteggiare usando uno scopeSelector. Ad esempio:
apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-medium
spec:
hard:
cpu: "10"
memory: "20Gi"
pods: "10"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["medium"]
Code language: JavaScript (javascript)
In questo caso stiamo contando solo le risorse associate ai Pod con PriorityClass “medium”.
Conclusione
LimitRange e ResourceQuota sono strumenti fondamentali per garantire un utilizzo corretto e bilanciato delle risorse all’interno di un cluster Kubernetes. Anche se spesso introdotti come strumenti per l’amministrazione, possono rivelarsi estremamente utili anche per chi sviluppa: sapere che esistono, e come funzionano, può aiutarti a capire perché un workload non viene schedulato, o viene improvvisamente terminato.
Imparare a leggere questi segnali e impostare correttamente le risorse ti permette non solo di evitare errori difficili da diagnosticare, ma anche di scrivere manifest in maniera più consapevole, pronti per la produzione!