Résoudre les problèmes liés aux clusters Autopilot


Cette page explique comment résoudre les problèmes liés aux clusters Autopilot de Google Kubernetes Engine (GKE).

Problèmes liés aux clusters

Impossible de créer un cluster : 0 nœud enregistré

Le problème suivant se produit lorsque vous essayez de créer un cluster Autopilot avec un compte de service IAM désactivé ou ne disposant pas des autorisations requises. La création du cluster échoue avec le message d'erreur suivant :

All cluster resources were brought up, but: only 0 nodes out of 2 have registered.

Pour identifier le problème, procédez comme suit :

  1. Vérifiez si le compte de service Compute Engine par défaut ou le compte de service IAM personnalisé que vous souhaitez utiliser est désactivé :

    gcloud iam service-accounts describe SERVICE_ACCOUNT
    

    Remplacez SERVICE_ACCOUNT par l'adresse e-mail du compte de service (par exemple, my-iam-account@my-first-project.iam.gserviceaccount.com).

    Si le compte de service est désactivé, le résultat ressemble à ce qui suit :

    disabled: true
    displayName: my-service-account
    email: my-service-account@my-project.iam.gserviceaccount.com
    ...
    
  2. Si le compte de service est désactivé, activez-le :

    gcloud iam service-accounts enable SERVICE_ACCOUNT
    

Si le compte de service est activé et que l'erreur persiste, accordez-lui les autorisations minimales requises pour GKE :

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:SERVICE_ACCOUNT" \
    --role roles/container.defaultNodeServiceAccount

Espace de noms bloqué à l'état de fin lorsque le cluster contient 0 nœud

Le problème suivant se produit lorsque vous supprimez un espace de noms dans un cluster après son scaling à la baisse à 0 nœud. Le composant metrics-server ne peut pas accepter la demande de suppression d'espace de noms, car il ne possède aucune instance répliquée.

Pour diagnostiquer ce problème, exécutez la commande suivante :

kubectl describe ns/NAMESPACE_NAME

Remplacez NAMESPACE_NAME par le nom de l'espace de noms.

Le résultat est le suivant :

Discovery failed for some groups, 1 failing: unable to retrieve the complete
list of server APIs: metrics.k8s.io/v1beta1: the server is currently unable to
handle the request

Pour résoudre ce problème, effectuez le scaling à la hausse de n'importe quelle charge de travail afin de déclencher la création d'un nœud par GKE. Lorsque le nœud est prêt, la demande de suppression d'espace de noms s'arrête automatiquement. Une fois que GKE a supprimé l'espace de noms, effectuez le scaling à la baisse de la charge de travail.

Problèmes de scaling

Échec du scaling à la hausse du nœud : le pod risque de ne pas être planifié

Le problème suivant se produit lorsque la journalisation du port série est désactivée dans votre projetGoogle Cloud . Les clusters GKE Autopilot nécessitent la journalisation du port série pour déboguer efficacement les problèmes de nœuds. Si la journalisation du port série est désactivée, Autopilot ne peut pas provisionner les nœuds pour exécuter vos charges de travail.

Le message d'erreur dans votre journal des événements Kubernetes est semblable à celui-ci :

LAST SEEN   TYPE      REASON          OBJECT                          MESSAGE
12s         Warning   FailedScaleUp   pod/pod-test-5b97f7c978-h9lvl   Node scale up in zones associated with this pod failed: Internal error. Pod is at risk of not being scheduled

La journalisation du port série peut être désactivée au niveau de l'organisation via une règle d'administration qui applique la contrainte compute.disableSerialPortLogging. La journalisation du port série peut également être désactivée au niveau du projet ou de l'instance de machine virtuelle (VM).

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

  1. Demandez à votre Google Cloud administrateur des règles d'administration de supprimer la contrainte compute.disableSerialPortLogging dans le projet avec votre cluster Autopilot.
  2. Si aucune règle d'administration n'applique cette contrainte, essayez d'activer la journalisation du port série dans vos métadonnées de projet. Cette action nécessite l'autorisation IAM compute.projects.setCommonInstanceMetadata.

Échec du scaling à la hausse du nœud : GCE manque de ressources

