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:
requestsdefinisce la quantità minima di risorse necessarie per schedulare il Pod.limitsrappresenta 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: ContainerCode 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!

