Utiliser GKE Dataplane V2

Cette page explique comment activer GKE Dataplane V2 et résoudre les problèmes associés pour les clusters Google Kubernetes Engine (GKE).

Les nouveaux clusters Autopilot disposent de GKE Dataplane V2 activé dans les versions 1.22.7-gke.1500 et ultérieures, et les versions 1.23.4-gke.1500 et ultérieures. Si vous rencontrez des problèmes avec GKE Dataplane V2, passez à la section Dépannage.

Créer un cluster GKE avec GKE Dataplane V2

Vous pouvez activer GKE Dataplane V2 lorsque vous créez des clusters avec GKE version 1.20.6-gke.700 ou une version ultérieure en utilisant gcloud CLI ou l'API GKE. Vous pouvez également activer GKE Dataplane V2 dans la version Bêta lorsque vous créez des clusters avec GKE version 1.17.9 ou une version ultérieure.

Console

Pour créer un cluster avec GKE Dataplane V2, procédez comme suit :

  1. Dans la Google Cloud console, accédez à la page Créer un cluster Kubernetes.

    Accéder à la page "Créer un cluster Kubernetes"

  2. Dans la section "Mise en réseau", cochez la case Activer Dataplane V2. L'option "Activer la règle de réseau Kubernetes" est désactivée lorsque vous sélectionnez "Activer Dataplane V2", car l'application de la règle de réseau est intégrée à GKE Dataplane V2.

  3. Cliquez sur Créer.

gcloud

Pour créer un cluster avec GKE Dataplane V2, utilisez la commande suivante :

gcloud container clusters create CLUSTER_NAME \
    --enable-dataplane-v2 \
    --enable-ip-alias \
    --release-channel CHANNEL_NAME \
    --location COMPUTE_LOCATION

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom de votre nouveau cluster
  • CHANNEL_NAME : canal de publication incluant la version 1.20.6-gke.700 ou ultérieure de GKE. Si vous préférez ne pas utiliser de canal de publication, vous pouvez également utiliser l'option --cluster-version au lieu de --release-channel, en spécifiant la version 1.20.6-gke.700 ou ultérieure.
  • COMPUTE_LOCATION : emplacement Compute Engine du nouveau cluster.

API

Pour créer un cluster avec GKE Dataplane V2, spécifiez le champ datapathProvider dans l'objet networkConfig dans la requête create du cluster.

L'extrait de code JSON suivant montre la configuration nécessaire pour activer GKE Dataplane V2 :

"cluster":{
   "initialClusterVersion":"VERSION",
   "ipAllocationPolicy":{
      "useIpAliases":true
   },
   "networkConfig":{
      "datapathProvider":"ADVANCED_DATAPATH"
   },
   "releaseChannel":{
      "channel":"CHANNEL_NAME"
   }
}

Remplacez les éléments suivants :

  • VERSION : version de votre cluster, qui doit être la version 1.20.6-gke.700 ou ultérieure de GKE.
  • CHANNEL_NAME : canal de publication incluant la version 1.20.6-gke.700 ou ultérieure de GKE.

Résoudre les problèmes liés à GKE Dataplane V2

