Se os apps do Google Kubernetes Engine (GKE) estiverem apresentando encerramentos inesperados de contêineres, instabilidade ou erros CrashLoopBackOff, isso pode ser devido a eventos de falta
de memória (OOM, na sigla em inglês). Os eventos de OOM ocorrem quando um contêiner ou nó fica sem memória, fazendo com que o OOM Killer do Linux encerre processos para recuperar
recursos.
Use esta página para identificar se um evento de OOM ocorreu no nível do contêiner ou do nó e aplicar estratégias de mitigação eficazes para evitar uma recorrência.
Essas informações são importantes para desenvolvedores de aplicativos que precisam garantir que os aplicativos estejam configurados com solicitações e limites de memória adequados e sem vazamentos de memória. Também é importante para administradores e operadores de plataforma que monitoram a utilização de recursos de nós e garantem que o cluster tenha capacidade de memória adequada para dar suporte às cargas de trabalho implantadas. Para mais informações sobre os papéis comuns e as tarefas de exemplo mencionados no conteúdo do Cloud de Confiance by S3NS , consulte Tarefas e papéis de usuário comuns do GKE.
Causas comuns de eventos de OOM
Os eventos de OOM geralmente ocorrem durante picos de carga ou tráfego, quando o uso da memória do app aumenta e atinge o limite de memória configurado para o contêiner.
Os seguintes cenários podem causar um evento de OOM:
- Limite de memória insuficiente: a configuração
resources.limits.memoryno manifesto do pod é muito baixa para as demandas de memória típicas ou de pico do app. - Solicitações ou limites de memória indefinidos: se
resources.limits.memoryeresources.requests.memorynão estiverem definidos, o uso da memória do contêiner será ilimitado. - Carga alta ou com picos: picos repentinos e extremos de carga podem sobrecarregar os recursos de um sistema, incluindo a memória, mesmo que os limites geralmente sejam adequados.
- Vazamento de memória: o app pode ter um defeito de código que impede a liberação adequada da memória.
Os eventos de OOM podem iniciar uma falha em cascata, porque menos contêineres permanecem para processar o tráfego, aumentando a carga nos contêineres restantes. Esses contêineres também podem ser encerrados.
Como o Kubernetes lida com eventos de OOM
O OOM Killer do Linux lida com todos os eventos de OOM. O OOM Killer é um processo do kernel que é ativado quando o sistema está com pouca memória. O objetivo dele é evitar uma falha total do sistema encerrando estrategicamente processos para liberar recursos. O kernel usa um sistema de pontuação para selecionar qual processo interromper, com o objetivo de preservar a estabilidade do sistema e minimizar a perda de dados.
Em um ambiente do Kubernetes, o OOM Killer opera em dois escopos diferentes: o grupo de controle (cgroup), que afeta um contêiner, e o sistema, que afeta todo o nó.
Encerramento por OOM no nível do contêiner
Uma eliminação por OOM no nível do contêiner ocorre quando um contêiner tenta exceder o limite de memória predefinido. O Kubernetes atribui cada contêiner a um cgroup específico com um limite de memória rígido. Quando o uso da memória de um contêiner atinge esse limite, o kernel tenta primeiro recuperar a memória dentro desse cgroup. Se o kernel não conseguir recuperar memória suficiente usando esse processo, o OOM Killer do cgroup será invocado. Ele encerra processos dentro desse cgroup específico para aplicar o limite de recursos.
Quando o processo principal em um contêiner é encerrado dessa maneira, o Kubernetes observa
o evento e marca o status do contêiner como OOMKilled. O restartPolicy configurado do pod dita o resultado:
AlwaysouOnFailure: o contêiner é reiniciado.Never: o contêiner não é reiniciado e permanece em um estado encerrado.
Ao isolar a falha no contêiner que está causando o problema, o OOM Killer impede que um único pod com defeito cause uma falha em todo o nó.
Como a versão do cgroup afeta o comportamento do OOM Killer
O comportamento de encerramento por OOM pode ser bem diferente entre as versões do cgroup. Se você não tiver certeza de qual versão do cgroup usa, verifique o modo do cgroup dos nós do cluster.
No
cgroup v1, um evento de OOM no cgroup de memória de um contêiner pode levar a um comportamento imprevisível. O OOM Killer pode encerrar qualquer processo dentro desse cgroup, incluindo processos filhos que não são o processo principal do contêiner (PID 1).Esse comportamento apresenta um desafio significativo para o Kubernetes. Como o Kubernetes monitora principalmente a integridade do processo do contêiner principal, ele não detecta essas eliminações "parciais" de OOM. O processo do contêiner principal pode continuar em execução, mesmo que os processos filhos críticos tenham sido encerrados. Esse comportamento pode resultar em falhas sutis no app que não são imediatamente visíveis para o Kubernetes ou para os operadores, mas que ainda são visíveis no diário do sistema do nó (
journalctl).O
cgroup v2oferece um comportamento mais previsível do OOM Killer.Para ajudar a garantir a integridade da carga de trabalho em um ambiente cgroup v2, o eliminador de OOM evita eliminações parciais e garante um de dois resultados: todas as tarefas pertencentes a esse cgroup e seus descendentes são encerradas (tornando a falha visível para o Kubernetes) ou, quando a carga de trabalho não tem tarefas que usam muita memória, ela é deixada intocada e continua a ser executada sem encerramentos inesperados de processos internos.
Para cenários em que você quer o comportamento
cgroup v1de encerrar um único processo, o kubelet fornece a flagsingleProcessOOMKillparacgroup v2. Essa flag oferece um controle mais granular, permitindo o encerramento de processos individuais durante um evento de OOM, em vez de todo o cgroup.
Encerramento por OOM no nível do sistema
Um encerramento por OOM no nível do sistema é um evento mais sério que ocorre quando todo o nó, e não apenas um único contêiner, fica sem memória disponível. Esse evento pode ocorrer se o uso da memória combinado de todos os processos (incluindo todos os pods e daemons do sistema) exceder a capacidade do nó.
Quando esse nó fica sem memória, o OOM Killer global avalia todos os processos no nó e encerra um processo para recuperar memória para todo o sistema. O processo selecionado geralmente é de curta duração e usa uma grande quantidade de memória.
Para evitar situações graves de OOM, o Kubernetes usa a remoção por pressão de nó para gerenciar recursos de nó. Esse processo envolve a remoção de pods menos críticos de um nó quando os recursos, como memória ou espaço em disco, ficam criticamente baixos. Uma eliminação de OOM no nível do sistema indica que esse processo de remoção não conseguiu liberar memória com rapidez suficiente para evitar o problema.
Se o OOM Killer encerrar o processo de um contêiner, o efeito geralmente será
idêntico a um encerramento acionado por cgroup: o contêiner será marcado como OOMKilled e
reiniciado com base na política dele. No entanto, se um processo crítico do sistema for encerrado
(o que é raro), o próprio nó poderá ficar instável.
Investigar eventos de OOM
As seções a seguir ajudam a detectar e confirmar um evento de OOM, começando com as ferramentas mais simples do Kubernetes e passando para uma análise de registros mais detalhada.
Verificar o status do pod para eventos de OOM visíveis
A primeira etapa para confirmar um evento de OOM é verificar se o Kubernetes observou
o evento de OOM. O Kubernetes observa o evento quando o processo principal do contêiner é encerrado, o que é um comportamento padrão em ambientes do cgroup v2.
Inspecione o status do pod:
kubectl describe pod POD_NAMESubstitua
POD_NAMEpelo nome do pod que você quer investigar.Se um evento de OOM visível tiver ocorrido, a saída será semelhante a esta:
... 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 você encontrar OOMKilled no campo Reason, o evento foi confirmado. Um
Exit Code de 137 também indica um encerramento por OOM. Se o campo Reason tiver um
valor diferente ou o pod ainda estiver em execução, apesar dos erros do app, prossiga para a
próxima seção para mais investigações.
Pesquisar registros de eventos de OOM invisíveis
Uma eliminação de OOM é "invisível" para o Kubernetes se um processo filho for eliminado, mas o
processo do contêiner principal continuar em execução (um cenário comum em ambientes
cgroup v1). Pesquise os registros do nó para encontrar evidências desses eventos.
Para encontrar encerramentos invisíveis por falta de memória, use a Análise de Registros:
No console do Cloud de Confiance , acesse a Análise de Registros.
No painel de consulta, digite uma das seguintes consultas:
Se você já tiver um pod que acredita ter passado por um evento de OOM, consulte esse pod específico:
resource.type="k8s_node" jsonPayload.MESSAGE:(("POD_NAME" AND "ContainerDied") OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"Substitua:
POD_NAME: o nome do pod que você quer consultar.CLUSTER_NAME: o nome do cluster ao qual o pod pertence.
Para descobrir quais pods ou nós tiveram um evento de OOM, consulte todas as cargas de trabalho do GKE:
resource.type="k8s_node" jsonPayload.MESSAGE:("ContainerDied" OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"
Clique em Executar consulta.
Na saída, localize eventos de OOM pesquisando entradas de registro que contenham a string
TaskOOM.Opcional: se você pesquisou eventos de OOM para todas as cargas de trabalho do GKE e quer identificar o pod específico que teve os eventos de OOM, siga estas etapas:
- Para cada evento, anote o ID do contêiner associado a ele.
Identifique as interrupções de contêiner procurando entradas de registro que contenham a string
ContainerDiede que tenham ocorrido logo após os eventos de OOM. Faça a correspondência do ID do contêiner do evento OOM com a linhaContainerDiedcorrespondente.Depois de corresponder ao
container IDs, a linhaContainerDiedgeralmente inclui o nome do pod associado ao contêiner com falha. Este pod foi afetado pelo evento de OOM.
Correlacionar eventos de OOM com reinicializações de contêineres
Quando um encerramento por OOM encerra o processo principal de um contêiner, o Kubernetes o reinicia
com base no restartPolicy do pod, conforme descrito em
Encerramento por OOM no nível do contêiner e
Encerramento por OOM no nível do sistema. Para conferir os eventos OOMKilling e as
inicializações de contêiner que os seguem em uma única lista cronológica, use
a Análise de registros:
No console do Cloud de Confiance , acesse a Análise de Registros.
No painel de consulta, digite a seguinte consulta:
log_id("events") resource.labels.cluster_name="CLUSTER_NAME" ( ( resource.type="k8s_pod" resource.labels.namespace_name="NAMESPACE_NAME" jsonPayload.message:"Started container" ) OR ( resource.type="k8s_node" jsonPayload.reason="OOMKilling" ) )Substitua:
CLUSTER_NAME: o nome do cluster que você quer consultar.NAMESPACE_NAME: o namespace dos pods que você quer examinar.
Os eventos
OOMKillingsão informados para o nó (tipo de recursok8s_node), portanto, não têm um rótulo de namespace. O filtro de namespace se aplica apenas a eventosStarted container, que são informados para o pod (tipo de recursok8s_pod).Clique em Executar consulta.
Na saída, procure eventos
Started containerque ocorrem logo após um eventoOOMKillingno mesmo nó. A mensagem de eventoOOMKillingidentifica o processo que foi encerrado, e o eventoStarted containeridentifica o pod e o contêiner que foram iniciados.Nem todo evento
Started containeré causado por um encerramento por OOM. Para confirmar que um contêiner foi reiniciado devido a um evento OOM, verifique o status do pod, conforme descrito em Verificar o status do pod para eventos OOM visíveis.
Usar journalctl para informações em tempo real
Se você precisar realizar uma análise em tempo real do sistema, use os comandos
journalctl.
Conecte-se ao nó usando SSH:
gcloud compute ssh NODE_NAME --location ZONESubstitua:
NODE_NAME: o nome do nó que você quer examinar.ZONE: a zona do Compute Engine a que o nó pertence.
No shell, analise as mensagens do kernel no diário do sistema do nó:
journalctl -kAnalise a saída para distinguir o tipo de evento:
- Encerramento no nível do contêiner: a entrada de registro contém termos como
memory cgroup,mem_cgroupoumemcg, que indicam que um limite de cgroup foi aplicado. - Encerramento no nível do sistema: a entrada de registro é uma mensagem geral,
como
Out of memory: Killed process..., sem mencionar um cgroup.
- Encerramento no nível do contêiner: a entrada de registro contém termos como
Resolver eventos de OOM
Para resolver um evento de OOM, tente as seguintes soluções:
- Aumentar os limites de memória: essa é a solução mais direta. Edite o manifesto do pod para fornecer um valor de
resources.limits.memorymais alto que acomode o pico de uso do app. Para mais informações sobre como definir limites, consulte Gerenciamento de recursos para pods e contêineres na documentação do Kubernetes. - Adicionar ou ajustar solicitações de memória: no manifesto do pod, verifique se
o campo
resources.requests.memoryestá definido como um valor realista para o uso típico. Essa configuração ajuda o Kubernetes a programar o pod em um nó com memória suficiente. - Escalonar horizontalmente a carga de trabalho: para distribuir a carga de tráfego e reduzir a pressão de memória em qualquer pod, aumente o número de réplicas. Para que o Kubernetes escalone a carga de trabalho de maneira proativa, ative o escalonamento automático horizontal de pods.
- Escalonar os nós verticalmente: se muitos pods em um nó estiverem próximos dos limites, o próprio nó poderá ser muito pequeno. Para aumentar o tamanho dos nós, migre as cargas de trabalho para um pool de nós com mais memória. Para que o Kubernetes escalone os nós de maneira proativa, considere ativar o escalonamento automático vertical de pods.
- Otimize seu app: revise o app para identificar e resolver vazamentos de memória e otimize o código que consome grandes quantidades de memória durante picos de tráfego.
- Excluir cargas de trabalho problemáticas: como último recurso para cargas de trabalho não críticas, exclua o pod para aliviar imediatamente a pressão no cluster.
A seguir
Se você não encontrar uma solução para seu problema na documentação, consulte Receber suporte para mais ajuda, incluindo conselhos sobre os seguintes tópicos:
- Abrir um caso de suporte entrando em contato com o Cloud Customer Care.
- Receber suporte da comunidade fazendo perguntas no StackOverflow e usando a tag
google-kubernetes-enginepara pesquisar problemas semelhantes. Você também pode participar do canal do Slack#kubernetes-enginepara receber mais suporte da comunidade. - Abrir problemas ou solicitações de recursos usando o Issue Tracker público.