Como usar o kube-dns

Nesta página, descrevemos como o Google Kubernetes Engine (GKE) implementa a descoberta de serviços usando o kube-dns, o provedor de DNS padrão para clusters do GKE.

Para clusters do Autopilot, não é possível modificar a configuração padrão do kube-dns.

Arquitetura

Quando você cria um cluster, o GKE implanta automaticamente os pods do kube-dns no namespace kube-system. Os pods acessam a implantação do kube-dns por um serviço correspondente que agrupa os pods do kube-dns e atribui a eles um único endereço IP (ClusterIP). Por padrão, todos os pods em um cluster usam esse serviço para resolver consultas DNS. O diagrama a seguir mostra a relação entre os pods e o serviço kube-dns.

Relação entre os pods do kube-dns e o serviço kube-dns

O kube-dns é escalonado para atender às demandas de DNS do cluster. Esse escalonamento é controlado pelo kube-dns-autoscaler, um pod implantado por padrão em todos os clusters do GKE. O kube-dns-autoscaler ajusta o número de réplicas na implantação do kube-dns com base no número de nós e núcleos no cluster.

O kube-dns é compatível com até 1.000 endpoints por serviço headless.

Como o DNS do pod é configurado

O agente kubelet em execução em cada nó configura o etc/resolv.conf do pod para usar o ClusterIP do serviço kube-dns. A configuração de exemplo a seguir mostra que o endereço IP do serviço kube-dns é 10.0.0.10. Esse endereço IP é diferente em outros clusters.

nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local c.my-project-id.internal google.internal
options ndots:5

O kube-dns é o servidor de nomes autoritativo do domínio do cluster (cluster.local). Ele resolve nomes externos recursivamente. Os nomes curtos que não são totalmente qualificados, como myservice, são preenchidos primeiro com caminhos de pesquisa local.

Como adicionar resolvedores personalizados para domínios de stub

É possível modificar o ConfigMap do kube-dns para definir domínios de stub como parte da infraestrutura de DNS nos clusters.

Os domínios de stub permitem configurar resolvedores personalizados por domínio para que o kube-dns encaminhe solicitações DNS para servidores DNS upstream específicos ao resolver esses domínios.

O manifesto do ConfigMap para kube-dns de exemplo a seguir inclui uma configuração stubDomains que define resolvedores personalizados para o domínio example.com.

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    addonmanager.kubernetes.io/mode: EnsureExists
  name: kube-dns
  namespace: kube-system
data:
  stubDomains: |
    {
      "example.com": [
        "8.8.8.8",
        "8.8.4.4",
        "1.1.1.1",
        "1.0.0.1"
      ]
    }

Execute o seguinte comando para abrir um editor de texto:

kubectl edit configmap kube-dns -n kube-system

Substitua o conteúdo do arquivo pelo manifesto e saia do editor de texto para aplicar o manifesto ao cluster.

Servidores de nomes upstream

Se você modificar o ConfigMap para kube-dns para incluir upstreamNameservers, o kube-dns encaminhará todas as solicitações de DNS, exceto *.cluster.local para esses servidores. Isso inclui metadata.internal e *.google.internal, que não podem ser resolvidos pelo servidor upstream.

Se você ativar a federação de identidade da carga de trabalho do GKE ou qualquer carga de trabalho que dependa da resolução metadata.internal, para manter a resolução de nome *.internal, adicione um stubDomain ao ConfigMap.

data:
  stubDomains: |
    {
      "internal": [
        "169.254.169.254"
      ]
    }
  upstreamNameservers: |
    ["8.8.8.8"]

Solução de problemas

Para informações sobre como resolver problemas do kube-dns, consulte as seguintes páginas:

Limitações

Leia as seções a seguir para informações sobre as limitações do kube-dns.

Limite do domínio de pesquisa

Há um limite de 32 domínios de pesquisa DNS no domínio /etc/resolv.conf. Se você definir mais de 32 domínios de pesquisa, a criação do pod vai falhar com o seguinte erro:

The Pod "dns-example" is invalid: spec.dnsConfig.searches: Invalid value: []string{"ns1.svc.cluster-domain.example", "my.dns.search.suffix1", "ns2.svc.cluster-domain.example", "my.dns.search.suffix2", "ns3.svc.cluster-domain.example", "my.dns.search.suffix3", "ns4.svc.cluster-domain.example", "my.dns.search.suffix4", "ns5.svc.cluster-domain.example", "my.dns.search.suffix5", "ns6.svc.cluster-domain.example", "my.dns.search.suffix6", "ns7.svc.cluster-domain.example", "my.dns.search.suffix7", "ns8.svc.cluster-domain.example", "my.dns.search.suffix8", "ns9.svc.cluster-domain.example", "my.dns.search.suffix9", "ns10.svc.cluster-domain.example", "my.dns.search.suffix10", "ns11.svc.cluster-domain.example", "my.dns.search.suffix11", "ns12.svc.cluster-domain.example", "my.dns.search.suffix12", "ns13.svc.cluster-domain.example", "my.dns.search.suffix13", "ns14.svc.cluster-domain.example", "my.dns.search.suffix14", "ns15.svc.cluster-domain.example", "my.dns.search.suffix15", "ns16.svc.cluster-domain.example", "my.dns.search.suffix16", "my.dns.search.suffix17"}: must not have more than 32 search paths.

