Resolver problemas do kube-dns no GKE


Nesta página, mostramos como resolver problemas com o kube-dns no Google Kubernetes Engine (GKE).

Identificar a origem dos problemas de DNS no kube-dns

Erros como dial tcp: i/o timeout, no such host ou Could not resolve host geralmente indicam problemas com a capacidade do kube-dns de resolver consultas.

Se você já encontrou um desses erros, mas não sabe a causa, use as seções a seguir para ajudar a encontrá-lo. As seções a seguir são organizadas para começar com as etapas que provavelmente vão ajudar você. Portanto, tente cada seção na ordem.

Verificar se os pods kube-dns estão em execução

Os pods kube-dns são essenciais para a resolução de nomes no cluster. Se eles não estiverem em execução, é provável que você tenha problemas com a resolução de DNS.

Para verificar se os pods kube-dns estão em execução sem reinicializações recentes, confira o status desses pods:

kubectl get pods -l k8s-app=kube-dns -n kube-system

O resultado será assim:

NAME                   READY          STATUS          RESTARTS       AGE
kube-dns-POD_ID_1      5/5            Running         0              16d
kube-dns-POD_ID_2      0/5            Terminating     0              16d

Nesta saída, POD_ID_1 e POD_ID_2 representam identificadores exclusivos que são adicionados automaticamente aos pods do kube-dns.

Se a saída mostrar que algum dos pods kube-dns não tem um status de Running, siga estas etapas:

  1. Use os registros de auditoria de atividades do administrador para investigar se houve mudanças recentes, como upgrades de versão do cluster ou do pool de nós ou mudanças no ConfigMap kube-dns. Para saber mais sobre os registros de auditoria, consulte Informações sobre a geração de registros de auditoria do GKE. Se você encontrar mudanças, reverta-as e confira o status dos pods novamente.

  2. Se você não encontrar mudanças recentes relevantes, investigue se está ocorrendo um erro de OOM no nó em que o pod kube-dns é executado. Se você encontrar um erro semelhante ao mostrado abaixo nas mensagens de registro do Cloud Logging, esses pods estão com um erro OOM:

    Warning: OOMKilling Memory cgroup out of memory
    

    Para resolver esse erro, consulte Mensagem de erro: "Warning: OOMKilling Memory cgroup out of memory".

  3. Se você não encontrar mensagens de erro de OOM, reinicie a implantação do kube-dns:

    kubectl rollout restart deployment/kube-dns --namespace=kube-system
    

    Depois de reiniciar a implantação, verifique se os pods kube-dns estão em execução.

Se essas etapas não funcionarem ou se todos os pods kube-dns tiverem um status de Running, mas você ainda tiver problemas de DNS, verifique se o arquivo /etc/resolv.conf está configurado corretamente.

Verifique se o /etc/resolv.conf está configurado corretamente

