Utilizzo di GKE Dataplane V2

Questa pagina spiega come abilitare e risolvere i problemi GKE Dataplane V2 per i cluster Google Kubernetes Engine (GKE).

I nuovi cluster Autopilot hanno GKE Dataplane V2 abilitato nelle versioni 1.22.7-gke.1500 e successive e nelle versioni 1.23.4-gke.1500 e successive. Se riscontri problemi con l'utilizzo di GKE Dataplane V2, vai alla sezione Risoluzione dei problemi.

Creazione di un cluster GKE con GKE Dataplane V2

Puoi abilitare GKE Dataplane V2 quando crei nuovi cluster con GKE versione 1.20.6-gke.700 e successive utilizzando gcloud CLI o l'API GKE. Puoi anche abilitare GKE Dataplane V2 in anteprima quando crei nuovi cluster con GKE versione 1.17.9 e successive.

Console

Per creare un nuovo cluster con GKE Dataplane V2, esegui le seguenti attività:

  1. Nella Cloud de Confiance console, vai alla pagina Crea un cluster Kubernetes.

    Vai a Crea un cluster Kubernetes

  2. Nella sezione Networking, seleziona la casella di controllo Abilita Dataplane V2. L'opzione Abilita policy di rete Kubernetes è disabilitata quando selezioni Abilita Dataplane V2 perché l'applicazione dei criteri di rete è integrata in GKE Dataplane V2.

  3. Fai clic su Crea.

gcloud

Per creare un nuovo cluster con GKE Dataplane V2, utilizza il seguente comando:

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

Sostituisci quanto segue:

  • CLUSTER_NAME: il nome del nuovo cluster.
  • CHANNEL_NAME: un canale di rilascio che include GKE versione 1.20.6-gke.700 o successive. Se preferisci non utilizzare un canale di rilascio, puoi anche utilizzare il flag --cluster-version anziché --release-channel, specificando la versione 1.20.6-gke.700 o successive.
  • COMPUTE_LOCATION: la località di Compute Engine per il nuovo cluster.

API

Per creare un nuovo cluster con GKE Dataplane V2, specifica il datapathProvider campo nell' networkConfig oggetto nella richiesta create del cluster.

Il seguente snippet JSON mostra la configurazione necessaria per abilitare GKE Dataplane V2:

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

Sostituisci quanto segue:

  • VERSION: la versione del cluster, che deve essere GKE 1.20.6-gke.700 o successive.
  • CHANNEL_NAME: un canale di rilascio che include GKE versione 1.20.6-gke.700 o successive.

Risoluzione dei problemi relativi a GKE Dataplane V2

Questa sezione mostra come esaminare e risolvere i problemi relativi a GKE Dataplane V2.

  1. Verifica che GKE Dataplane V2 sia abilitato:

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

    Se GKE Dataplane V2 è in esecuzione, l'output include i pod con il prefisso anetd-. anetd è il controller di rete per GKE Dataplane V2.

  2. Se il problema riguarda i servizi o l'applicazione dei criteri di rete, controlla i log dei pod anetd. Utilizza i seguenti selettori di log in Cloud Logging:

    resource.type="k8s_container"
    labels."k8s-pod/k8s-app"="cilium"
    resource.labels.cluster_name="CLUSTER_NAME"
    
  3. Se la creazione dei pod non riesce, controlla i log di kubelet per trovare indizi. Utilizza i seguenti selettori di log in Cloud Logging:

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

    Sostituisci CLUSTER_NAME con il nome del cluster o rimuovilo completamente per visualizzare i log di tutti i cluster.

  4. Se i pod anetd non sono in esecuzione, esamina la ConfigMap cilium-config per verificare la presenza di modifiche. Evita di modificare i campi esistenti all'interno di questa ConfigMap, perché queste modifiche possono destabilizzare il cluster e interrompere anetd. La ConfigMap viene ripristinata allo stato predefinito solo se vengono aggiunti nuovi campi. Le modifiche ai campi esistenti non vengono ripristinate e ti consigliamo di non modificare o personalizzare la ConfigMap.

