Configurar o NodeLocal DNSCache

Este documento descreve como usar o NodeLocal DNSCache para reduzir a latência de busca DNS e melhorar o desempenho do aplicativo no cluster do Google Kubernetes Engine (GKE).

O NodeLocal DNSCache é um complemento do GKE que melhora o desempenho do DNS executando um cache DNS diretamente em cada nó do cluster como um DaemonSet. Quando seus pods fazem uma solicitação DNS, ela vai primeiro para o cache local no mesmo nó. O processamento local de solicitações reduz significativamente os tempos médios de busca DNS e diminui a carga no provedor de DNS central do cluster, como kube-dns ou Cloud DNS para GKE. Para uma explicação detalhada da arquitetura de DNS e dos benefícios do NodeLocal DNSCache, consulte Sobre a descoberta de serviços.

Nos clusters do GKE Autopilot, o NodeLocal DNSCache é ativado por padrão e não pode ser desativado. Nos clusters do GKE Standard que executam a versão 1.33.1 e mais recente, o NodeLocal DNSCache está ativado por padrão, mas é possível desativá-lo.

Este documento é destinado a usuários do GKE, incluindo desenvolvedores, administradores e arquitetos. Para saber mais sobre papéis comuns e tarefas de exemplo no Cloud de Confiance by S3NS, consulte Funções e tarefas de usuário comuns do GKE Enterprise.

Este documento pressupõe que você esteja familiarizado com o seguinte:

Arquitetura

O NodeLocal DNSCache é um complemento do GKE que pode ser executado além do kube-dns.

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

Quando um pod faz uma solicitação DNS, ela vai para o cache DNS em execução no mesmo nó que o pod. Se o cache não conseguir resolver a solicitação DNS, ele encaminhará a solicitação 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 kube-dns. Os pods node-local-dns usam o serviço kube-dns-upstream para acessar os pods kube-dns.
  • Domínios de stub personalizados ou servidores de nomes upstream: as consultas são encaminhadas diretamente dos pods do NodeLocal DNSCache.
  • Cloud DNS: todas as outras consultas são encaminhadas para o servidor de metadados local, que é executado no mesmo nó em que a consulta foi originada. O servidor de metadados local acessa o Cloud DNS.

O caminho de uma solicitação DNS, conforme descrito no parágrafo anterior.

Quando você ativa o NodeLocal DNSCache em um cluster atual, o GKE recria todos os nós do cluster que executam a versão 1.15 e mais recentes do GKE de acordo com o processo de upgrade de nós.

Depois que o GKE recria os nós, ele adiciona automaticamente o rótulo addon.gke.io/node-local-dns-ds-ready=true aos nós. Não adicione esse identificador aos nós do cluster manualmente.

Benefícios do NodeLocal DNSCache

O NodeLocal DNSCache oferece as seguintes vantagens:

  • Tempo médio da busca DNS reduzido
  • As conexões de pods para o cache local não criam entradas de tabela conntrack. Esse comportamento evita conexões descartadas e rejeitadas causadas por esgotamento da tabela de conexões e condições de corrida.
  • É possível usar o NodeLocal DNSCache com o Cloud DNS para GKE.
  • As consultas DNS para URLs externos (URLs que não se referem a recursos de cluster) são encaminhadas diretamente para o servidor de metadados local e ignoram kube-dns.
  • Os caches de DNS local automaticamente selecionam os domínios de stub e os servidores de nomes upstream especificados na seção Como adicionar resolvedores personalizados para domínios de stub.

