
Há pouco tempo, lançamos o Kubernetes 1.9 na AWS usando o Kops. Ontem, enquanto lançava um novo tráfego sem problemas para o maior de nossos clusters Kubernetes, comecei a perceber erros incomuns de resolução de nomes DNS registrados pelo nosso aplicativo.
O GitHub falou sobre isso por um bom tempo, então eu também decidi descobrir. No final, percebi que, no nosso caso, isso se deve ao aumento da carga no kube-dns
e no dnsmasq
. O mais interessante e novo para mim foi o motivo de um aumento significativo no tráfego de consultas DNS. Sobre isso e o que fazer com isso, meu post.
A resolução do DNS dentro do contêiner - como em qualquer sistema Linux - é determinada pelo arquivo de configuração /etc/resolv.conf
. Por padrão, o Kubernetes dnsPolicy
é ClusterFirst
, o que significa que qualquer consulta DNS será redirecionada para o dnsmasq
em execução na kube-dns
dentro do cluster, que, por sua vez, redirecionará a consulta para o aplicativo kube-dns
se o nome terminar com um sufixo do cluster ou caso contrário, para um servidor DNS de nível superior.
O arquivo /etc/resolv.conf
dentro de cada container terá a seguinte aparência por padrão:
nameserver 100.64.0.10 search namespace.svc.cluster.local svc.cluster.local cluster.local eu-west-1.compute.internal options ndots:5
Como você pode ver, existem três diretivas:
- O servidor de nomes é o serviço IP do
kube-dns
- 4 domínios de pesquisa local especificados
- Há uma opção
ndots:5
Uma parte interessante dessa configuração é como os domínios e ndots:5
pesquisa local ndots:5
configurações se dão bem. Para entender isso, você precisa entender como a resolução DNS funciona para nomes parciais.
Qual é o nome completo?
Um nome totalmente qualificado é um nome para o qual nenhuma pesquisa local será realizada e o nome será considerado absoluto durante a resolução do nome. Por convenção, o software DNS considera um nome totalmente qualificado se terminar com um ponto (.). E não é totalmente definido de outra forma. Esse é o google.com.
totalmente definido, mas google.com
não.
Como é tratado um nome incompleto?
Quando um aplicativo se conecta ao host remoto especificado no nome, a resolução de nomes DNS geralmente é feita usando uma chamada do sistema, por exemplo, getaddrinfo()
. Mas se o nome estiver incompleto (não termina com.), Pergunto-me se a chamada do sistema tentará resolver o nome como absoluto primeiro ou se passará pelos domínios de pesquisa local primeiro? Depende da opção ndots
.
Do manual no resolv.conf
:
ndots:n , , . n 1, , - , , - .
Isso significa que, se ndots
estiver definido como 5 e o nome contiver menos de 5 pontos, a chamada do sistema tentará resolvê-lo sequencialmente, primeiro percorrendo todos os domínios de pesquisa local e, se malsucedido, acabará por resolvê-lo como um nome absoluto.
Por que os ndots:5
podem afetar adversamente o desempenho do aplicativo?
Como você entende, se o seu aplicativo usar muito tráfego externo, para cada conexão TCP estabelecida (ou, mais precisamente, para cada nome resolvido), ele emitirá 5 consultas DNS antes que o nome seja resolvido corretamente, pois passará por 4 primeiro domínio de pesquisa local e, no final, emitirá uma solicitação de resolução de nome absoluta.
O diagrama a seguir mostra o tráfego total em nossos 3 módulos kube-dns antes e depois da troca de vários nomes de host configurados em nosso aplicativo para nomes totalmente definidos.

O diagrama a seguir mostra o atraso do aplicativo antes e depois da troca de vários nomes de host configurados em nosso aplicativo (a linha azul vertical é a implantação):

Solução 1 - use nomes totalmente qualificados
Se você tiver poucos nomes externos estáticos (ou seja, definidos na configuração do aplicativo) aos quais você cria um grande número de conexões, talvez a solução mais simples seja trocá-los por nomes totalmente definidos, simplesmente adicionando-os. no final.
Esta não é uma decisão final, mas ajuda a melhorar rapidamente, embora não de forma limpa, a situação. Aplicamos esse patch para resolver nosso problema, cujos resultados foram mostrados nas capturas de tela acima.
Solução # 2 - personalizando ndots
no dnsConfig
No Kubernetes 1.9, um recurso apareceu no modo alfa (versão beta v1.10), que permite um melhor controle dos parâmetros DNS através da propriedade pod no dnsConfig
. Entre outras coisas, permite ajustar o valor de ndots
para uma lareira específica, ou seja,
apiVersion: v1 kind: Pod metadata: namespace: default name: dns-example spec: containers: - name: test image: nginx dnsConfig: options: - name: ndots value: "1"
Fontes
Leia também outros artigos em nosso blog: