Comment puis-je dépanner l'état des pods dans Amazon EKS ?

Dernière mise à jour : 08/12/2021

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és sont bloqués. Je souhaite que mes pods retrouvent l'état « Running » (En cours d'exécution).

Solution

Important : les étapes suivantes s'appliquent uniquement aux pods lancés sur des instances Amazon EC2 ou sur un groupe de nœuds gérés. Ces étapes ne concernent pas les pods lancés sur AWS Fargate.

Découvrir l'état de votre pod

1.    Pour obtenir l'état de votre pod, exécutez la commande suivante :

$ kubectl get pod

2.    Exécutez la commande suivante afin d'obtenir des informations à partir de l'historique des Événements de votre pod :

$ kubectl describe pod YOUR_POD_NAME

Remarque : les exemples de commandes couverts dans les étapes suivantes se trouvent dans l'espace de noms par défaut. Pour les autres espaces de noms, ajoutez le suffixe -n YOURNAMESPACE à la commande.

3.    En fonction de l'état de votre pod, effectuez les étapes décrites dans l'une des sections suivantes : Votre pod est à l'état « Pending » (En attente), Votre pod est à l'état « Waiting » (En suspens) ou Votre pod est à l'état « CrashLoopBackOff ».

Votre pod est à l'état Pending (En attente)

Les pods à l'état Pending (En attente) ne peuvent pas être planifiés sur un nœud. Cela peut se produire en raison de ressources insuffisantes ou en utilisant hostPort. Pour plus d'informations, consultez la phase Pod dans la documentation Kubernetes.

Si les ressources disponibles sur les composants master sont insuffisantes, pensez à supprimer les pods inutiles. Vous pouvez également ajouter des ressources supplémentaires sur les composants master. Vous pouvez utiliser Kubernetes Cluster Autoscaler pour mettre à l'échelle automatiquement votre groupe de composants master lorsque les ressources de votre cluster sont rares.

CPU insuffisant

$ kubectl describe pod frontend-cpu                               
Name:         frontend-cpu
Namespace:    default
Priority:     0
Node:         <none>
Labels:       <none>
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Pending
...
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  22s (x14 over 13m)  default-scheduler  0/3 nodes are available: 3 Insufficient cpu.

Mémoire insuffisante

$ kubectl describe pod frontend-memory
Name:         frontend-memory
Namespace:    default
Priority:     0
Node:         <none>
Labels:       <none>
Annotations:  kubernetes.io/psp: eks.privileged
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 votre pod, suivez les bonnes pratiques suivantes :

  • Ne spécifiez pas un hostPort sauf en cas de besoin. En effet, la combinaison hostIP, hostPort et protocol doit être unique.
  • Si vous devez spécifier un hostPort, planifiez le même nombre de pods qu'il y a de composants master.

Remarque : il existe un nombre limité d'emplacements dans lesquels un pod peut être planifié lorsque vous liez un pod à un hostPort.

L'exemple suivant montre la sortie de la commande describe pour frontend-port-77f67cff67-2bv7w, qui est à l'état Pending (En attente). Le pod n'est pas planifié, car le port hôte demandé n'est pas disponible pour les composants master du cluster.

Port non disponible

$ kubectl describe pod frontend-port-77f67cff67-2bv7w                                            
Name:           frontend-port-77f67cff67-2bv7w
Namespace:      default
Priority:       0
Node:           <none>
Labels:         app=frontend-port
                pod-template-hash=77f67cff67
Annotations:    kubernetes.io/psp: eks.privileged
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 la planification des pods n’est pas possible, car les nœuds présentent des rejets que le pod ne peut pas autoriser, l'exemple de sortie est semblable à ce qui suit :

$ kubectl describe pod nginx                                                  
Name:         nginx
Namespace:    default
Priority:     0
Node:         <none>
Labels:       run=nginx
Annotations:  kubernetes.io/psp: eks.privileged
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.

Vous pouvez vérifier les rejets de vos nœuds à l'aide de la commande suivante :

$ kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints             
NAME                                                TAINTS
ip-192-168-4-78.ap-southeast-2.compute.internal     [map[effect:NoSchedule key:key1 value:value1]]
ip-192-168-56-162.ap-southeast-2.compute.internal   [map[effect:NoSchedule key:key1 value:value1]]
ip-192-168-91-249.ap-southeast-2.compute.internal   [map[effect:NoSchedule key:key1 value:value1]]

Si vous souhaitez retenir les rejets de votre nœud, vous pouvez spécifier une tolérance pour un pod dans PodSpec. Pour plus d'informations, consultez la section Concepts de la documentation Kubernetes.

