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.

gcloud

Como ativar o NodeLocal DNSCache em um novo cluster

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:

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.

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.

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.

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