Résoudre les problèmes

Découvrez les étapes de dépannage qui pourraient vous être utiles si vous rencontrez des problèmes avec Google Kubernetes Engine (GKE).

Déboguer les ressources Kubernetes

Si vous rencontrez un problème lié à votre cluster, reportez-vous à la section relative au dépannage des clusters dans la documentation de Kubernetes.

Si vous rencontrez un problème avec votre application, ses pods ou son objet contrôleur, reportez-vous à la section relative au dépannage des applications.

La commande kubectl est introuvable.

  1. Installez le binaire kubectl en exécutant la commande suivante :

    sudo gcloud components update kubectl
    
  2. Répondez "Oui" lorsque le programme d'installation vous invite à modifier votre variable d'environnement $PATH. La modification de cette variable vous permet d'utiliser les commandes kubectl sans avoir besoin de saisir leur chemin d'accès complet.

    Vous pouvez également ajouter la ligne suivante à ~/.bashrc (ou à ~/.bash_profile sous macOS, ou dans tout fichier où votre interface système stocke les variables d'environnement) :

    export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/
    
  3. Exécutez la commande suivante pour charger votre fichier .bashrc ou .bash_profile mis à jour :

    source ~/.bashrc
    

Les commandes kubectl renvoient une erreur de connexion refusée

Définissez le contexte du cluster avec la commande suivante :

gcloud container clusters get-credentials cluster-name

Si vous ne savez pas quoi indiquer pour cluster-name, utilisez la commande suivante pour répertorier vos clusters :

gcloud container clusters list

Les commandes kubectl renvoient une erreur d'échec de négociation d'une version d'API

Assurez-vous que kubectl dispose d'identifiants d'authentification :

gcloud auth application-default login

Les commandes kubectl logs, attach, exec et port-forward cessent de répondre

Ces commandes dépendent de la capacité du plan de contrôle du cluster à communiquer avec les nœuds du cluster. Toutefois, comme le plan de contrôle ne fait pas partie du même réseau Compute Engine que les nœuds de votre cluster, nous nous appuyons sur des tunnels SSH pour une communication sécurisée.

GKE enregistre un fichier de clé publique SSH dans les métadonnées de votre projet Compute Engine. Toutes les VM Compute Engine utilisant des images fournies par Google vérifient régulièrement les métadonnées communes de leur projet et celles de leur instance pour détecter les clés SSH à ajouter à la liste des utilisateurs autorisés de la VM. GKE ajoute également à votre réseau Compute Engine une règle de pare-feu qui autorise l'accès SSH à chaque nœud du cluster à partir de l'adresse IP du plan de contrôle.

Si l'une des commandes kubectl ci-dessus ne s'exécute pas, il est probable que le serveur d'API n'est pas en mesure d'ouvrir les tunnels SSH avec les nœuds. Penchez-vous sur ces causes potentielles :

  1. Le cluster ne comporte aucun nœud.

    Si vous avez réduit à zéro le nombre de nœuds du cluster, les tunnels SSH ne fonctionnent pas.

    Pour résoudre ce problème, redimensionnez le cluster afin de disposer d'au moins un nœud.

  2. Les pods du cluster se sont bloqués dans un état d'arrêt et ont empêché la suppression des nœuds qui n'existent plus.

    Ce problème ne doit concerner que la version 1.1 de Kubernetes, mais peut être dû à un redimensionnement répété du cluster.

    Pour résoudre ce problème, supprimez les pods placés dans un état d'arrêt depuis quelques minutes au minimum. Les anciens nœuds sont alors supprimés du plan de contrôle et remplacés par les nouveaux nœuds.

  3. Les règles de pare-feu de votre réseau n'autorisent pas l'accès SSH au plan de contrôle.

    Tous les réseaux Compute Engine sont créés avec une règle de pare-feu appelée default-allow-ssh qui autorise l'accès SSH à partir de toutes les adresses IP (clé privée valide requise). GKE insère également une règle SSH pour chaque cluster public sous la forme gke-cluster-name-random-characters-ssh. Cette règle autorise l'accès SSH spécifiquement à partir de l'adresse IP du plan de contrôle vers les nœuds du cluster. Si aucune de ces règles n'existe, le plan de contrôle ne peut pas ouvrir les tunnels SSH.

    Pour résoudre ce problème, ajoutez à nouveau une règle de pare-feu permettant d'accéder aux VM avec le tag présent sur tous les nœuds du cluster à partir de l'adresse IP du plan de contrôle.

  4. L'entrée des métadonnées communes de votre projet pour "ssh-keys" est saturée.

    Si l'entrée des métadonnées du projet nommée "ssh-keys" est proche de la limite de taille, GKE ne peut pas ajouter sa propre clé SSH permettant l'ouverture des tunnels SSH. Vous pouvez voir les métadonnées de votre projet en exécutant la commande suivante :

    gcloud compute project-info describe [--project=PROJECT]
    

    Ensuite, vérifiez la longueur de la liste des clés SSH.

    Pour résoudre ce problème, supprimez des clés SSH dont vous n'avez plus besoin.

  5. Vous avez défini un champ de métadonnées avec la clé "ssh-keys" sur les VM du cluster.

    L'agent de nœud sur les VM utilise préférentiellement les clés SSH propres à une instance plutôt que celles définies à l'échelle du projet. Par conséquent, si vous avez défini des clés SSH spécifiquement sur les nœuds du cluster, la clé SSH du plan de contrôle dans les métadonnées du projet n'est pas respectée par les nœuds. Pour effectuer une vérification, exécutez la commande gcloud compute instances describe <VM-name> et recherchez un champ "ssh-keys" dans les métadonnées.

    Pour résoudre ce problème, supprimez les clés SSH d'instance des métadonnées de l'instance.

Notez que ces fonctionnalités ne sont pas requises au fonctionnement correct du cluster. Si vous préférez empêcher tout accès extérieur au réseau de votre cluster, sachez que ces fonctionnalités ne sont pas opérationnelles.

La version du nœud n'est pas compatible avec la version du plan de contrôle

Vérifiez la version de Kubernetes exécutée par le plan de contrôle de votre cluster, puis vérifiez la version de Kubernetes exécutée par les pools de nœuds de votre cluster. Si l'un des pools de nœuds du cluster a plus de deux versions mineures antérieures au plan de contrôle, cela peut être dû à des problèmes avec votre cluster.

L'équipe GKE effectue régulièrement des mises à niveau du plan de contrôle du cluster en votre nom. Les plans de contrôle sont mis à niveau vers les versions stables les plus récentes de Kubernetes. Par défaut, la mise à niveau automatique est activée sur les nœuds d'un cluster. Nous vous recommandons de ne pas la désactiver.

Si la mise à niveau automatique est désactivée pour les nœuds d'un cluster et que vous ne mettez pas à niveau manuellement la version du pool de nœuds vers une version compatible avec le plan de contrôle, votre plan de contrôle finira par être incompatible avec vos nœuds, car le plan de contrôle est automatiquement mis à niveau au fil du temps. Une incompatibilité entre le plan de contrôle de votre cluster et les nœuds peut provoquer des problèmes inattendus.

Les règles de compatibilité de la version de Kubernetes et du décalage de version garantissent que les plans de contrôle sont compatibles avec les nœuds jusqu'à deux versions mineures antérieures à celle du plan de contrôle. Par exemple, les plans de contrôle Kubernetes 1.19 sont compatibles avec les nœuds Kubernetes 1.19, 1.18 et 1.17. Pour résoudre ce problème, mettez à niveau manuellement la version du pool de nœuds vers une version compatible avec le plan de contrôle.

Si vous craignez que le processus de mise à niveau entraîne des perturbations pour les charges de travail s'exécutant sur les nœuds affectés, suivez les étapes décrites dans la section sur la migration des charges de travail du tutoriel concernant la migration des charges de travail vers différents types de machines. Ces étapes vous permettent de migrer correctement en créant un pool de nœuds, puis en confinant et en drainant l'ancien pool de nœuds.

Les métriques de votre cluster n'apparaissent pas dans Cloud Monitoring

Vérifiez que vous avez activé l'API Cloud Monitoring et l'API Cloud Logging sur votre projet, et que vous pouvez afficher votre projet dans Cloud Monitoring.

Si le problème persiste, penchez-vous sur les causes potentielles suivantes :

  1. Assurez-vous que vous avez activé la surveillance sur votre cluster.

    La surveillance est activée par défaut pour les clusters créés à partir de Google Cloud Console et de l'outil de ligne de commande gcloud, mais vous pouvez vérifier que c'est bien le cas en exécutant la commande suivante ou en cliquant sur les détails du cluster Cloud Console :

    gcloud container clusters describe cluster-name
    

    Le résultat de cette commande doit indiquer que le "monitoringService" est "monitoring.googleapis.com" et Cloud Monitoring doit être activé dans Cloud Console.

    Si la surveillance n'est pas activée, exécutez la commande suivante pour l'activer :

    gcloud container clusters update cluster-name --monitoring-service=monitoring.googleapis.com
    
  2. Depuis combien de temps votre cluster a-t-il été créé ou sa surveillance activée ?

    L'apparition des métriques d'un nouveau cluster dans Cloud Monitoring peut prendre jusqu'à une heure.

  3. Est-ce qu'un pod heapster ou gke-metrics-agent (OpenTelemetry Collector) s'exécute dans votre cluster dans l'espace de noms "kube-system" ?

    Ce pod ne parvient peut-être pas à planifier les charges de travail parce que votre cluster manque de ressources. Vérifiez que Heapster ou OpenTelementry est en cours d'exécution en ayant recours à la commande kubectl get pods --namespace=kube-system et en recherchant les pods dont le nom contient heapster ou gke-metrics-agent.

  4. Le plan de contrôle de votre cluster est-il capable de communiquer avec les nœuds ?

    Cloud Monitoring s'appuie sur cette capacité. Pour vérifier que Cloud Monitoring n'est pas bloqué par un problème de communication, exécutez la commande suivante :

    kubectl logs pod-name
    

    Si cette commande renvoie une erreur, le problème peut être causé par les tunnels SSH. Pour en savoir plus, consultez cette section.

Si vous rencontrez un problème lié à l'agent Cloud Logging, consultez sa documentation de dépannage.

Pour en savoir plus, consultez la documentation de Logging.

Erreur 404 : ressource introuvable lors de l'appel des commandes gcloud container

Ré-authentifiez-vous sur l'outil de ligne de commande gcloud :

gcloud auth login

Erreur 400/403 : le compte n'est pas autorisé à apporter des modifications

Votre compte de service Compute Engine par défaut ou le compte de service associé à GKE a été supprimé ou modifié manuellement.

Lorsque vous activez l'API Compute Engine ou Kubernetes Engine, un compte de service est créé et doté d'autorisations de modification sur votre projet. Si, à un moment donné, vous modifiez les autorisations, supprimez le rôle d'agent de service Kubernetes Engine, supprimez entièrement le compte ou désactivez l'API, alors la création du cluster et toutes les fonctionnalités de gestion échouent.

Le nom de votre compte de service Google Kubernetes Engine se présente comme suit, où project-number est votre numéro de projet :

service-project-number@container-engine-robot.iam.gserviceaccount.com

Pour résoudre le problème, si vous avez supprimé le rôle Agent de service Kubernetes Engine de votre compte de service Google Kubernetes Engine, ajoutez-le à nouveau. Sinon, vous devez réactiver l'API Kubernetes Engine afin de restaurer correctement vos comptes de service et vos autorisations. Pour ce faire, utilisez l'outil gcloud ou Cloud Console.

Console

  1. Consultez la page API et services dans Cloud Console.

    Page API et services

  2. Sélectionnez votre projet.

  3. Cliquez sur Activer les API et les services.

  4. Recherchez Kubernetes, puis sélectionnez l'API dans les résultats de la recherche.

  5. Cliquez sur Activer. Si vous avez déjà activé l'API, vous devez d'abord la désactiver, puis la réactiver. L'activation de l'API et des services associés peut prendre plusieurs minutes.

gcloud

Exécutez la commande suivante dans l'outil gcloud :

gcloud services enable container.googleapis.com

Répliquer des règles de pare-feu automatiques de la version 1.8.x (ou antérieure) sur la version 1.9.x ou ultérieure

Si votre cluster exécute Kubernetes version 1.9.x, les règles de pare-feu automatiques ont été modifiées pour interdire aux charges de travail d'un cluster GKE de lancer la communication avec d'autres VM Compute Engine qui se trouvent en dehors du cluster, mais sur le même réseau.

Vous pouvez répliquer le comportement des règles de pare-feu automatiques d'un cluster 1.8.x (ou version antérieure) en procédant comme suit :

  1. Recherchez le réseau de votre cluster :

    gcloud container clusters describe cluster-name --format=get"(network)"
    
  2. Obtenez le bloc CIDR IPv4 du cluster, utilisé pour les conteneurs :

    gcloud container clusters describe cluster-name --format=get"(clusterIpv4Cidr)"
    
  3. Créez une règle de pare-feu pour le réseau, avec le CIDR comme plage source, et autorisez tous les protocoles :

    gcloud compute firewall-rules create "cluster-name-to-all-vms-on-network" \
      --network="network" --source-ranges="cluster-ipv4-cidr" \
      --allow=tcp,udp,icmp,esp,ah,sctp
    

Restaurer le compte de service par défaut sur votre projet GCP

Le compte de service par défaut de GKE, container-engine-robot, peut être dissocié accidentellement d'un projet. Le rôle d'agent de service GKE est un rôle Identity and Access Management (IAM) qui accorde au compte de service les autorisations nécessaires pour gérer les ressources du cluster. Si vous supprimez cette liaison de rôle du compte de service, le compte de service par défaut est dissocié du projet, ce qui peut vous empêcher de déployer des applications et d'effectuer d'autres opérations sur le cluster.

Vous pouvez vérifier si le compte de service a été supprimé de votre projet à l'aide de l'outil gcloud ou de Cloud Console.

gcloud

Exécutez la commande suivante :

gcloud projects get-iam-policy project-id

Remplacez project-id par l'ID du projet.

Console

Accédez à la page IAM et admin dans Cloud Console.

Si la commande ou le tableau de bord n'affiche pas container-engine-robot parmi vos comptes de service, c'est que ce compte a été dissocié.

Si vous avez supprimé la liaison de rôle d'agent de service GKE, exécutez les commandes suivantes pour la restaurer :

PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format "value(projectNumber)")
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member "serviceAccount:service-${PROJECT_NUMBER}@container-engine-robot.iam.gserviceaccount.com" \
  --role roles/container.serviceAgent