Analise o arquivo /etc/resolv.conf dos pods com problemas de DNS e verifique se as entradas são corretas:

  1. Confira o arquivo /etc/resolv.conf do pod:

    kubectl exec -it POD_NAME -- cat /etc/resolv.conf
    

    Substitua POD_NAME pelo nome do pod que está com problemas de DNS. Se houver vários pods com problemas, repita as etapas desta seção para cada um deles.

    Se o binário do pod não oferecer suporte ao comando kubectl exec, ele poderá falhar. Se isso acontecer, crie um pod simples para usar como ambiente de teste. Esse procedimento permite executar um pod de teste no mesmo namespace do pod com problemas.

  2. Verifique se o endereço IP do servidor de nomes no arquivo /etc/resolv.conf está correto:

    • Os pods que usam uma rede de host precisam usar os valores no arquivo /etc/resolv.conf do nó. O endereço IP do servidor de nomes precisa ser 169.254.169.254.
    • Para pods que não usam uma rede de host, o endereço IP do serviço kube-dns precisa ser o mesmo que o endereço IP do servidor de nomes. Para comparar os endereços IP, siga estas etapas:

      1. Encontre o endereço IP do serviço kube-dns:

        kubectl get svc kube-dns -n kube-system
        

        O resultado será assim:

        NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
        kube-dns   ClusterIP   192.0.2.10   <none>        53/UDP,53/TCP   64d
        
      2. Anote o valor na coluna "IP do cluster". Neste exemplo, é 192.0.2.10.

      3. Compare o endereço IP do serviço kube-dns com o endereço IP do arquivo /etc/resolv.conf:

        # cat /etc/resolv.conf
        
        search default.svc.cluster.local svc.cluster.local cluster.local c.PROJECT_NAME google.internal
        nameserver 192.0.2.10
        options ndots:5
        

        Neste exemplo, os dois valores correspondem, então um endereço IP do servidor de nomes incorreto não é a causa do problema.

        No entanto, se os endereços IP não corresponderem, isso significa que um campo dnsConfig está configurado no manifesto do pod do aplicativo.

        Se o valor no campo dnsConfig.nameservers estiver correto, investigue o servidor DNS e verifique se ele está funcionando corretamente.

        Se você não quiser usar o servidor de nome personalizado, remova o campo e realize uma reinicialização progressiva do pod:

        kubectl rollout restart deployment POD_NAME
        

        Substitua POD_NAME pelo nome do pod.

  3. Verifique as entradas search e ndots em /etc/resolv.conf. Verifique se não há erros de ortografia, configurações desaturadas e se a solicitação com falha aponta para o serviço existente no namespace correto.

Fazer uma busca DNS

Depois de confirmar que /etc/resolv.conf está configurado corretamente e que o registro DNS está correto, use a ferramenta de linha de comando dig para realizar pesquisas DNS no pod que está relatando erros de DNS:

  1. Faça uma consulta direta em um pod abrindo um shell dentro dele:

    kubectl exec -it POD_NAME -n NAMESPACE_NAME -- SHELL_NAME
    

    Substitua:

    • POD_NAME: o nome do pod que está informando erros de DNS.
    • NAMESPACE_NAME: o namespace ao qual o pod pertence.
    • SHELL_NAME: o nome do shell que você quer abrir. Por exemplo, sh ou /bin/bash.

    Esse comando pode falhar se o pod não permitir o comando kubectl exec ou se o pod não tiver o binário dig. Se isso acontecer, crie um pod de teste com uma imagem que tenha o dig instalado:

    kubectl run "test-$RANDOM" ti --restart=Never --image=thockin/dnsutils - bash
    
  2. Verifique se o pod pode resolver corretamente o serviço DNS interno do cluster:

    dig kubernetes
    

    Como o arquivo /etc/resolv.conf está apontando para o endereço IP do serviço kube-dns, quando você executa esse comando, o servidor DNS é o serviço kube-dns.

    Você vai ver uma resposta DNS com o endereço IP do serviço da API do Kubernetes (geralmente algo como 10.96.0.1). Se você encontrar SERVFAIL ou nenhuma resposta, isso geralmente indica que o pod kube-dns não consegue resolver os nomes de serviço internos.

  3. Verifique se o serviço kube-dns pode resolver um nome de domínio externo:

    dig example.com
    
  4. Se você estiver com dificuldades com um pod kube-dns específico respondendo a consultas DNS, verifique se ele pode resolver um nome de domínio externo:

     dig example.com @KUBE_DNS_POD_IP
    

    Substitua KUBE_DNS_POD_IP pelo endereço IP do pod kube-dns. Se você não souber o valor desse endereço IP, execute o comando a seguir:

     kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
    

    O endereço IP está na coluna IP.

    Se a resolução do comando for bem-sucedida, você verá status: NOERROR e os detalhes do registro A, conforme mostrado no exemplo abaixo:

     ; <<>> DiG 9.16.27 <<>> example.com
     ;; global options: +cmd
     ;; Got answer:
     ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31256
     ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
    
     ;; OPT PSEUDOSECTION:
     ; EDNS: version: 0, flags:; udp: 512
     ;; QUESTION SECTION:
     ;example.com.                   IN      A
    
     ;; ANSWER SECTION:
     example.com.            30      IN      A       93.184.215.14
    
     ;; Query time: 6 msec
     ;; SERVER: 10.76.0.10#53(10.76.0.10)
     ;; WHEN: Tue Oct 15 16:45:26 UTC 2024
     ;; MSG SIZE  rcvd: 56
    
  5. Saia do shell:

    exit
    

