Usar o GKE Dataplane V2

Esta página explica 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 tiver problemas com a utilização do GKE Dataplane V2, avance para a secção de Resolução de problemas.

Criar um cluster do GKE com o GKE Dataplane V2

Pode ativar o GKE Dataplane V2 quando criar novos clusters com a versão 1.20.6-gke.700 e posteriores do GKE através da CLI gcloud ou da API GKE. Também pode ativar o GKE Dataplane V2 na pré-visualização quando cria novos clusters com a versão 1.17.9 e posterior do GKE

Consola

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

  1. Na Trusted Cloud consola, aceda à página Criar um cluster do Kubernetes.

    Aceda a Crie um cluster do Kubernetes

  2. Na secção Networking, selecione a caixa de verificação Ativar Dataplane V2. A opção Ativar política de rede do Kubernetes está desativada quando seleciona Ativar Dataplane V2, porque a aplicação da política de rede está integrada no GKE 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 o seguinte:

  • 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 preferir não usar um canal de lançamento, também pode usar a flag --cluster-version em vez de --release-channel, especificando a versão 1.20.6-gke.700 ou posterior.
  • COMPUTE_LOCATION: a localização 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 no seu pedido create de cluster.

O fragmento JSON seguinte mostra 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 o seguinte:

  • VERSION: a versão do cluster, que tem de 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.

Resolução de problemas com o GKE Dataplane V2

Esta secção mostra-lhe 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, o resultado inclui pods com o prefixo anetd-. anetd é o controlador de rede para o GKE Dataplane V2.

  2. Se o problema estiver relacionado com os serviços ou a aplicação da política de rede, verifique os registos do anetdpod. Use os seguintes seletores de registos no Cloud Logging:

    resource.type="k8s_container"
    labels."k8s-pod/k8s-app"="cilium"
    resource.labels.cluster_name="CLUSTER_NAME"
    
  3. Se a criação de pods estiver a falhar, verifique os registos do kubelet para encontrar pistas. Use os seguintes seletores de registos 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 ver os registos de todos os clusters.

  4. Se os anetd pods não estiverem em execução, examine o ConfigMap cilium-config para ver se existem modificações. Evite alterar os campos existentes neste ConfigMap, porque essas alterações podem desestabilizar o cluster e interromper o anetd. O ConfigMap é corrigido para o estado predefinido apenas se forem adicionados novos campos. As alterações aos campos existentes não são corrigidas e recomendamos que não altere nem personalize o ConfigMap.

Problemas conhecidos

Problemas de conetividade intermitentes relacionados com conflitos de intervalo NodePort em clusters do GKE Dataplane V2

Nos clusters do GKE Dataplane V2, podem ocorrer problemas de conetividade intermitentes para o tráfego mascarado ou com a utilização de portas efémeras. Estes problemas devem-se a potenciais conflitos de portas com o intervalo NodePort reservado e ocorrem normalmente nos seguintes cenários:

  • Personalizado ip-masq-agent: se usar um ip-masq-agentpersonalizado (versão 2.10 ou posterior), em que o cluster tem serviços NodePort ou Load Balancer, pode observar problemas de conetividade intermitentes devido ao respetivo conflito com o intervalo NodePort. Desde a versão 2.10 e posteriores, o ip-masq-agent tem o argumento --random-fully implementado internamente por predefinição. Para mitigar esta situação, defina explicitamente --random-fully=false (aplicável desde a versão 2.11) nos argumentos na configuração ip-masq-agent. Para ver detalhes da configuração, consulte o artigo Configurar um agente de ocultação de IP em clusters padrão.

  • Sobreposição do intervalo de portas efémeras: se o intervalo de portas efémeras definido por net.ipv4.ip_local_port_range nos seus nós do GKE se sobrepuser ao intervalo NodePort (30000-32767), também pode acionar problemas de conetividade. Para evitar este problema, certifique-se de que estes dois intervalos não se sobrepõem.

Reveja a configuração ip-masq-agent e as definições do intervalo de portas efémeras para garantir que não entram em conflito com o intervalo NodePort. Se tiver problemas de conetividade intermitentes, considere estas potenciais causas e ajuste a configuração em conformidade.