Requisitos e limitações

  • O NodeLocal DNSCache consome recursos de computação em cada nó do cluster.
  • O NodeLocal DNSCache não é compatível com os pools de nós do Windows Server.
  • O NodeLocal DNSCache requer a versão 1.15 ou posterior do GKE.
  • O NodeLocal DNSCache acessa pods kube-dns usando TCP.
  • O NodeLocal DNSCache acessa upstreamServers e stubDomains usando TCP e UDP nas versões 1.18 ou mais recentes do GKE. O servidor DNS precisa ser acessível usando TCP e UDP.
  • Os registros DNS são armazenados em cache pelos seguintes períodos:
    • O time to live (TTL) do registro ou então 30 segundos, se o TTL tiver mais de 30 segundos.
    • Cinco segundos se a resposta DNS for NXDOMAIN.
  • Os pods NodeLocal DNSCache monitoram as portas 53, 9253, 9353 e 8080 dos nós. Se você executar qualquer outro pod hostNetwork ou configurar um hostPorts com essas portas, o NodeLocal DNSCache falhará e ocorrerão erros no 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.
  • O cache DNS local é executado apenas em pools de nós que executam versões 1.15 e posteriores do GKE. Se você ativar o NodeLocal DNSCache em um cluster com nós que executam versões anteriores, os pods nesses nós usarão kube-dns.

Antes de começar

Antes de começar, verifique se você realizou as tarefas a seguir:

  • Ativar a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a CLI do Google Cloud para essa tarefa, instale e inicialize a gcloud CLI. Se você instalou a gcloud CLI anteriormente, instale a versão mais recente executando o comando gcloud components update. Talvez as versões anteriores da gcloud CLI não sejam compatíveis com a execução dos comandos neste documento.
  • Verifique se você tem um cluster do Autopilot ou Standard. Se precisar de um, crie um cluster do Autopilot. Em clusters do Autopilot, o NodeCache DNSCache é ativado por padrão e não pode ser substituído.

Ativar NodeLocal DNSCache

Para clusters padrão, é possível ativar o NodeLocal DNSCache usando a Google Cloud CLI ou o console Cloud de Confiance .

gcloud

Para ativar o NodeLocal DNSCache em um cluster atual, use a sinalização --update-addons com o argumento NodeLocalDNS=ENABLED:

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

Substitua:

Console

Para ativar o NodeLocal DNSCache em um novo cluster, siga estas etapas:

  1. Acesse a página do Google Kubernetes Engine no console do Cloud de Confiance .

    Acessar os clusters do Kubernetes

  2. Clique no nome do cluster que você quer modificar.

  3. Em Rede, no campo Provedor de DNS, clique em Editar provedor de DNS.

  4. Marque a caixa de seleção Ativar NodeLocal DNSCache.

  5. Clique em Salvar alterações.

Essa mudança exige a recriação dos nós, o que pode causar interrupções nas cargas de trabalho em execução. Para mais detalhes sobre essa mudança específica, encontre a linha correspondente na tabela Alterações manuais que recriam os nós usando uma estratégia de upgrade de nós e respeitando as políticas de manutenção. Para saber mais sobre atualizações de nós, consulte Planejar interrupções de atualização de nós.

Verificar se o NodeLocal DNSCache está ativado

Para verificar se o NodeLocal DNSCache está em execução, liste os pods node-local-dns:

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

O resultado será o 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>

A saída mostra um pod node-local-dns para cada nó que executa a versão 1.15 ou posterior do GKE.

Desativar o NodeLocal DNSCache

É possível desativar o NodeLocal DNSCache usando o seguinte comando:

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

Substitua:

Essa mudança exige a recriação dos nós, o que pode causar interrupções nas cargas de trabalho em execução. Para mais detalhes sobre essa mudança específica, encontre a linha correspondente na tabela Alterações manuais que recriam os nós usando uma estratégia de upgrade de nós e respeitando as políticas de manutenção. Para saber mais sobre atualizações de nós, consulte Planejar interrupções de atualização de nós.

Solução de problemas do NodeLocal DNSCache

Veja informações gerais sobre como diagnosticar problemas de DNS do Kubernetes em Como depurar a resolução de DNS.

O NodeLocal DNSCache não é ativado imediatamente

Quando você ativa o NodeLocal DNSCache em um cluster atual, o GKE pode não atualizar os nós imediatamente se o cluster tiver uma janela ou exclusão de manutenção configurada. Para mais informações, consulte Atenção para janelas de recriação e manutenção de nós.