Essa mensagem de erro é retornada pelo kube-apiserver em resposta a uma tentativa de criação de um pod.

Para resolver esse problema, remova os caminhos de pesquisa extras da configuração.

Considere o limite de upstreamNameservers

O Kubernetes impõe um limite de até três valores de upstreamNameservers. Se você definir mais de três upstreamNameservers, verá o erro a seguir no Cloud Logging nos registros de implantação do kube-dns:

Invalid configuration: upstreamNameserver cannot have more than three entries (value was &TypeMeta{Kind:,APIVersion:,}), ignoring update

Quando isso acontece, o kube-dns se comporta como se não houvesse upstreamNameservers configurados. Para resolver esse problema, remova os upstreamNameservers extras da configuração.

Limitações de desempenho com o kube-dns

Se você estiver enfrentando alta latência com buscas DNS ou falhas de resolução de DNS com o provedor kube-dns padrão, isso pode ser causado por:

  • Como executar buscas DNS frequentes na sua carga de trabalho
  • Implantar uma densidade de pods maior por nó.
  • Exceder o limite de consultas por segundo (QPS) de 20 para cada pod kube-dns.
  • Executar o kube-dns em VMs Spot ou preemptivas, o que pode levar a exclusões inesperadas de nós e problemas subsequentes de resolução de DNS.

Para melhorar os tempos de busca DNS, escolha uma das seguintes opções:

  • Evite executar componentes críticos do sistema, como kube-dns no VMs Spot ou preemptivas. O uso de VMs Spot ou preemptivas para DNS pode causar falhas e interromper o cluster.
  • Como prática recomendada, crie pelo menos um pool de nós composto por VMs padrão (não Spot ou preemptivas) para hospedar componentes críticos do sistema, como o kube-dns. Para garantir que cargas de trabalho críticas sejam programadas apenas no pool de nós confiável que as impede de serem executadas em VMs preemptivas ou do Spot, use taints e tolerâncias para VMs Spot.
  • Ative NodeLocal DNSCache.
  • Escalone verticalmente o kube-dns.
  • Verifique se o aplicativo usa funções baseadas em dns.resolve* em vez de em dns.lookup, porque o segundo é síncrono. As funções dns.resolve* sempre executam uma consulta DNS assíncrona na rede.

Registros DNS de serviço

O kube-dns só cria registros DNS para serviços que têm Endpoints.

TTL grande de servidores upstream de DNS

Se o kube-dns receber uma resposta DNS de um resolvedor de DNS upstream com um TTL grande ou "infinito", ele vai manter esse valor de TTL para a entrada DNS no cache. A entrada nunca expira e pode criar uma discrepância entre a entrada e o endereço IP real resolvido para o nome do TTL.

O GKE resolve esse problema nas seguintes versões do plano de controle definindo um valor de TTL máximo como 30 segundos para qualquer resposta DNS que tenha um TTL maior que 30 segundos:

  • 1.21.14-gke.9100
  • 1.22.15-gke.2100
  • 1.23.13-gke.500
  • 1.24.7-gke.500
  • 1.25.2-gke.500 ou mais recente.

Esse comportamento é semelhante ao NodeLocal DNSCache.

Registrar métricas do kube-dns ou dnsmasq

É possível receber métricas sobre consultas de DNS no cluster do GKE. Essa é uma maneira rápida de receber métricas do kube-dns ou do dnsmasq sem modificar a implantação.

  1. Liste os pods na implantação do kube-dns.

    $ kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    

    A saída será semelhante a esta:

    NAME                        READY     STATUS    RESTARTS   AGE
    kube-dns-548976df6c-98fkd   4/4       Running   0          48m
    kube-dns-548976df6c-x4xsh   4/4       Running   0          47m
    
  2. Escolha um pod e defina o nome dele como uma variável.

    POD="kube-dns-548976df6c-98fkd"
    
  3. Configure o encaminhamento de portas para o pod kube-dns escolhido.

    $ kubectl port-forward pod/${POD} -n kube-system 10054:10054 10055:10055
    

    A saída será semelhante a esta:

    Forwarding from 127.0.0.1:10054 -> 10054
    Forwarding from 127.0.0.1:10055 -> 10055
    
  4. Para receber as métricas, execute o seguinte comando curl no endpoint.

    $ curl http://127.0.0.1:10054/metrics; curl http://127.0.0.1:10055/metrics

    A porta 10054 contém métricas do dnsmasq, e a porta 10055 contém métricas do kube-dns.

    A saída será semelhante a esta:

    kubedns_dnsmasq_errors 0
    kubedns_dnsmasq_evictions 0
    kubedns_dnsmasq_hits 3.67351e+06
    kubedns_dnsmasq_insertions 254114
    kubedns_dnsmasq_max_size 1000
    kubedns_dnsmasq_misses 3.278166e+06
    
    

A seguir