Cette section explique comment examiner et résoudre les problèmes liés à GKE Dataplane V2.

  1. Vérifiez que GKE Dataplane V2 est activé :

    kubectl -n kube-system get pods -l k8s-app=cilium -o wide
    

    Si GKE Dataplane V2 est en cours d'exécution, la sortie inclut les pods portant le préfixe anetd-. anetd est le contrôleur réseau pour GKE Dataplane V2.

  2. Si le problème concerne les services ou l'application de la règle de réseau, consultez les journaux du pod anetd. Utilisez les sélecteurs de journal suivants dans Cloud Logging :

    resource.type="k8s_container"
    labels."k8s-pod/k8s-app"="cilium"
    resource.labels.cluster_name="CLUSTER_NAME"
    
  3. Si la création de pod échoue, consultez les journaux du kubelet pour obtenir des indices. Utilisez les sélecteurs de journal suivants dans Cloud Logging :

    resource.type="k8s_node"
    log_name=~".*/logs/kubelet"
    resource.labels.cluster_name="CLUSTER_NAME"
    

    Remplacez CLUSTER_NAME par le nom du cluster ou supprimez-le complètement pour afficher les journaux de tous les clusters.

  4. Si les pods anetd ne sont pas en cours d'exécution, examinez le ConfigMap cilium-config pour détecter d'éventuelles modifications. Évitez de modifier les champs existants dans ce ConfigMap, car de telles modifications peuvent déstabiliser le cluster et perturber anetd. Le ConfigMap n'est rétabli à l'état par défaut que si de nouveaux champs y sont ajoutés. Les modifications apportées aux champs existants ne sont pas rétablies, et nous vous recommandons de ne pas modifier ni personnaliser le ConfigMap.

Problèmes connus

Lorsque vous utilisez GKE Dataplane V2, vous pouvez rencontrer les problèmes connus suivants.

Délais d'expiration des connexions pour les pods non prêts

Lorsqu'un pod n'est pas prêt, les connexions au service associé peuvent expirer. Il s'agit du comportement attendu pour GKE Dataplane V2, qui diffère de kube-proxy, qui peut renvoyer une erreur connection refused plus rapidement.

Le filtrage des libellés pertinents pour l'identité pour l'identité Cilium n'est pas appliqué et les pods sont bloqués à l'état ContainerCreating

Versions concernées : 1.34, 1.35

Dans les clusters GKE Dataplane V2, l'utilisation d'urgence du filtrage des libellés pertinents pour l'identité via le ConfigMap kube-system/cilium-config-emergency-override n'est pas correctement appliquée dans les versions concernées.

Cette approche limite les libellés de pod utilisés pour la génération d'identité Cilium.

Lorsque d'autres mécanismes de prévention/suppression des clés/valeurs d'étiquette à forte cardinalité des pods ne sont pas disponibles (par exemple, lorsque des étiquettes sont appliquées par un outil ou un framework), le filtrage des étiquettes pertinentes pour l'identité peut être utilisé pour exclure les clés d'étiquette du calcul de l'identité Cilium. Pour en savoir plus sur la configuration de ces règles, consultez la section Libellés pertinents pour l'identité dans la documentation Cilium.

Pour les versions GKE concernées, les identités Cilium créées par l'opérateur continuent d'inclure les libellés exclus.