Pour confirmer que la liaison de rôle a été activée :

gcloud projects get-iam-policy $PROJECT_ID

Si vous voyez le nom du compte de service avec le rôle container.serviceAgent, la liaison de rôle a été activée. Exemple :

- members:
  - serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
  role: roles/container.serviceAgent

La clé Cloud KMS est désactivée

Le compte de service par défaut de GKE ne peut pas utiliser une clé Cloud KMS désactivée pour le chiffrement des secrets au niveau de l'application.

Pour réactiver une clé, consultez la page Activer une version de clé désactivée.

Pods bloqués à l'état "en attente" après l'activation des ressources pouvant être allouées aux nœuds

Si vous rencontrez un problème avec des pods bloqués à l'état en attente après avoir activé des ressources pouvant être allouées aux nœuds, veuillez noter les points suivants :

À partir de la version 1.7.6, GKE réserve le processeur et la mémoire pour les frais généraux de Kubernetes, y compris Docker et le système d'exploitation. Consultez la section Architecture de cluster pour connaître la quantité de chaque type de machine pouvant être programmé par les pods.

Si les pods sont en attente après une mise à niveau, nous vous suggérons de suivre les conseils suivants :

  1. Assurez-vous que les demandes de ressources mémoire et de processeur pour vos pods ne dépassent pas leur pic d'utilisation. Étant donné que GKE réserve le processeur et la mémoire pour les frais généraux, les pods ne peuvent pas demander ces ressources. Les pods qui demandent plus de ressources mémoire et de processeur qu'ils n'en utilisent empêchent les autres pods de demander ces ressources et peuvent laisser le cluster sous-exploité. Pour en savoir plus, consultez la section Programmation des pods avec des demandes de ressources.

  2. Envisagez de redimensionner votre cluster. Pour obtenir des instructions, consultez la page Redimensionner un cluster.

  3. Pour annuler cette modification, faites revenir votre cluster à une version antérieure. Pour obtenir des instructions, consultez la page Mettre à jour manuellement un cluster ou un pool de nœuds.