Problemi noti

Quando utilizzi GKE Dataplane V2, potresti riscontrare i seguenti problemi noti.

Timeout di connessione per i pod non pronti

Quando un pod non è pronto, le connessioni al servizio associato possono andare in timeout. Questo è il comportamento previsto per GKE Dataplane V2 ed è diverso da kube-proxy, che può restituire un errore connection refused più rapido.

Il filtro delle etichette pertinenti all'identità per l'identità Cilium non ha effetto e i pod rimangono bloccati nello stato ContainerCreating

Versioni interessate: 1.34, 1.35

Nei cluster GKE Dataplane V2, l'utilizzo di emergenza del filtro delle etichette pertinenti all'identità tramite la ConfigMap kube-system/cilium-config-emergency-override non viene applicato correttamente nelle versioni interessate.

Questo approccio limita le etichette dei pod utilizzate per la generazione dell'identità Cilium.

Quando altri meccanismi per impedire/rimuovere le coppie chiave/valore di etichetta ad alta cardinalità dai pod non sono disponibili (ad esempio quando le etichette vengono applicate da uno strumento o un framework), è possibile utilizzare il filtro delle chiavi di etichetta pertinenti all'identità per escludere le chiavi delle etichette dal calcolo dell'identità Cilium. Per ulteriori informazioni sulla configurazione di queste regole, consulta Etichette pertinenti all'identità nella documentazione di Cilium.

Per le versioni GKE interessate, le identità Cilium create dall'operatore continuano a includere le etichette escluse.

Sintomi

  • I pod con etichette che devono essere filtrate per la generazione dell'identità Cilium potrebbero non essere avviati e rimanere bloccati nello stato ContainerCreating. Gli eventi dei pod potrebbero mostrare errori di timeout:

      {"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"}
    
  • Anziché condividere le identità in base alle etichette filtrate, i pod con valori di etichetta univoci continuano a generare identità Cilium univoche. Ciò può comportare un forte aumento delle identità, potenzialmente esaurire le identità Cilium disponibili (fino a un limite di 65.536) e causare problemi di scalabilità.

Versioni corrette

Per risolvere il problema, esegui l'upgrade del cluster a una delle seguenti versioni GKE:

  • 1.34.6-gke.1307000 o versioni successive
  • 1.35.2-gke.1962000 o versioni successive

Soluzione

Come soluzione, applica le regole di filtro delle etichette al campo data.labels in alla ConfigMap cilium-config principale e rimuovile da cilium-config-emergency-override. Questa situazione persiste durante le operazioni del control plane, come gli upgrade, perché GKE conserva le modifiche apportate dall'utente ai campi che non gestisce all'interno della ConfigMap cilium-config.

  1. Rimuovi la chiave labels dalla sezione data della ConfigMap cilium-config-emergency-override, se esiste.
  2. Modifica la ConfigMap cilium-config aggiungendo o modificando la chiave labels nella sezione data. Ad esempio, per impedire l'utilizzo delle etichette denominate uuid per la generazione dell'identità:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cilium-config
      namespace: kube-system
    data:
      # ... other existing keys
      labels: "!uuid"
      # ... other existing keys
    
  3. Riavvia anet-operator sul control plane eseguendo l'upgrade del control plane alla stessa versione in esecuzione. In questo modo, l'operatore viene riavviato e la sua configurazione viene ricaricata:

    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. Dopo il riavvio del control plane, riavvia il DaemonSet anetd per assicurarti che anche gli agenti dei nodi acquisiscano le modifiche necessarie:

    kubectl rollout restart daemonset anetd -n kube-system
    

Problemi di connettività intermittenti correlati a conflitti di intervalli NodePort nei cluster GKE Dataplane V2