Symptômes

  • Les pods avec des libellés qui doivent être filtrés pour la génération d'identité Cilium peuvent ne pas démarrer et rester bloqués à l'état ContainerCreating. Les événements de pod peuvent afficher des erreurs de délai d'expiration :

      {"level":"warning", "msg":"Error changing endpoint identity", "error":"unable to resolve identity: timed out waiting for cilium-operator to allocate CiliumIdentity for key ...;, error: exponential backoff cancelled via context: context canceled", "k8sPodName":"...", "subsys":"endpoint"}
    
  • Au lieu de partager des identités basées sur des libellés filtrés, les pods avec des valeurs de libellé uniques continuent de générer des identités Cilium uniques. Cela peut entraîner une forte augmentation des identités, ce qui peut épuiser les identités Cilium disponibles (jusqu'à une limite de 65 536) et entraîner des problèmes d'évolutivité.

Solutions

Pour contourner ce problème, appliquez les règles de filtrage des libellés au champ data.labels dans le ConfigMap cilium-config principal et supprimez-les de cilium-config-emergency-override. Cette situation persiste lors des opérations du plan de contrôle, telles que les mises à niveau, car GKE conserve les modifications apportées par l'utilisateur aux champs qu'il ne gère pas dans le ConfigMap cilium-config.

  1. Supprimez la clé labels de la section data du ConfigMap cilium-config-emergency-override si elle existe.
  2. Modifiez le ConfigMap cilium-config en ajoutant ou en modifiant la clé labels dans la section data. Par exemple, pour empêcher l'utilisation de libellés nommés uuid pour la génération d'identité :

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cilium-config
      namespace: kube-system
    data:
      # ... other existing keys
      labels: "!uuid"
      # ... other existing keys
    
  3. Redémarrez anet-operator sur le plan de contrôle en mettant à niveau le plan de contrôle vers la même version qu'il exécute. Cela force l'opérateur à redémarrer et à recharger sa configuration :

    gcloud container clusters upgrade CLUSTER_NAME \
        --location CLUSTER_LOCATION \
        --project PROJECT_ID \
        --cluster-version $(gcloud container clusters describe CLUSTER_NAME --location CLUSTER_LOCATION --project PROJECT_ID --format="value(currentMasterVersion)") \
        --master
    
  4. Une fois le plan de contrôle redémarré, redémarrez le DaemonSet anetd pour vous assurer que les agents de nœud récupèrent également les modifications requises :

    kubectl rollout restart daemonset anetd -n kube-system
    

Problèmes de connectivité intermittents liés aux conflits de plage NodePort dans les clusters GKE Dataplane V2

Dans les clusters GKE Dataplane V2, des problèmes de connectivité intermittents peuvent se produire pour le trafic masqué ou avec l'utilisation de ports éphémères. Ces problèmes sont dus aux conflits potentiels de port avec la plage NodePort réservée et se produisent généralement dans les scénarios suivants :

  • **ip-masq-agent personnalisé** : si vous utilisez un ip-masq-agent personnalisé (version 2.10 ou ultérieure), dans lequel le cluster dispose de services NodePort ou d'équilibreur de charge, vous risquez de constater des problèmes de connectivité intermittents dus à leur conflit avec la plage NodePort .ip-masq-agentip-masq-agentNodePortNodePort Depuis la version 2.10, l'argument --random-fully est implémenté en interne par défaut dans ip-masq-agent. Pour éviter cela, définissez explicitement --random-fully=false (applicable depuis la version 2.11) sous les arguments dans votre configuration ip-masq-agent. Pour plus d'informations sur la configuration, consultez la section Configurer un agent de masquage d'adresses IP dans les clusters standards.

  • Chevauchement de la plage de ports éphémère : si la plage de ports éphémère définie par net.ipv4.ip_local_port_range sur vos nœuds GKE chevauche la plage NodePort (30000-32767), cela peut également déclencher des problèmes de connectivité. Pour éviter ce problème, assurez-vous que ces deux plages ne se chevauchent pas.

Vérifiez votre configuration ip-masq-agent et les paramètres de plage de ports éphémères pour vous assurer qu'ils ne sont pas en conflit avec la plage NodePort. Si vous rencontrez des problèmes de connectivité intermittents, tenez compte de ces causes potentielles et ajustez votre configuration en conséquence.

Problèmes de connectivité avec hostPort dans les clusters GKE Dataplane V2

Versions de GKE concernées : 1.29 et versions ultérieures

Dans les clusters qui utilisent GKE Dataplane V2, vous pouvez rencontrer des échecs de connectivité lorsque le trafic cible l'adresse IP:Port d'un nœud où le port est le hostPort défini sur le pod. Ces problèmes surviennent dans deux scénarios principaux :

  • Nœuds avec hostPort derrière un équilibreur de charge réseau passthrough :

    hostPort lie un pod au port d'un nœud spécifique, et un équilibreur de charge réseau passthrough distribue le trafic sur tous les nœuds. Lorsque vous exposez des pods à Internet à l'aide de hostPort et d'un équilibreur de charge réseau passthrough, l'équilibreur de charge peut envoyer du trafic vers un nœud sur lequel le pod n'est pas en cours d'exécution, ce qui entraîne des échecs de connexion. Cela est dû à une limitation connue de GKE Dataplane V2, où le trafic de l'équilibreur de charge réseau passthrough n'est pas systématiquement transféré vers les pods hostPort.

    Solution : lorsque vous exposez les hostPort d'un pod sur le nœud avec un équilibreur de charge réseau passthrough, spécifiez l'adresse IP interne ou externe de l'équilibreur de charge réseau dans le champ hostIP du pod.

    ports:
    - containerPort: 62000
      hostPort: 62000
      protocol: TCP
      hostIP: 35.232.62.64
    - containerPort: 60000
      hostPort: 60000
      protocol: TCP
      hostIP: 35.232.62.64
      # Assuming 35.232.62.64 is the external IP address of a passthrough Network Load Balancer.
    
  • Conflit hostPort avec la plage NodePort réservée :

    Si le hostPort d'un pod est en conflit avec la plage NodePort réservée (30000-32767), Cilium peut ne pas transférer le trafic vers le pod. Ce comportement a été observé dans les versions de cluster 1.29 et ultérieures, car Cilium gère désormais les fonctionnalités hostPort, en remplaçant la méthode Portmap précédente. Il s'agit d'un comportement attendu pour Cilium, mentionné dans sa documentation publique.

Nous ne prévoyons pas de corriger ces limitations dans les versions ultérieures. La cause première de ces problèmes est liée au comportement de Cilium et échappe au contrôle direct de GKE.

Recommandation : nous vous recommandons de migrer vers des services NodePort au lieu de hostPort pour améliorer la fiabilité. Les services NodePort offrent des fonctionnalités similaires.

Les plages de ports des règles de réseau ne prennent pas effet

Si vous spécifiez un champ endPort dans une règle de réseau sur un cluster sur lequel GKE Dataplane V2 est activé, il ne sera pas appliqué.

L'API Network Policy de Kubernetes vous permet de spécifier une plage de ports sur lesquels la règle de réseau est appliquée. Cette API est compatible avec les clusters utilisant une règle de réseau Calico, mais pas avec les clusters avec GKE Dataplane V2.

Vous pouvez vérifier le comportement des objets NetworkPolicy en les lisant après avoir écrit sur le serveur d'API. Si l'objet contient toujours le champ endPort, la fonctionnalité est appliquée. Si le champ endPort n'est pas renseigné, la fonctionnalité n'est pas appliquée. Dans tous les cas, l'objet stocké dans le serveur d'API est la source de vérité pour la règle de réseau.

Pour plus d'informations, consultez KEP-2079 : Règles de réseau compatibles avec les plages de ports.

Versions corrigées

Pour résoudre ce problème, mettez à niveau votre cluster vers la version 1.32 ou ultérieure de GKE.

La règle de réseau supprime une connexion en raison d'une recherche de suivi des connexions incorrecte

Lorsqu'un pod client se connecte lui-même via un Service ou l'adresse IP virtuelle d'un équilibreur de charge réseau passthrough interne, le paquet de réponse n'est pas identifié comme faisant partie d'une connexion existante en raison d'une recherche conntrack incorrecte dans le plan de données. Cela signifie qu'une règle de réseau qui limite le trafic entrant pour le pod est appliquée de manière incorrecte sur le paquet.

L'impact de ce problème dépend du nombre de pods configurés pour le service. Par exemple, si le service dispose d'un pod de backend, la connexion échoue toujours. Si le service dispose de deux pods de backend, la connexion échoue la moitié du temps.

Versions corrigées

Pour résoudre ce problème, mettez à niveau votre cluster vers l'une des versions GKE suivantes :

  • 1.28.3-gke.1090000 (et versions ultérieures).

Solutions

Vous pouvez limiter les conséquences de ce problème en configurant la même valeur pour port et containerPort dans le fichier manifeste du Service.

Suppressions de paquets pour les flux de connexion "hairpin"

Lorsqu'un pod crée une connexion TCP vers lui-même à l'aide d'un service, de sorte que le pod est à la fois la source et la destination de la connexion, le suivi des connexions GKE Dataplane V2 eBPF suit les états de connexion de manière incorrecte, ce qui entraîne des fuites dans les entrées conntrack.

En cas de fuite d'un tuple de connexion (protocole, adresse IP source/de destination et port source/de destination), les nouvelles connexions utilisant le même tuple de connexion peuvent entraîner des suppressions de paquets de retour.

Versions corrigées

Pour résoudre ce problème, mettez à niveau votre cluster vers l'une des versions GKE suivantes :

  • 1.28.3-gke.1090000 (et versions ultérieures)
  • 1.27.11-gke.1097000 (et versions ultérieures)

Solutions

Utilisez l'une des solutions suivantes :

  • Activez la réutilisation TCP (message keep-alive) pour les applications exécutées dans des pods pouvant communiquer avec eux-mêmes à l'aide d'un service. Cette solution permet d'empêcher l'envoi de l'option TCP FIN et d'éviter les fuites sur l'entrée conntrack.

  • Lorsque vous utilisez des connexions de courte durée, exposez le pod à l'aide d'un équilibreur de charge proxy, tel que Gateway, pour exposer le service. La destination de la requête de connexion est alors définie sur l'adresse IP de l'équilibreur de charge, ce qui empêche GKE Dataplane V2 d'effectuer une traduction d'adresse réseau source (SNAT) vers l'adresse IP de rebouclage.

La mise à niveau du plan de contrôle GKE provoque un blocage du pod anetd

Lorsque vous mettez à niveau un cluster GKE sur lequel GKE Dataplane V2 (chemin de données avancé) est activé de la version 1.27 à la version 1.28, vous pouvez rencontrer une situation d'interblocage. Les charges de travail peuvent subir des interruptions en raison de l'impossibilité d'arrêter les anciens pods ou de planifier les composants nécessaires tels que anetd.

Cause

Le processus de mise à niveau du cluster augmente les besoins en ressources des composants GKE Dataplane V2. Cette augmentation peut entraîner une contention des ressources, ce qui perturbe la communication entre le plug-in Cilium Container Network Interface (CNI) et le daemon Cilium.

Symptômes

Vous pouvez observer les symptômes suivants :

  • Les pods anetd restent bloqués à l'état Pending.
  • Les pods de charge de travail sont bloqués à l'état Terminating.
  • Erreurs indiquant des échecs de communication Cilium, telles que failed to connect to Cilium daemon.
  • Erreurs lors du nettoyage des ressources réseau pour les bacs à sable de pod, par exemple :

    1rpc error: code = Unknown desc = failed to destroy network for sandbox "[sandbox_id]": plugin type="cilium-cni" failed (delete): unable to connect to Cilium daemon... connection refused
    

Solution

Clusters standards : pour résoudre le problème et autoriser la planification du pod anetd, augmentez temporairement les ressources allouables sur le nœud concerné.

  1. Pour identifier le nœud concerné et vérifier son processeur et sa mémoire allouables, exécutez la commande suivante :

    kubectl get nodes $NODE_NAME -o json | jq '.status.allocatable | {cpu, memory}'
    
  2. Pour augmenter temporairement le processeur et la mémoire allouables, exécutez la commande suivante :

    kubectl patch node $NODE_NAME -p '{"status":{"allocatable":{"cpu":CPU_VALUE, "memory":MEMORY_VALUE}}}'
    

Clusters Autopilot : pour résoudre le problème d'interblocage sur les clusters Autopilot, libérez des ressources en supprimant de force le pod concerné :

kubectl delete pod POD_NAME -n NAMESPACE --grace-period=0 --force

Remplacez les éléments suivants :

  • POD_NAME : nom du pod.
  • NAMESPACE : espace de noms du pod.

Une fois que vous avez augmenté les ressources allouables sur le nœud et que la mise à niveau de la version 1.27 à la version 1.28 de GKE est terminée, le pod anetd s'exécute sur la version la plus récente.

Nœuds à l'état NodeNotReady en raison d'une erreur containerID manquante

Lorsque les clusters sont mis à niveau vers la version 1.35.1-gke.1616000 ou ultérieure de GKE, les nœuds peuvent immédiatement passer à l'état NodeNotReady si GKE Dataplane V2 et Cloud Service Mesh sont activés.

Cause

À partir de la version 1.35.1-gke.1616000 de GKE, les clusters GKE Dataplane V2 utilisent la version 1.1.0 de CNI dans leurs fichiers de configuration CNI. Cette modification nécessite que les plug-ins CNI en aval, tels que Google Managed Istio, soient également compatibles avec la version 1.1.0 de CNI. En raison d'un retard dans le déploiement de Managed Istio, certains clusters n'ont pas encore reçu la version compatible (1.23), ce qui entraîne l'échec de l'initialisation.

Symptômes

Les nœuds concernés s'affichent immédiatement comme NodeNotReady. Le message d'erreur suivant s'affiche dans les journaux containerd :

NetworkPluginNotReady message:Network plugin returns error: missing containerID

Solution

Pour atténuer le problème, rétrogradez le cluster concerné vers une version de GKE antérieure à la version 1.35.1-gke.1616000.

Interférence des programmes eBPF personnalisés

GKE utilise des programmes eBPF pour gérer la mise en réseau de GKE Dataplane V2. Si vous déployez des programmes eBPF personnalisés sur des interfaces réseau de nœud gérées par GKE, ces programmes peuvent interférer avec les programmes eBPF gérés par GKE et entraîner des problèmes de réseau.

GKE n'est pas compatible avec les programmes eBPF personnalisés associés aux interfaces réseau suivantes :

  • eth*
  • ens4
  • lo
  • cilium*
  • gke*
  • veth*

La présence de programmes eBPF personnalisés sur ces interfaces peut interférer avec les programmes installés par l'agent anetd de GKE Dataplane V2, ce qui peut perturber la mise en réseau du cluster. Nous vous recommandons de supprimer tous les programmes eBPF personnalisés ou les charges de travail qui injectent de tels programmes dans votre cluster.

Découvrir les programmes eBPF personnalisés

Pour découvrir les programmes eBPF personnalisés exécutés sur les nœuds de cluster, vous pouvez créer un DaemonSet configuré avec le paramètre hostNetwork: true, qui utilise bpftool pour interroger ces programmes eBPF :

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: bpftool-logger
  labels:
    app: bpftool-logger
spec:
  selector:
    matchLabels:
      app: bpftool-logger
  template:
    metadata:
      labels:
        app: bpftool-logger
    spec:
      hostPID: true
      hostNetwork: true
      containers:
      - name: bpftool
        image: ubuntu:22.04
        securityContext:
          privileged: true
        env:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        command:
        - /bin/bash
        - -c
        - |
          echo "Installing dependencies..."
          apt-get update -y > /dev/null 2>&1
          apt-get install -y curl tar > /dev/null 2>&1

          echo "Downloading and setting up bpftool..."
          curl -sL https://github.com/libbpf/bpftool/releases/download/v7.7.0/bpftool-v7.7.0-amd64.tar.gz | tar xz
          chmod +x bpftool
          mv bpftool /usr/local/bin/

          echo "========== $(date) | Node: ${NODE_NAME} =========="
          bpftool net | grep -E '^(eth|ens4|lo|cilium|gke|veth)' | grep -v ' cil_'
          sleep infinity
  1. Enregistrez le fichier manifeste sous le nom ebpf-discovery.yaml et appliquez le DaemonSet :

    kubectl apply -f ebpf-discovery.yaml
    
  2. Attendez que les pods soient en cours d'exécution :

    kubectl rollout status ds/bpftool-logger
    
  3. Consultez les journaux des pods pour découvrir les programmes eBPF :

    kubectl logs -l app=bpftool-logger
    
  4. Lorsque vous avez terminé, supprimez le DaemonSet :

    kubectl delete -f ebpf-discovery.yaml
    

Étape suivante