Nœuds de cluster privé créés, mais non associés au cluster

Souvent, lorsque vous utilisez des dispositifs de routage personnalisé et de réseau tiers sur le VPC utilisé par votre cluster privé, la route par défaut (0.0.0.0/0) est redirigée vers le dispositif au lieu de la passerelle Internet par défaut. Outre la connectivité du plan de contrôle, vous devez vous assurer que les destinations suivantes sont accessibles :

  • *.googleapis.com
  • *.gcr.io
  • gcr.io

Configurez l'accès privé à Google pour les trois domaines. Cette bonne pratique permet de démarrer les nouveaux nœuds et de les associer au cluster, tout en continuant à limiter le trafic Internet.

Résoudre les problèmes liés aux charges de travail déployées

GKE renvoie une erreur en cas de problème avec les pods d'une charge de travail. Vous pouvez vérifier l'état d'un pod à l'aide de l'outil de ligne de commande kubectl ou de Cloud Console.

kubectl

Pour afficher tous les pods exécutés dans votre cluster, utilisez la commande suivante :

kubectl get pods

Résultat :

NAME       READY  STATUS             RESTARTS  AGE
pod-name   0/1    CrashLoopBackOff   23        8d

Pour obtenir plus d'informations sur un pod spécifique, exécutez la commande suivante :

