Sobre o kube-dns para GKE

Se você estiver executando aplicativos em clusters padrão, o kube-dns será o provedor de DNS padrão que ajuda a ativar a descoberta de serviços e a comunicação. Este documento descreve como gerenciar o DNS com o kube-dns, incluindo a arquitetura, a configuração e as práticas recomendadas para otimizar a resolução de DNS no ambiente do GKE.

Este documento é destinado a desenvolvedores, administradores e arquitetos responsáveis por gerenciar o DNS no GKE. Para contextualizar as funções e tarefas comuns, consulte Funções e tarefas comuns do usuário do GKE e tarefas. Google Cloud

Antes de começar, conheça os serviços do Kubernetes e os conceitos gerais de DNS.

Entender a arquitetura do kube-dns

O kube-dns opera dentro do cluster do GKE para ativar a resolução de DNS entre pods e serviços.

O diagrama a seguir mostra como os pods interagem com o serviço kube-dns:

Figura 1: diagrama mostrando como os pods enviam consultas DNS ao serviço "kube-dns", que é apoiado por pods "kube-dns". Os pods `kube-dns` processam
a resolução de DNS interno e encaminham consultas externas para servidores DNS
upstream.

Principais componentes

O kube-dns inclui os seguintes componentes principais:

  • Pods kube-dns:esses pods executam o software do servidor kube-dns. Várias réplicas desses pods são executadas no namespace kube-system e fornecem alta disponibilidade e redundância.
  • Serviço kube-dns:a tabela a seguir compara a escalonabilidade e os limites de configuração das versões legada e baseada em CoreDNS do kube-dns:
    Recurso Legado (kube-dns 1.35 e versões anteriores) kube-dns no CoreDNS (1.36 e versões mais recentes)
    Reconhecimento de endpoints Reconhece até 1.000 endpoints por serviço. Se um serviço tiver mais de 1.000 pods, o kube-dns não reconhecerá os endpoints adicionais. Reconhece todos os endpoints. Essa versão usa EndpointSlices para garantir a correção e melhorar a eficiência de serviços grandes.
    Servidores de nomes upstream Limitado a 3 Suporta até 15
    Conexões TCP de saída simultâneas Limitado a 200 Suporta até 1.500
  • kube-dns-autoscaler: esse pod ajusta o número de kube-dns réplicas com base no tamanho do cluster, que inclui o número de nós e núcleos de CPU. Essa abordagem ajuda a garantir que o kube-dns possa lidar com cargas de consulta DNS variáveis.

Resolução de DNS interna

Quando um pod precisa resolver um nome DNS no domínio do cluster, como myservice.my-namespace.svc.cluster.local, o processo a seguir ocorre:

  1. Configuração de DNS do pod:o kubelet em cada nó configura o arquivo /etc/resolv.conf do pod. Esse arquivo usa o ClusterIP do serviço kube-dns como o servidor de nomes.
  2. Consulta DNS:o pod envia uma consulta DNS para o serviço kube-dns.
  3. Resolução de nome :

    • GKE versão 1.36 ou mais recente:a implementação baseada em CoreDNS usa EndpointSlices para que o kube-dns reconheça todos os pods em um serviço. Isso melhora a correção e a eficiência de serviços em grande escala.
    • GKE versão 1.35 ou anterior:o kube-dns resolve nomes com base na API Cloud Endpoints mais antiga, que é limitada a 1.000 endpoints. Se um serviço tiver mais de 1.000 pods de apoio, o kube-dns não reconhecerá os endpoints adicionais.
  4. Comunicação:o pod usa o endereço IP resolvido para se comunicar com o serviço de destino.

Resolução de DNS externa

Quando um pod precisa resolver um nome DNS externo ou um nome que está fora do domínio do cluster, o kube-dns atua como um resolvedor recursivo. Ele encaminha a consulta para servidores DNS upstream configurados no arquivo ConfigMap. Também é possível configurar resolvedores personalizados para domínios específicos, também conhecidos como domínios de stub. Essa configuração direciona o kube-dns para encaminhar solicitações desses domínios para servidores DNS upstream específicos.

Configurar o DNS do pod

No GKE, o agente kubelet em cada nó configura as definições de DNS para os pods executados nesse nó.

Configurar o arquivo /etc/resolv.conf

