Si vos applications Google Kubernetes Engine (GKE) rencontrent des arrêts de conteneur inattendus, une instabilité ou des erreurs CrashLoopBackOff, cela peut être dû à des événements de mémoire insuffisante (OOM). Les événements de mémoire insuffisante se produisent lorsqu'un conteneur ou un nœud manque de mémoire, ce qui entraîne l'arrêt des processus par le robot tueur OOM Linux pour récupérer des ressources.
Utilisez cette page pour déterminer si un événement OOM s'est produit au niveau du conteneur ou du nœud, et appliquez des stratégies d'atténuation efficaces pour éviter qu'il ne se reproduise.
Ces informations sont importantes pour les développeurs d'applications qui doivent s'assurer que leurs applications sont configurées avec des demandes et des limites de mémoire appropriées, et qu'elles ne présentent pas de fuites de mémoire. Il est également important pour les administrateurs et les opérateurs de plate-forme qui surveillent l'utilisation des ressources des nœuds et s'assurent que le cluster dispose d'une capacité de mémoire suffisante pour prendre en charge les charges de travail déployées. Pour en savoir plus sur les rôles courants et les exemples de tâches que nous citons dans le contenu Google Cloud , consultez Rôles utilisateur et tâches courantes de GKE.
Causes courantes des événements OOM
Les événements OOM se produisent généralement lors de pics de charge ou de trafic, lorsque l'utilisation de la mémoire de l'application augmente et atteint la limite de mémoire configurée pour le conteneur.
Les scénarios suivants peuvent provoquer un événement OOM :
- Limite de mémoire insuffisante : le paramètre
resources.limits.memorydans le fichier manifeste du pod est trop faible pour les demandes de mémoire typiques ou maximales de l'application. - Demandes ou limites de mémoire non définies : si
resources.limits.memoryetresources.requests.memoryne sont pas définis, l'utilisation de la mémoire du conteneur n'est pas limitée. - Charge élevée ou pics de charge : des pics de charge soudains et extrêmes peuvent saturer les ressources d'un système, y compris la mémoire, même si les limites sont généralement adéquates.
- Fuite de mémoire : l'application peut présenter un défaut de code qui l'empêche de libérer correctement de la mémoire.
Les événements OOM peuvent déclencher une défaillance en cascade, car il reste moins de conteneurs pour gérer le trafic, ce qui augmente la charge sur les conteneurs restants. Ces conteneurs peuvent alors également être arrêtés.
Comment Kubernetes gère les événements OOM
Le tueur OOM Linux gère chaque événement OOM. Le tueur OOM est un processus du kernel qui s'active lorsque la mémoire du système est très faible. Son but est d'empêcher un plantage total du système en mettant fin de manière stratégique à des processus pour libérer des ressources. Le noyau utilise un système de notation pour sélectionner le processus à arrêter, dans le but de préserver la stabilité du système et de minimiser la perte de données.
Dans un environnement Kubernetes, l'OOM Killer fonctionne à deux niveaux différents : le groupe de contrôle (cgroup), qui affecte un conteneur, et le système, qui affecte l'ensemble du nœud.
Arrêt OOM au niveau du conteneur
Un arrêt OOM au niveau du conteneur se produit lorsqu'un conteneur tente de dépasser sa limite de mémoire prédéfinie. Kubernetes attribue chaque conteneur à un cgroup spécifique avec une limite de mémoire stricte. Lorsque l'utilisation de la mémoire d'un conteneur atteint cette limite, le noyau tente d'abord de récupérer de la mémoire dans ce cgroup. Si le noyau ne peut pas récupérer suffisamment de mémoire à l'aide de ce processus, le tueur OOM du cgroup est appelé. Il met fin aux processus au sein de ce cgroup spécifique pour appliquer la limite de ressources.
Lorsque le processus principal d'un conteneur est arrêté de cette manière, Kubernetes observe l'événement et marque l'état du conteneur comme OOMKilled. Le restartPolicy configuré du pod détermine ensuite le résultat :
AlwaysouOnFailure: le conteneur est redémarré.Never: le conteneur n'est pas redémarré et reste à l'état "arrêté".
En isolant la défaillance au conteneur incriminé, l'OOM Killer empêche un seul pod défaillant de faire planter l'ensemble du nœud.
Impact de la version de cgroup sur le comportement d'OOM Killer
Le comportement d'arrêt OOM peut varier considérablement d'une version de cgroup à l'autre. Si vous ne savez pas quelle version de cgroup vous utilisez, vérifiez le mode cgroup des nœuds de cluster.
Dans
cgroup v1, un événement de mémoire insuffisante dans le cgroup de mémoire d'un conteneur peut entraîner un comportement imprévisible. Le tueur OOM peut arrêter n'importe quel processus au sein de ce cgroup, y compris les processus enfants qui ne sont pas le processus principal du conteneur (PID 1).Ce comportement présente un défi de taille pour Kubernetes. Étant donné que Kubernetes surveille principalement l'état du processus du conteneur principal, il n'est pas informé de ces arrêts "partiels" pour cause de mémoire insuffisante. Le processus du conteneur principal peut continuer à s'exécuter, même si des processus enfants critiques ont été arrêtés. Ce comportement peut entraîner des défaillances subtiles de l'application qui ne sont pas immédiatement visibles par Kubernetes ou par les opérateurs, mais qui sont toujours visibles dans le journal système du nœud (
journalctl).cgroup v2offre un comportement plus prévisible du tueur OOM.Pour garantir l'intégrité de la charge de travail dans un environnement cgroup v2, le tueur OOM empêche les arrêts partiels et garantit l'un des deux résultats suivants : soit toutes les tâches appartenant à ce cgroup et à ses descendants sont arrêtées (rendant l'échec visible par Kubernetes), soit lorsque la charge de travail ne comporte aucune tâche utilisant trop de mémoire, la charge de travail reste intacte et continue de s'exécuter sans arrêt inattendu du processus interne.
Pour les scénarios dans lesquels vous souhaitez que le comportement
cgroup v1mette fin à un seul processus, kubelet fournit l'optionsingleProcessOOMKillpourcgroup v2. Cette option vous offre un contrôle plus précis, ce qui permet d'arrêter des processus individuels lors d'un événement OOM, plutôt que l'ensemble du cgroup.
Arrêt pour cause de mémoire insuffisante (OOM) au niveau du système
Un arrêt pour cause de mémoire insuffisante au niveau du système est un événement plus grave qui se produit lorsque l'ensemble du nœud, et pas seulement un seul conteneur, manque de mémoire disponible. Cet événement peut se produire si l'utilisation combinée de la mémoire de tous les processus (y compris tous les pods et les daemons système) dépasse la capacité du nœud.
Lorsque ce nœud manque de mémoire, le robot tueur OOM global évalue tous les processus du nœud et met fin à un processus pour récupérer de la mémoire pour l'ensemble du système. Le processus sélectionné est généralement un processus de courte durée qui utilise une grande quantité de mémoire.
Pour éviter les situations de mémoire insuffisante graves, Kubernetes utilise l'éviction par pression sur les nœuds pour gérer les ressources des nœuds. Ce processus implique l'éviction des pods moins critiques d'un nœud lorsque les ressources, telles que la mémoire ou l'espace disque, deviennent extrêmement faibles. Un arrêt OOM au niveau du système indique que ce processus d'éviction n'a pas pu libérer de la mémoire assez rapidement pour éviter le problème.
Si l'OOM Killer met fin au processus d'un conteneur, l'effet est généralement identique à un arrêt déclenché par un cgroup : le conteneur est marqué OOMKilled et redémarré en fonction de sa règle. Toutefois, si un processus système critique est arrêté (ce qui est rare), le nœud lui-même peut devenir instable.
Examiner les événements de mémoire insuffisante
Les sections suivantes vous aident à détecter et à confirmer un événement OOM, en commençant par les outils Kubernetes les plus simples, puis en passant à une analyse plus détaillée des journaux.
Vérifier l'état du pod pour détecter les événements OOM visibles
La première étape pour confirmer un événement OOM consiste à vérifier si Kubernetes l'a observé. Kubernetes observe l'événement lorsque le processus principal du conteneur est arrêté, ce qui est un comportement standard dans les environnements cgroup v2.
Inspectez l'état du pod :
kubectl describe pod POD_NAMERemplacez
POD_NAMEpar le nom du pod que vous souhaitez examiner.Si un événement OOM visible s'est produit, le résultat ressemble à ce qui suit :
... 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 vous voyez OOMKilled dans le champ Reason, cela signifie que vous avez confirmé l'événement. Un Exit Code de 137 indique également un arrêt OOM. Si le champ Reason a une valeur différente ou si le pod est toujours en cours d'exécution malgré les erreurs de l'application, passez à la section suivante pour approfondir l'analyse.
Rechercher des événements OOM invisibles dans les journaux
Un arrêt OOM est "invisible" pour Kubernetes si un processus enfant est arrêté, mais que le processus du conteneur principal continue de s'exécuter (scénario courant dans les environnements cgroup v1). Vous devez rechercher les journaux du nœud pour trouver des preuves de ces événements.
Pour trouver les arrêts OOM invisibles, utilisez l'explorateur de journaux :
Dans la console Google Cloud , accédez à l'explorateur de journaux.
Dans le volet de requête, saisissez l'une des requêtes suivantes :
Si vous disposez déjà d'un pod qui, selon vous, a rencontré un événement OOM, interrogez ce pod spécifique :
resource.type="k8s_node" jsonPayload.MESSAGE:(("POD_NAME" AND "ContainerDied") OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"Remplacez les éléments suivants :
POD_NAME: nom du pod que vous souhaitez interroger.CLUSTER_NAME: nom du cluster auquel appartient le pod.
Pour découvrir quels pods ou nœuds ont rencontré un événement OOM, interrogez toutes les charges de travail GKE :
resource.type="k8s_node" jsonPayload.MESSAGE:("ContainerDied" OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"
Cliquez sur Exécuter la requête.
Dans le résultat, localisez les événements OOM en recherchant les entrées de journal contenant la chaîne
TaskOOM.Facultatif : Si vous avez recherché des événements de mémoire insuffisante pour toutes les charges de travail GKE et que vous souhaitez identifier le pod spécifique qui a rencontré ces événements, procédez comme suit :
- Pour chaque événement, notez l'ID de conteneur qui lui est associé.
Identifiez les arrêts de conteneur en recherchant les entrées de journal contenant la chaîne
ContainerDiedet qui se sont produites peu de temps après les événements OOM. Faites correspondre l'ID de conteneur de l'événement OOM à la ligneContainerDiedcorrespondante.Une fois que vous avez mis en correspondance
container IDs, la ligneContainerDiedinclut généralement le nom du pod associé au conteneur défaillant. Ce pod a été affecté par l'événement OOM.
Corréler les événements de mémoire insuffisante avec les redémarrages de conteneurs
Lorsqu'un arrêt OOM met fin au processus principal d'un conteneur, Kubernetes redémarre le conteneur en fonction de la valeur restartPolicy du pod, comme décrit dans Arrêt OOM au niveau du conteneur et Arrêt OOM au niveau du système. Pour afficher les événements OOMKilling et les démarrages de conteneurs qui les suivent dans une seule liste chronologique, utilisez l'explorateur de journaux :
Dans la console Google Cloud , accédez à l'explorateur de journaux.
Dans le volet de requête, saisissez la requête suivante :
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" ) )Remplacez les éléments suivants :
CLUSTER_NAME: nom du cluster que vous souhaitez interroger.NAMESPACE_NAME: espace de noms des pods que vous souhaitez examiner.
Les événements
OOMKillingsont signalés pour le nœud (type de ressourcek8s_node). Ils n'ont donc pas d'étiquette d'espace de noms. Le filtre d'espace de noms ne s'applique qu'aux événementsStarted container, qui sont signalés pour le pod (type de ressourcek8s_pod).Cliquez sur Exécuter la requête.
Dans le résultat, recherchez les événements
Started containerqui se produisent peu de temps après un événementOOMKillingsur le même nœud. Le message d'événementOOMKillingidentifie le processus qui a été arrêté, et l'événementStarted containeridentifie le pod et le conteneur qui ont démarré.Tous les événements
Started containerne sont pas causés par un arrêt OOM. Pour confirmer qu'un conteneur a été redémarré en raison d'un événement OOM, vérifiez l'état du pod comme décrit dans Vérifier l'état du pod pour les événements OOM visibles.
Utiliser journalctl pour obtenir des informations en temps réel
Si vous devez effectuer une analyse en temps réel de votre système, utilisez les commandes journalctl.
Connectez-vous au nœud à l'aide de SSH :
gcloud compute ssh NODE_NAME --location ZONERemplacez les éléments suivants :
NODE_NAME: nom du nœud que vous souhaitez examiner.ZONE: zone Compute Engine à laquelle appartient votre nœud.
Dans le shell, explorez les messages du noyau à partir du journal système du nœud :
journalctl -kAnalysez le résultat pour distinguer le type d'événement :
- Arrêt au niveau du conteneur : l'entrée de journal contient des termes tels que
memory cgroup,mem_cgroupoumemcg, qui indiquent qu'une limite de cgroup a été appliquée. - Arrêt au niveau du système : l'entrée de journal est un message général tel que
Out of memory: Killed process..., sans mentionner de cgroup.
- Arrêt au niveau du conteneur : l'entrée de journal contient des termes tels que
Résoudre les événements OOM
Pour résoudre un événement OOM, essayez les solutions suivantes :
- Augmentez les limites de mémoire : c'est la solution la plus directe. Modifiez le fichier manifeste du pod pour fournir une valeur
resources.limits.memoryplus élevée qui s'adapte à l'utilisation maximale de l'application. Pour en savoir plus sur la définition de limites, consultez Gestion des ressources pour les pods et les conteneurs dans la documentation Kubernetes. - Ajouter ou ajuster les demandes de mémoire : dans le fichier manifeste du pod, vérifiez que le champ
resources.requests.memoryest défini sur une valeur réaliste pour une utilisation standard. Ce paramètre aide Kubernetes à planifier le pod sur un nœud disposant de suffisamment de mémoire. - Utilisez le scaling horizontal de la charge de travail : pour répartir la charge de trafic et réduire la pression de la mémoire sur un seul pod, augmentez le nombre d'instances répliquées. Pour que Kubernetes effectue un scaling proactif de la charge de travail, envisagez d'activer l'autoscaling horizontal des pods.
- Effectuez un scaling vertical des nœuds : si de nombreux pods d'un nœud sont proches de leurs limites, le nœud lui-même est peut-être trop petit. Pour augmenter la taille des nœuds, migrez vos charges de travail vers un pool de nœuds disposant de plus de mémoire. Pour que Kubernetes effectue un scaling proactif des nœuds, envisagez d'activer l'autoscaling vertical des pods.
- Optimisez votre application : examinez votre application pour identifier et résoudre les fuites de mémoire, et optimisez le code qui consomme de grandes quantités de mémoire lors des pics de trafic.
- Supprimer les charges de travail problématiques : en dernier recours pour les charges de travail non critiques, supprimez le pod pour soulager immédiatement la pression sur le cluster.
Étapes suivantes
Si vous ne trouvez pas de solution à votre problème dans la documentation, consultez Obtenir de l'aide pour bénéficier d'une assistance supplémentaire, y compris des conseils sur les sujets suivants :
- Ouvrir une demande d'assistance en contactant Cloud Customer Care.
- Obtenir de l'aide de la communauté en posant des questions sur Stack Overflow et en utilisant le tag
google-kubernetes-enginepour rechercher des problèmes similaires. Vous pouvez également rejoindre le canal Slack#kubernetes-enginepour obtenir une assistance supplémentaire de la communauté. - Signaler des problèmes ou demander des fonctionnalités à l'aide de l'outil public de suivi des problèmes.