kubectl describe pod pod-name

Remplacez pod-name par le nom du pod souhaité.

Console

Procédez comme suit :

  1. Consultez le tableau de bord des charges de travail GKE dans Cloud Console.

    Consulter le tableau de bord des charges de travail GKE

  2. Sélectionnez la charge de travail souhaitée. L'onglet Aperçu affiche l'état de la charge de travail.

  3. Dans la section Pods gérés, cliquez sur le message d'état d'erreur.

Les sections suivantes expliquent certaines erreurs courantes renvoyées par les charges de travail et indiquent comment les corriger.

CrashLoopBackOff

CrashLoopBackOff indique qu'un conteneur plante de manière répétée après le redémarrage. Un conteneur peut planter pour plusieurs raisons. La consultation des journaux d'un pod peut aider à en identifier la cause.

Par défaut, les conteneurs qui ont planté redémarrent avec un délai exponentiel limité à cinq minutes. Vous pouvez modifier ce comportement en définissant la spécification de pod du déploiement de champ restartPolicy sous spec: restartPolicy. La valeur par défaut du champ est Always.

Vous pouvez déterminer la raison pour laquelle le conteneur de votre pod plante en utilisant l'outil de ligne de commande kubectl ou Cloud Console.

kubectl

Pour afficher tous les pods exécutés dans votre cluster, utilisez la commande suivante :