Quando o GKE cria um pod, o agente kubelet modifica o arquivo /etc/resolv.conf do pod. Esse arquivo configura o servidor DNS para resolução de nomes e especifica domínios de pesquisa. Por padrão, o kubelet configura o pod para usar o serviço DNS interno do cluster, kube-dns, como servidor de nomes. Ele também preenche os domínios de pesquisa no arquivo. Esses domínios de pesquisa permitem usar nomes não qualificados em consultas DNS. Por exemplo, se um pod consultar myservice, o Kubernetes primeiro tentará resolver myservice.default.svc.cluster.local, depois myservice.svc.cluster.local e, em seguida, outros domínios da lista search.

O exemplo a seguir mostra uma configuração /etc/resolv.conf padrão:

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

Esse arquivo tem as seguintes entradas:

  • nameserver: define o ClusterIP do serviço kube-dns.
  • search: define os domínios de pesquisa que são anexados a nomes não qualificados durante as buscas DNS.
  • options ndots:5: define o limite para quando o GKE considera um nome totalmente qualificado. Um nome é considerado totalmente qualificado se tiver cinco ou mais pontos.

Os pods configurados com hostNetwork: true herdam a configuração de DNS do host e não consultam o kube-dns diretamente, a menos que usem a dnsPolicy ClusterFirstWithHostNet.

Personalizar o kube-dns

O kube-dns fornece uma resolução de DNS padrão robusta. É possível adaptar o comportamento dele para necessidades específicas, como melhorar a eficiência da resolução ou usar resolvedores de DNS preferenciais. Os domínios de stub e os servidores de nomes upstream são configurados modificando o ConfigMap kube-dns no namespace kube-system.

Modificar o ConfigMap kube-dns

Para modificar o ConfigMap kube-dns, faça o seguinte:

  1. Abra o ConfigMap para edição:

    kubectl edit configmap kube-dns -n kube-system
    
  2. Na seção data, adicione os campos stubDomains e upstreamNameservers da seguinte maneira:

    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"
          ],
          "internal": [ # Required if your upstream nameservers can't resolve GKE internal domains
            "169.254.169.254" # IP of the metadata server
          ]
        }
      upstreamNameservers: |
        [
          "8.8.8.8", # Google Public DNS
          "8.8.4.4" # Google Public DNS Backup
        ]
    
  3. Salve o ConfigMap. O kube-dns recarrega automaticamente a configuração.

Domínios stub

Os domínios de stub permitem definir resolvedores DNS personalizados para domínios específicos. Quando um pod consulta um nome nesse domínio de stub, o kube-dns encaminha a consulta para o resolvedor especificado em vez de usar o mecanismo de resolução padrão.

Inclua uma seção stubDomains no ConfigMap kube-dns.

Essa seção especifica o domínio e os servidores de nomes upstream correspondentes. O kube-dns encaminha consultas de nomes nesse domínio para os servidores designados. Por exemplo, é possível encaminhar todas as consultas DNS de internal.mycompany.com para 192.168.0.10, adicione "internal.mycompany.com": ["192.168.0.10"] a stubDomains.

Ao definir um resolvedor personalizado para um domínio de stub, como example.com, kube-dns encaminha todas as solicitações de resolução de nome para esse domínio, incluindo subdomínios como *.example.com, para os servidores especificados.

Servidores de nomes upstream

É possível configurar o kube-dns para usar servidores de nomes upstream personalizados para resolver nomes de domínio externos. Essa configuração instrui o kube-dns a encaminhar todas as solicitações DNS, exceto as solicitações do domínio interno do cluster (*.cluster.local), para os servidores upstream designados. Domínios internos como metadata.internal e *.google.internal podem não ser resolvidos pelos servidores upstream personalizados. Se você ativar a federação de identidade da carga de trabalho para GKE ou tiver cargas de trabalho que dependam desses domínios, adicione um domínio de stub para internal em ConfigMap. Use 169.254.169.254, o endereço IP do servidor de metadados, como o resolvedor desse domínio de stub.

Gerenciar uma implantação personalizada do kube-dns

Em um cluster padrão, o kube-dns é executado como uma implantação. Uma implantação personalizada do kube-dns significa que você, como administrador do cluster, pode controlar a implantação e personalizá-la de acordo com suas necessidades, em vez de usar a implantação padrão fornecida pelo GKE.

