Configurar a DNSCache NodeLocal

Esta página explica como melhorar a latência de procura de DNS num cluster do Google Kubernetes Engine (GKE) através da utilização de NodeLocal DNSCache.

Para clusters do GKE Autopilot, o NodeLocal DNSCache está ativado por predefinição e não pode ser substituído.

Arquitetura

O NodeLocal DNSCache é um suplemento do GKE que pode executar além do kube-dns.

O GKE implementa o NodeLocal DNSCache como um DaemonSet que executa uma cache DNS em cada nó no seu cluster.

Quando um Pod faz um pedido DNS, o pedido é enviado para a cache DNS em execução no mesmo nó que o Pod. Se a cache não conseguir resolver o pedido DNS, encaminha o pedido para um dos seguintes locais com base no destino da consulta:

  • kube-dns: todas as consultas para o domínio DNS do cluster (cluster.local) são encaminhadas para o kube-dns. Os pods node-local-dns usam o serviço kube-dns-upstream para aceder aos pods kube-dns. No diagrama seguinte, o endereço IP do serviço kube-dns é 10.0.0.10:53.
  • Domínios stub personalizados ou servidores de nomes a montante: as consultas são encaminhadas diretamente dos pods DNSCache locais do nó.
  • Cloud DNS: todas as outras consultas são encaminhadas para o servidor de metadados local que é executado no mesmo nó que o pod de onde a consulta se originou. O servidor de metadados local acede ao Cloud DNS.

O caminho de um pedido de DNS, conforme descrito no parágrafo anterior.

Quando ativa o NodeLocal DNSCache num cluster existente, o GKE recria todos os nós do cluster que executam a versão 1.15 e posterior do GKE de acordo com o processo de atualização de nós.

Depois de o GKE recriar os nós, o GKE adiciona automaticamente a etiqueta addon.gke.io/node-local-dns-ds-ready=true aos nós. Não deve adicionar esta etiqueta aos nós do cluster manualmente.

Vantagens da NodeLocal DNSCache

A NodeLocal DNSCache oferece as seguintes vantagens:

  • Tempo médio de pesquisa de DNS reduzido
  • As ligações dos Pods à respetiva cache local não criam entradas na tabela conntrack. Isto evita ligações rejeitadas e interrompidas causadas por condições de corrida e esgotamento da tabela de conntrack.
  • Pode usar o NodeLocal DNSCache com o Cloud DNS para GKE.
  • As consultas DNS para URLs externos (URLs que não se referem a recursos do cluster) são encaminhadas diretamente para o servidor de metadados do Cloud DNS local, ignorando o kube-dns.
  • As caches DNS locais selecionam automaticamente domínios stub e servidores de nomes a montante especificados na secção Adicionar resolvedores personalizados para domínios stub.

Requisitos e limitações

  • O NodeLocal DNSCache consome recursos de computação em cada nó do cluster.
  • O NodeLocal DNSCache não é suportado com pools de nós do Windows Server.
  • O NodeLocal DNSCache requer a versão 1.15 ou posterior do GKE.
  • O NodeLocal DNSCache acede aos pods kube-dns através de TCP.
  • O NodeLocal DNSCache acede a upstreamServers e stubDomains através de TCP e UDP nas versões 1.18 ou posteriores do GKE. O servidor DNS tem de estar acessível através de TCP e UDP.
  • Os registos de DNS são colocados em cache durante os seguintes períodos:
    • O tempo de vida (TTL) do registo ou 30 segundos se o TTL for superior a 30 segundos.
    • 5 segundos se a resposta de DNS for NXDOMAIN.
  • Os pods NodeLocal DNSCache ouvem nas portas 53, 9253, 9353 e 8080 nos nós. Se executar qualquer outro hostNetworkpodhostNetwork ou configurar um hostPorts com essas portas, o NodeLocal DNSCache falha e ocorrem erros de DNS. Os pods NodeLocal DNSCache não usam o modo hostNetwork quando usam o GKE Dataplane V2 e não usam o Cloud DNS para GKE.
  • A cache DNS local só é executada em conjuntos de nós com versões do GKE 1.15 e posteriores. Se ativar a NodeLocal DNSCache num cluster com nós que executam versões anteriores, os pods nesses nós usam o kube-dns.

Antes de começar

Antes de começar, certifique-se de que realizou as seguintes tarefas:

  • Ative a API Google Kubernetes Engine.
  • Ative a API Google Kubernetes Engine
  • Se quiser usar a CLI gcloud para esta tarefa, instale-a e, em seguida, inicialize-a. Se instalou anteriormente a CLI gcloud, execute o comando gcloud components update para obter a versão mais recente. As versões anteriores da CLI gcloud podem não suportar a execução dos comandos neste documento.
  • Certifique-se de que tem um cluster do Autopilot ou Standard existente. Se precisar de um, crie um cluster do Autopilot. Para os clusters do Autopilot, o NodeLocal DNSCache está ativado por predefinição e não pode ser substituído.

Ative a NodeLocal DNSCache

Para clusters padrão, pode ativar a NodeLocal DNSCache através da CLI Google Cloud ou da Google Cloud consola.

gcloud

Para ativar o NodeLocal DNSCache num cluster existente, use a flag --update-addons com o argumento NodeLocalDNS=ENABLED:

gcloud container clusters update CLUSTER_NAME \
    --location=COMPUTE_LOCATION \
    --update-addons=NodeLocalDNS=ENABLED

Substitua o seguinte:

Consola

Para ativar a NodeLocal DNSCache num novo cluster, siga estes passos:

  1. Aceda à página do Google Kubernetes Engine na Google Cloud consola.

    Aceda aos clusters do Kubernetes

  2. Clique no nome do cluster que quer modificar.

  3. Em Networking, no campo DNS provider, clique em Edit DNS provider.

  4. Selecione a caixa de verificação Ativar NodeLocal DNSCache.

  5. Clique em Guardar alterações.

Esta alteração requer a recriação dos nós, o que pode causar interrupções nas suas cargas de trabalho em execução. Para ver detalhes acerca desta alteração específica, encontre a linha correspondente na tabela alterações manuais que recriam os nós através de uma estratégia de atualização de nós e respeitam as políticas de manutenção. Para saber mais sobre as atualizações de nós, consulte o artigo Planeamento de interrupções de atualizações de nós.

Verifique se a NodeLocal DNSCache está ativada

Pode verificar se o NodeLocal DNSCache está em execução listando os node-local-dns Pods:

kubectl get pods -n kube-system -o wide | grep node-local-dns

O resultado é semelhante ao seguinte:

node-local-dns-869mt    1/1   Running   0   6m24s   10.128.0.35   gke-test-pool-69efb6b8-5d7m   <none>   <none>
node-local-dns-htx4w    1/1   Running   0   6m24s   10.128.0.36   gke-test-pool-69efb6b8-wssk   <none>   <none>
node-local-dns-v5njk    1/1   Running   0   6m24s   10.128.0.33   gke-test-pool-69efb6b8-bhz3   <none>   <none>

O resultado mostra um node-local-dns pod para cada nó que esteja a executar a versão 1.15 ou posterior do GKE.

Desative a DNSCache local do nó

Pode desativar o NodeLocal DNSCache através do seguinte comando:

gcloud container clusters update CLUSTER_NAME \
    --location=COMPUTE_LOCATION \
    --update-addons=NodeLocalDNS=DISABLED

Substitua o seguinte:

Esta alteração requer a recriação dos nós, o que pode causar interrupções nas suas cargas de trabalho em execução. Para ver detalhes acerca desta alteração específica, encontre a linha correspondente na tabela alterações manuais que recriam os nós através de uma estratégia de atualização de nós e respeitam as políticas de manutenção. Para saber mais sobre as atualizações de nós, consulte o artigo Planeamento de interrupções de atualizações de nós.

Resolva problemas de NodeLocal DNSCache

Para obter informações gerais sobre o diagnóstico de problemas de DNS do Kubernetes, consulte o artigo Depurar a resolução de DNS.

A NodeLocal DNSCache não é ativada imediatamente

Quando ativa a NodeLocal DNSCache num cluster existente, o GKE pode não atualizar os nós imediatamente se o cluster tiver uma janela de manutenção ou uma exclusão configurada. Para mais informações, consulte as restrições para a recriação de nós e os períodos de manutenção.

Se preferir não esperar, pode aplicar manualmente as alterações aos nós chamando o comando gcloud container clusters upgrade e transmitindo a flag --cluster-version com a mesma versão do GKE que o conjunto de nós já está a executar. Tem de usar a CLI do Google Cloud para esta solução alternativa.

NodeLocal DNSCache com o Cloud DNS

Se usar o NodeLocal DNSCache com o Cloud DNS, o cluster usa o endereço IP do servidor de nomes 169.254.20.10, conforme mostrado no diagrama seguinte:

NodeLocal DNSCache com arquitetura do Cloud DNS.

Como resultado, o endereço IP do serviço kube-dns pode ser diferente do endereço IP do servidor de nomes que os seus pods usam. Esta diferença nos endereços IP é esperada, uma vez que o endereço IP do servidor de nomes 169.254.20.10 é necessário para que o Cloud DNS funcione corretamente.

Para verificar os endereços IP, execute os seguintes comandos:

  1. Veja o endereço IP do kube-dns serviço:

    kubectl get svc -n kube-system kube-dns -o jsonpath="{.spec.clusterIP}"
    

    O resultado é o endereço IP de kube-dns, como 10.0.0.10:53

  2. Abra uma sessão de shell no seu pod:

    kubectl exec -it POD_NAME -- /bin/bash
    
  3. Na sessão de shell do pod, leia o conteúdo do ficheiro /etc/resolv.conf:

    cat /etc/resolv.conf
    

    O resultado é 169.254.20.10

Política de rede com NodeLocal DNSCache

Se usar a política de rede com a NodeLocal DNSCache e não estiver a usar o Cloud DNS ou o GKE Dataplane V2, tem de configurar regras para permitir que as suas cargas de trabalho e os node-local-dns pods enviem consultas DNS.

Use uma regra ipBlock no manifesto para permitir a comunicação entre os seus agrupamentos e o kube-dns.