kubectl get pods

Recherchez le pod avec l'erreur CrashLoopBackOff.

Pour obtenir les journaux du pod, exécutez la commande suivante :

kubectl logs pod-name

Remplacez pod-name par le nom du pod qui pose problème.

Vous pouvez également transmettre l'option -p pour obtenir les journaux de l'instance précédente du conteneur d'un pod, si elle existe.

Console

Procédez comme suit :

  1. Consultez le tableau de bord des charges de travail GKE dans Cloud Console.

    Consulter le tableau de bord des charges de travail GKE

  2. Sélectionnez la charge de travail souhaitée. L'onglet Aperçu affiche l'état de la charge de travail.

  3. Dans la section Pods gérés, cliquez sur le pod qui pose problème.

  4. Dans le menu du pod, cliquez sur l'onglet Journaux.

Vérifier le code de sortie du conteneur qui plante

Vous pouvez trouver le code de sortie en effectuant les tâches suivantes :

  1. Exécutez la commande suivante :

    kubectl describe pod pod-name
    

    Remplacez pod-name par le nom du pod.

  2. Vérifiez la valeur du champ containers: container-name: last state: exit code :

    • Si le code de sortie est 1, le conteneur a planté car l'application a planté.
    • Si le code de sortie est 0, vérifiez la durée d'exécution de l'application.

    Les conteneurs se ferment à la fin du processus principal de l'application. Si l'exécution de l'application se termine très rapidement, il arrive que le conteneur continue à redémarrer.

Se connecter à un conteneur en cours d'exécution

Ouvrez une interface système sur le pod :

kubectl exec -it pod-name -- /bin/bash

Si le pod comporte plusieurs conteneurs, ajoutez -c container-name.

Vous pouvez maintenant exécuter les commandes bash à partir du conteneur : vous pouvez tester le réseau, ou vérifier si vous avez accès aux fichiers ou aux bases de données qu'utilise votre application.

ImagePullBackOff et ErrImagePull

ImagePullBackOff et ErrImagePull indiquent que l'image utilisée par un conteneur ne peut pas être chargée à partir du registre d'images.

Vous pouvez examiner ce problème à l'aide de Cloud Console ou de l'outil de ligne de commande kubectl.

kubectl

Pour obtenir plus d'informations sur l'image de conteneur d'un pod, exécutez la commande suivante :

kubectl describe pod pod-name

Console

Procédez comme suit :

  1. Consultez le tableau de bord des charges de travail GKE dans Cloud Console.

    Consulter le tableau de bord des charges de travail GKE

  2. Sélectionnez la charge de travail souhaitée. L'onglet Aperçu affiche l'état de la charge de travail.

  3. Dans la section Pods gérés, cliquez sur le pod qui pose problème.

  4. Dans le menu du pod, cliquez sur l'onglet Événements.

Si l'image est introuvable

Si votre image est introuvable :

  1. Vérifiez que le nom de l'image est correct.
  2. Vérifiez que le tag de l'image est correct. (Essayez :latestou aucun tag pour extraire la dernière image).
  3. Si le chemin d'accès au registre de l'image est complet, vérifiez qu'il existe dans le registre Docker que vous utilisez. Si vous ne fournissez que le nom de l'image, vérifiez le registre Docker Hub.
  4. Essayez d'extraire l'image Docker manuellement :

    • Connectez-vous en SSH sur le nœud :

      Par exemple, pour vous connecter en SSH sur example-instance dans la zone us-central1-a, procédez comme suit :

      gcloud compute ssh example-instance --zone us-central1-a
      
    • Exécutez docker pull image-name.

    Si cette option fonctionne, vous devrez probablement spécifier ImagePullSecrets sur un pod. Les pods ne peuvent référencer que des codes secrets d'extraction d'image dans leur propre espace de noms. Ce processus doit donc être effectué une fois par espace de noms.

Si vous rencontrez une erreur "Autorisation refusée" ou "Aucun accès en extraction", vérifiez que vous êtes connecté et/ou que vous avez accès à l'image.

Si vous utilisez un registre privé, des clés peuvent être nécessaires pour lire les images.

Si votre image est hébergée dans Container Registry, le compte de service associé à votre pool de nœuds doit disposer d'un accès en lecture au bucket Cloud Storage contenant l'image. Pour plus d'informations, consultez la documentation sur Container Registry.

PodUnschedulable

PodUnschedulable indique que votre pod ne peut pas être planifié en raison de ressources insuffisantes ou d'une erreur de configuration.

Ressources insuffisantes

Vous pouvez rencontrer une erreur indiquant un manque de ressources processeur, de mémoire ou autre. Par exemple : "Aucun nœud disponible ne correspond à tous les prédicats : processeur insuffisant (2)" indique que sur deux nœuds, le processeur disponible est insuffisant pour répondre aux requêtes d'un pod.