Motivos para uma implantação personalizada

Considere uma implantação personalizada do kube-dns pelos seguintes motivos:

  • Alocação de recursos:ajuste os recursos de CPU e memória para pods kube-dns para otimizar o desempenho em clusters com tráfego DNS alto.
  • Versão da imagem:use uma versão específica da imagem kube-dns ou mude para um provedor de DNS alternativo, como o CoreDNS.
  • Configuração avançada:personalize os níveis de geração de registros, as políticas de segurança e o comportamento de armazenamento em cache de DNS.

Escalonamento automático para implantações personalizadas

O kube-dns-autoscaler integrado funciona com a implantação kube-dns padrão. Se você criar uma implantação kube-dns personalizada, o escalonamento automático integrado não a gerenciará. Portanto, é necessário configurar um escalonamento automático separado, especificamente configurado para monitorar e ajustar a contagem de réplicas da implantação personalizada. Essa abordagem envolve a criação e a implantação da própria configuração de escalonamento automático no cluster.

Ao gerenciar uma implantação personalizada, você é responsável por todos os componentes dela, como manter a imagem do escalonamento automático atualizada. O uso de componentes desatualizados pode levar à degradação do desempenho ou a falhas de DNS.

Para instruções detalhadas sobre como configurar e gerenciar sua própria kube-dns implantação, consulte Como configurar uma implantação personalizada do kube-dns Deployment.

Resolver problemas

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

Otimizar a resolução de DNS

Esta seção descreve problemas comuns e práticas recomendadas para gerenciar o DNS no GKE.

Limite de domínios de pesquisa dnsConfig de um pod

O Kubernetes limita o número de domínios de pesquisa DNS a 32. Se você tentar definir mais de 32 domínios de pesquisa no dnsConfig de um pod, o kube-apiserver não criará o pod, com um erro semelhante ao seguinte:

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.

O kube-apiserver retorna essa mensagem de erro em resposta a uma tentativa de criação de pod. Para resolver esse problema, remova os caminhos de pesquisa extras da configuração.

Limite de nameservers upstream para kube-dns

As versões legadas do kube-dns (versão 1.35 e anteriores) limitam o número de upstreamNameservers a três. Se você definir mais de três, o Cloud Logging mostrará um erro semelhante ao seguinte:

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

Nesse cenário, o kube-dns ignora a configuração upstreamNameservers e continua usando a configuração válida anterior. Para resolver esse problema, remova os upstreamNameservers extras do ConfigMap kube-dns.

Escalonar verticalmente kube-dns

Em clusters padrão, é possível usar um valor menor para nodesPerReplica para que mais pods kube-dns sejam criados quando os nós do cluster escalonar verticalmente. Recomendamos definir um valor explícito para o campo max para ajudar a garantir que a máquina virtual (VM) do plano de controle do GKE não seja sobrecarregada devido ao grande número de pods kube-dns que estão assistindo à API Kubernetes.

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

É possível modificar o número de kube-dns réplicas editando o kube-dns-autoscaler ConfigMap.

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 kube-dns é calculado usando a seguinte fórmula:

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

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}'

Essa 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 crescer além de 120 nós, o número de réplicas kube-dns não crescerá além de 15, que é o valor do campo max.

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

A saída do ConfigMap kube-dns-autoscaler com o campo min configurado é semelhante à seguinte:

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

Melhorar os tempos busca DNS

Vários fatores podem causar alta latência com buscas DNS ou falhas de resolução de DNS com o provedor kube-dns padrão. Os aplicativos podem apresentar esses problemas como erros getaddrinfo EAI_AGAIN, que indicam uma falha temporária na resolução de nomes. As causas incluem o seguinte:

  • Buscas DNS frequentes na sua carga de trabalho.
  • Alta densidade de pods por nó.
  • Executar o kube-dns em VMs Spot ou preemptivas, o que pode levar a exclusões inesperadas de nós.
  • Limites de conexão:as versões legadas do kube-dns (GKE versão 1.35 e anteriores) são limitadas a 200 conexões TCP simultâneas. O kube-dns no CoreDNS (GKE versão 1.36 e mais recentes) remove esses limites fixos para conexões de entrada e oferece capacidade significativamente maior para conexões de saída.

