Como usar o GKE Dataplane V2

Nesta página, explicamos como ativar e resolver problemas do GKE Dataplane V2 para clusters do Google Kubernetes Engine (GKE).

Os novos clusters do Autopilot têm o GKE Dataplane V2 ativado nas versões 1.22.7-gke.1500 e posteriores e nas versões 1.23.4-gke.1500 e posteriores. Se você tiver problemas ao usar o GKE Dataplane V2, pule para a Solução de problemas.

Como criar um cluster do GKE com o GKE Dataplane V2

É possível ativar o GKE Dataplane V2 ao criar novos clusters com a versão 1.20.6-gke.700 e mais recentes do GKE e usando a CLI gcloud ou a API GKE. Também é possível ativar o GKE Dataplane V2 em Visualização ao criar novos clusters com a versão 1.17.9 e mais recentes do GKE

Console

Para criar um novo cluster com o GKE Dataplane V2, realize as seguintes tarefas:

  1. No console Google Cloud , acesse a página Criar um cluster do Kubernetes.

    Acessar "Criar um cluster do Kubernetes"

  2. Na seção "Rede", marque a caixa de seleção Ativar DataPlane V2. A opção Ativar política de rede do Kubernetes é desativada quando você seleciona Ativar GKE Dataplane V2, porque a aplicação da política de rede é integrada ao Dataplane V2.

  3. Clique em Criar.

gcloud

Para criar um novo cluster com o GKE Dataplane v2, use o seguinte comando:

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

Substitua:

  • CLUSTER_NAME: o nome do novo cluster;
  • CHANNEL_NAME: um canal de lançamento que inclui a versão 1.20.6-gke.700 ou posterior do GKE. Se você preferir não usar um canal de lançamento, use a sinalização --cluster-version em vez de --release-channel, especificando a versão 1.20.6-gke.700 ou posterior.
  • COMPUTE_LOCATION: o local do Compute Engine para o novo cluster.

API

Para criar um novo cluster com o GKE Dataplane V2, especifique o campo datapathProvider no objeto networkConfig em sua solicitação create do cluster.

No seguinte snippet JSON, mostramos a configuração necessária para ativar o GKE Dataplane V2:

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

Substitua:

  • VERSION: a versão do cluster, que precisa ser GKE 1.20.6-gke.700 ou posterior.
  • CHANNEL_NAME: um canal de lançamento que inclui a versão 1.20.6-gke.700 ou posterior do GKE.

Solução de problemas com o GKE Dataplane V2

Nesta seção, mostramos como investigar e resolver problemas com o GKE Dataplane V2.

  1. Confirme se o GKE Dataplane V2 está ativado:

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

    Se o GKE Dataplane V2 estiver em execução, a saída incluirá pods com o prefixo anetd-. O anetd é o controlador de rede do GKE Dataplane V2.

  2. Se o problema for com a aplicação da política de serviços ou rede, verifique os registros do pod anetd: Use os seguintes seletores de registros no Cloud Logging:

    resource.type="k8s_container"
    labels."k8s-pod/k8s-app"="cilium"
    resource.labels.cluster_name="CLUSTER_NAME"
    
  3. Se a criação do pod falhar, verifique as dicas nos registros do kubelet. Use os seguintes seletores de registros no Cloud Logging:

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

    Substitua CLUSTER_NAME pelo nome do cluster ou remova-o completamente para visualizar os registros de todos os clusters.

  4. Se os pods anetd não estiverem em execução, examine o ConfigMap cilium-config para verificar se há modificações. Evite alterar os campos atuais no ConfigMap, porque essas mudanças podem desestabilizar o cluster e interromper o anetd. O ConfigMap só recebe patch de volta ao estado padrão se novos campos forem adicionados a ele. As mudanças nos campos atuais não são corrigidas, e recomendamos não mudar nem personalizar o ConfigMap.

Problemas conhecidos

Problemas de conectividade intermitente relacionados a conflitos de intervalo NodePort em clusters do GKE Dataplane V2

Nos clusters do GKE Dataplane V2, podem ocorrer problemas de conectividade intermitente para tráfego mascarado ou com uso temporário de portas. Esses problemas são causados por possíveis conflitos de porta com o intervalo NodePort reservado e geralmente acontecem nos seguintes cenários:

  • ip-masq-agent personalizado:se você usa um ip-masq-agent personalizado (versão 2.10 ou mais recente), em que o cluster tem serviços NodePort ou de balanceador de carga, é possível observar problemas de conectividade intermitentes devido ao conflito com o intervalo NodePort. A partir da versão 2.10, ip-masq-agent tem o argumento --random-fully implementado internamente por padrão. Para mitigar isso, defina explicitamente --random-fully=false (aplicável desde a versão 2.11) em argumentos na configuração ip-masq-agent. Para detalhes de configuração, consulte Como configurar um agente de mascaramento de IP em clusters padrão.

  • Overlap de intervalo de porta temporário:se o intervalo de porta temporário definido por net.ipv4.ip_local_port_range nos nós do GKE se sobrepõem ao intervalo NodePort (30000-32767), o que também pode gerar problemas de conectividade. Para evitar esse problema, verifique se esses dois intervalos não se sobrepõem.

Revise a configuração de ip-masq-agent e as configurações do intervalo de porta temporário para garantir que elas não conflitem com o intervalo de NodePort. Se você encontrar problemas de conectividade intermitente, considere essas possíveis causas e ajuste sua configuração de acordo.

Problemas de conectividade com hostPort em clusters do GKE Dataplane V2

Versões afetadas do GKE:1.29 e mais recentes

Em clusters que usam o GKE Dataplane V2, podem ocorrer falhas de conectividade quando o tráfego tem como destino o IP:porta de um nó, em que a porta é o hostPort definido no pod. Esses problemas surgem em dois cenários principais:

  • Nós com hostPort atrás de um balanceador de carga de rede de passagem:

    O hostPort vincula um pod à porta de um nó específico, e um balanceador de carga de rede de passagem distribui o tráfego entre todos os nós. Quando você expõe pods à Internet usando hostPort e um balanceador de carga de rede de passagem, o balanceador de carga pode enviar tráfego para um nó em que o pod não está em execução, causando falhas de conexão. Isso ocorre devido a uma limitação conhecida no GKE Dataplane V2, em que o tráfego do balanceador de carga de rede de transmissão não é encaminhado de maneira consistente para pods hostPort.

    Solução alternativa:ao expor hostPorts de um pod no nó com um balanceador de carga de rede de passagem, especifique o endereço IP interno ou externo do balanceador de carga de rede no campo hostIP do 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 conflita com o intervalo reservado NodePort:

    Se o hostPort de um pod entrar em conflito com o intervalo NodePort reservado (30000-32767), o Cilium poderá não encaminhar o tráfego para o pod. Esse comportamento foi observado nas versões 1.29 e mais recentes do cluster, já que o Cilium agora gerencia os recursos hostPort, substituindo o método Portmap anterior. Esse é um comportamento esperado do Cilium e está mencionado na documentação pública.

Não planejamos corrigir essas limitações em versões posteriores. A causa raiz desses problemas está relacionada ao comportamento do Cilium e fora do controle direto do GKE.

Recomendação:migre para os serviços NodePort em vez de hostPort para melhorar a confiabilidade. Os serviços do NodePort oferecem recursos semelhantes.

Os intervalos de portas da política de rede não entram em vigor

Se você especificar um campo endPort em uma política de rede em um cluster que tenha GKE Dataplane V2 ativado, ele não terá efeito.

A partir do GKE 1.22, a API Kubernetes Network Policy permite especificar um intervalo de portas em que a política de rede é aplicada. Essa API é compatível com clusters com a Política de rede do Calico, mas não com clusters que têm o GKE Dataplane V2.

Para verificar o comportamento dos objetos NetworkPolicy, leia-os depois de serem gravados no servidor da API. Se o objeto ainda contiver o campo endPort, o recurso será aplicado. Se o campo endPort estiver ausente, o recurso não será aplicado. Em todos os casos, o objeto armazenado no servidor de API é a fonte da verdade da política de rede.