Nei cluster GKE Dataplane V2 possono verificarsi problemi di connettività intermittenti per il traffico con mascheramento IP o con l'utilizzo di porte effimere. Questi problemi sono dovuti a potenziali conflitti di porte con l'intervallo NodePort riservato e in genere si verificano nei seguenti scenari:

  • Personalizzato ip-masq-agent: se utilizzi un ip-masq-agent (versione 2.10 o successive), in cui il cluster ha NodePort o bilanciamento del carico servizi, potresti riscontrare problemi di connettività intermittenti a causa del conflitto con l'intervallo NodePort. A partire dalla versione 2.10 e successive, ip-masq-agent ha l'argomento --random-fully implementato internamente per impostazione predefinita. Per risolvere questo problema, imposta esplicitamente --random-fully=false (applicabile dalla versione 2.11) negli argomenti della configurazione di ip-masq-agent. Per i dettagli sulla configurazione, consulta Configurazione di un agente di mascheramento IP nei cluster standard.

  • Sovrapposizione dell'intervallo di porte effimere: se l'intervallo di porte effimere definito da net.ipv4.ip_local_port_range sui nodi GKE si sovrappone all'intervallo NodePort (30000-32767), può anche causare problemi di connettività. Per evitare questo problema, assicurati che questi due intervalli non si sovrappongano.

Esamina la configurazione di ip-masq-agent e le impostazioni dell'intervallo di porte effimere per assicurarti che non siano in conflitto con l'intervallo NodePort. Se riscontri problemi di connettività intermittenti, considera queste potenziali cause e modifica la configurazione di conseguenza.

Problemi di connettività con hostPort nei cluster GKE Dataplane V2

Versioni GKE interessate: 1.29 e successive

Nei cluster che utilizzano GKE Dataplane V2, potresti riscontrare errori di connettività quando il traffico è destinato all'IP:Porta di un nodo in cui la porta è la hostPort definita nel pod. Questi problemi si verificano in due scenari principali:

  • Nodi con hostPort dietro un bilanciatore del carico di rete passthrough:

    hostPort associa un pod alla porta di un nodo specifico e un bilanciatore del carico di rete passthrough distribuisce il traffico su tutti i nodi. Quando esponi i pod a internet utilizzando hostPort e un bilanciatore del carico di rete passthrough, il bilanciatore del carico potrebbe inviare il traffico a un nodo in cui il pod non è in esecuzione, causando errori di connessione. Ciò è dovuto a una limitazione nota in GKE Dataplane V2, in cui il traffico del bilanciatore del carico di rete passthrough non viene inoltrato in modo coerente ai pod hostPort.

    Soluzione: quando esponi le hostPort di un pod sul nodo con un bilanciatore del carico di rete passthrough, specifica l'indirizzo IP interno o esterno del bilanciatore del carico di rete nel campo hostIP del 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.
    
  • Conflitto di hostPort con l'intervallo NodePort riservato:

    Se la hostPort di un pod è in conflitto con l'intervallo NodePort riservato (30000-32767), Cilium potrebbe non riuscire a inoltrare il traffico al pod. Questo comportamento è stato osservato nelle versioni del cluster 1.29 e successive, poiché Cilium ora gestisce le funzionalità hostPort, sostituendo il metodo Portmap precedente. Si tratta di un comportamento previsto per Cilium ed è menzionato nella documentazione pubblica.

Non prevediamo di risolvere queste limitazioni nelle versioni successive. La causa principale di questi problemi è correlata al comportamento di Cilium ed è al di fuori del controllo diretto di GKE.

Consiglio: ti consigliamo di eseguire la migrazione ai servizi NodePort anziché a hostPort per una maggiore affidabilità. I servizi NodePort forniscono funzionalità simili.

Gli intervalli di porte dei criteri di rete non hanno effetto

Se specifichi un campo endPort in un criterio di rete su un cluster con GKE Dataplane V2 abilitato, non avrà effetto.

L'API Kubernetes Network Policy consente di specificare un intervallo di porte in cui viene applicato il criterio di rete. Questa API è supportata nei cluster con Calico Network Policy, ma non nei cluster con GKE Dataplane V2.