Para melhorar os tempos de busca DNS, faça o seguinte:

  • Evite executar componentes críticos do sistema, como kube-dns no VMs Spot ou preemptivas. Crie pelo menos um pool de nós que tenha VMs padrão e não tenha VMs Spot ou VMs preemptivas. Use taints e tolerâncias para garantir que cargas de trabalho críticas sejam programadas nesses nós confiáveis.
  • Ative o NodeLocal DNSCache. O NodeLocal DNSCache armazena em cache as respostas DNS diretamente em cada nó, o que reduz a latência e a carga no serviço kube-dns. Se você ativar o NodeLocal DNSCache e usar políticas de rede com regras de negação padrão, adicione uma política para permitir que as cargas de trabalho enviem consultas DNS para os pods node-local-dns.
  • Escalonar 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.dns.lookup
  • Use nomes de domínio totalmente qualificados (FQDNs), por exemplo, https://google.com./ em vez de https://google.com/.

Falhas de resolução de DNS podem ocorrer durante upgrades cluster do GKE devido a upgrades simultâneos de componentes do plano de controle, incluindo kube-dns. Essas falhas geralmente afetam uma pequena porcentagem de nós. Teste completamente os upgrades de cluster em um ambiente que não seja de produção antes de aplicá-los aos clusters de produção.

Garantir a capacidade de descoberta de serviços

O kube-dns só cria registros DNS para serviços que têm Endpoints. Se um serviço não tiver nenhum endpoint, o kube-dns não criará registros DNS para ele.

Gerenciar discrepâncias de TTL de DNS

Se o kube-dns receber uma resposta DNS de um resolvedor de DNS upstream com um TTL grande ou infinito, ele manterá esse valor de TTL. Esse comportamento pode criar uma discrepância entre a entrada armazenada em cache e o endereço IP real.

O GKE resolve esse problema em versões específicas do plano de controle, como 1.21.14-gke.9100 e mais recentes ou 1.22.15-gke.2100 e mais recentes. Essas versões definem um valor máximo de TTL como 30 segundos para qualquer resposta DNS que tenha um TTL maior. Esse comportamento é semelhante ao NodeLocal DNSCache.

Conferir métricas do kube-dns

É possível recuperar métricas sobre consultas DNS diretamente dos pods kube-dns. A maneira como você recupera essas métricas depende da versão do GKE.

GKE versão 1.36 e mais recentes

Se o cluster executar o GKE versão 1.36 ou mais recente (kube-dns no CoreDNS), é possível monitorar o desempenho do DNS usando painéis predefinidos no Cloud Monitoring ou recuperar métricas manualmente dos pods.

Conferir métricas no Google Cloud console

  1. No Google Cloud console do Cloud, acesse a página Painéis.
  2. Selecione o painel Observabilidade de DNS do GKE – visualização do cluster.

Como alternativa, é possível consultar essas métricas diretamente no Google Cloud console acessando Monitoring > Metrics explorer e pesquisando os nomes de métricas específicos.

Recuperar métricas manualmente

Para recuperar métricas do pod manualmente, faça o seguinte:

  1. Encontre os pods kube-dns.

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    
  2. Encaminhe a porta 9153 para um dos pods.

    kubectl port-forward pod/POD_NAME -n kube-system 9153:9153
    

    Substitua POD_NAME pelo nome de um dos pods kube-dns da saída anterior.

  3. Acesse as métricas.

    curl http://127.0.0.1:9153/metrics
    

GKE versão 1.35 e anteriores

Essa versão do kube-dns usa pods de vários contêineres. Para recuperar métricas, faça o seguinte:

  1. Encontre os pods kube-dns no namespace kube-system.

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    
  2. Encaminhe para as portas 10055 (para o contêiner kube-dns) e 10054 (para o contêiner dnsmasq):

    #For the kube-dns container
    kubectl port-forward pod/POD_NAME -n kube-system 10055:10055
    #For the dnsmasq container
    kubectl port-forward pod/POD_NAME -n kube-system 10054:10054
    

    Substitua POD_NAME pelo nome de um dos pods kube-dns da saída anterior. Execute esses comandos de encaminhamento de portas em sessões de terminal separadas.

  3. Acesse as métricas.

    #Metrics from the kube-dns container
    curl http://127.0.0.1:10055/metrics
    
    #Metrics from the dnsmasq container
    curl http://127.0.0.1:10054/metrics
    

A seguir