Búsqueda DNS en Kubernetes

Nota de traducción.: El problema de DNS en Kubernetes, específicamente en la configuración de parámetros ndots, es sorprendentemente popular, y ya no es la primera año. En una nueva nota sobre este tema, su autor—un ingeniero DevOps de una gran empresa de corretaje en la India—explica de manera bastante sencilla y concisa lo que es útil saber para los colegas que utilizan Kubernetes.

Búsqueda DNS en Kubernetes

Una de las principales ventajas de desplegar aplicaciones en Kubernetes es el descubrimiento sin problemas de las aplicaciones. La interacción dentro del clúster se simplifica considerablemente gracias al concepto de servicio (Servicio), que representa una IP virtual que soporta un conjunto de direcciones IP de pods. Por ejemplo, si el servicio vanilla desea comunicarse con el servicio chocolate, puede dirigirse directamente a la IP virtual de chocolate. Surge la pregunta: ¿quién resolverá la consulta DNS para chocolate y cómo?

La resolución de nombres DNS se configura en el clúster de Kubernetes a través de CoreDNS. Kubelet registra el pod con CoreDNS como servidor de nombres en los archivos /etc/resolv.conf de todos los pods. Si observamos el contenido de /etc/resolv.conf cualquier pod, se verá aproximadamente de la siguiente manera:

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

Esta configuración es utilizada por los clientes DNS para redirigir las consultas al servidor DNS. En el archivo resolv.conf se encuentra la siguiente información:

  • nameserver: el servidor al que se dirigirán las consultas DNS. En nuestro caso, es la dirección del servicio CoreDNS;
  • search: define el camino para buscar un dominio específico. Curiosamente, google.com o mrkaran.dev no es un FQDN (nombre de dominio completo). Según el estándar seguido por la mayoría de los resolutores DNS, los dominios completos (FDQN) son solo aquellos que terminan con un punto «.», que representa la zona raíz. Algunos resolutores pueden agregar el punto por su cuenta. Así, mrkaran.dev. es un nombre de dominio completo (FQDN), mientras que mrkaran.dev no lo es;
  • ndots: el parámetro más interesante (de eso trata este artículo). ndots establece el número umbral de puntos en el nombre de la consulta, al alcanzar el cual se considera como un nombre de dominio "completo". Hablaremos más de esto más adelante, cuando analicemos la secuencia de búsqueda DNS.

Búsqueda DNS en Kubernetes

Veamos qué sucede cuando solicitamos mrkaran.dev en el pod:

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

Non-authoritative answer:
Name: mrkaran.dev
Address: 157.230.35.153
Name: mrkaran.dev
Address: 2400:6180:0:d1::519:6001

Para este experimento, configuré el nivel de registro de CoreDNS en todo (lo que lo hace bastante prolijo). Vamos a ver los logs del 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

Uf. Dos cosas aquí llaman la atención:

  • La solicitud avanza a través de todas las etapas de búsqueda hasta que la respuesta no contiene el código NOERROR (los clientes DNS lo entienden y lo almacenan como resultado). NXDOMAIN significa que no se encontró un registro para este nombre de dominio. Dado que mrkaran.dev no es un nombre FQDN (de acuerdo con ndots=5), el resolver consulta la ruta de búsqueda y determina el orden de las solicitudes;
  • Los registros A y AAAA se envían en paralelo. El hecho es que las solicitudes únicas en /etc/resolv.conf están configuradas por defecto para realizar búsquedas en paralelo sobre protocolos IPv4 e IPv6. Se puede desactivar este comportamiento agregando la opción single-request en resolv.conf.

Nota: glibc puede configurarse para enviar estas solicitudes de manera secuencial, y musl no, así que los usuarios de Alpine deben tener esto en cuenta.

Experimentando con ndots

Vamos a experimentar un poco más con ndots y veamos cómo se comporta este parámetro. La idea es simple: ndots determina si el cliente DNS considera el dominio absoluto o relativo. Por ejemplo, como en el caso de un simple google, ¿cómo sabe el cliente DNS si este dominio es absoluto? Si se establece ndots en 1, el cliente dirá: "Oh, en google no hay ningún punto; mejor reviso toda la lista de búsqueda". Sin embargo, si se solicita google.com, la lista de sufijos será completamente ignorada, ya que el nombre solicitado cumple con el umbral ndots (hay al menos un punto).

Asegurémonos de esto:

$ cat /etc/resolv.conf
options ndots:1
$ nslookup mrkaran
Servidor: 10.152.183.10
Dirección: 10.152.183.10#53

** el servidor no puede encontrar mrkaran: NXDOMAIN

Registros de 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

Dado que no se pueden definir pistas de tabla en mrkaran no hay ningún punto, se buscó en toda la lista de sufijos.

Nota: en la práctica, el valor máximo ndots está limitado a 15; por defecto en Kubernetes es 5.

Uso en producción

Si una aplicación realiza muchas llamadas de red externas, el DNS puede convertirse en un cuello de botella en caso de tráfico activo, ya que se realizan muchas consultas innecesarias al resolver un nombre (antes de que el sistema llegue al correcto). Las aplicaciones generalmente no añaden la zona raíz a los nombres de dominio, sin embargo, esto podría considerarse un hack. Es decir, en lugar de solicitar api.twitter.com, puedes 'hardcodear' api.twitter.com. (con un punto) en la aplicación, lo que hará que los clientes DNS realicen una búsqueda autoritativa de inmediato en el dominio absoluto.

Además, a partir de la versión 1.14 de Kubernetes, las extensiones dnsConfig y dnsPolicy han obtenido estado estable. Por lo tanto, al desplegar un pod, se puede reducir el valor ndots, digamos, a 3 (¡e incluso a 1!). Debido a esto, cada mensaje dentro del nodo deberá incluir el dominio completo. Este es uno de los clásicos compromisos entre rendimiento y portabilidad. Me parece que solo vale la pena preocuparse por esto si las latencias extremadamente bajas son vitales para tu aplicación, dado que los resultados de DNS también se almacenan en caché internamente.

Enlaces

Descubrí esta característica por primera vez en el K8s-meetup, que tuvo lugar el 25 de enero. Allí se discutió, entre otras cosas, este problema.

Aquí hay algunos enlaces para un estudio más profundo:

Nota: Preferí no usar dig en este artículo. dig agrega automáticamente un punto (identificador de la zona raíz), convirtiendo el dominio en 'completo' (FQDN), no paseándolo previamente por la lista de búsqueda. Escribí sobre esto en una de las publicaciones anteriores. Sin embargo, es bastante sorprendente que, en general, el comportamiento estándar requiera establecer una bandera separada.

¡Buena gestión de DNS! ¡Hasta pronto!

P.D. del traductor

También puedes leer en nuestro blog:

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster