Comment puis-je résoudre les problèmes liés à l’état d’un pod dans Amazon EKS ?

Lecture de 11 minute(s)
0

Mes pods Amazon Elastic Kubernetes Service (Amazon EKS) exécutés sur des instances Amazon Elastic Compute Cloud (Amazon EC2) ou sur un groupe de nœuds géré sont bloqués. Je souhaite que ces pods passent à l’état « En cours d’exécution » ou « Hors service ».

Résolution

Important : les étapes suivantes ne s’appliquent qu’aux pods lancés sur des instances Amazon EC2 ou dans un groupe de nœuds géré. Elles ne s’appliquent pas aux pods lancés sur AWS Fargate.

Vérification de l’état du pod

Pour résoudre les problèmes liés à l’état d’un pod dans Amazon EKS, procédez comme suit :

  1. Pour connaître l’état d’un pod, exécutez la commande suivante :

    $ kubectl get pod
  2. Pour obtenir des informations provenant de l’historique des événements du pod en question, exécutez la commande suivante :

    $ kubectl describe pod YOUR_POD_NAME
  3. En fonction de l’état du pod, suivez les étapes de la section ci-dessous.

Pod en attente

Remarque : les exemples de commandes des étapes suivantes se trouvent dans l’espace de noms par défaut. Si vous utilisez d’autres espaces de noms, ajoutez la commande avec -n YOURNAMESPACE.

Les pods peuvent se trouver bloqués à l’état En attente en raison de ressources insuffisantes ou parce que vous avez défini un hostPort. Pour plus d’informations, consultez la page Phase d’un pod sur le site Web de Kubernetes.

Si vous ne disposez pas de ressources suffisantes sur les composants master, supprimez les pods inutiles. Vous pouvez également ajouter des ressources supplémentaires sur les composants master. Si le cluster ne dispose pas de suffisamment de ressources, dimensionnez automatiquement le groupe de composants master à l’aide de la fonctionnalité Kubernetes Cluster Autoscaler.

Exemple de processeur insuffisant :

$ kubectl describe pod frontend-cpu
Name:         frontend-cpu
...
Status:       Pending
...
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  22s (x14 over 13m)  default-scheduler  0/3 nodes are available: 3 Insufficient cpu.

Exemple de mémoire insuffisante :

$ kubectl describe pod frontend-memory
Name:         frontend-memory
...
Status:       Pending
...
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  80s (x14 over 15m)  default-scheduler  0/3 nodes are available: 3 Insufficient memory.

Si vous avez défini un hostPort pour le pod, suivez ces bonnes pratiques :

  • Comme la combinaison hostIP, hostPort et protocole doit être unique, ne spécifiez le champ hostPort que si cela est nécessaire.
  • Si vous spécifiez un hostPort, programmez autant de pods qu’il y a de composants master.

Remarque : lorsque vous liez un pod à un hostPort, il existe un nombre limité de nœuds où vous pouvez programmer un pod.

L’exemple suivant montre la sortie de la commande describe pour un pod en attente, frontend-port-77f67cff67-2bv7w. Le pod n’est pas programmé parce que le port hôte demandé n’est pas disponible pour les composants master du cluster :

$ kubectl describe pod frontend-port-77f67cff67-2bv7w
Name:           frontend-port-77f67cff67-2bv7w
...
Status:         Pending
IP:
IPs:            <none>
Controlled By:  ReplicaSet/frontend-port-77f67cff67
Containers:
  app:
    Image:      nginx
    Port:       80/TCP
    Host Port:  80/TCP
...
Events:
  Type     Reason            Age                  From               Message
  ----     ------            ----                 ----               -------
  Warning  FailedScheduling  11s (x7 over 6m22s)  default-scheduler  0/3 nodes are available: 3 node(s) didn't have free ports for the requested pod ports.

Si vous ne pouvez pas programmer de pods parce que les nœuds présentent des rejets non tolérés, l’exemple de sortie est semblable à ce qui suit :

$ kubectl describe pod nginx
Name:         nginx
...
Status:       Pending
...
Events:
  Type     Reason            Age                  From               Message
  ----     ------            ----                 ----               -------
  Warning  FailedScheduling  8s (x10 over 9m22s)  default-scheduler  0/3 nodes are available: 3 node(s) had taint {key1: value1}, that the pod didn't tolerate.

Pour inspecter les rejets d’un nœud, exécutez la commande suivante :

$ kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

Pour conserver les rejets d’un nœud, spécifiez une tolérance pour un pod dans le fichier PodSpec. Pour plus d’informations, consultez la section Concepts sur le site Web de Kubernetes. Vous pouvez également supprimer le rejet du nœud en ajoutant - à la fin de la valeur du rejet :

$ kubectl taint nodes NODE_Name key1=value1:NoSchedule-

Si les pods sont toujours en attente, suivez les étapes décrites dans la section Conseils de dépannage supplémentaires.

Conteneur en attente

Le conteneur peut être mis en attente en raison d’une image Docker ou d’un nom de référentiel incorrect. De même, un pod peut être mis en attente parce que l’image n’existe pas ou parce que vous ne disposez pas des autorisations nécessaires.

Pour vérifier si l’image et le nom du référentiel sont corrects, connectez-vous à Docker Hub, à Amazon Elastic Container Registry (Amazon ECR) ou à un autre référentiel d’images de conteneur. Comparez le référentiel ou l’image du référentiel avec le nom du référentiel ou de l’image spécifié dans la spécification du pod. Si l’image n’existe pas ou si vous ne disposez pas des autorisations nécessaires, procédez comme suit :

  1. Vérifiez que l’image spécifiée est disponible dans le référentiel et que les autorisations appropriées sont configurées pour vous permettre d’extraire l’image.

  2. Pour vérifier que vous pouvez extraire l’image et qu’il n’y a pas de problèmes généraux liés au réseau et aux autorisations sur le référentiel, extrayez l’image manuellement. Pour extraire l’image des composants master Amazon EKS, vous devez utiliser Docker :

    $ docker pull yourImageURI:yourImageTag
  3. Pour vérifier l’existence de l’image, vérifiez que l’image et la balise se trouvent dans Docker Hub ou Amazon ECR.

Remarque : si vous utilisez Amazon ECR, vérifiez que la stratégie de référentiel autorise l’extraction d’images pour le NodeInstanceRole. Vous pouvez également vérifier que le rôle AmazonEC2ContainerRegistryReadOnly est bien associé à la stratégie.
L’exemple suivant montre un pod en attente avec le conteneur également en attente en raison d’une erreur d’extraction d’image :

$ kubectl describe po web-test

Name:               web-test
...
Status:             Pending
IP:                 192.168.1.143
Containers:
  web-test:
    Container ID:
    Image:          somerandomnonexistentimage
    Image ID:
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       ErrImagePull
...
Events:
  Type     Reason            Age                 From  Message
  ----     ------            ----                ----                                                 -------
  Normal   Scheduled         66s                 default-scheduler                                    Successfully assigned default/web-test to ip-192-168-6-51.us-east-2.compute.internal
  Normal   Pulling           14s (x3 over 65s)   kubelet, ip-192-168-6-51.us-east-2.compute.internal  Pulling image "somerandomnonexistentimage"
  Warning  Failed            14s (x3 over 55s)   kubelet, ip-192-168-6-51.us-east-2.compute.internal  Failed to pull image "somerandomnonexistentimage": rpc error: code = Unknown desc = Error response from daemon: pull access denied for somerandomnonexistentimage, repository does not exist or may require 'docker login'
  Warning  Failed            14s (x3 over 55s)   kubelet, ip-192-168-6-51.us-east-2.compute.internal  Error: ErrImagePull

Si les conteneurs sont toujours en attente, suivez les étapes décrites dans la section Conseils de dépannage supplémentaires.

Pod à l’état CrashLoopBackOff

Si vous recevez le message de sortie « Back-Off restarting failed container », cela signifie que le conteneur s’est peut-être fermé peu de temps après avoir été démarré par Kubernetes.

Pour rechercher des erreurs dans les journaux du pod actuel, exécutez la commande suivante :

$ kubectl logs YOUR_POD_NAME

Pour rechercher des erreurs dans les journaux du pod précédent, exécutez la commande suivante :

$ kubectl logs --previous YOUR-POD_NAME

Si vous utilisez un pod multiconteneur, ajoutez le nom du conteneur à la fin. Exemple :

$ kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]

Si la sonde de vivacité ne renvoie pas l’état Réussi, vérifiez qu’elle est correctement configurée pour l’application. Pour plus d’informations, consultez la page Configuration des sondes sur le site Web de Kubernetes.

L’exemple suivant montre un pod à l’état CrashLoopBackOff parce que l’application se ferme après son démarrage :

$ kubectl describe pod crash-app-b9cf4587-66ftw
Name:         crash-app-b9cf4587-66ftw
...
Containers:
  alpine:
    Container ID:   containerd://a36709d9520db92d7f6d9ee02ab80125a384fee178f003ee0b0fcfec303c2e58
    Image:          alpine
    Image ID:       docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 12 Oct 2021 12:26:21 +1100
      Finished:     Tue, 12 Oct 2021 12:26:21 +1100
    Ready:          False
    Restart Count:  4
    ...
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Started    97s (x4 over 2m25s)  kubelet            Started container alpine
  Normal   Pulled     97s                  kubelet            Successfully pulled image "alpine" in 1.872870869s
  Warning  BackOff    69s (x7 over 2m21s)  kubelet            Back-off restarting failed container
  Normal   Pulling    55s (x5 over 2m30s)  kubelet            Pulling image "alpine"
  Normal   Pulled     53s                  kubelet            Successfully pulled image "alpine" in 1.858871422s