Le problème suivant se produit lorsque vos charges de travail demandent plus de ressources que celles disponibles dans cette région ou zone Compute Engine. Vos pods peuvent rester à l'état Pending.

  • Vérifiez les événements du pod :

    kubectl events --for='pod/POD_NAME' --types=Warning
    

    Remplacez RESOURCE_NAME par le nom de la ressource Kubernetes en attente. Par exemple, pod/example-pod.

    Le résultat ressemble à ce qui suit :

    LAST SEEN         TYPE            REASON                  OBJECT                   Message
    19m               Warning         FailedScheduling        pod/example-pod          gke.io/optimize-utilization-scheduler  0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
    14m               Warning         FailedScheduling        pod/example-pod          gke.io/optimize-utilization-scheduler  0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
    12m (x2 over 18m) Warning         FailedScaleUp           cluster-autoscaler       Node scale up in zones us-central1-f associated with this pod failed: GCE out of resources. Pod is at risk of not being scheduled.
    34s (x3 over 17m) Warning         FailedScaleUp           cluster-autoscaler       Node scale up in zones us-central1-b associated with this pod failed: GCE out of resources. Pod is at risk of not being scheduled.
    

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

  • Déployez le pod dans une autre région ou zone. Si votre pod comporte une restriction zonale, comme un sélecteur de topologie, supprimez-la si possible. Pour obtenir des instructions, consultez la section Placer les pods GKE dans des zones spécifiques.
  • Créez un cluster dans une autre région, puis réessayez le déploiement.
  • Essayez d'utiliser une autre classe de calcul. Les classes de calcul qui sont compatibles avec des types de machines Compute Engine plus petits ont plus de chances de disposer de ressources disponibles. Par exemple, le type de machine par défaut pour Autopilot offre la plus haute disponibilité. Pour obtenir la liste des classes de calcul et des types de machines correspondants, consultez la section Quand utiliser des classes de calcul spécifiques.
  • Si vous exécutez des charges de travail GPU, le GPU demandé peut ne pas être disponible à l'emplacement de votre nœud. Essayez de déployer votre charge de travail à un autre emplacement ou de demander un autre type de GPU.

Pour éviter les problèmes de scaling à la hausse causés par la disponibilité des ressources à l'avenir, envisagez les approches suivantes :

Échec du scaling à la hausse des nœuds : ressources zonales de pod dépassées

Le problème suivant se produit lorsqu'Autopilot ne provisionne pas de nouveaux nœuds pour un pod dans une zone spécifique, car cela enfreindrait les limites de ressources.