Saiba mais em KEP-2079: política de rede compatível com intervalos de portas.

Os pods exibem a mensagem de erro failed to allocate for range 0: no IP addresses available in range set

Versões afetadas do GKE: de 1.22 a 1.25

Os clusters do GKE que executam pools de nós que usam containerd e têm o GKE Dataplane V2 ativado podem ter problemas de vazamento de endereço IP e esgotar todos os endereços de IP do pod em um nó. Um pod programado em um nó afetado exibe uma mensagem de erro semelhante a esta:

failed to allocate for range 0: no IP addresses available in range set: 10.48.131.1-10.48.131.62

Saiba mais consultando o problema 5768 do containerd.

Versões corrigidas

Para corrigir esse problema, faça upgrade do cluster para uma das seguintes versões do GKE:

  • 1.22.17-gke.3100 ou mais recente.
  • 1.23.16-gke.200 ou mais recente.
  • 1.24.9-gke.3200 ou mais recente.
  • 1.25.6-gke.200 ou mais recentes.

Soluções alternativas para clusters padrão do GKE

Para atenuar esse problema, exclua os endereços IP do pod com vazamentos no nó.

Para excluir os endereços IP do pod com vazamento, consiga credenciais de autenticação para o cluster e execute as etapas a seguir para limpar um único nó, se você souber o nome dele.

  1. Salve o seguinte script de shell em um arquivo chamado cleanup.sh:

    for hash in $(sudo find /var/lib/cni/networks/gke-pod-network -iregex '/var/lib/cni/networks/gke-pod-network/[0-9].*' -exec head -n1 {} \;); do hash="${hash%%[[:space:]]}"; if [ -z $(sudo ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then sudo grep -ilr $hash /var/lib/cni/networks/gke-pod-network; fi; done | sudo xargs -r rm
    
  2. Execute o script em um nó do cluster:

    gcloud compute ssh --zone "ZONE" --project "PROJECT" NODE_NAME --command "$(cat cleanup.sh)"
    

    Substitua NODE_NAME pelo nome do nó.

Também é possível executar uma versão do DaemonSet desse script para execução paralela em todos os nós de uma só vez:

  1. Salve o seguinte manifesto em um arquivo chamado cleanup-ips.yaml:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: cleanup-ipam-dir
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          name: cleanup-ipam
      template:
        metadata:
          labels:
            name: cleanup-ipam
        spec:
          hostNetwork: true
          securityContext:
            runAsUser: 0
            runAsGroup: 0
          containers:
          - name: cleanup-ipam
            image: gcr.io/gke-networking-test-images/ubuntu-test:2022
            command:
              - /bin/bash
              - -c
              - |
                while true; do
                for hash in $(find /hostipam -iregex '/hostipam/[0-9].*' -mmin +10 -exec head -n1 {} \; ); do
                hash="${hash%%[[:space:]]}"
                if [ -z $(ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then
                grep -ilr $hash /hostipam
                fi
                done | xargs -r rm
                echo "Done cleaning up /var/lib/cni/networks/gke-pod-network at $(date)"
                sleep 120s
                done
            volumeMounts:
            - name: host-ipam
              mountPath: /hostipam
            - name: host-ctr
              mountPath: /run/containerd
          volumes:
          - name: host-ipam
            hostPath:
              path: /var/lib/cni/networks/gke-pod-network
          - name: host-ctr
            hostPath:
              path: /run/containerd
    
  2. Execute o daemonset no cluster:

    kubectl apply -f cleanup-ips.yaml
    

    Você precisa ter acesso ao kubectl como administrador do cluster para executar este comando.

  3. Verifique os registros do DaemonSet em execução:

    kubectl -n kube-system logs -l name=cleanup-ipam
    

A política de rede descarta uma conexão devido à pesquisa incorreta de acompanhamento de conexão

Quando um pod cliente se conecta a si mesmo usando um serviço ou o endereço IP virtual de um balanceador de carga de rede de passagem interno, o pacote de resposta não é identificado como parte de uma conexão devido a uma pesquisa de conntrack incorreta no plano de dados. Isso significa que uma política de rede que restringe o tráfego de entrada do pod é aplicada incorretamente no pacote.

O impacto desse problema depende do número de pods configurados para o serviço. Por exemplo, se o serviço tiver um pod de back-end, a conexão sempre falhará. Se o serviço tiver dois pods de back-end, a conexão falhará 50% do tempo.

Versões corrigidas

Para corrigir esse problema, faça upgrade do cluster para uma das seguintes versões do GKE:

  • 1.28.3-gke.1090000 ou mais recente.

Alternativas

É possível atenuar esse problema configurando port e containerPort no manifesto do serviço com o mesmo valor.

Quedas de pacotes para fluxos de conexão com alça de cabelo

Quando um pod cria uma conexão TCP com ele mesmo, de modo que o pod é a origem e o destino da conexão, o rastreamento de conexão eBPF do GKE Dataplane V2 rastreia incorretamente os estados de conexão, levando a um vazamento{101 }conntrack entradas.

Quando uma tupla de conexão (protocolo, IP de origem/destino e porta de origem/destino) vaza, novas conexões que usam a mesma tupla de conexão podem resultar no descarte de pacotes de retorno.

Versões corrigidas

Para corrigir esse problema, faça upgrade do cluster para uma das seguintes versões do GKE:

  • 1.28.3-gke.1090000 ou mais recente
  • 1.27.11-gke.1097000 ou mais recente

Alternativas

Use uma das seguintes soluções alternativas:

  • Ative a reutilização de TCP (sinal de atividade) para aplicativos em execução em pods que podem se comunicar com eles mesmos usando um serviço. Isso impede que a sinalização TCP FIN seja emitida e evita o vazamento da entrada do conntrack.

  • Ao usar conexões de curta duração, exponha o pod usando um balanceador de carga de proxy, como o Gateway, para expor o serviço. Isso faz com que o destino da solicitação de conexão seja definido como o endereço IP do balanceador de carga, impedindo que o GKE Dataplane V2 execute SNAT no endereço IP de loopback.

O upgrade do plano de controle do GKE causa um deadlock de pod anetd

Ao fazer upgrade de um cluster do GKE com o GKE Dataplane V2 (datapath avançado) ativado da versão 1.27 para 1.28, talvez você encontre uma situação de deadlock. As cargas de trabalho podem sofrer interrupções devido à incapacidade de encerrar pods antigos ou programar componentes necessários, como anetd.

Causa

O processo de upgrade do cluster aumenta o requisito de recursos para os componentes do GKE Dataplane V2. Esse aumento pode levar à disputa de recursos, o que interrompe a comunicação entre o plug-in da interface de rede de contêiner (CNI) do Cilium e o daemon do Cilium.

Sintomas

Você pode encontrar os seguintes sintomas:

  • Os pods anetd permanecem travados no estado Pending.
  • Os pods de carga de trabalho ficam presos no estado Terminating.
  • Erros que indicam falhas de comunicação do Cilium, como failed to connect to Cilium daemon.
  • Erros durante a limpeza de recursos de rede para sandboxes de pods, por exemplo:

    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
    

Alternativa

Clusters padrão: para resolver o problema e permitir que o pod anetd seja programado, aumente temporariamente os recursos alocáveis no nó afetado.

  1. Para identificar o nó afetado e verificar a CPU e a memória alocáveis dele, execute o seguinte comando:

    kubectl get nodes $NODE_NAME -o json | jq '.status.allocatable | {cpu, memory}'
    
  2. Para aumentar temporariamente a CPU e a memória alocáveis, execute o seguinte comando:

    kubectl patch
    

Clusters do Autopilot: para resolver o problema de deadlock em clusters do Autopilot, libere recursos excluindo à força o pod afetado:

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

Substitua:

  • POD_NAME: o nome do pod.
  • NAMESPACE: o namespace do pod.

Depois que você aumenta os recursos alocáveis no nó e quando o upgrade da versão 1.27 para 1.28 do GKE é concluído, o pod anetd é executado na versão mais recente.

A seguir