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 NodeLocal DNSCache.
  • 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

O 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 o GKE nas versões 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.

Ative a NodeLocal DNSCache

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

Para clusters padrão, pode ativar a NodeLocal DNSCache em clusters novos ou existentes através da CLI do Google Cloud. Pode ativar a NodeLocal DNSCache em novos clusters através da Trusted Cloud consola.

Ative a DNSCache local do nó num novo cluster

gcloud

Para ativar o NodeLocal DNSCache num novo cluster, use a flag --addons com o argumento NodeLocalDNS:

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

Substitua o seguinte:

Consola

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

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

    Aceda ao Google Kubernetes Engine

  2. Junto a Padrão, clique em Configurar.

  3. Configure o cluster como quiser.

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

  5. Na secção Opções de rede avançadas, selecione a caixa de verificação Ativar NodeLocal DNSCache.

  6. Clique em Criar.

Ative a DNSCache local do nó num cluster existente

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:

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 o NodeLocal DNSCache está ativado

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 advertências 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 Trusted 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?