Pesquisa DNS no Kubernetes

Nota do tradutor.: Problema de DNS no Kubernetes, mais especificamente - a configuração do parâmetro ndots, - surpreendentemente popular, e já não é a primeira ano. Em mais uma nota sobre o tema, seu autor - um engenheiro DevOps de uma grande corretora na Índia - explica de maneira bastante simples e concisa o que é importante saber para colegas que utilizam Kubernetes.

Pesquisa DNS no Kubernetes

Uma das principais vantagens de implantar aplicativos no Kubernetes - é a descoberta sem problemas de aplicativos. A interação intra-cluster é muito simplificada graças ao conceito de serviço (Service), que representa um IP virtual que suporta um conjunto de endereços IP de pods. Por exemplo, se um serviço vanilla quiser se conectar ao serviço chocolate, ele pode se direcionar diretamente para o IP virtual de chocolate. Surge a pergunta: quem nesse caso resolverá a consulta DNS para chocolate e como?

A resolução de nomes DNS é configurada no cluster Kubernetes através de CoreDNS. O Kubelet registra o pod com o CoreDNS como servidor de nomes nos arquivos /etc/resolv.conf de todos os pods. Se olharmos o conteúdo /etc/resolv.conf de qualquer pod, ele se parecerá aproximadamente com o seguinte:

search hello.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.152.183.10
options ndots:5

Essa configuração é usada pelos clientes DNS para redirecionar consultas ao servidor DNS. No arquivo resolv.conf está a seguinte informação:

  • nameserver: servidor para onde as consultas DNS serão direcionadas. No nosso caso, este é o endereço do serviço CoreDNS;
  • search: define o caminho de busca para um domínio específico. Curiosamente, google.com ou mrkaran.dev não são FQDN (nomes de domínio completos). De acordo com o padrão seguido pela maioria dos resolvers DNS, apenas os domínios que terminam com um ponto ".", representando a zona raiz, são considerados completos (FQDN). Alguns resolvers conseguem adicionar o ponto por conta própria. Assim, mrkaran.dev. - é um nome de domínio completo (FQDN), enquanto mrkaran.dev - não é;
  • ndots: O parâmetro mais interessante (este artigo trata exatamente dele). ndots define o número limite de pontos no nome da consulta; ao alcançá-lo, ele é considerado um nome de domínio "completo". Vamos discutir mais sobre isso mais adiante, quando analisarmos a sequência de pesquisa DNS.

Pesquisa DNS no Kubernetes

Vamos ver o que acontece quando solicitamos mrkaran.dev em um pod:

$ nslookup mrkaran.dev
Server: 10.152.183.10
Address: 10.152.183.10#53

Resposta não-autoritativa:
Name: mrkaran.dev
Address: 157.230.35.153
Name: mrkaran.dev
Address: 2400:6180:0:d1::519:6001

Para este experimento, configurei o nível de registro do CoreDNS para all (o que o torna bastante verboso). Vamos dar uma olhada nos logs do pod coredns:

[INFO] 10.1.28.1:35998 - 11131 "A IN mrkaran.dev.hello.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000263728s
[INFO] 10.1.28.1:34040 - 36853 "A IN mrkaran.dev.svc.cluster.local. udp 47 false 512" NXDOMAIN qr,aa,rd 140 0.000214201s
[INFO] 10.1.28.1:33468 - 29482 "A IN mrkaran.dev.cluster.local. udp 43 false 512" NXDOMAIN qr,aa,rd 136 0.000156107s
[INFO] 10.1.28.1:58471 - 45814 "A IN mrkaran.dev. udp 29 false 512" NOERROR qr,rd,ra 56 0.110263459s
[INFO] 10.1.28.1:54800 - 2463 "AAAA IN mrkaran.dev. udp 29 false 512" NOERROR qr,rd,ra 68 0.145091744s

Ufa. Duas coisas aqui chamam a atenção:

  • A consulta percorre todas as etapas de busca até que a resposta contenha o código NOERROR (os clientes DNS entendem isso e armazenam como resultado). NXDOMAIN significa que não foi encontrada nenhuma entrada para este nome de domínio. Como mrkaran.dev não é um nome FQDN (de acordo com ndots=5), o resolvedor observa o caminho de busca e determina a ordem das consultas;
  • As entradas A e AAAA são feitas em paralelo. A questão é que consultas únicas em /etc/resolv.conf por padrão estão configuradas para executar busca paralela em protocolos IPv4 e IPv6. O comportamento pode ser revertido adicionando a opção single-request em resolv.conf.