Problemas de conetividade com o hostPort em clusters do GKE Dataplane V2

Versões do GKE afetadas: 1.29 e posteriores

Em clusters que usam o GKE Dataplane V2, pode encontrar falhas de conetividade quando o tráfego segmenta o IP:Port de um nó em que a porta é a hostPort definida no pod. Estes problemas surgem em dois cenários principais:

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

    hostPort associa um Pod à porta de um nó específico e um Network Load Balancer de passagem distribui o tráfego por todos os nós. Quando expõe Pods à Internet através de hostPort e um Network Load Balancer de passagem, o Load Balancer pode enviar tráfego para um nó onde o Pod não está em execução, o que provoca falhas de ligação. Isto deve-se a uma limitação conhecida no GKE Dataplane V2, em que o tráfego do Network Load Balancer de passagem não é encaminhado de forma consistente para os pods hostPort.

    Solução: quando expõe hostPorts de um pod no nó com um Network Load Balancer de passagem, especifique o endereço IP interno ou externo do Network Load Balancer 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 conflito com o intervalo NodePort reservado:

    Se o hostPort de um pod entrar em conflito com o intervalo NodePort reservado (30000-32767), o Cilium pode não encaminhar o tráfego para o pod. Este comportamento foi observado nas versões 1.29 e posteriores do cluster, uma vez que o Cilium gere agora as capacidades, substituindo o método Portmap anterior.hostPort Este é um comportamento esperado para o Cilium e é mencionado na respetiva documentação pública.

Não planeamos corrigir estas limitações em versões posteriores. A causa principal destes problemas está relacionada com o comportamento do Cilium e está fora do controlo direto do GKE.

Recomendação: recomendamos que migre para os serviços NodePort em vez de hostPort para melhorar a fiabilidade. NodePort Os serviços oferecem capacidades semelhantes.

Os intervalos de portas da Política de Rede não entram em vigor

Se especificar um campo endPort numa política de rede num cluster que tenha o GKE Dataplane V2 ativado, este não vai ter efeito.

A partir do GKE 1.22, a API Kubernetes Network Policy permite especificar um intervalo de portas onde a política de rede é aplicada. Esta API é suportada em clusters com a política de rede do Calico, mas não é suportada em clusters com o GKE Dataplane V2.

Pode validar o comportamento dos seus objetos NetworkPolicy lendo-os novamente depois de os escrever no servidor da API. Se o objeto ainda contiver o campo endPort, a funcionalidade é aplicada. Se o campo endPort estiver em falta, a funcionalidade não é aplicada. Em todos os casos, o objeto armazenado no servidor da API é a fonte de verdade para a política de rede.

Para mais informações, consulte o artigo KEP-2079: Network Policy to support Port Ranges.

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

Versões do GKE afetadas: 1.22 a 1.25

Os clusters do GKE que executam pools de nós que usam o containerd e têm o GKE Dataplane V2 ativado podem ter problemas de fuga de endereços IP e esgotar todos os endereços IP de pods num nó. Um pod agendado num nó afetado apresenta uma mensagem de erro semelhante à seguinte:

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

Para mais informações sobre o problema, consulte o problema n.º 5768 do containerd.

Versões corrigidas

Para corrigir este problema, atualize o cluster para uma das seguintes versões do GKE:

  • 1.22.17-gke.3100 ou posterior.
  • 1.23.16-gke.200 ou posterior.
  • 1.24.9-gke.3200 ou posterior.
  • 1.25.6-gke.200 ou posterior.

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

Pode mitigar este problema eliminando os endereços IP do pod divulgados para o nó.

Para eliminar os endereços IP do pod divulgados, obtenha credenciais de autenticação para o cluster e execute os seguintes passos para limpar um único nó, se souber o respetivo nome.

  1. Guarde o seguinte script de shell num ficheiro denominado 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 num 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 pode executar uma versão DaemonSet deste script para ser executada em paralelo em todos os nós em simultâneo:

  1. Guarde o seguinte manifesto num ficheiro com o nome 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
    

    Tem de ter acesso ao kubectl como administrador do cluster para executar este comando.

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

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