Le nombre de requêtes par défaut sur le processeur est de 100 millions ou 10 % d'un processeur (ou un cœur). Si vous souhaitez demander plus ou moins de ressources, indiquez la valeur dans la spécification de pod sous spec: containers: resources: requests.

MatchNodeSelector

MatchNodeSelector indique qu’aucun nœud ne correspond au sélecteur de libellés du pod.

Pour vous en assurer, vérifiez les libellés indiqués dans le champ nodeSelector de la spécification de pod, sous spec: nodeSelector.

Pour savoir comment les nœuds de votre cluster sont libellés, exécutez la commande suivante :

kubectl get nodes --show-labels

Pour associer un libellé à un nœud, exécutez la commande suivante :

kubectl label nodes node-name label-key=label-value

Remplacez les éléments suivants :

  • node-name par le nœud souhaité
  • label-key par la clé du libellé
  • label-value par la valeur du libellé

Pour plus d'informations, reportez-vous à l'article Affecter des pods à des nœuds.

PodToleratesNodeTaints

PodToleratesNodeTaints indique que le pod ne peut pas être planifié sur un nœud, car aucun nœud ne tolère actuellement sa propriété de rejet.

Pour vous en assurer, exécutez la commande suivante :

kubectl describe nodes node-name

Dans le résultat, examinez le champ Taints, qui répertorie les paires valeur/clé et les effets de planification.

Si l'effet indiqué est NoSchedule, alors aucun pod ne peut être planifié sur ce nœud sans la tolérance correspondante.

Pour résoudre ce problème, vous pouvez supprimer la propriété de rejet. Par exemple, pour supprimer le rejet NoSchedule, exécutez la commande suivante :

kubectl taint nodes node-name key:NoSchedule-

PodFitsHostPorts

PodFitsHostPorts indique qu'un port qu'un nœud tente d'utiliser est déjà en cours d'utilisation.

Pour résoudre ce problème, vérifiez la valeur hostPort de la spécification de pod sous spec: containers: ports: hostPort. Vous devrez peut-être remplacer cette valeur par un autre port.

Aucune disponibilité minimale

Si un nœud dispose de ressources suffisantes mais que vous obtenez toujours le message Does not have minimum availability, vérifiez l'état du pod. Si l'état est SchedulingDisabled ou Cordoned, le nœud ne peut pas planifier de nouveaux pods. Vous pouvez vérifier l'état d'un nœud à l'aide de Cloud Console ou de l'outil de ligne de commande kubectl.

kubectl

Pour obtenir l'état de vos nœuds, exécutez la commande suivante :

kubectl get nodes

Pour activer la planification sur le nœud, exécutez cette commande :

kubectl uncordon node-name

Console

Procédez comme suit :

  1. Consultez le tableau de bord des charges de travail GKE dans Cloud Console.

    Consulter le tableau de bord des clusters GKE

  2. Sélectionnez le cluster souhaité. L'onglet Nœuds affiche les nœuds et leur état.

Pour activer la planification sur le nœud, procédez comme suit :

  1. Dans la liste, cliquez sur le nœud souhaité.

  2. Dans les détails du nœud, cliquez sur le bouton Reprendre l'ordonnancement.

PersistantVolumeClaim non lié

Unbound PersistentVolumeClaims indique que le pod fait référence à un objet PersistantVolumeClaim non lié. Cette erreur peut se produire en cas d'échec du provisionnement du PersistentVolume. Vous pouvez vérifier si le provisionnement a échoué en récupérant les événements associés au PersistentVolumeClaim et en examinant s'ils signalent un échec.

Pour obtenir la liste des événements, exécutez la commande suivante :

kubectl describe pvc statefulset-name-pvc-name-0

Remplacez les éléments suivants :

  • statefulset-name par le nom de l'objet StatefulSet
  • pvc-name par le nom de l'objet PersistentVolumeClaim

Cette erreur peut également être causée par une erreur de configuration lors du provisionnement manuel préalable d'un PersistentVolume et de sa liaison à un PersistentVolumeClaim. Dans ce cas, vous pouvez essayer de préprovisionner le volume à nouveau.

Problèmes de connectivité

Comme indiqué dans la partie Présentation du réseau, il est important de comprendre comment les pods sont connectés entre leurs espaces de noms réseau et l'espace de noms racine sur le nœud afin de procéder au dépannage de façon efficace. Dans la démonstration suivante, sauf indication contraire, nous supposerons que le cluster utilise la CNI native (Container Network Interface) de GKE plutôt que celle de Calico. C'est-à-dire qu'aucune stratégie réseau n'a été appliquée.

Les pods sur les nœuds sélectionnés n'ont pas de disponibilité

Si les pods sur certains nœuds ne disposent pas d'une connectivité réseau, assurez-vous que le pont Linux est actif :

ip address show cbr0

Si le pont Linux est arrêté, activez-le :

sudo ip link set cbr0 up