-ou-

Supprimez le rejet du nœud en ajoutant - à la fin de la valeur de rejet :

$ kubectl taint nodes NODE_Name key1=value1:NoSchedule-

Si vos pods sont toujours à l'état Pending (En attente) après avoir effectué les étapes précédentes, procédez comme suit dans la section Dépannage supplémentaire.

Votre conteneur est à l’état Waiting (En suspens)

Un conteneur à l'état Waiting (En suspens) est planifié sur un composant master (par exemple, une instance EC2), mais ne peut pas s'exécuter sur ce nœud.

Votre conteneur peut être à l'état Waiting (En suspens) en raison d'une image Docker incorrecte ou d'un nom de référentiel incorrect. Il est également possible que votre pod soit à l'état Waiting (En suspens), car l'image n'existe pas ou que vous ne disposez pas des autorisations nécessaires.

Si vous n'avez pas la bonne image Docker ou le bon nom de référentiel, effectuez les opérations suivantes :

1.    Vérifiez que l'image et le nom du référentiel sont corrects en vous connectant à Docker Hub, Amazon Elastic Container Registry (Amazon ECR) ou à un autre référentiel d'images de conteneur.

2.    Comparez le référentiel ou l'image du référentiel au nom du référentiel ou de l'image spécifié dans la description du pod.

Si l'image n'existe pas ou si vous n'avez pas les autorisations requises, effectuez les opérations suivantes :

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 permettre l'extraction de l'image.

2.    Pour confirmer que l'extraction d'image est possible et pour exclure les problèmes généraux d'autorisation de mise en réseau et de référentiel, extrayez manuellement l'image. Vous devez extraire l'image des nœuds de travail Amazon EKS avec Docker. Par exemple :

$ docker pull yourImageURI:yourImageTag

3.    Pour vérifier que l'image existe, vérifiez que l'image et la balise sont toutes deux présentes dans Docker Hub ou Amazon ECR.

Remarque : si vous utilisez Amazon ECR, vérifiez que la politique de référentiel autorise l'extraction d'images pour NodeInstanceRole. Vous pouvez également vérifier que le rôle AmazonEC2ContainerRegistryReadOnly est attaché à la politique.

L'exemple suivant montre un pod à l'état Pending (En attente), le conteneur étant à l'état Waiting (En suspens) en raison d'une erreur d'extraction d'images :

$ kubectl describe po web-test

