En esta página, se te ayuda a solucionar problemas y resolver eventos de memoria insuficiente (OOM) en Google Kubernetes Engine (GKE). Aprende a identificar las causas comunes de los eventos de OOM, a distinguir entre las ocurrencias a nivel del contenedor y a nivel del nodo, y a aplicar soluciones.
Esta página está dirigida a los desarrolladores de aplicaciones que desean verificar que sus apps se implementaron correctamente y a los administradores y operadores de la plataforma que desean comprender la causa raíz de los eventos de OOM y verificar la configuración de la plataforma. Para obtener más información sobre los roles comunes y las tareas de ejemplo a las que hacemos referencia en el contenido de Google Cloud , consulta Tareas y roles comunes de los usuarios de GKE Enterprise.
Causas comunes de los eventos de OOM
Por lo general, los eventos de OOM se producen durante los aumentos repentinos de carga o tráfico, en los que el uso de memoria de la app aumenta y alcanza el límite de memoria configurado para el contenedor.
Los siguientes casos pueden generar un evento de OOM:
- Límite de memoria insuficiente: El parámetro de configuración
resources.limits.memory
en el manifiesto del Pod es demasiado bajo para las demandas típicas o máximas de memoria de la app. - Solicitudes o límites de memoria no definidos: Si no se definen
resources.limits.memory
niresources.requests.memory
, el uso de memoria del contenedor no está limitado. - Carga alta o repentina: Los aumentos repentinos y extremos en la carga pueden sobrecargar los recursos de un sistema, incluida la memoria, incluso si los límites suelen ser adecuados.
- Fuga de memoria: Es posible que la app tenga un defecto de código que impida que libere la memoria de forma adecuada.
Los eventos de OOM pueden iniciar una falla en cascada, ya que quedan menos contenedores para controlar el tráfico, lo que aumenta la carga en los contenedores restantes. Es posible que también se cierren estos contenedores.
Cómo Kubernetes controla los eventos de OOM
El OOM Killer de Linux controla todos los eventos de OOM. El OOM Killer es un proceso del kernel que se activa cuando el sistema tiene poca memoria. Su objetivo es evitar una falla total del sistema cerrando estratégicamente procesos para liberar recursos. El kernel usa un sistema de puntuación para seleccionar qué proceso detener, con el objetivo de preservar la estabilidad del sistema y minimizar la pérdida de datos.
En un entorno de Kubernetes, el OOM Killer opera en dos ámbitos diferentes: el grupo de control (cgroup), que afecta a un contenedor, y el sistema, que afecta a todo el nodo.
Eliminación por falta de memoria a nivel del contenedor
Un cierre por OOM a nivel del contenedor ocurre cuando un contenedor intenta exceder su límite de memoria predefinido. Kubernetes asigna cada contenedor a un cgroup específico con un límite de memoria fijo. Cuando el uso de memoria de un contenedor alcanza este límite, el kernel primero intenta recuperar memoria dentro de ese cgroup. Si el kernel no puede recuperar suficiente memoria con este proceso, se invoca el OOM Killer del cgroup. Finaliza los procesos dentro de ese cgroup específico para aplicar el límite de recursos.
Cuando el proceso principal de un contenedor finaliza de esta manera, Kubernetes observa el evento y marca el estado del contenedor como OOMKilled
. El restartPolicy
configurado del Pod determina el resultado:
Always
oOnFailure
: Se reinicia el contenedor.Never
: El contenedor no se reinicia y permanece en estado finalizado.
Al aislar la falla en el contenedor infractor, el OOM Killer evita que un solo Pod defectuoso falle en todo el nodo.
Cómo la versión de cgroup afecta el comportamiento de OOM Killer
El comportamiento de la eliminación por falta de memoria puede diferir significativamente entre las versiones de cgroup. Si no sabes qué versión de cgroup usas, verifica el modo de cgroup de los nodos del clúster.
En
cgroup v1
, un evento de OOM dentro del cgroup de memoria de un contenedor puede generar un comportamiento impredecible. El OOM Killer puede finalizar cualquier proceso dentro de ese cgroup, incluidos los procesos secundarios que no son el proceso principal del contenedor (PID 1).Este comportamiento representa un desafío importante para Kubernetes. Dado que Kubernetes supervisa principalmente el estado del proceso del contenedor principal, no detecta estas finalizaciones por falta de memoria "parciales". Es posible que el proceso principal del contenedor siga ejecutándose, incluso si se finalizaron procesos secundarios críticos. Este comportamiento puede provocar fallas sutiles en la app que no son visibles de inmediato para Kubernetes ni para los operadores, pero que sí se pueden ver en el registro del sistema del nodo (
journalctl
).cgroup v2
ofrece un comportamiento más predecible del OOM Killer.Para ayudar a garantizar la integridad de la carga de trabajo en un entorno de cgroup v2, el kernel de OOM evita las eliminaciones parciales y garantiza uno de los dos resultados: o bien se finalizan todas las tareas que pertenecen a ese cgroup y a sus descendientes (lo que hace que la falla sea visible para Kubernetes), o bien, cuando la carga de trabajo no tiene tareas que usen demasiada memoria, la carga de trabajo se deja intacta y continúa ejecutándose sin finalizaciones inesperadas de procesos internos.
Para situaciones en las que deseas el comportamiento de
cgroup v1
de finalizar un solo proceso, kubelet proporciona la marcasingleProcessOOMKill
paracgroup v2
. Esta marca te brinda un control más detallado, ya que permite la finalización de procesos individuales durante un evento de OOM, en lugar de todo el cgroup.
Terminación por falta de memoria a nivel del sistema
Un cierre por OOM a nivel del sistema es un evento más grave que ocurre cuando todo el nodo, no solo un contenedor, se queda sin memoria disponible. Este evento puede ocurrir si el uso de memoria combinado de todos los procesos (incluidos todos los Pods y los daemons del sistema) supera la capacidad del nodo.
Cuando este nodo se queda sin memoria, el OOM Killer global evalúa todos los procesos del nodo y finaliza uno para recuperar memoria para todo el sistema. Por lo general, el proceso seleccionado es de corta duración y usa una gran cantidad de memoria.
Para evitar situaciones graves de OOM, Kubernetes usa el desalojo por presión del nodo para administrar los recursos del nodo. Este proceso implica desalojar los Pods menos críticos de un nodo cuando los recursos, como la memoria o el espacio en el disco, se agotan de forma crítica. Un cierre por OOM a nivel del sistema indica que este proceso de expulsión no pudo liberar memoria lo suficientemente rápido como para evitar el problema.
Si el OOM Killer finaliza el proceso de un contenedor, el efecto suele ser idéntico a una finalización activada por cgroup: el contenedor se marca como OOMKilled
y se reinicia según su política. Sin embargo, si se detiene un proceso crítico del sistema (lo que es poco frecuente), el nodo podría volverse inestable.
Investiga eventos de OOM
En las siguientes secciones, se explica cómo detectar y confirmar un evento de OOM, comenzando con las herramientas de Kubernetes más simples y pasando al análisis de registros más detallado.
Verifica el estado del Pod para detectar eventos de OOM visibles
El primer paso para confirmar un evento de OOM es verificar si Kubernetes observó el evento de OOM. Kubernetes observa el evento cuando se detiene el proceso principal del contenedor, lo que es un comportamiento estándar en los entornos de cgroup v2
.
Inspecciona el estado del Pod:
kubectl describe pod POD_NAME
Reemplaza
POD_NAME
por el nombre del Pod que deseas investigar.Si se produjo un evento de OOM visible, el resultado es similar al siguiente:
... 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 ...
Si ves OOMKilled
en el campo Reason
, confirmaste el evento. Un Exit Code
de 137
también indica una eliminación por falta de memoria. Si el campo Reason
tiene un valor diferente o el Pod sigue en ejecución a pesar de los errores de la app, continúa con la siguiente sección para seguir investigando.
Cómo buscar registros de eventos de OOM invisibles
Kubernetes no detecta la finalización por falta de memoria si se finaliza un proceso secundario, pero el proceso principal del contenedor sigue ejecutándose (una situación común en los entornos de cgroup v1
). Debes buscar en los registros del nodo para encontrar evidencia de estos eventos.
Para encontrar las finalizaciones por falta de memoria invisibles, usa el Explorador de registros:
En la consola de Google Cloud , ve al Explorador de registros.
En el panel de consultas, ingresa una de las siguientes consultas:
Si ya tienes un Pod que crees que experimentó un evento de OOM, consulta ese Pod específico:
resource.type="k8s_node" jsonPayload.MESSAGE:(("POD_NAME" AND "ContainerDied") OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"
Reemplaza lo siguiente:
POD_NAME
: Es el nombre del Pod que deseas consultar.CLUSTER_NAME
: Es el nombre del clúster al que pertenece el Pod.
Para descubrir qué Pods o nodos experimentaron un evento de OOM, consulta todas las cargas de trabajo de GKE:
resource.type="k8s_node" jsonPayload.MESSAGE:("ContainerDied" OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"
Haz clic en Ejecutar consulta.
En el resultado, busca eventos de OOM buscando entradas de registro que contengan la cadena
TaskOOM
.Opcional: Si buscaste eventos de OOM para todas las cargas de trabajo de GKE y quieres identificar el Pod específico que experimentó los eventos de OOM, completa los siguientes pasos:
- Para cada evento, anota el ID del contenedor asociado.
Para identificar las detenciones del contenedor, busca entradas de registro que contengan la cadena
ContainerDied
y que se hayan producido poco después de los eventos de OOM. Haz coincidir el ID del contenedor del evento de OOM con la líneaContainerDied
correspondiente.Después de que coincida el
container IDs
, la líneaContainerDied
suele incluir el nombre del Pod asociado con el contenedor que falló. Este Pod se vio afectado por el evento de OOM.
Usa journalctl para obtener información en tiempo real
Si necesitas realizar un análisis en tiempo real de tu sistema, usa los comandos journalctl
.
Conéctate al nodo con SSH:
gcloud compute ssh NODE_NAME --location ZONE
Reemplaza lo siguiente:
NODE_NAME
: Es el nombre del nodo que deseas examinar.ZONE
: Es la zona de Compute Engine a la que pertenece tu nodo.
En la shell, explora los mensajes del kernel del registro del sistema del nodo:
journalctl -k
Analiza el resultado para distinguir el tipo de evento:
- Eliminación a nivel del contenedor: La entrada de registro contiene términos como
memory cgroup
,mem_cgroup
omemcg
, que indican que se aplicó un límite de cgroup. - Eliminación a nivel del sistema: La entrada de registro es un mensaje general, como
Out of memory: Killed process...
, sin mencionar un cgroup.
- Eliminación a nivel del contenedor: La entrada de registro contiene términos como
Cómo resolver eventos de OOM
Para resolver un evento de OOM, prueba las siguientes soluciones:
- Aumenta los límites de memoria: Esta es la solución más directa. Edita el manifiesto del Pod para proporcionar un valor de
resources.limits.memory
más alto que se adapte al uso máximo de la app. Si deseas obtener más información para establecer límites, consulta Administración de recursos para Pods y contenedores en la documentación de Kubernetes. - Agrega o ajusta las solicitudes de memoria: En el manifiesto del Pod, verifica que el campo
resources.requests.memory
esté establecido en un valor realista para el uso típico. Este parámetro de configuración ayuda a Kubernetes a programar el Pod en un nodo con suficiente memoria. - Escala horizontalmente la carga de trabajo: Para distribuir la carga de tráfico y reducir la presión de memoria en cualquier Pod individual, aumenta la cantidad de réplicas. Para que Kubernetes escale la carga de trabajo de forma proactiva, considera habilitar el ajuste de escala automático horizontal de Pods.
- Aumenta la escala vertical de los nodos: Si muchos Pods en un nodo están cerca de sus límites, es posible que el nodo en sí sea demasiado pequeño. Para aumentar el tamaño de los nodos, migra tus cargas de trabajo a un grupo de nodos con más memoria. Para que Kubernetes escale los nodos de forma proactiva, considera habilitar el ajuste de escala automático vertical de Pods.
- Optimiza tu app: Revisa tu app para identificar y resolver fugas de memoria, y optimiza el código que consume grandes cantidades de memoria durante los picos de tráfico.
- Borra las cargas de trabajo problemáticas: Como último recurso para las cargas de trabajo no críticas, borra el Pod para aliviar de inmediato la presión sobre el clúster.
¿Qué sigue?
Si no encuentras una solución a tu problema en la documentación, consulta Obtener asistencia para obtener más ayuda, incluidos consejos sobre los siguientes temas:
- Abrir un caso de asistencia comunicándose con Atención al cliente de Cloud
- Obtén asistencia de la comunidad haciendo preguntas en StackOverflow y usando la etiqueta
google-kubernetes-engine
para buscar problemas similares. También puedes unirte al canal de Slack#kubernetes-engine
para obtener más asistencia de la comunidad. - Abrir errores o solicitudes de funciones con la herramienta de seguimiento de errores pública