Questa pagina ti aiuta a risolvere i problemi relativi agli eventi Out of Memory (OOM) in Google Kubernetes Engine (GKE). Impara a identificare le cause comuni degli eventi OOM, a distinguere tra occorrenze a livello di contenitore e di nodo e ad applicare le soluzioni.
Questa pagina è dedicata agli sviluppatori di applicazioni che vogliono verificare che le loro app vengano implementate correttamente e agli amministratori e agli operatori della piattaforma che vogliono comprendere la causa principale degli eventi OOM e verificare la configurazione della piattaforma. Per maggiori informazioni sui ruoli comuni e sulle attività di esempio a cui facciamo riferimento nei contenuti di Google Cloud , consulta Ruoli utente e attività comuni di GKE Enterprise.
Cause comuni degli eventi OOM
Gli eventi OOM si verificano in genere durante i picchi di carico o di traffico, quando l'utilizzo della memoria dell'app aumenta e raggiunge il limite di memoria configurato per il container.
I seguenti scenari possono causare un evento OOM:
- Limite di memoria insufficiente: l'impostazione
resources.limits.memory
nel manifest del pod è troppo bassa per le richieste di memoria tipiche o di picco dell'app. - Richieste o limiti di memoria non definiti: se non sono definiti né
resources.limits.memory
néresources.requests.memory
, l'utilizzo della memoria del container è illimitato. - Carico elevato o a picchi: picchi improvvisi ed estremi di carico possono sovraccaricare le risorse di un sistema, inclusa la memoria, anche se i limiti sono generalmente adeguati.
- Perdita di memoria: l'app potrebbe avere un difetto di codice che le impedisce di rilasciare correttamente la memoria.
Gli eventi OOM possono avviare un errore a cascata, perché rimangono meno container per gestire il traffico, aumentando il carico sui container rimanenti. Questi contenitori potrebbero poi essere terminati.
Come Kubernetes gestisce gli eventi OOM
Linux OOM Killer gestisce ogni evento OOM. OOM Killer è un processo del kernel che si attiva quando la memoria del sistema è molto ridotta. Il suo scopo è prevenire un arresto anomalo totale del sistema terminando strategicamente i processi per liberare risorse. Il kernel utilizza un sistema di punteggio per selezionare il processo da arrestare, con l'obiettivo di preservare la stabilità del sistema e ridurre al minimo la perdita di dati.
In un ambiente Kubernetes, OOM Killer opera in due ambiti diversi: il gruppo di controllo (cgroup), che interessa un container, e il sistema, che interessa l'intero nodo.
Terminazione OOM a livello di container
Un arresto anomalo OOM a livello di contenitore si verifica quando un contenitore tenta di superare il limite di memoria predefinito. Kubernetes assegna ogni container a un cgroup specifico con un limite di memoria rigido. Quando l'utilizzo della memoria di un container raggiunge questo limite, il kernel tenta innanzitutto di recuperare la memoria all'interno di questo cgroup. Se il kernel non riesce a recuperare memoria sufficiente utilizzando questo processo, viene richiamato il cgroup OOM Killer. Termina i processi all'interno di quel cgroup specifico per applicare il limite delle risorse.
Quando il processo principale in un container viene terminato in questo modo, Kubernetes osserva
l'evento e contrassegna lo stato del container come OOMKilled
. Il restartPolicy
configurato del pod determina il risultato:
Always
oOnFailure
: il container viene riavviato.Never
: il contenitore non viene riavviato e rimane nello stato Terminato.
Isolando l'errore nel container problematico, OOM Killer impedisce a un singolo pod difettoso di arrestare in modo anomalo l'intero nodo.
In che modo la versione di cgroup influisce sul comportamento di OOM Killer
Il comportamento di OOM kill può variare in modo significativo tra le versioni di cgroup. Se non sai quale versione di cgroup utilizzi, controlla la modalità cgroup dei nodi del cluster.
In
cgroup v1
, un evento OOM all'interno del cgroup di memoria di un container può portare a un comportamento imprevedibile. OOM Killer potrebbe terminare qualsiasi processo all'interno di questo cgroup, inclusi i processi secondari che non sono il processo principale del container (PID 1).Questo comportamento rappresenta una sfida significativa per Kubernetes. Poiché Kubernetes monitora principalmente l'integrità del processo del container principale, non è a conoscenza di questi errori OOM "parziali". Il processo contenitore principale potrebbe continuare a essere eseguito, anche se i processi secondari critici sono stati terminati. Questo comportamento può causare errori sottili dell'app che non sono immediatamente visibili a Kubernetes o agli operatori, ma sono comunque visibili nel journal di sistema del nodo (
journalctl
).cgroup v2
offre un comportamento più prevedibile di OOM Killer.Per garantire l'integrità del workload in un ambiente cgroup v2, OOM killer impedisce le interruzioni parziali e garantisce uno dei due risultati: o tutte le attività appartenenti a quel cgroup e ai suoi discendenti vengono terminate (rendendo l'errore visibile a Kubernetes) oppure, quando il workload non ha attività che utilizzano troppa memoria, il workload viene lasciato intatto e continua a essere eseguito senza interruzioni impreviste dei processi interni.
Per gli scenari in cui vuoi che
cgroup v1
termini un singolo processo, kubelet fornisce il flagsingleProcessOOMKill
percgroup v2
. Questo flag offre un controllo più granulare, consentendo la terminazione di singoli processi durante un evento OOM, anziché l'intero cgroup.
Terminazione OOM a livello di sistema
Un arresto anomalo OOM a livello di sistema è un evento più grave che si verifica quando l'intero nodo, non solo un singolo container, esaurisce la memoria disponibile. Questo evento può verificarsi se l'utilizzo combinato della memoria di tutti i processi (inclusi tutti i pod e i daemon di sistema) supera la capacità del nodo.
Quando questo nodo esaurisce la memoria, OOM Killer globale valuta tutti i processi sul nodo e termina un processo per recuperare memoria per l'intero sistema. Il processo selezionato è in genere di breve durata e utilizza una grande quantità di memoria.
Per evitare gravi situazioni di OOM, Kubernetes utilizza l'espulsione node-pressure per gestire le risorse dei nodi. Questo processo prevede l'espulsione dei pod meno critici da un nodo quando le risorse, come memoria o spazio su disco, stanno per esaurirsi. Un'interruzione OOM a livello di sistema indica che questo processo di rimozione non è riuscito a liberare memoria abbastanza rapidamente da evitare il problema.
Se OOM Killer termina il processo di un container, l'effetto è in genere
identico a un'interruzione attivata da cgroup: il container viene contrassegnato come OOMKilled
e
riavviato in base al criterio. Tuttavia, se un processo di sistema critico viene interrotto
(cosa rara), il nodo stesso potrebbe diventare instabile.
Esamina gli eventi OOM
Le sezioni seguenti ti aiutano a rilevare e confermare un evento OOM, a partire dagli strumenti Kubernetes più semplici e passando all'analisi dei log più dettagliata.
Controlla lo stato del pod per gli eventi OOM visibili
Il primo passo per confermare un evento OOM è verificare se Kubernetes ha osservato
l'evento OOM. Kubernetes osserva l'evento quando il processo principale del container viene interrotto, il che è un comportamento standard negli ambienti cgroup v2
.
Controlla lo stato del pod:
kubectl describe pod POD_NAME
Sostituisci
POD_NAME
con il nome del pod che vuoi esaminare.Se si è verificato un evento OOM visibile, l'output è simile al seguente:
... Last State: Terminated Reason: OOMKilled Exit Code: 137 Started: Tue, 13 May 2025 19:05:28 +0000 Finished: Tue, 13 May 2025 19:05:30 +0000 ...
Se vedi OOMKilled
nel campo Reason
, hai confermato l'evento. Un
Exit Code
di 137
indica anche un'interruzione OOM. Se il campo Reason
ha un
valore diverso o il pod è ancora in esecuzione nonostante gli errori dell'app, vai alla
sezione successiva per ulteriori indagini.
Cercare nei log eventi OOM invisibili
Un'interruzione OOM è "invisibile" a Kubernetes se un processo secondario viene interrotto, ma il
processo del container principale continua a essere eseguito (uno scenario comune negli ambienti cgroup v1
). Devi cercare nei log del nodo per trovare prove di questi eventi.
Per trovare gli errori OOM invisibili, utilizza Esplora log:
Nella console Google Cloud , vai a Esplora log.
Nel riquadro della query, inserisci una delle seguenti query:
Se hai già un pod che ritieni abbia riscontrato un evento OOM, esegui una query su quel pod specifico:
resource.type="k8s_node" jsonPayload.MESSAGE:(("POD_NAME" AND "ContainerDied") OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"
Sostituisci quanto segue:
POD_NAME
: il nome del pod per cui vuoi eseguire una query.CLUSTER_NAME
: il nome del cluster a cui appartiene il pod.
Per scoprire quali pod o nodi hanno riscontrato un evento OOM, esegui una query su tutti i workload GKE:
resource.type="k8s_node" jsonPayload.MESSAGE:("ContainerDied" OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"
Fai clic su Esegui query.
Nell'output, individua gli eventi OOM cercando le voci di log contenenti la stringa
TaskOOM
.(Facoltativo) Se hai cercato eventi OOM per tutti i carichi di lavoro GKE e vuoi identificare il pod specifico che ha riscontrato gli eventi OOM, completa i seguenti passaggi:
- Per ogni evento, prendi nota dell'ID contenitore associato.
Identifica gli arresti dei container cercando voci di log contenenti la stringa
ContainerDied
e che si sono verificate poco dopo gli eventi OOM. Abbina l'ID container dell'evento OOM alla rigaContainerDied
corrispondente.Dopo aver trovato la corrispondenza con
container IDs
, la rigaContainerDied
in genere include il nome del pod associato al container non riuscito. Questo pod è stato interessato dall'evento OOM.
Utilizzare journalctl per informazioni in tempo reale
Se devi eseguire l'analisi in tempo reale del tuo sistema, utilizza i comandi journalctl
.
Connettiti al nodo tramite SSH:
gcloud compute ssh NODE_NAME --location ZONE
Sostituisci quanto segue:
NODE_NAME
: il nome del nodo che vuoi esaminare.ZONE
: la zona di Compute Engine a cui appartiene il tuo nodo.
Nella shell, esplora i messaggi del kernel dal journal di sistema del nodo:
journalctl -k
Analizza l'output per distinguere il tipo di evento:
- Interruzione a livello di contenitore: la voce di log contiene termini come
memory cgroup
,mem_cgroup
omemcg
, che indicano che è stato applicato un limite cgroup. - Interruzione a livello di sistema: la voce di log è un messaggio generale
come
Out of memory: Killed process...
senza menzionare un cgroup.
- Interruzione a livello di contenitore: la voce di log contiene termini come
Risolvere gli eventi OOM
Per risolvere un evento OOM, prova le seguenti soluzioni:
- Aumenta i limiti di memoria: questa è la soluzione più diretta. Modifica il manifest
del pod per fornire un valore
resources.limits.memory
più elevato che tenga conto del picco di utilizzo dell'app. Per ulteriori informazioni sull'impostazione dei limiti, consulta la sezione Gestione delle risorse per pod e container nella documentazione di Kubernetes. - Aggiungi o modifica le richieste di memoria: nel manifest del pod, verifica che il campo
resources.requests.memory
sia impostato su un valore realistico per l'utilizzo tipico. Questa impostazione aiuta Kubernetes a pianificare il pod su un nodo con memoria sufficiente. - Scalare orizzontalmente il workload: per distribuire il carico di traffico e ridurre la pressione sulla memoria di un singolo pod, aumenta il numero di repliche. Per fare in modo che Kubernetes esegua lo scale up proattivo del carico di lavoro, valuta la possibilità di abilitare la scalabilità automatica orizzontale dei pod.
- Scalare verticalmente i nodi: se molti pod su un nodo sono vicini ai limiti, il nodo stesso potrebbe essere troppo piccolo. Per aumentare le dimensioni dei nodi, esegui la migrazione dei workload a un pool di nodi con più memoria. Per consentire a Kubernetes di scalare in modo proattivo i nodi, valuta la possibilità di abilitare la scalabilità automatica pod verticale.
- Ottimizza la tua app: esamina la tua app per identificare e risolvere le perdite di memoria e ottimizza il codice che consuma grandi quantità di memoria durante i picchi di traffico.
- Elimina i carichi di lavoro problematici: come ultima risorsa per i carichi di lavoro non critici, elimina il pod per ridurre immediatamente la pressione sul cluster.
Passaggi successivi
Se non riesci a trovare una soluzione al tuo problema nella documentazione, consulta la sezione Richiedere assistenza per ulteriore aiuto, inclusi consigli sui seguenti argomenti:
- Aprire una richiesta di assistenza contattando l'assistenza clienti cloud.
- Ricevere assistenza dalla community
ponendo domande su StackOverflow e utilizzando il tag
google-kubernetes-engine
per cercare problemi simili. Puoi anche unirti al canale Slack#kubernetes-engine
per ulteriore assistenza della community. - Apertura di bug o richieste di funzionalità utilizzando lo strumento di monitoraggio dei problemi pubblico.