Puoi verificare il comportamento degli oggetti NetworkPolicy leggendoli dopo averli scritti nel server API. Se l'oggetto contiene ancora il campo endPort, la funzionalità viene applicata. Se il campo endPort non è presente, la funzionalità non viene applicata. In tutti i casi, l'oggetto archiviato nel server API è la fonte attendibile per il criterio di rete.

Per ulteriori informazioni, consulta KEP-2079: Network Policy to support Port Ranges.

Versioni corrette

Per risolvere il problema, esegui l'upgrade del cluster a GKE versioni 1.32 o successive

Il criterio di rete elimina una connessione a causa di una ricerca di tracciamento delle connessioni errata

Quando un pod client si connette a se stesso utilizzando un servizio o l'indirizzo IP virtuale di un bilanciatore del carico di rete passthrough interno, il pacchetto di risposta non viene identificato come parte di una connessione esistente a causa di una ricerca conntrack errata nel piano dati. Ciò significa che un criterio di rete che limita il traffico in entrata per il pod viene applicato in modo errato al pacchetto.

L'impatto di questo problema dipende dal numero di pod configurati per il servizio. Ad esempio, se il servizio ha 1 pod di backend, la connessione non riesce sempre. Se il servizio ha 2 pod di backend, la connessione non riesce il 50% delle volte.

Versioni corrette

Per risolvere il problema, esegui l'upgrade del cluster a una delle seguenti versioni GKE:

  • 1.28.3-gke.1090000 o versioni successive.

Soluzioni

Puoi risolvere questo problema configurando port e containerPort nel manifest del servizio in modo che abbiano lo stesso valore.

Eliminazione di pacchetti per i flussi di connessione hairpin

Quando un pod crea una connessione TCP a se stesso utilizzando un servizio, in modo che il pod sia sia l'origine che la destinazione della connessione, il tracciamento delle connessioni eBPF di GKE Dataplane V2 tiene traccia in modo errato degli stati della connessione, causando la perdita di voci conntrack.

Quando una tupla di connessione (protocollo, IP di origine/destinazione e porta di origine/destinazione) è stata persa, le nuove connessioni che utilizzano la stessa tupla di connessione potrebbero comportare l'eliminazione dei pacchetti di risposta.

Versioni corrette

Per risolvere il problema, esegui l'upgrade del cluster a una delle seguenti versioni GKE:

  • 1.28.3-gke.1090000 o versioni successive
  • 1.27.11-gke.1097000 o versioni successive

Soluzioni

Utilizza una delle seguenti soluzioni:

  • Abilita il riutilizzo TCP (keep-alive) per le applicazioni in esecuzione nei pod che potrebbero comunicare con se stessi utilizzando un servizio. In questo modo, il flag TCP FIN non viene emesso e la voce conntrack non viene persa.

  • Quando utilizzi connessioni di breve durata, esponi il pod utilizzando un bilanciatore del carico proxy, ad esempio Gateway, per esporre il servizio. Di conseguenza, la destinazione della richiesta di connessione viene impostata sull'indirizzo IP del bilanciatore del carico, impedendo a GKE Dataplane V2 di eseguire SNAT sull'indirizzo IP di loopback.

L'upgrade del control plane GKE causa il deadlock dei pod anetd

Quando esegui l'upgrade di un cluster GKE con GKE Dataplane V2 (datapath avanzato) abilitato dalla versione 1.27 alla 1.28, potresti riscontrare una situazione di deadlock. I workload potrebbero subire interruzioni a causa dell'impossibilità di terminare i pod precedenti o pianificare i componenti necessari come anetd.

Causa

Il processo di upgrade del cluster aumenta il requisito di risorse per i componenti GKE Dataplane V2. Questo aumento potrebbe causare una contesa di risorse, che interrompe la comunicazione tra il plug-in Cilium Container Network Interface (CNI) e il daemon Cilium.

Sintomi