Se algum desses comandos falhar, faça uma reinicialização progressiva da implantação do kube-dns:

kubectl rollout restart deployment/kube-dns --namespace=kube-system

Depois de concluir a reinicialização, tente novamente os comandos dig e veja se eles funcionam. Se eles ainda falharem, faça uma captura de pacote.

Fazer uma captura de pacotes

Faça uma captura de pacote para verificar se as consultas DNS estão sendo recebidas e respondidas adequadamente pelos pods kube-dns:

  1. Usando o SSH, conecte-se ao nó que executa o pod kube-dns. Exemplo:

    1. No console do Google Cloud , acesse a página Instâncias de VM.

      Acessar instâncias de VM

    2. Localize o nó que você quer conectar. Se você não souber o nome do nó no pod kube-dns, execute o seguinte comando:

      kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
      

      O nome do nó é listado na coluna .

    3. Na coluna Conectar, clique em SSH.

  2. No terminal, inicie a toolbox, uma ferramenta de depuração pré-instalada:

    toolbox
    
  3. No prompt raiz, instale o pacote tcpdump:

    apt update -y && apt install -y tcpdump
    
  4. Usando tcpdump, faça uma captura de pacotes do seu tráfego DNS:

    tcpdump -i eth0 port 53" -w FILE_LOCATION
    

    Substitua FILE_LOCATION por um caminho para onde você quer salvar a captura.

  5. Analise a captura de pacotes. Verifique se há pacotes com endereços IP de destino que correspondem ao endereço IP do serviço kube-dns. Isso garante que as solicitações de DNS estejam chegando ao destino certo para resolução. A falha em ver o tráfego DNS chegando aos pods corretos pode indicar a presença de uma política de rede que está bloqueando as solicitações.

Verificar uma política de rede

Às vezes, políticas de rede restritivas podem interromper o tráfego de DNS. Para verificar se uma política de rede existe no namespace kube-system, execute o seguinte comando:

kubectl get networkpolicy -n kube-system

Se você encontrar uma política de rede, revise-a e verifique se ela permite a comunicação de DNS necessária. Por exemplo, se você tiver uma política de rede que bloqueia todo o tráfego de saída, ela também bloqueará as solicitações de DNS.

Se a saída for No resources found in kube-system namespace, você não tem políticas de rede e pode descartar isso como a causa do problema. A investigação de registros pode ajudar a encontrar mais pontos de falha.

Ativar o registro temporário de consultas DNS

Para ajudar a identificar problemas como respostas DNS incorretas, ative temporariamente a geração de registros de depuração de consultas DNS.

Esse é um procedimento que consome muitos recursos. Por isso, recomendamos que você desative esse registro depois de coletar uma amostra adequada de registros.

Investigar o pod kube-dns

Confira como os pods kube-dns recebem e resolvem consultas de DNS com o Cloud Logging.

Para conferir as entradas de registro relacionadas ao pod kube-dns, siga estas etapas:

  1. No console do Google Cloud , acesse a página Análise de registros.

    Acessar o Explorador de registros

  2. No painel de consulta, insira o seguinte filtro para conferir eventos relacionados ao contêiner kube-dns:

    resource.type="k8s_container"
    resource.labels.namespace_name="kube-system"
    resource.labels.Pod_name:"kube-dns"
    resource.labels.cluster_name="CLUSTER_NAME"
    resource.labels.location="CLUSTER_LOCATION"
    

    Substitua:

    • CLUSTER_NAME: o nome do cluster ao qual o pod kube-dns pertence.
    • CLUSTER_LOCATION: o local do cluster.
  3. Clique em Executar consulta.

  4. Verifique a saída. O exemplo de saída a seguir mostra um possível erro que você pode encontrar:

    {
       "timestamp": "2024-10-10T15:32:16.789Z",
       "severity": "ERROR",
       "resource": {
          "type": "k8s_container",
          "labels": {
          "namespace_name": "kube-system",
          "Pod_name": "kube-dns",
          "cluster_name": "CLUSTER_NAME",
          "location": "CLUSTER_LOCATION"
          }
       },
       "message": "Failed to resolve 'example.com': Timeout."
    },
    

    Neste exemplo, o kube-dns não conseguiu resolver example.com em um tempo razoável. Esse tipo de erro pode ser causado por vários problemas. Por exemplo, o servidor upstream pode estar configurado incorretamente no ConfigMap kube-dns ou pode haver um tráfego de rede alto.