O manifesto seguinte descreve uma política de rede que usa uma regra ipBlock:

spec:
  egress:
  - ports:
    - port: 53
      protocol: TCP
    - port: 53
      protocol: UDP
    to:
    - ipBlock:
        cidr: KUBE_DNS_SVC_CLUSTER_IP/32
  podSelector: {}
  policyTypes:
    - Egress

Substitua KUBE_DNS_SVC_CLUSTER_IP pelo endereço IP do serviço kube-dns. Pode obter o endereço IP do serviço kube-dns através do seguinte comando:

kubectl get svc -n kube-system kube-dns -o jsonpath="{.spec.clusterIP}"

Problemas conhecidos

Limite de tempo de DNS na dnsPolicy ClusterFirstWithHostNet quando usa NodeLocal DNSCache e GKE Dataplane V2

Em clusters que usam o GKE Dataplane V2 e o NodeLocal DNSCache, os pods com hostNetwork definido como true e dnsPolicy definido como ClusterFirstWithHostNet não conseguem alcançar os back-ends de DNS do cluster. Os registos de DNS podem conter entradas semelhantes às seguintes:

nslookup: write to 'a.b.c.d': Operation not permitted

;; connection timed out; no servers could be reached

O resultado indica que os pedidos DNS não conseguem alcançar os servidores de back-end.

Uma solução alternativa é definir o dnsPolicy e o dnsConfig para os pods hostNetwork:

spec:
 dnsPolicy: "None"
 dnsConfig:
   nameservers:
     - KUBE_DNS_UPSTREAM
   searches:
     - cluster.local
     - svc.cluster.local
     - NAMESPACE.svc.cluster.local
     - c.PROJECT_ID.internal
     - google.internal
   options:
     - name: ndots
       value: "5"

Substitua o seguinte:

  • NAMESPACE: o espaço de nomes da cápsula hostNetwork.
  • PROJECT_ID: o ID do seu projeto Google Cloud .
  • KUBE_DNS_UPSTREAM: o ClusterIP do serviço kube-dns a montante. Pode obter este valor através do seguinte comando:

    kubectl get svc -n kube-system kube-dns-upstream -o jsonpath="{.spec.clusterIP}"
    

Os pedidos DNS do pod podem agora alcançar o kube-dns e ignorar o NodeLocal DNSCache.

Erros de tempo limite do DNSCache NodeLocal

Em clusters com o NodeLocal DNSCache ativado, os registos podem conter entradas semelhantes às seguintes:

[ERROR] plugin/errors: 2 <hostname> A: read tcp <node IP: port>-><kubedns IP>:53: i/o timeout

A saída inclui o endereço IP do serviço kube-dns-upstream Cluster IP. Neste exemplo, a resposta a um pedido DNS não foi recebida de kube-dns em 2 segundos. Isto pode dever-se a um dos seguintes motivos:

  • Um problema de conetividade de rede subjacente.
  • Aumento significativo das consultas DNS da carga de trabalho ou devido ao aumento da escala do conjunto de nós.

Como resultado, os pods kube-dns existentes não conseguem processar todos os pedidos a tempo. A solução alternativa consiste em aumentar o número de réplicas do kube-dns ajustando os parâmetros de dimensionamento automático.

Aumentar a escala do kube-dns

Pode usar um valor inferior para nodesPerReplica para garantir que são criados mais pods kube-dns à medida que os nós do cluster são dimensionados. Recomendamos vivamente que defina um valor max explícito para garantir que a máquina virtual (VM) do plano de controlo do GKE não fica sobrecarregada devido ao grande número de pods kube-dns a monitorizar a API Kubernetes.

Pode definir max para o número de nós no cluster. Se o cluster tiver mais de 500 nós, defina max como 500.

Para clusters padrão, pode modificar o número de réplicas do kube-dns editando o kube-dns-autoscaler ConfigMap. Esta configuração não é suportada em clusters do Autopilot.

kubectl edit configmap kube-dns-autoscaler --namespace=kube-system

O resultado é semelhante ao seguinte:

linear: '{"coresPerReplica":256, "nodesPerReplica":16,"preventSinglePointFailure":true}'

O número de réplicas do kube-dns é calculado através da seguinte fórmula:

replicas = max( ceil( cores × 1/coresPerReplica ) , ceil( nodes × 1/nodesPerReplica ), maxValue )

Para aumentar a escala, altere nodesPerReplica para um valor mais pequeno e inclua um valor de max.

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"preventSinglePointFailure":true}'

A configuração cria 1 pod kube-dns para cada 8 nós no cluster. Um cluster de 24 nós tem 3 réplicas e um cluster de 40 nós tem 5 réplicas. Se o cluster crescer para além de 120 nós, o número de réplicas do kube-dns não cresce para além de 15, o valor max.

Para garantir um nível base de disponibilidade de DNS no seu cluster, defina uma contagem mínima de réplicas para o kube-dns.

A saída do kube-dns-autoscaler ConfigMap com o campo min seria semelhante ao seguinte:

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"min": 5,"preventSinglePointFailure":true}'

O que se segue?