Assurez-vous que le nœud apprend les adresses MAC du pod associées à cbr0 :

arp -an

La connectivité des pods sur certains nœuds est minimale

Si les pods sur certains nœuds ont une connectivité minimale, vous devez d’abord rechercher une perte de paquets éventuelle en exécutant la commande tcpdump dans le conteneur de la boîte à outils :

sudo toolbox bash

Installez tcpdump dans la boîte à outils si ce n'est déjà fait :

apt install -y tcpdump

Exécutez tcpdump sur cbr0 :

tcpdump -ni cbr0 host hostname and port port-number and [tcp|udp|icmp]

Si vous constatez que des paquets volumineux sont rejetés en aval du pont (par exemple, le handshake TCP a bien lieu, mais aucun "hello" SSL n'est reçu), assurez-vous que la MTU du pont Linux est correctement définie sur la MTU de réseau VPC du cluster.

ip address show cbr0

En cas d'utilisation de superpositions (par exemple, Weave ou Flannel), cette MTU doit être encore réduite pour tolérer la surcharge d'encapsulation sur la superposition.

Échecs de connexion intermittents

Les connexions vers et depuis les pods sont transférées au moyen de règles iptables. Les flux sont suivis en tant qu'entrées dans la table conntrack et, lorsqu'il existe de nombreuses charges de travail par nœud, l'épuisement de la table conntrack peut se traduire par un échec. Ceux-ci peuvent être enregistrés dans la console série du nœud, par exemple :

nf_conntrack: table full, dropping packet

Si vous parvenez à déterminer que les déconnexions intermittentes sont liées à l'épuisement de conntrack, augmentez la taille du cluster (réduisant ainsi le nombre de charges de travail et de flux par nœud), ou augmentez nf_conntrack_max :

new_ct_max=$(awk '$1 == "MemTotal:" { printf "%d\n", $2/32; exit; }' /proc/meminfo)
sysctl -w net.netfilter.nf_conntrack_max="${new_ct_max:?}" \
  && echo "net.netfilter.nf_conntrack_max=${new_ct_max:?}" >> /etc/sysctl.conf

"Liaison : adresse déjà utilisée" signalé pour un conteneur

Un conteneur dans un pod ne parvient pas à démarrer car, d'après les journaux du conteneur, le port auquel l'application tente de se connecter est déjà réservé. Le conteneur est bloqué dans une boucle de plantage. Par exemple, dans Cloud Logging :

resource.type="container"
textPayload:"bind: Address already in use"
resource.labels.container_name="redis"

2018-10-16 07:06:47.000 CEST 16 Oct 05:06:47.533 # Creating Server TCP listening socket *:60250: bind: Address already in use
2018-10-16 07:07:35.000 CEST 16 Oct 05:07:35.753 # Creating Server TCP listening socket *:60250: bind: Address already in use

Lorsque Docker plante, un conteneur en cours d'exécution est parfois laissé de côté et n'est plus actualisé. Le processus est toujours en cours d'exécution dans l'espace de noms réseau attribué au pod et en écoute sur son port. Comme Docker et le kubelet ignorent que le conteneur est obsolète, ils tentent de démarrer un nouveau conteneur avec un nouveau processus, qui ne peut pas se connecter au port puisqu'il est ajouté à l'espace de nom réseau déjà associé au pod.

Pour diagnostiquer ce problème, procédez comme suit :

  1. Vous avez besoin de l'UUID du pod dans le champ .metadata.uuid :

    kubectl get pod -o custom-columns="name:.metadata.name,UUID:.metadata.uid" ubuntu-6948dd5657-4gsgg
    
    name                      UUID
    ubuntu-6948dd5657-4gsgg   db9ed086-edba-11e8-bdd6-42010a800164
    
  2. Obtenez le résultat des commandes suivantes à partir du nœud :

    docker ps -a
    ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep [Pod UUID]
    
  3. Vérifiez les processus en cours depuis ce pod. Comme l'UUID des espaces de noms cgroup contient l'UUID du pod, vous pouvez utiliser une commande grep pour le pod UUID dans le résultat ps. Appliquez également une commande grep à la ligne précédente, de façon à obtenir les processus docker-containerd-shim qui contiennent aussi l'identifiant du conteneur dans l'argument. Coupez le reste de la colonne cgroup pour simplifier la sortie obtenue :

    # ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep -B 1 db9ed086-edba-11e8-bdd6-42010a800164 | sed s/'blkio:.*'/''/
    1283089     959 Sl   futex_wait_queue_me  4026531993       docker-co       docker-containerd-shim 276e173b0846e24b704d4 12:
    1283107 1283089 Ss   sys_pause            4026532393         pause           /pause                                     12:
    1283150     959 Sl   futex_wait_queue_me  4026531993       docker-co       docker-containerd-shim ab4c7762f5abf40951770 12:
    1283169 1283150 Ss   do_wait              4026532393         sh              /bin/sh -c echo hello && sleep 6000000     12:
    1283185 1283169 S    hrtimer_nanosleep    4026532393           sleep           sleep 6000000                            12:
    1283244     959 Sl   futex_wait_queue_me  4026531993       docker-co       docker-containerd-shim 44e76e50e5ef4156fd5d3 12:
    1283263 1283244 Ss   sigsuspend           4026532393         nginx           nginx: master process nginx -g daemon off; 12:
    1283282 1283263 S    ep_poll              4026532393           nginx           nginx: worker process
    
  4. Dans cette liste, les identifiants de conteneur s'affichent et devraient également être visibles dans docker ps.

    Dans ce cas :

    • docker-containerd-shim 276e173b0846e24b704d4 pour la mise en pause
    • docker-containerd-shim ab4c7762f5abf40951770 pour sh avec mise en veille (sleep-ctr)
    • docker-containerd-shim 44e76e50e5ef4156fd5d3 pour nginx (echoserver-ctr)
  5. Vérifiez les identifiants dans le résultat de docker ps :

    # docker ps --no-trunc | egrep '276e173b0846e24b704d4|ab4c7762f5abf40951770|44e76e50e5ef4156fd5d3'
    44e76e50e5ef4156fd5d383744fa6a5f14460582d0b16855177cbed89a3cbd1f   gcr.io/google_containers/echoserver@sha256:3e7b182372b398d97b747bbe6cb7595e5ffaaae9a62506c725656966d36643cc                   "nginx -g 'daemon off;'"                                                                                                                                                                                                                                                                                                                                                                     14 hours ago        Up 14 hours                             k8s_echoserver-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0
    ab4c7762f5abf40951770d3e247fa2559a2d1f8c8834e5412bdcec7df37f8475   ubuntu@sha256:acd85db6e4b18aafa7fcde5480872909bd8e6d5fbd4e5e790ecc09acc06a8b78                                                "/bin/sh -c 'echo hello && sleep 6000000'"                                                                                                                                                                                                                                                                                                                                                   14 hours ago        Up 14 hours                             k8s_sleep-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0
    276e173b0846e24b704d41cf4fbb950bfa5d0f59c304827349f4cf5091be3327   k8s.gcr.io/pause-amd64:3.1
    

    Normalement, tous les identifiants de conteneur de ps apparaissent dans docker ps. Si l'un d'entre eux n'apparaît pas, il s'agit d'un conteneur obsolète, et vous verrez probablement un processus enfant de docker-containerd-shim process en écoute sur le port TCP signalé comme déjà utilisé.

    Pour le vérifier, exécutez la commande netstat dans l'espace de noms réseau du conteneur. Récupérez le pid d'un processus de conteneur pour le pod (et NON docker-containerd-shim).

    Dans l'exemple ci-dessus :

    • 1283107 - pause
    • 1283169 - sh
    • 1283185 - veille
    • 1283263 - maître nginx
    • 1283282 - nœud de calcul nginx
    # nsenter -t 1283107 --net netstat -anp
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1283263/nginx: mast
    Active UNIX domain sockets (servers and established)
    Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
    unix  3      [ ]         STREAM     CONNECTED     3097406  1283263/nginx: mast
    unix  3      [ ]         STREAM     CONNECTED     3097405  1283263/nginx: mast
    
    gke-zonal-110-default-pool-fe00befa-n2hx ~ # nsenter -t 1283169 --net netstat -anp
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1283263/nginx: mast
    Active UNIX domain sockets (servers and established)
    Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
    unix  3      [ ]         STREAM     CONNECTED     3097406  1283263/nginx: mast
    unix  3      [ ]         STREAM     CONNECTED     3097405  1283263/nginx: mast
    

    Vous pouvez également exécuter netstat en utilisant ip netns, mais vous devez relier manuellement l'espace de noms réseau du processus, car Docker n'effectue par la liaison :

    # ln -s /proc/1283169/ns/net /var/run/netns/1283169
    gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns list
    1283169 (id: 2)
    gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns exec 1283169 netstat -anp
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1283263/nginx: mast
    Active UNIX domain sockets (servers and established)
    Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
    unix  3      [ ]         STREAM     CONNECTED     3097406  1283263/nginx: mast
    unix  3      [ ]         STREAM     CONNECTED     3097405  1283263/nginx: mast
    gke-zonal-110-default-pool-fe00befa-n2hx ~ # rm /var/run/netns/1283169
    

Atténuation :

L'atténuation à court terme consiste à identifier les processus obsolètes à l'aide de la méthode décrite ci-dessus, puis à les éliminer en exécutant la commande kill [PID].

L'atténuation à long terme consiste à identifier l'origine des plantages de Docker et à y remédier. Voici les différents motifs possibles :

  • Les processus zombies s'empilent et les espaces de noms PID deviennent insuffisants
  • Bug dans Docker
  • Ressource saturée/OOM