Utiliser GKE Dataplane V2

Cette page explique comment activer et dépanner GKE Dataplane V2 pour les clusters Google Kubernetes Engine (GKE).

GKE Dataplane V2 est toujours activé dans les nouveaux clusters Autopilot. Si vous rencontrez des problèmes avec GKE Dataplane V2, passez à la section Dépannage.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  • Activez l'API Google Kubernetes Engine.
  • Activer l'API Google Kubernetes Engine
  • Pour utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé la gcloud CLI, obtenez la dernière version en exécutant la commande gcloud components update. Il est possible que les versions antérieures de la gcloud CLI ne permettent pas d'exécuter les commandes de ce document.

Rôles requis

Pour obtenir les autorisations nécessaires pour créer un cluster GKE, demandez à votre administrateur de vous accorder le rôle IAM Administrateur de cluster Kubernetes Engine (container.clusterAdmin) sur votre projet. Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Vous pouvez également obtenir les autorisations requises avec des rôles personnalisés ou d'autres rôles prédéfinis.

Créer un cluster GKE avec GKE Dataplane V2

Vous ne pouvez activer GKE Dataplane V2 que lorsque vous créez un cluster GKE. Vous ne pouvez pas modifier ce paramètre pour un cluster existant.

Pour créer un cluster Standard qui utilise GKE Dataplane V2, sélectionnez l'une des options suivantes :

Console

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

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

  2. Dans le menu de navigation, cliquez sur Mise en réseau.

  3. Développez la section Container Network Interface (CNI).

  4. Cochez la case Dataplane V2.

  5. Cliquez sur Créer.

gcloud

Exécutez la commande ci-dessous.

gcloud container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-dataplane-v2

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom de votre nouveau cluster.
  • CONTROL_PLANE_LOCATION : emplacement du plan de contrôle du 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":{
    "networkConfig":{
      "datapathProvider":"ADVANCED_DATAPATH"
    }
}

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 toute modification. Évitez de modifier les champs existants dans ce ConfigMap, car cela pourrait déstabiliser le cluster et perturber anetd. Le ConfigMap n'est rétabli dans son état par défaut que si de nouveaux champs y sont ajoutés. Les modifications apportées aux champs existants ne sont pas corrigées. 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élai d'expiration de la connexion 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 liés à l'identité pour l'identité Cilium ne prend pas effet 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 liés à l'identité via 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és Cilium.

Lorsque d'autres mécanismes de prévention/suppression des clés/valeurs d'étiquette à cardinalité élevée des pods ne sont pas disponibles (par exemple, lorsque les étiquettes sont appliquées par un outil ou un framework), le filtrage des étiquettes liées à 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 Libellés liés à l'identité dans la documentation Cilium.

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

Symptômes

  • Il est possible que les pods avec des libellés qui doivent être filtrés pour la génération d'identité Cilium ne démarrent pas et restent bloqués à l'état ContainerCreating. Les événements de pod peuvent afficher des erreurs de délai avant 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 du nombre d'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é.

Versions corrigées

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

  • 1.34.6-gke.1307000 ou versions ultérieures
  • 1.35.2-gke.1962000 ou versions ultérieures

Solution

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, le cas échéant.
  2. Modifiez le fichier ConfigMap cilium-config en ajoutant ou en modifiant la clé labels dans la section data. Par exemple, pour empêcher l'utilisation des libellés nommés uuid pour la génération d'identités :

    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 prennent également en compte les modifications requises :

    kubectl rollout restart daemonset anetd -n kube-system
    

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

Dans les clusters GKE Dataplane V2, des problèmes de connectivité intermittents peuvent survenir 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. Depuis la version 2.10, l'argument --random-fully est implémenté en interne par défaut dans ip-masq-agent. Pour atténuer ce problème, définissez explicitement --random-fully=false (applicable depuis la version 2.11) sous les arguments de votre configuration ip-masq-agent. Pour en savoir plus sur la configuration, consultez 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 la configuration de 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, examinez 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 : toutes les versions disponibles

Dans les clusters qui utilisent GKE Dataplane V2, vous pouvez rencontrer des échecs de connectivité lorsque le trafic cible l'adresse IP et le 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 associe 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 à 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 limite connue dans GKE Dataplane V2, où le trafic de l'équilibreur de charge réseau direct n'est pas systématiquement transféré vers les pods hostPort.

    Solution de contournement : lorsque vous exposez des 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.
    
  • hostPort en conflit avec la plage réservée NodePort :

    Si le hostPort d'un pod est en conflit avec la plage NodePort réservée (30000-32767), Cilium risque de ne pas pouvoir transférer le trafic vers le pod. Ce comportement se produit, car Cilium gère les capacités hostPort, en remplaçant la méthode Portmap précédente. Il s'agit d'un comportement attendu pour Cilium, qui est mentionné dans sa documentation publique.

Nous ne prévoyons pas de corriger ces limites 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 les services NodePort au lieu de hostPort pour améliorer la fiabilité. NodePort Les services offrent des capacités similaires.

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

Versions de GKE concernées : antérieures à 1.32

Si vous spécifiez le champ endPort dans un objet NetworkPolicy sur un cluster sur lequel GKE Dataplane V2 est activé et qui exécute une version de GKE antérieure à la version 1.32, Kubernetes ignore le champ.

L'API NetworkPolicy de Kubernetes vous permet de spécifier une plage de ports sur lesquels Kubernetes applique la règle de réseau. Cette API est compatible avec les clusters utilisant une règle de réseau Calico, ainsi qu'avec les clusters avec GKE Dataplane V2 qui exécutent la version 1.32 ou ultérieure de GKE. L'API n'est pas compatible avec les clusters GKE Dataplane V2 qui exécutent des versions antérieures à 1.32.

Pour vérifier le comportement de vos objets NetworkPolicy, relisez-les après les avoir écrits sur le serveur d'API. Si l'objet contient toujours le champ endPort, Kubernetes applique la fonctionnalité. Si le champ endPort est manquant, Kubernetes n'applique pas la fonctionnalité. L'objet stocké dans le serveur d'API est la source de vérité pour la règle de réseau.

Pour en savoir plus, 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 de GKE ou ultérieure.

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

Lorsque les clusters sont mis à niveau vers la version 1.35.1-gke.1616000 de GKE ou une version ultérieure, 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 d'Istio géré, 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 résoudre ce problème, rétrogradez le cluster concerné vers une version GKE antérieure à 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œuds gérés 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 de votre cluster tous les programmes eBPF personnalisés ou les charges de travail qui injectent de tels programmes.

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
    

Étapes suivantes