A política de rede rejeita uma ligação devido a uma pesquisa de acompanhamento de ligações incorreta

Quando um pod cliente se liga a si próprio através de um serviço ou do endereço IP virtual de um equilibrador de carga de passagem interno, o pacote de resposta não é identificado como parte de uma ligação existente devido a uma pesquisa conntrack incorreta no plano de dados. Isto significa que uma política de rede que restringe o tráfego de entrada para o pod é aplicada incorretamente ao pacote.

O impacto deste problema depende do número de pods configurados para o serviço. Por exemplo, se o serviço tiver 1 pod de back-end, a ligação falha sempre. Se o serviço tiver 2 pods de back-end, a ligação falha 50% das vezes.

Versões corrigidas

Para corrigir este problema, atualize o seu cluster para uma das seguintes versões do GKE:

  • 1.28.3-gke.1090000 ou posterior.

Soluções alternativas

Pode mitigar este problema configurando o port e o containerPort no manifesto do serviço para terem o mesmo valor.

Perdas de pacotes para fluxos de ligação em cotovelo

Quando um Pod cria uma ligação TCP a si próprio através de um serviço, de modo que o Pod seja a origem e o destino da ligação, a monitorização de ligações eBPF do plano de dados V2 do GKE monitoriza incorretamente os estados de ligação, o que leva a entradas de conntrack com fugas.

Quando uma tupla de ligação (protocolo, IP de origem/destino e porta de origem/destino) foi divulgada, as novas ligações que usam a mesma tupla de ligação podem resultar na rejeição de pacotes de retorno.

Versões corrigidas

Para corrigir este problema, atualize o seu cluster para uma das seguintes versões do GKE:

  • 1.28.3-gke.1090000 ou posterior
  • 1.27.11-gke.1097000 ou posterior

Soluções alternativas

Use uma das seguintes soluções alternativas:

  • Ativar a reutilização de TCP (keep-alives) para aplicações executadas em pods que possam comunicar entre si através de um serviço. Isto impede que o indicador TCP FIN seja emitido e evita a fuga da entrada conntrack.

  • Quando usar ligações de curta duração, exponha o pod através de um equilibrador de carga de proxy, como o Gateway, para expor o serviço. Isto faz com que o destino do pedido de ligação seja definido como o endereço IP do balanceador de carga, o que impede que o GKE Dataplane V2 execute o SNAT para o endereço IP de loopback.

A atualização do plano de controlo do GKE provoca um anetd deadlock de pods

Quando atualiza um cluster do GKE que tem o GKE Dataplane V2 (caminho de dados avançado) ativado da versão 1.27 para a 1.28, pode deparar-se com uma situação de impasse. As cargas de trabalho podem sofrer interrupções devido à incapacidade de terminar pods antigos ou agendar componentes necessários, como anetd.

Causa

O processo de atualização do cluster aumenta o requisito de recursos para os componentes do GKE Dataplane V2. Este aumento pode levar a contenção de recursos, o que interrompe a comunicação entre o plug-in da interface de rede de contentores (CNI) do Cilium e o daemon do Cilium.

Sintomas

Pode ver os seguintes sintomas:

  • anetd Os pods permanecem bloqueados num estado Pending.
  • Os pods de carga de trabalho ficam bloqueados num 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 as caixas de areia 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 anetd Pod seja agendado, aumente temporariamente os recursos atribuíveis no nó afetado.

  1. Para identificar o nó afetado e verificar a respetiva CPU e memória alocáveis, 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 atribuíveis, execute o seguinte comando:

    kubectl patch
    

Clusters do Autopilot: para resolver o problema de impasse nos clusters do Autopilot, liberte recursos eliminando à força o pod afetado:

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

Substitua o seguinte:

  • POD_NAME: o nome do agrupamento.
  • NAMESPACE: o espaço de nomes do Pod.

Depois de aumentar os recursos atribuíveis no nó e quando a atualização da versão 1.27 do GKE para a 1.28 estiver concluída, o pod é executado na versão mais recente.anetd

O que se segue?