Name:               web-test
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               ip-192-168-6-51.us-east-2.compute.internal/192.168.6.51
Start Time:         Wed, 22 Jul 2021 08:18:16 +0200
Labels:             app=web-test
Annotations:        kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"web-test"},"name":"web-test","namespace":"default"},"spec":{...
                    kubernetes.io/psp: eks.privileged
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 vos conteneurs sont toujours à l'état Waiting (En suspens) après avoir effectué les étapes précédentes, procédez comme suit dans la section Dépannage supplémentaire.

Votre pod est à l'état CrashLoopBackOff

Les pods bloqués à l’état CrashLoopBackOff démarrent et se bloquent à plusieurs reprises.

Si vous recevez le message de sortie « Back-Off restarting failed container », c'est que votre conteneur s'est probablement fermé peu de temps après que Kubernetes l'a démarré.

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 qui s'est bloqué, exécutez la commande suivante :

$ kubectl logs --previous YOUR-POD_NAME

Remarque : pour un pod à plusieurs conteneurs, vous pouvez ajouter le nom du conteneur à la fin. Par exemple :

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

si la sonde vive ne renvoie pas un statut de réussite, alors vérifiez qu'elle est configurée correctement pour l'application. Pour plus d'informations, Configurer les sondes dans la documentation Kubernetes.

L'exemple suivant montre un pod à l'état CrashLoopBackOff, car l'application se ferme après le démarrage, Notice State (État de notification), Last State (Dernier état), Reason (Motif), Exit Code (Code de sortie) et Restart Count with Events (Nombre de redémarrages avec des événements).

$ kubectl describe pod crash-app-b9cf4587-66ftw 
Name:         crash-app-b9cf4587-66ftw
Namespace:    default
Priority:     0
Node:         ip-192-168-91-249.ap-southeast-2.compute.internal/192.168.91.249
Start Time:   Tue, 12 Oct 2021 12:24:44 +1100
Labels:       app=crash-app
              pod-template-hash=b9cf4587
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Running
IP:           192.168.82.93
IPs:
  IP:           192.168.82.93
Controlled By:  ReplicaSet/crash-app-b9cf4587
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   Scheduled  2m30s                default-scheduler  Successfully assigned default/crash-app-b9cf4587-66ftw to ip-192-168-91-249.ap-southeast-2.compute.internal
  Normal   Pulled     2m25s                kubelet            Successfully pulled image "alpine" in 5.121853269s
  Normal   Pulled     2m22s                kubelet            Successfully pulled image "alpine" in 1.894443044s
  Normal   Pulled     2m3s                 kubelet            Successfully pulled image "alpine" in 1.878057673s
  Normal   Created    97s (x4 over 2m25s)  kubelet            Created container alpine
  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

Exemple de défaillance d'une sonde vive pour le pod :

$ kubectl describe pod nginx
Name:         nginx
Namespace:    default
Priority:     0
Node:         ip-192-168-91-249.ap-southeast-2.compute.internal/192.168.91.249
Start Time:   Tue, 12 Oct 2021 13:07:55 +1100
Labels:       app=nginx
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Running
IP:           192.168.79.220
IPs:
  IP:  192.168.79.220
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   Scheduled  2m47s                  default-scheduler  Successfully assigned default/nginx to ip-192-168-91-249.ap-southeast-2.compute.internal
  Normal   Pulled     2m44s                  kubelet            Successfully pulled image "nginx" in 1.891238002s
  Normal   Pulled     2m35s                  kubelet            Successfully pulled image "nginx" in 1.878230117s
  Normal   Created    2m25s (x3 over 2m44s)  kubelet            Created container nginx
  Normal   Started    2m25s (x3 over 2m44s)  kubelet            Started container nginx
  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 vos pods sont toujours à l'état CrashLoopBackOff après avoir effectué les étapes précédentes, procédez comme suit dans la section Dépannage supplémentaire.

Dépannage supplémentaire

Si votre pod est encore bloqué après les étapes des sections précédentes, alors essayez les étapes suivantes :

1.    Pour confirmer que les nœuds de travail existent dans le cluster et sont à l'état « Ready » (Prêt), exécutez la commande suivante :

$ kubectl get nodes

Exemple de sortie :

NAME                                          STATUS   ROLES    AGE   VERSION
ip-192-168-6-51.us-east-2.compute.internal    Ready    <none>   25d   v1.21.2-eks-5047ed
ip-192-168-86-33.us-east-2.compute.internal   Ready    <none>   25d   v1.21.2-eks-5047ed

Si les nœuds sont à l’état NotReady, consultez la section Comment puis-je passer l'état de mes nœuds de l'état NotReady ou Inconnu à l'état Prêt ? ou je ne peux pas rejoindre le cluster, Comment puis-je faire en sorte que mes composants master rejoignent mon cluster Amazon EKS ?

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

$ kubectl version --short

Exemple de sortie :

Client Version: v1.21.2-eks-5047ed
Server Version: v1.21.2-eks-c0eccc

3.    Pour vérifier la version du nœud de travail Kubernetes, exécutez la commande suivante :

$ kubectl get node -o custom-columns=NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion

Exemple de sortie :

NAME                                          VERSION
ip-192-168-6-51.us-east-2.compute.internal    v1.21.2-eks-5047ed
ip-192-168-86-33.us-east-2.compute.internal   v1.21.2-eks-5047ed

4.    Vérifiez que la version du serveur Kubernetes pour le cluster correspond à celle des composants master dans une différence de version acceptable (depuis la documentation Kubernetes). Utilisez la sortie des étapes 2 et 3 précédentes comme base de cette comparaison.

Important : les versions de correctifs peuvent être différentes (par exemple, v1.21.x pour le cluster et v1.21.y pour le composant master).

Si les versions du cluster et du composant master ne sont pas compatibles, créez un groupe de nœuds avec eksctl (voir l'onglet eksctl) ou AWS CloudFormation (voir l'onglet Self-managed nodes [Nœuds autogérés]).

-ou-

Créez un nouveau groupe de nœuds gérés (Kubernetes : v1.21, plateforme : eks.1 et versions ultérieures) à l'aide d'une version Kubernetescompatible. Supprimez ensuite le groupe de nœuds ayant la version Kubernetes incompatible.

5.    Confirmez que le plan de contrôle Kubernetes peut communiquer avec les nœuds de travail, en vérifiant les règles de pare-feu par rapport aux règles recommandées dans Considérations relatives aux groupes de sécurité Amazon EKS. Vérifiez ensuite que les nœuds sont à l'état « Ready » (Prêt).


Cet article vous a-t-il été utile ?


Avez-vous besoin d'aide pour une question technique ou de facturation ?