Se o Cloud Logging não estiver ativado, acesse os registros do Kubernetes:

Pod=$(kubectl get Pods -n kube-system -l k8s-app=kube-dns -o name | head -n1)
kubectl logs -n kube-system $Pod -c dnsmasq
kubectl logs -n kube-system $Pod -c kubedns
kubectl logs -n kube-system $Pod -c sidecar

Investigar mudanças recentes no ConfigMap kube-dns

Se você encontrar falhas de resolução de DNS no cluster, uma das causas é uma mudança de configuração incorreta feita no ConfigMap kube-dns. Em particular, mudanças de configuração nas definições de servidores upstream e domínios de stub podem causar problemas.

Para verificar se há atualizações nas configurações do domínio stub, siga estas etapas:

  1. No console do Google Cloud , acesse a página Análise de registros.

    Acessar o Explorador de registros

  2. No painel de consulta, digite a seguinte consulta:

    resource.labels.cluster_name="clouddns"
    resource.type="k8s_container"
    resource.labels.namespace_name="kube-system"
    labels.k8s-pod/k8s-app="kube-dns" jsonPayload.message=~"Updated stubDomains to"
    
  3. Clique em Executar consulta.

  4. Verifique a saída. Se houver atualizações, a saída será semelhante a esta:

    Updated stubDomains to map[example.com: [8.8.8.8 8.8.4.4 1.1.3.3 1.0.8.111]]
    

    Se houver uma atualização, abra o resultado para saber mais sobre as mudanças. Verifique se todos os domínios stub e os servidores DNS upstream correspondentes estão definidos corretamente. Entradas incorretas podem levar a falhas de resolução para esses domínios.

Para verificar se há mudanças no servidor upstream, siga estas etapas:

  1. No console do Google Cloud , acesse a página Análise de registros.

    Acessar o Explorador de registros

  2. No painel de consulta, digite a seguinte consulta:

    resource.labels.cluster_name="clouddns"
    resource.type="k8s_container" resource.labels.namespace_name="kube-system"
    labels.k8s-pod/k8s-app="kube-dns" jsonPayload.message=~"Updated upstreamNameservers to"
    
  3. Clique em Executar consulta.

  4. Verifique a saída. Se houver mudanças, a saída será semelhante a esta:

    Updated upstreamNameservers to [8.8.8.8]
    

    Abra o resultado para saber mais sobre as mudanças. Verifique se a lista de servidores DNS upstream está correta e se esses servidores podem ser acessados pelo cluster. Se esses servidores estiverem indisponíveis ou configurados incorretamente, a resolução geral do DNS poderá falhar.

Se você verificou se há mudanças nos domínios stub e nos servidores upstream, mas não encontrou resultados, verifique todas as mudanças com o seguinte filtro:

resource.type="k8s_cluster"
protoPayload.resourceName:"namespaces/kube-system/configmaps/kube-dns"
protoPayload.methodName=~"io.k8s.core.v1.configmaps."

Analise as mudanças listadas para saber se elas causaram o erro.

Entrar em contato com o atendimento ao cliente do Cloud

Se você já trabalhou nas seções anteriores, mas ainda não conseguiu diagnosticar a causa do problema, entre em contato com o atendimento ao cliente do Cloud.

Resolver problemas comuns

Se você tiver um erro ou problema específico, use os conselhos nas seções a seguir.

Problema: tempos limite de DNS intermitentes