Nota: glibc pode ser configurado para enviar essas consultas de forma sequencial, enquanto musl não pode, então os usuários do Alpine devem estar cientes disso.

Experimentando com ndots

Vamos experimentar um pouco mais com ndots e ver como esse parâmetro se comporta. A ideia é simples: ndots determina se o cliente DNS considera o domínio absoluto ou relativo. Por exemplo, como no caso do simples google, como o cliente DNS descobre se este domínio é absoluto? Se definir ndots como 1, o cliente dirá: "Opa, em google não há nenhum ponto; talvez eu percorra toda a lista de busca." No entanto, se solicitar google.com, a lista de sufixos será completamente ignorada, uma vez que o nome solicitado atende ao limite ndots (tem pelo menos um ponto).

Vamos verificar isso:

$ cat /etc/resolv.conf
options ndots:1
$ nslookup mrkaran
Server: 10.152.183.10
Address: 10.152.183.10#53

** servidor não consegue encontrar mrkaran: NXDOMAIN

Logs do CoreDNS:

[INFO] 10.1.28.1:52495 - 2606 "A IN mrkaran.hello.svc.cluster.local. udp 49 false 512" NXDOMAIN qr,aa,rd 142 0.000524939s
[INFO] 10.1.28.1:59287 - 57522 "A IN mrkaran.svc.cluster.local. udp 43 false 512" NXDOMAIN qr,aa,rd 136 0.000368277s
[INFO] 10.1.28.1:53086 - 4863 "A IN mrkaran.cluster.local. udp 39 false 512" NXDOMAIN qr,aa,rd 132 0.000355344s
[INFO] 10.1.28.1:56863 - 41678 "A IN mrkaran. udp 25 false 512" NXDOMAIN qr,rd,ra 100 0.034629206s

Como em mrkaran não há nenhum ponto, a busca foi realizada em toda a lista de sufixos.

Nota: na prática, o valor máximo ndots limitado a 15; por padrão no Kubernetes é igual a 5.

Aplicação em produção

Se a aplicação faz muitas chamadas de rede externas, o DNS pode se tornar um gargalo em caso de tráfego intenso, pois muitas solicitações desnecessárias são feitas durante a resolução do nome (antes que o sistema chegue ao desejado). Normalmente, as aplicações não adicionam a zona raiz aos nomes de domínio, mas isso pode ser considerado uma solução alternativa. Ou seja, em vez de solicitar api.twitter.com, você pode 'hardcode' api.twitter.com. (com o ponto) na aplicação, o que fará com que os clientes DNS realizem uma busca autoritativa imediatamente no domínio absoluto.

Além disso, a partir da versão 1.14 do Kubernetes, as extensões dnsConfig e dnsPolicy receberam status de estáveis. Assim, ao implantar um pod, você pode reduzir o valor ndots, digamos, para 3 (e até mesmo para 1!). Como resultado, cada mensagem dentro do nó precisará incluir o domínio completo. Este é um dos compromissos clássicos ao escolher entre desempenho e portabilidade. Acho que vale a pena se preocupar com isso apenas se latências extremamente baixas forem vitais para sua aplicação, pois os resultados do DNS também são armazenados em cache internamente.

Links

Soube pela primeira vez sobre essa característica no K8s-meetup, que ocorreu em 25 de janeiro. A discussão incluiu também esse problema.

Aqui estão alguns links para estudos adicionais:

Nota: Prefiri não usar dig neste artigo. dig adiciona automaticamente um ponto (identificador da zona raiz), tornando o domínio 'completo' (FQDN), não passando-o previamente pela lista de busca. Falei sobre isso em uma das publicações anteriores. No entanto, é bastante surpreendente que, em geral, um sinalizador separado deva ser definido para o comportamento padrão.

Bom DNS! Até breve!

P.S. do tradutor

Confira também em nosso blog:

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster