Como configurar o NodeLocal DNSCache


Nesta página, explicamos como melhorar a latência de busca DNS em um cluster do Google Kubernetes Engine (GKE) usando o NodeLocal DNSCache.

Observação: para clusters do GKE Autopilot, o NodeLocal DNSCache está ativado por padrão e não pode ser modificado.

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. No diagrama a seguir, o endereço IP do Serviço kube-dns é 10.0.0.10:53.
  • 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 demais consultas são encaminhadas para o servidor de metadados local, que é executado no mesmo nó que o pod da consulta de origem; 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, conforme o processo de upgrade do nó.

Depois que o GKE recria os nós, ele adiciona automaticamente o identificador 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. Isso evita conexões descartadas e rejeitadas devido ao 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 do Cloud DNS, ignorando kube-dns.
  • Os caches de DNS local automaticamente selecionam os domínios de stub e os servidores de nomes upstream especificados no kube-dns ConfigMap.

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 na versão 1.18 ou posterior 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 ao usar o GKE Dataplane V2 e 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 executando versões anteriores, os pods desses nós usarão o kube-dns.

Ativar NodeLocal DNSCache

Em clusters do Autopilot, o NodeLocal DNSCache é ativado por padrão e não pode ser substituído.

Para clusters padrão, é possível ativar o NodeLocal DNSCache em clusters novos ou atuais usando a CLI do Google Cloud. É possível ativar o NodeLocal DNSCache em novos clusters usando o Console do Google Cloud.

Como ativar o NodeLocal DNSCache em um novo cluster

gcloud

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

gcloud container clusters create CLUSTER_NAME \
    --location=COMPUTE_LOCATION \
    --addons=NodeLocalDNS

Substitua:

Console

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

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

    Acessar o Google Kubernetes Engine

  2. Ao lado de "Standard", clique em Configurar.

  3. Configure o cluster como quiser.

  4. No painel de navegação, clique em Rede.

  5. Na seção Opções de rede avançadas, marque a caixa de seleção Ativar NodeLocal DNSCache.

  6. Clique em Criar.

Como ativar o NodeLocal DNSCache em um cluster atual

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 \
    --update-addons=NodeLocalDNS=ENABLED

Substitua:

  • CLUSTER_NAME: o nome do cluster.

Essa mudança requer a recriação dos nós, o que pode causar interrupções nas cargas de trabalho em execução. Para detalhes sobre essa mudança específica, encontre a linha correspondente na tabela mudanças manuais que recriam os nós usando uma estratégia de upgrade de nó e respeitando as políticas de manutenção. Para saber mais sobre as atualizações de nós, consulte Planejar para 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á assim:

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

Desative o NodeLocal DNSCache usando o seguinte comando:

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

Substitua:

  • CLUSTER_NAME: o nome do cluster a ser desativado.

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

  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. Você pode receber o endereço IP do serviço kube-dns usando o seguinte comando:

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

Problemas conhecidos

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

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

nslookup: 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 alternativa é definir os seguintes dnsPolicy e dnsConfig para 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:

  • NAMESPACE: o namespace do pod hostNetwork.
  • PROJECT_ID: o ID do seu projeto do Google Cloud.
  • KUBE_DNS_UPSTREAM: o ClusterIP do serviço upstream kube-dns. É 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 o 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. A causa pode ser:

  • 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 do kube-dns, ajustando os parâmetros de escalonamento automático.

Como escalonar o kube-dns

Use um valor menor para nodesPerReplica para garantir que mais pods kube-dns sejam criados à medida que os nós do cluster forem escalonados 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 devido ao grande número de pods kube-dns que assistem à API Kubernetes.

É possível definir max com o número de nós do cluster. Se o cluster tiver mais de 500 nós, defina 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á assim:

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

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

réplicas = max( ceil( cores × 1/coresPerReplica ) , ceil( nodes × 1/nodesPerReplica ), maxValue )

Para escalonar verticalmente, altere nodesPerReplica para um valor menor e inclua um valor max.

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

Essa configuração cria um pod kube-dns para cada oito nós no cluster. Um cluster de 24 nós terá três réplicas, e um cluster de 40 nós terá cinco réplicas. Se o cluster ultrapassar 120 nós, o número de réplicas do kube-dns não ultrapassará 15, 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 o kube-dns.

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

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

A seguir