Se você preferir não esperar, aplique manualmente as alterações aos nós chamando o comando gcloud container clusters upgrade e transmitindo a sinalização --cluster-version com a mesma versão do GKE que o pool de nós já está em execução. Use a Google Cloud CLI para essa solução alternativa.

NodeLocal DNSCache com o Cloud DNS

Se você usar o NodeLocal DNSCache com o Cloud DNS, o cluster usará o endereço IP 169.254.20.10 do servidor de nomes, conforme mostrado no diagrama a seguir:

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 usado pelos pods. Essa diferença nos endereços IP é esperado, porque o endereço IP do servidor de nomes 169.254.20.10 é obrigató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 serviço kube-dns:

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

    A saída é o endereço IP de kube-dns, como 10.0.0.10

  2. Abra uma sessão do shell no pod:

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

    cat /etc/resolv.conf
    

    O resultado é 169.254.20.10

Política de rede com NodeLocal DNSCache

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

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

O manifesto a seguir 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. Use o comando a seguir para encontrar o endereço IP do serviço kube-dns:

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

Problemas conhecidos

Esta seção lista problemas conhecidos com o NodeLocal DNSCache.

Tempo limite do DNS em ClusterFirstWithHostNet dnsPolicy ao usar o NodeLocal DNSCache e o GKE Dataplane V2

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

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

;; connection timed out; no servers could be reached

A saída indica que as solicitações DNS não conseguem alcançar os servidores de back-end.

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

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

Substitua:

  • NAMESPACE: o namespace do pod hostNetwork.
  • PROJECT_ID: o ID do seu projeto do Cloud de Confiance .
  • KUBE_DNS_UPSTREAM: o ClusterIP do serviço kube-dns upstream. É possível conseguir esse valor usando o seguinte comando:

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

As solicitações de DNS do pod agora podem acessar kube-dns e ignorar o NodeLocal DNSCache.

Erros de tempo limite do NodeLocal DNSCache

Em clusters com o NodeLocal DNSCache ativado, os registros podem conter entradas semelhantes a estas:

[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 de IP do cluster kube-dns-upstream. Neste exemplo, a resposta a uma solicitação DNS não foi recebida do kube-dns em dois segundos. Esse problema pode ocorrer por um dos seguintes motivos:

  • Um problema de conectividade de rede subjacente.
  • Aumento significativo nas consultas DNS da carga de trabalho ou devido ao aumento do pool de nós.

Como resultado, os pods kube-dns atuais não podem processar todas as solicitações a tempo. A alternativa é aumentar o número de réplicas de kube-dns escalonando verticalmente o kube-dns.

Como expandir kube-dns

Use um valor menor para o campo nodesPerReplica para garantir que mais pods kube-dns sejam criados enquanto os nós do cluster escalonar verticalmente. É altamente recomendável definir um valor max explícito para garantir que a máquina virtual (VM) do plano de controle do GKE não fique sobrecarregada pelo grande número de pods kube-dns que monitoram a API Kubernetes.

É possível definir o campo max com o número de nós do cluster. Se o cluster tiver mais de 500 nós, defina o campo max como 500.

Para clusters padrão, modifique o número de réplicas do kube-dns editando o ConfigMap kube-dns-autoscaler. Essa configuração não é compatível com clusters do Autopilot.

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

O resultado será o seguinte:

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

O número de réplicas do kube-dns é calculado usando a seguinte fórmula:

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

Se você definir os campos min e max no ConfigMap, as réplicas serão limitadas por esses valores. Para escalonar verticalmente, mude o valor do campo nodesPerReplica para um valor menor e inclua um valor para o campo max:

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

A configuração cria um pod kube-dns para cada oito nós no cluster. Um cluster de 24 nós tem três réplicas, e um cluster de 40 nós tem cinco réplicas. Se o cluster ultrapassar 120 nós, o número de réplicas do kube-dns não vai ultrapassar 15, que é o valor max.

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

A saída do ConfigMap kube-dns-autoscaler que tem um campo min definido seria semelhante a esta:

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

A seguir