Potresti riscontrare i seguenti sintomi:

  • I pod anetd rimangono bloccati nello stato Pending.
  • I pod dei workload rimangono bloccati nello stato Terminating.
  • Errori che indicano errori di comunicazione Cilium, ad esempio failed to connect to Cilium daemon.
  • Errori durante la pulizia delle risorse di rete per le sandbox dei pod, ad esempio:

    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
    

Soluzione

Cluster standard: per risolvere il problema e consentire la pianificazione del pod anetd, aumenta temporaneamente le risorse allocabili sul nodo interessato.

  1. Per identificare il nodo interessato e controllare la CPU e la memoria allocabili, esegui il seguente comando:

    kubectl get nodes $NODE_NAME -o json | jq '.status.allocatable | {cpu, memory}'
    
  2. Per aumentare temporaneamente la CPU e la memoria allocabili, esegui il seguente comando:

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

Cluster Autopilot: per risolvere il problema di deadlock nei cluster Autopilot, libera le risorse eliminando forzatamente il pod interessato:

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

Sostituisci quanto segue:

  • POD_NAME: il nome del pod.
  • NAMESPACE: lo spazio dei nomi del pod.

Dopo aver aumentato le risorse allocabili sul nodo e al termine dell'upgrade da GKE versione 1.27 alla 1.28, il pod anetd viene eseguito sulla versione più recente.

Nodi nello stato NodeNotReady a causa dell'errore containerID mancante

Quando i cluster vengono sottoposti ad upgrade a GKE versione 1.35.1-gke.1616000 e successive, i nodi potrebbero entrare immediatamente nello stato NodeNotReady se sono abilitati sia GKE Dataplane V2 che Cloud Service Mesh.

Causa

A partire da GKE versione 1.35.1-gke.1616000, i cluster GKE Dataplane V2 utilizzano la versione CNI 1.1.0 nei file di configurazione CNI. Questa modifica richiede che anche i plug-in CNI downstream, come Google Managed Istio, supportino la versione CNI 1.1.0. A causa di un ritardo nel lancio di Managed Istio, alcuni cluster non hanno ancora ricevuto la versione compatibile (1.23), causando l'errore di inizializzazione.

Sintomi

I nodi interessati vengono visualizzati immediatamente come NodeNotReady. Nei log di containerd viene visualizzato il seguente messaggio di errore:

NetworkPluginNotReady message:Network plugin returns error: missing containerID

Soluzione

Per risolvere il problema, esegui il downgrade del cluster interessato a una versione GKE precedente alla 1.35.1-gke.1616000.

Interferenza dei programmi eBPF personalizzati

GKE utilizza i programmi eBPF per gestire il networking per GKE Dataplane V2. Se esegui il deployment di programmi eBPF personalizzati sulle interfacce di rete dei nodi gestiti da GKE, questi programmi possono interferire con i programmi eBPF gestiti da GKE e causare problemi di networking.

GKE non supporta i programmi eBPF personalizzati collegati alle seguenti interfacce di rete:

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

La presenza di programmi eBPF personalizzati su queste interfacce può interferire con i programmi installati dall'agente anetd di GKE Dataplane V2, il che può interrompere il networking del cluster. Ti consigliamo di rimuovere dal cluster tutti i programmi eBPF personalizzati o i workload che inseriscono questi programmi.

Individuare i programmi eBPF personalizzati

Per individuare i programmi eBPF personalizzati in esecuzione sui nodi del cluster, puoi creare un DaemonSet configurato con l'impostazione hostNetwork: true, che utilizza bpftool per eseguire query su questi programmi 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. Salva il manifest come ebpf-discovery.yaml e applica il DaemonSet:

    kubectl apply -f ebpf-discovery.yaml
    
  2. Attendi che i pod siano in esecuzione:

    kubectl rollout status ds/bpftool-logger
    
  3. Controlla i log dei pod per scoprire i programmi eBPF:

    kubectl logs -l app=bpftool-logger
    
  4. Al termine, elimina il DaemonSet:

    kubectl delete -f ebpf-discovery.yaml
    

Passaggi successivi