Resolva problemas do kube-dns no GKE

Se usar o kube-dns para a deteção de serviços, pode ter erros de ligação, como dial tcp: i/o timeout ou no such host. Estes erros indicam frequentemente problemas com os pods kube-dns no espaço de nomes kube-system, como configurações incorretas, limitações de recursos ou problemas de conetividade de rede que afetam estes pods.

Use esta página para diagnosticar e resolver problemas comuns específicos da implementação do kube-dns, o que ajuda a garantir uma resolução de DNS fiável para as suas cargas de trabalho.

Estas informações são importantes para os administradores e os operadores da plataforma, que são responsáveis pela manutenção dos componentes principais do cluster, como o kube-dns, e para os programadores de aplicações, cujas aplicações dependem dele para estabelecer ligação a outros serviços no cluster. Para mais informações sobre as funções comuns e as tarefas de exemplo a que fazemos referência no conteúdo, consulte o artigo Funções e tarefas comuns do utilizador do GKE. Trusted Cloud by S3NS

Identifique a origem dos problemas de DNS no kube-dns

As secções seguintes ajudam a diagnosticar o motivo pelo qual o kube-dns está a ter dificuldade em resolver consultas.

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

Os pods do Kube-dns são fundamentais para a resolução de nomes no cluster. Se não estiverem em execução, é provável que tenha problemas com a resolução de DNS.

Para verificar se os pods kube-dns estão a ser executados sem reinícios recentes, veja o estado destes pods:

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

O resultado é semelhante ao seguinte:

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

Neste resultado, POD_ID_1 e POD_ID_2 representam identificadores únicos que são anexados automaticamente aos pods kube-dns.

Se o resultado mostrar que algum dos seus pods kube-dns não tem o estado Running, siga os passos seguintes:

  1. Use os registos de auditoria da atividade do administrador para investigar se houve alterações recentes, como atualizações de versões de clusters ou conjuntos de nós, ou alterações ao ConfigMap kube-dns. Para saber mais sobre os registos de auditoria, consulte as informações de registo de auditoria do GKE. Se encontrar alterações, reverta-as e veja novamente o estado dos Pods.

  2. Se não encontrar alterações recentes relevantes, investigue se está a ter um erro de falta de memória no nó em que o pod kube-dns é executado. Se vir um erro semelhante ao seguinte nas mensagens de registo do Cloud Logging, estes pods estão a ter um erro de falta de memória:

    Warning: OOMKilling Memory cgroup out of memory
    

    Esta mensagem indica que o Kubernetes terminou um processo devido ao consumo excessivo de recursos. O Kubernetes agenda pods com base em pedidos de recursos, mas permite que os pods consumam até aos respetivos limites de recursos. Se os limites forem superiores aos pedidos ou não existirem limites, a utilização de recursos do pod pode exceder os recursos do sistema.

    Para resolver este erro, pode eliminar as cargas de trabalho problemáticas ou definir limites de memória ou CPU. Para saber mais sobre a definição de limites, consulte o artigo Gestão de recursos para pods e contentores na documentação do Kubernetes. Para mais informações sobre eventos OOM, consulte o artigo Resolva problemas de eventos OOM.

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

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

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

Se estes passos não funcionarem ou todos os seus pods kube-dns tiverem o estado Running, mas continuar a ter problemas de DNS, verifique se o ficheiro /etc/resolv.conf está configurado corretamente.

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

Reveja o ficheiro /etc/resolv.conf dos pods com problemas de DNS e certifique-se de que as entradas que contém estão corretas:

  1. Veja o ficheiro /etc/resolv.conf do Pod:

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

    Substitua POD_NAME pelo nome do pod que está a ter problemas de DNS. Se existirem vários Pods com problemas, repita os passos nesta secção para cada Pod.

    Se o ficheiro binário do Pod não suportar o comando kubectl exec, este comando pode falhar. Se isto acontecer, crie um pod simples para usar como ambiente de teste. Este procedimento permite-lhe executar um Pod de teste no mesmo espaço de nomes que o seu Pod problemático.

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

    • Os pods que usam uma rede de anfitriões devem usar os valores no ficheiro /etc/resolv.conf do nó. O endereço IP do servidor de nomes deve ser 169.254.169.254.
    • Para os pods que não estão a usar uma rede de anfitrião, o endereço IP do serviço kube-dns deve ser o mesmo que o endereço IP do servidor de nomes. Para comparar os endereços IP, conclua os seguintes passos:

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

        kubectl get svc kube-dns -n kube-system
        

        O resultado é semelhante ao seguinte:

        NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
        kube-dns   ClusterIP   192.0.2.10   <none>        53/UDP,53/TCP   64d
        
      2. Tome nota do 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 ficheiro /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, pelo que 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, significa que um campo dnsConfig está configurado no manifesto do pod da aplicação.

        Se o valor no campo dnsConfig.nameservers estiver correto, investigue o seu servidor DNS e certifique-se de que está a funcionar corretamente.

        Se não quiser usar o servidor de nomes personalizado, remova o campo e reinicie o pod de forma gradual:

        kubectl rollout restart deployment POD_NAME
        

        Substitua POD_NAME pelo nome do seu Pod.

  3. Valide as entradas search e ndots em /etc/resolv.conf. Certifique-se de que não existem erros ortográficos, configurações desatualizadas e que o pedido com falha aponta para um serviço existente no espaço de nomes correto.

Efetue uma procura de DNS

Depois de confirmar que /etc/resolv.conf está configurado corretamente e que o registo DNS está correto, use a ferramenta de linha de comandos dig para fazer pesquisas de DNS a partir do pod que está a comunicar erros de DNS:

  1. Consultar diretamente um pod abrindo um shell no respetivo interior:

    kubectl exec -it POD_NAME -n NAMESPACE_NAME -- SHELL_NAME
    

    Substitua o seguinte:

    • POD_NAME: o nome do Pod que está a comunicar erros de DNS.
    • NAMESPACE_NAME: o espaço de nomes ao qual o Pod pertence.
    • SHELL_NAME: o nome da shell que quer abrir. Por exemplo, sh ou /bin/bash.

    Este comando pode falhar se o seu Pod não permitir o comando kubectl exec ou se o Pod não tiver o ficheiro binário dig. Se isto 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 consegue resolver corretamente o serviço DNS interno do cluster:

    dig kubernetes
    

    Uma vez que o ficheiro /etc/resolv.conf aponta para o endereço IP do serviço kube-dns, quando executa este comando, o servidor DNS é o serviço kube-dns.

    Deve ver uma resposta de DNS bem-sucedida com o endereço IP do serviço de API do Kubernetes (geralmente, algo como 10.96.0.1). Se vir SERVFAIL ou nenhuma resposta, isto indica normalmente que o pod kube-dns não consegue resolver os nomes de serviços internos.

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

    dig example.com
    
  4. Se estiver a ter dificuldades com um Pod kube-dns específico a responder a consultas de DNS, verifique se esse Pod consegue 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 não souber o valor deste endereço IP, execute o seguinte comando:

     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, é apresentado status: NOERROR e os detalhes do registo A, conforme mostrado no exemplo seguinte:

     ; <<>> 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 da shell:

    exit
    

Se algum destes comandos falhar, faça um reinício contínuo da implementação do kube-dns:

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

Depois de concluir o reinício, tente novamente os comandos dig e verifique se têm êxito. Se continuarem a falhar, avance para a captura de pacotes.

Faça uma captura de pacotes

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

  1. Usando o SSH, estabeleça ligação ao nó que executa o pod kube-dns. Por exemplo:

    1. Na Trusted Cloud consola, aceda à página Instâncias de VM.

      Aceder a Instâncias de VM

    2. Localize o nó ao qual quer estabelecer ligação. Se não souber o nome do nó no seu pod kube-dns, execute o seguinte comando:

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

      O nome do nó é apresentado na coluna .

    3. Na coluna Ligar, clique em SSH.

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

    toolbox
    
  3. No comando root, instale o pacote tcpdump:

    apt update -y && apt install -y tcpdump
    
  4. Usando o 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 quer guardar a captura.

  5. Reveja a captura de pacotes. Verifique se existem pacotes com endereços IP de destino que correspondem ao endereço IP do serviço kube-dns. Isto garante que os pedidos de DNS estão a alcançar o destino certo para resolução. A não visualização do tráfego DNS a chegar aos pods corretos pode indicar a presença de uma política de rede que está a bloquear os pedidos.

Verifique se existe uma política de rede

Por vezes, as políticas de rede restritivas podem interromper o tráfego DNS. Para verificar se existe uma política de rede no espaço de nomes kube-system, execute o seguinte comando:

kubectl get networkpolicy -n kube-system

Se encontrar uma política de rede, reveja-a e certifique-se de que a política permite a comunicação DNS necessária. Por exemplo, se tiver uma política de rede que bloqueie todo o tráfego de saída, a política também bloqueia os pedidos de DNS.

Se o resultado for No resources found in kube-system namespace, significa que não tem políticas de rede e pode excluir esta hipótese como a causa do seu problema. A investigação de registos pode ajudar a encontrar mais pontos de falha.

Ative o registo de consultas DNS temporário

Para ajudar a identificar problemas, como respostas DNS incorretas, ative temporariamente o registo de depuração de consultas DNS. Para ativar as consultas, crie um Pod com base num Pod kube-dns existente. Todas as alterações à implementação do kube-dns são revertidas automaticamente.

A ativação do registo de consultas DNS temporário é um procedimento que requer muitos recursos, pelo que recomendamos que elimine o pod que criar assim que recolher uma amostra adequada de registos.

Para ativar o registo temporário de consultas DNS, conclua os seguintes passos:

  1. Recupere um pod kube-dns e armazene-o na variável denominada POD:

    POD=$(kubectl -n kube-system get pods --selector=k8s-app=kube-dns -o jsonpath="{.items[0].metadata.name}")
    
  2. Crie um pod com o nome kube-dns-debug. Este Pod é uma cópia do Pod armazenado na variável POD, mas com o registo do dnsmasq ativado. Este comando não modifica o pod kube-dns original:

    kubectl apply -f <(kubectl get pod -n kube-system ${POD} -o json | jq -e '
    
    (
    
    (.spec.containers[] | select(.name == "dnsmasq") | .args) += ["--log-queries"]
    
    )
    
    | (.metadata.name = "kube-dns-debug")
    
    | (del(.metadata.labels."pod-template-hash"))
    
    ')
    
  3. Inspecione os registos:

    kubectl logs -f --tail 100 -c dnsmasq -n kube-system kube-dns-debug
    

    Também pode ver as consultas no Cloud Logging.

  4. Depois de terminar a visualização dos registos de consultas DNS, elimine o kube-dns-debug pod:

    kubectl -n kube-system delete pod kube-dns-debug
    

Investigue o pod kube-dns

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

Para ver as entradas de registo relacionadas com o pod kube-dns, conclua os seguintes passos:

  1. Na Trusted Cloud consola, aceda à página Explorador de registos.

    Aceda ao Explorador de registos

  2. No painel de consultas, introduza o seguinte filtro para ver eventos relacionados com o contentor 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 o seguinte:

    • CLUSTER_NAME: o nome do cluster ao qual o pod kube-dns pertence.
    • CLUSTER_LOCATION: a localização do seu cluster.
  3. Clique em Executar consulta.

  4. Reveja o resultado. O exemplo de resultado seguinte mostra um possível erro que pode ver:

    {
       "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 num período razoável. Este tipo de erro pode ser causado por vários problemas. Por exemplo, o servidor a montante pode estar configurado incorretamente no ConfigMap kube-dns ou pode haver um volume elevado de tráfego de rede.

Se não tiver o Cloud Logging ativado, veja os registos 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

Investigue alterações recentes no ConfigMap kube-dns

Se de repente encontrar falhas de resolução de DNS no seu cluster, uma das causas é uma alteração de configuração incorreta feita ao ConfigMap kube-dns. Em particular, as alterações de configuração às definições dos domínios stub e dos servidores a montante podem causar problemas.

Para verificar se existem atualizações das definições do domínio auxiliar, conclua os seguintes passos:

  1. Na Trusted Cloud consola, aceda à página Explorador de registos.

    Aceda ao Explorador de registos

  2. No painel de consultas, introduza 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. Reveja o resultado. Se tiverem sido feitas atualizações, o resultado é semelhante ao seguinte:

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

    Se vir uma atualização, expanda o resultado para saber mais sobre as alterações. Verifique se todos os domínios stub e os respetivos servidores DNS upstream estão definidos corretamente. As entradas incorretas aqui podem levar a falhas de resolução para esses domínios.

Para verificar se existem alterações no servidor a montante, conclua os seguintes passos:

  1. Na Trusted Cloud consola, aceda à página Explorador de registos.

    Aceda ao Explorador de registos

  2. No painel de consultas, introduza 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. Reveja o resultado. Se tiverem sido feitas alterações, o resultado é semelhante ao seguinte:

    Updated upstreamNameservers to [8.8.8.8]
    

    Expanda o resultado para saber mais sobre as alterações. Verifique se a lista de servidores DNS upstream está correta e se estes servidores estão acessíveis a partir do seu cluster. Se estes servidores estiverem indisponíveis ou configurados incorretamente, a resolução de DNS geral pode falhar.

Se verificou se existem alterações aos domínios de stub e aos servidores a montante, mas não encontrou resultados, verifique todas as alterações com o seguinte filtro:

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

Reveja as alterações apresentadas para ver se causaram o erro.

Contacte o Cloud Customer Care

Se seguiu as secções anteriores, mas ainda não consegue diagnosticar a causa do problema, contacte o apoio ao cliente do Google Cloud.

Resolva problemas comuns

Se tiver tido um erro ou um problema específico, use as sugestões nas secções seguintes.

Problema: limites de tempo de DNS intermitentes

Se notar limites de tempo de resolução de DNS intermitentes que ocorrem quando existe um aumento no tráfego de DNS ou quando o horário de funcionamento começa, experimente as seguintes soluções para otimizar o desempenho de 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 existirem recursos suficientes, considere aumentar a escala dos pods kube-dns.

  • Para melhorar o tempo médio de procura de DNS, ative a cache DNS NodeLocal.

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

    O exemplo seguinte é o ficheiro /etc/resolv.conf de um pod de aplicação:

    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 consultado. Se o pod fizer uma chamada de resolução de DNS para example.com, os seus registos serão semelhantes ao seguinte exemplo:

    "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 este problema, altere o valor de ndots para 1 para procurar apenas um ponto ou acrescente um ponto (.) no final do domínio que consulta ou usa. Por exemplo:

    dig example.com.
    

Problema: as consultas DNS falham intermitentemente a partir de alguns nós

Se notar que as consultas DNS falham intermitentemente em alguns nós, pode ver os seguintes sintomas:

  • Quando executa comandos dig para o endereço IP do serviço kube-dns ou o endereço IP do pod, as consultas DNS falham intermitentemente com tempos limite.
  • A execução de comandos dig a partir de um pod no mesmo nó que o pod kube-dns falha.

Para resolver este problema, conclua os seguintes passos:

  1. Faça um teste de conetividade. Defina o pod ou o nó problemático como a origem e o endereço IP do pod kube-dns como o destino. Isto permite-lhe verificar se tem as regras de firewall necessárias implementadas para permitir este tráfego.
  2. Se o teste não for bem-sucedido e o tráfego estiver a ser bloqueado por uma regra de firewall, use o Cloud Logging para listar as alterações manuais feitas às regras de firewall. Procure alterações que bloqueiem um tipo específico de tráfego:

    1. Na Trusted Cloud consola, aceda à página Explorador de registos.

      Aceda ao Explorador de registos

    2. No painel de consultas, introduza a seguinte consulta:

      logName="projects/project-name/logs/cloudaudit.googleapis.com/activity"
      resource.type="gce_firewall_rule"
      
    3. Clique em Executar consulta. Use o resultado da consulta para determinar se foram feitas alterações. Se detetar algum erro, corrija-o e volte a aplicar a regra da firewall.

      Certifique-se de que não faz alterações a nenhuma regra de firewall automatizada.

  3. Se não tiverem sido feitas alterações às regras de firewall, verifique a versão do conjunto de nós e certifique-se de que é compatível com o plano de controlo e outros conjuntos de nós em funcionamento. Se algum dos conjuntos de nós do cluster tiver mais de duas versões secundárias anteriores ao plano de controlo, isto pode estar a causar problemas. Para mais informações acerca desta incompatibilidade, consulte o artigo Versão do nó não compatível com a versão do plano de controlo.

  4. Para determinar se os pedidos estão a ser enviados para o IP de serviço kube-dns correto, capture o tráfego de rede no nó problemático e filtre por porta 53 (tráfego DNS). Capture o tráfego nos próprios pods kube-dns para ver se os pedidos estão a chegar aos pods pretendidos e se estão a ser resolvidos com êxito.

O que se segue?