Voici un exemple d’échec de la sonde de vivacité pour le pod :

$ kubectl describe pod nginx
Name:         nginx
...
Containers:
  nginx:
    Container ID:   containerd://950740197c425fa281c205a527a11867301b8ec7a0f2a12f5f49d8687a0ee911
    Image:          nginx
    Image ID:       docker.io/library/nginx@sha256:06e4235e95299b1d6d595c5ef4c41a9b12641f6683136c18394b858967cd1506
    Port:           80/TCP
    Host Port:      0/TCP
    State:
          Waiting      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 12 Oct 2021 13:10:06 +1100
      Finished:     Tue, 12 Oct 2021 13:10:13 +1100
    Ready:          False
    Restart Count:  5
    Liveness:       http-get http://:8080/ delay=3s timeout=1s period=2s #success=1 #failure=3
    ...
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Pulled     2m25s                  kubelet            Successfully pulled image "nginx" in 1.876232575s
  Warning  Unhealthy  2m17s (x9 over 2m41s)  kubelet            Liveness probe failed: Get "http://192.168.79.220:8080/": dial tcp 192.168.79.220:8080: connect: connection refused
  Normal   Killing    2m17s (x3 over 2m37s)  kubelet            Container nginx failed liveness probe, will be restarted
  Normal   Pulling    2m17s (x4 over 2m46s)  kubelet            Pulling image "nginx"

Si les pods sont toujours à l’état CrashLoopBackOff, suivez les étapes décrites dans la section Autres conseils de dépannage.

Pod hors service

Si les pods sont bloqués à l’état hors service, vérifiez l’intégrité du nœud sur lequel ils s’exécutent et les finalisateurs. Un finalisateur est une fonction qui effectue le traitement de mise hors service d’un pod avant que ce dernier ne passe à l’état Hors service. Pour plus d’informations, consultez la page Finalisateurs sur le site Web de Kubernetes. Pour vérifier le finalisateur d’un pod en cours de mise hors service, exécutez la commande suivante :

$ kubectl get po nginx -o yaml  

apiVersion: v1  
kind: Pod  
metadata:  
...  
  finalizers:  
  - sample/do-something  
...

Dans l’exemple précédent, le pod ne passe à l’état Hors service qu’après la suppression de sample/do-something du finalisateur. En général, un contrôleur personnalisé traite le finalisateur, puis le supprime. Le pod passe ensuite à l’état Hors service.

Pour résoudre ce problème, vérifiez si le pod du contrôleur personnalisé fonctionne correctement. Résolvez tous les problèmes liés au pod du contrôleur, puis laissez le contrôleur personnalisé terminer le processus du finalisateur. Ensuite, le pod passe automatiquement à l’état Hors service. Vous pouvez également supprimer directement le finalisateur en exécutant la commande suivante :

$ kubectl edit po nginx

Conseils de dépannage supplémentaires

Si un pod est toujours bloqué, procédez comme suit :

  1. Pour vérifier que les composants master se trouvent bien dans le cluster à l’état Prêt, exécutez la commande suivante :

    $ kubectl get nodes

    Si les nœuds sont à l’état NotReady, consultez la page Comment puis-je faire passer le statut de mes nœuds du statut NotReady ou Inconnu au statut Prêt ?Si vous ne parvenez pas à joindre des nœuds au cluster, consultez Comment puis-je joindre des composants master à un mon cluster Amazon EKS ?

  2. Pour vérifier la version du cluster Kubernetes, exécutez la commande suivante :

    $ kubectl version --short
  3. Pour vérifier la version du composant master Kubernetes, exécutez la commande suivante :

    $ kubectl get node -o custom-columns=NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion
  4. Vérifiez que la version du serveur Kubernetes du cluster correspond bien à celle des composants master avec une asymétrie de version acceptable. Pour plus d’informations, consultez la page Stratégie d’asymétrie de version sur le site Web de Kubernetes.
    Important : les versions des correctifs peuvent différer entre le cluster et le composant master, par exemple, le cluster peut avoir la version v1.21.x et le composant master la version v1.21.y. En cas d’incompatibilité entre la version du cluster et celle du composant master, utilisez eksctl ou AWS CloudFormation pour créer un groupe de nœuds. Vous pouvez également utiliser une version compatible de Kubernetes pour créer un groupe de nœuds gérés, telle que Kubernetes : v1.21, plateforme : eks.1 et les versions ultérieures. Supprimez ensuite le groupe de nœuds qui contient la version incompatible de Kubernetes.

  5. Vérifiez que le plan de contrôle Kubernetes communique avec les composants master. Vérifiez que les règles de pare-feu sont conformes à celles requises dans les exigences et considérations relatives au groupe de sécurité Amazon EKS. Vérifiez ensuite si les nœuds sont bien à l’état Prêt.

AWS OFFICIEL
AWS OFFICIELA mis à jour il y a 3 mois