Se você notar tempos limite intermitentes de resolução de DNS que ocorrem quando há um aumento no tráfego de DNS ou quando o horário comercial começa, tente as seguintes soluções para otimizar a performance do DNS:

  • Verifique o número de pods kube-dns em execução no cluster e compare-o com o número total de nós do GKE. Se não houver recursos suficientes, considere aumentar os pods kube-dns.

  • Para melhorar o tempo médio de busca DNS, ative o NodeLocal DNS Cache.

  • A resolução de DNS para nomes externos pode sobrecarregar o pod kube-dns. Para reduzir o número de consultas, ajuste a configuração ndots no arquivo /etc/resolv.conf. ndots representa o número de pontos que precisam aparecer em um nome de domínio para resolver uma consulta antes da consulta absoluta inicial.

    O exemplo a seguir é o arquivo /etc/resolv.conf de um pod de aplicativo:

    search default.svc.cluster.local svc.cluster.local cluster.local c.PROJECT_ID.internal google.internal
    nameserver 10.52.16.10
    options ndots:5
    

    Neste exemplo, o kube-dns procura cinco pontos no domínio que está sendo consultado. Se o pod fizer uma chamada de resolução de DNS para example.com, seus registros serão semelhantes ao exemplo abaixo:

    "A IN example.com.default.svc.cluster.local." NXDOMAIN
    "A IN example.com.svc.cluster.local." NXDOMAIN
    "A IN example.com.cluster.local." NXDOMAIN
    "A IN example.com.google.internal." NXDOMAIN
    "A IN example.com.c.PROJECT_ID.internal." NXDOMAIN
    "A IN example.com." NOERROR
    

    Para resolver esse problema, mude o valor de ndots para 1 para procurar apenas um ponto ou adicione um ponto (.) ao final do domínio que você consulta ou usa. Exemplo:

    dig example.com.
    

Problema: as consultas DNS falham intermitentemente em alguns nós

Se você notar que as consultas DNS estão falhando de forma intermitente em alguns nós, poderá observar os seguintes sintomas:

  • Quando você executa comandos de busca no endereço IP do serviço kube-dns ou no endereço IP do pod, as consultas DNS falham de forma intermitente com timeouts.
  • A execução de comandos dig de um pod no mesmo nó que o pod kube-dns falha.

Para resolver esse problema, siga estas etapas:

  1. Faça um teste de conectividade. Defina o pod ou nó problemático como a origem e o destino como o endereço IP do pod kube-dns. Isso permite verificar se você tem as regras de firewall necessárias para permitir esse tráfego.
  2. Se o teste não for bem-sucedido e o tráfego estiver sendo bloqueado por uma regra de firewall, use o Cloud Logging para listar as alterações manuais feitas nas regras de firewall. Procure mudanças que bloqueiam um tipo específico de tráfego:

    1. No console do Google Cloud , acesse a página Análise de registros.

      Acessar o Explorador de registros

    2. No painel de consulta, digite a seguinte consulta:

      logName="projects/project-name/logs/cloudaudit.googleapis.com/activity"
      resource.type="gce_firewall_rule"
      
    3. Clique em Executar consulta. Use a saída da consulta para determinar se houve alterações. Se você notar algum erro, corrija-o e replique a regra de firewall.

      Não faça mudanças nas regras de firewall automatizadas.

  3. Se não houver mudanças nas regras do firewall, verifique a versão do pool de nós e verifique se ela é compatível com o plano de controle e outros pools de nós em funcionamento. Se algum dos pools de nós do cluster tiver mais de duas versões secundárias mais antigas que o plano de controle, isso pode causar problemas. Para mais informações sobre essa incompatibilidade, consulte A versão do nó não é compatível com a versão do plano de controle.

  4. Para determinar se as solicitações estão sendo enviadas para o IP do serviço kube-dns correto, capture o tráfego de rede no nó problemático e filtre a porta 53 (tráfego DNS). Capture o tráfego nos pods kube-dns para ver se as solicitações estão chegando aos pods pretendidos e se elas estão sendo resolvidas.

A seguir