Le message d'erreur dans vos journaux est semblable à celui-ci :

    "napFailureReasons": [
            {
              "messageId": "no.scale.up.nap.pod.zonal.resources.exceeded",
              ...

Cette erreur fait référence à un événement noScaleUp, dans lequel le provisionnement automatique des nœuds n'a provisionné aucun groupe de nœuds pour le pod de la zone.

Si vous rencontrez cette erreur, vérifiez les points suivants :

Problèmes liés aux charges de travail

Charges de travail bloquées en raison d'une erreur de stockage éphémère

GKE ne crée pas de pods si vos demandes de stockage éphémère de pod dépassent la limite maximale d'Autopilot de 10 Go dans la version 1.28.6-gke.1317000 de GKE ou version ultérieure.

Pour diagnostiquer ce problème, décrivez le contrôleur de charge de travail, tel que le déploiement ou la tâche :

kubectl describe CONTROLLER_TYPE/CONTROLLER_NAME

Remplacez les éléments suivants :

  • CONTROLLER_TYPE : type de contrôleur de charge de travail, tel que replicaset ou daemonset. Pour obtenir la liste des types de contrôleurs, consultez la section Gestion des charges de travail.
  • CONTROLLER_NAME : nom de la charge de travail bloquée.

Si le pod n'est pas créé parce que la demande de stockage éphémère dépasse la valeur maximale, le résultat ressemble à ce qui suit :

# lines omitted for clarity

Events:

{"[denied by autogke-pod-limit-constraints]":["Max ephemeral-storage requested by init containers for workload '' is higher than the Autopilot maximum of '10Gi'.","Total ephemeral-storage requested by containers for workload '' is higher than the Autopilot maximum of '10Gi'."]}

Pour résoudre ce problème, mettez à jour vos demandes de stockage éphémère afin que le stockage éphémère total demandé par les conteneurs de charge de travail et par les conteneurs que les webhooks injectent soit inférieur ou égal au maximum autorisé. Pour en savoir plus sur la valeur maximale, consultez la section Demandes de ressources dans Autopilot pour la configuration de la charge de travail.

Pods bloqués à l'état "Pending"

Un pod peut rester bloqué à l'état Pending dans le cas où vous sélectionnez un nœud spécifique à utiliser pour le pod, mais la somme des demandes de ressources dans le pod et dans les objets DaemonSet devant être exécutés sur le nœud dépasse la capacité maximale pouvant être allouée au nœud : Il se peut alors que votre pod affiche l'état Pending et ne soit pas planifié.

Pour éviter ce problème, évaluez les tailles de vos charges de travail déployées afin de vous assurer qu'elles correspondent aux demandes de ressources maximales autorisées pour Autopilot.

Vous pouvez également essayer de planifier vos DaemonSets avant de programmer vos pods de charge de travail standards.

Performances des charges de travail systématiquement peu fiables sur un nœud spécifique

Dans la version 1.24 ou ultérieure de GKE, si vos charges de travail sur un nœud spécifique subissent systématiquement des perturbations, des plantages ou un comportement peu fiable similaire, vous pouvez signaler le nœud problématique à GKE en l'ordonnançant à l'aide de la commande suivante :

kubectl drain NODE_NAME --ignore-daemonsets

Remplacez NODE_NAME par le nom du nœud problématique. Vous pouvez trouver le nom du nœud en exécutant la commande kubectl get nodes.

GKE effectue les opérations suivantes :

  • Il supprime les charges de travail existantes du nœud et arrête la planification des charges de travail sur ce nœud.
  • Il recrée automatiquement toutes les charges de travail évincées qui sont gérées par un contrôleur, tel qu'un objet Deployment ou StatefulSet, sur d'autres nœuds.
  • Il arrête toutes les charges de travail qui restent sur le nœud et répare ou recrée le nœud au fil du temps.
  • Si vous utilisez Autopilot, GKE s'arrête et remplace le nœud immédiatement et ignore tous les PodDisruptionBudgets configurés.

La programmation des pods prend plus de temps que prévu sur des clusters vides

Cet événement se produit lorsque vous déployez une charge de travail sur un cluster Autopilot qui ne comporte aucune autre charge de travail. Les clusters Autopilot démarrent avec zéro nœud utilisable et le scaling à zéro nœud si le cluster est vide pour éviter d'avoir des ressources de calcul non utilisées dans le cluster. Le déploiement d'une charge de travail dans un cluster qui ne comporte aucun nœud déclenche un événement d'ajustement à la hausse.

Si vous rencontrez ce problème, cela signifie qu'Autopilot fonctionne comme prévu et qu'aucune action n'est requise. Votre charge de travail sera déployée comme prévu une fois les nouveaux nœuds démarrés.

Vérifiez si vos pods attendent de nouveaux nœuds :

  1. Décrivez votre pod en attente :

    kubectl describe pod POD_NAME
    

    Remplacez POD_NAME par le nom de votre pod en attente.

  2. Vérifiez la section Events du résultat. Si le pod attend de nouveaux nœuds, le résultat ressemble à ce qui suit :

    Events:
      Type     Reason            Age   From                                   Message
      ----     ------            ----  ----                                   -------
      Warning  FailedScheduling  11s   gke.io/optimize-utilization-scheduler  no nodes available to schedule pods
      Normal   TriggeredScaleUp  4s    cluster-autoscaler                     pod triggered scale-up: [{https://www.googleapis.com/compute/v1/projects/example-project/zones/example-zone/instanceGroups/gk3-example-cluster-pool-2-9293c6db-grp 0->1 (max: 1000)} {https://www.googleapis.com/compute/v1/projects/example-project/zones/example-zone/instanceGroups/gk3-example-cluster-pool-2-d99371e7-grp 0->1 (max: 1000)}]
    

    L'événement TriggeredScaleUp indique que votre cluster effectue un scaling à partir de zéro nœud vers autant de nœuds nécessaires pour exécuter la charge de travail déployée.

Échec de la planification des pods système sur des clusters vides

Cet événement se produit lorsqu'aucune de vos propres charges de travail n'est exécutée dans un cluster, ce qui entraîne la réduction de la capacité du cluster à zéro nœud. Les clusters Autopilot démarrent avec zéro nœud utilisable et le scaling à zéro nœud si vous n'exécutez aucune de vos charges de travail dans le cluster. Ce comportement réduit le gaspillage de ressources de calcul dans le cluster.

Lorsqu'un cluster est réduit à zéro nœud, les charges de travail du système GKE ne sont pas planifiées et restent à l'état Pending. Il s'agit d'un comportement intentionnel et aucune action n'est requise. La prochaine fois que vous déploierez une charge de travail sur le cluster, GKE effectuera un scaling à la hausse du cluster et les pods système en attente s'exécuteront sur ces nœuds.

Pour vérifier si des pods système sont en attente en raison d'un cluster vide, procédez comme suit:

  1. Vérifiez si votre cluster comporte des nœuds:

    kubectl get nodes
    

    Le résultat est le suivant, ce qui indique que le cluster ne comporte aucun nœud:

    No resources found
    
  2. Vérifiez l'état des pods système:

    kubectl get pods --namespace=kube-system
    

    Le résultat ressemble à ce qui suit :

    NAME                                                       READY   STATUS    RESTARTS   AGE
    antrea-controller-horizontal-autoscaler-6d97f7cf7c-ngfd2   0/1     Pending   0          9d
    egress-nat-controller-84bc985778-6jcwl                     0/1     Pending   0          9d
    event-exporter-gke-5c5b457d58-7njv7                        0/2     Pending   0          3d5h
    event-exporter-gke-6cd5c599c6-bn665                        0/2     Pending   0          9d
    konnectivity-agent-694b68fb7f-gws8j                        0/2     Pending   0          3d5h
    konnectivity-agent-7d659bf64d-lp4kt                        0/2     Pending   0          9d
    konnectivity-agent-7d659bf64d-rkrw2                        0/2     Pending   0          9d
    konnectivity-agent-autoscaler-5b6ff64fcd-wn7fw             0/1     Pending   0          9d
    konnectivity-agent-autoscaler-cc5bd5684-tgtwp              0/1     Pending   0          3d5h
    kube-dns-65ccc769cc-5q5q7                                  0/5     Pending   0          3d5h
    kube-dns-7f7cdb9b75-qkq4l                                  0/5     Pending   0          9d
    kube-dns-7f7cdb9b75-skrx4                                  0/5     Pending   0          9d
    kube-dns-autoscaler-6ffdbff798-vhvkg                       0/1     Pending   0          9d
    kube-dns-autoscaler-8b7698c76-mgcx8                        0/1     Pending   0          3d5h
    l7-default-backend-87b58b54c-x5q7f                         0/1     Pending   0          9d
    metrics-server-v1.31.0-769c5b4896-t5jjr                    0/1     Pending   0          9d
    
  3. Vérifiez pourquoi les pods système ont l'état Pending:

    kubectl describe pod --namespace=kube-system SYSTEM_POD_NAME
    

    Remplacez SYSTEM_POD_NAME par le nom de n'importe quel pod système dans la sortie de la commande précédente.

    Le résultat ressemble à ce qui suit :

    ...
    Events:
    Type     Reason            Age                       From               Message
    ----     ------            ----                      ----               -------
    Warning  FailedScheduling  4m35s (x27935 over 3d5h)  default-scheduler  no nodes available to schedule pods
    ...
    

    Dans la sortie, la valeur no nodes available to schedule pods dans le champ Message de l'événement FailedScheduling indique que le pod système n'a pas été planifié, car le cluster est vide.

L'accès aux nœuds sous-jacents est interdit dans un cluster GKE Autopilot. Il est donc nécessaire d'exécuter l'utilitaire tcpdump à partir d'un pod, puis de le copier à l'aide de la commande kubectl cp. Si vous exécutez généralement l'utilitaire tcpdump à partir d'un pod d'un cluster GKE Autopilot, l'erreur suivante peut s'afficher :

    tcpdump: eth0: You don't have permission to perform this capture on that device
    (socket: Operation not permitted)

En effet, GKE Autopilot applique par défaut un contexte de sécurité à tous les pods qui abandonnent la fonctionnalité NET_RAW afin de limiter les failles potentielles. Exemple :

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: tcpdump
  name: tcpdump
spec:
  containers:
  - image: nginx
    name: nginx
    resources:
      limits:
        cpu: 500m
        ephemeral-storage: 1Gi
        memory: 2Gi
      requests:
        cpu: 500m
        ephemeral-storage: 1Gi
        memory: 2Gi
    securityContext:
      capabilities:
        drop:
        - NET_RAW

Pour remédier à ce problème, si votre charge de travail nécessite la fonctionnalité NET_RAW, vous pouvez la réactiver comme suit :

  1. Ajoutez la fonctionnalité NET_RAW à la section securityContext de la spécification YAML de votre pod :

    securityContext:
      capabilities:
        add:
        - NET_RAW
    
  2. Exécutez tcpdump à partir d'un pod :

    tcpdump port 53 -w packetcap.pcap
    tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
    
  3. Utilisez la commande kubectl cp pour effectuer une copie sur votre ordinateur local afin de procéder à une analyse plus approfondie :

    kubectl cp POD_NAME:/PATH_TO_FILE/FILE_NAME/PATH_TO_FILE/FILE_NAME
    
  4. Utilisez kubectl exec pour exécuter la commande tcpdump afin d'effectuer une capture de paquets réseau et de rediriger la sortie :

    kubectl exec -it POD_NAME -- bash -c "tcpdump port 53 -w -" > packet-new.pcap
    

Étapes suivantes