Configurar NodeLocal DNSCache

En esta página, se explica cómo mejorar la latencia de búsqueda de DNS en un clúster de Google Kubernetes Engine (GKE) con NodeLocal DNSCache.

En el caso de los clústeres de Autopilot de GKE, NodeLocal DNSCache está habilitado de forma predeterminada y no se puede anular.

Arquitectura

NodeLocal DNSCache es un complemento de GKE que puedes ejecutar además de kube-dns.

GKE implementa NodeLocal DNSCache como un DaemonSet que ejecuta una caché de DNS en cada nodo de tu clúster.

Cuando un Pod realiza una solicitud de DNS, la solicitud va a la caché de DNS que se ejecuta en el mismo nodo que el Pod. Si la caché no puede resolver la solicitud de DNS, la caché reenvía la solicitud a uno de los siguientes lugares según el destino de la consulta:

  • kube-dns: todas las consultas para el dominio DNS del clúster (cluster.local) se reenvían a kube-dns. Los Pods node-local-dns usan el Service kube-dns-upstream para acceder a los Pods kube-dns. En el siguiente diagrama, la dirección IP del servicio de kube-dns es 10.0.0.10:53.
  • Dominios de stub personalizados o servidores de nombres ascendentes: las consultas se reenvían directamente desde los Pods de NodeLocal DNSCache.
  • Cloud DNS: todas las demás consultas se reenvían al servidor de metadatos local que se ejecuta en el mismo nodo que el pod desde el que se originó la consulta. El servidor de metadatos local accede a Cloud DNS.

La ruta de acceso de una solicitud de DNS, como se describe en el párrafo anterior

Beneficios de NodeLocal DNSCache

NodeLocal DNSCache proporciona los siguientes beneficios:

  • Tiempo de búsqueda de DNS promedio reducido
  • Las conexiones desde los pods a su caché local no crean entradas de tabla conntrack. Esto evita las conexiones caídas y rechazadas causadas por el agotamiento de la tabla de Conntrack y las condiciones de carrera.
  • Puedes usar NodeLocal DNSCache con Cloud DNS para GKE.
  • Las consultas de DNS para URL externas (URL que no hacen referencia a recursos de clúster) se reenvían directamente al servidor de metadatos local de Cloud DNS, sin pasar por kube-dns.
  • Las cachés de DNS locales recogen de forma automática los dominios de stub y los servidores de nombres ascendentes que se especifican en kube-dns ConfigMap.

Requisitos y limitaciones

  • NodeLocal DNSCache consume recursos de procesamiento en cada nodo de tu clúster.
  • NodeLocal DNSCache requiere GKE versión 1.15 o superior.
  • NodeLocal DNSCache accede a los pods kube-dns a través de TCP.
  • NodeLocal DNSCache accede a upstreamServers y stubDomains mediante TCP y UDP en las versiones 1.18 o posteriores de GKE. Se debe poder acceder al servidor DNS con TCP y UDP.
  • Los registros DNS se almacenan en caché durante los siguientes períodos:
    • El tiempo de actividad (TTL) del registro o 30 segundos si el TTL es más de 30 segundos.
    • 5 segundos si la respuesta de DNS es NXDOMAIN.
  • Los Pods de NodeLocal DNSCache escuchan en los puertos 53, 9253, 9353 y 8080 en los nodos. Si ejecutas cualquier otro Pod hostNetwork o configuras un hostPorts con esos puertos, NodeLocal DNSCache falla y se producen errores de DNS. Los Pods de NodeLocal DNSCache no usan el modo hostNetwork cuando se usan GKE Dataplane V2 y Cloud DNS para GKE.
  • La caché de DNS local solo se ejecuta en grupos de nodos que ejecutan la versión 1.15 de GKE y versiones posteriores. Si habilitas NodeLocal DNSCache en un clúster con nodos que ejecutan versiones anteriores, los Pods en esos nodos usan kube-dns.

Habilitar NodeLocal DNSCache

En el caso de los clústeres de Autopilot, NodeLocal DNSCache está habilitado de forma predeterminada y no se puede anular.

Verifica que NodeLocal DNSCache esté habilitado

Para verificar que NodeLocal DNSCache se esté ejecutando, enumera los pods node-local-dns.

kubectl get pods -n kube-system -o wide | grep node-local-dns

El resultado es similar al siguiente:

node-local-dns-869mt    1/1   Running   0   6m24s   10.128.0.35   gke-test-pool-69efb6b8-5d7m   <none>   <none>
node-local-dns-htx4w    1/1   Running   0   6m24s   10.128.0.36   gke-test-pool-69efb6b8-wssk   <none>   <none>
node-local-dns-v5njk    1/1   Running   0   6m24s   10.128.0.33   gke-test-pool-69efb6b8-bhz3   <none>   <none>

El resultado muestra un pod node-local-dns para cada nodo que ejecuta la versión 1.15 o posterior de GKE.

Soluciona problemas de NodeLocal DNSCache

Para obtener información general sobre el diagnóstico de problemas de DNS de Kubernetes, consulta Depuración de la resolución de DNS.

NodeLocal DNSCache con Cloud DNS

Si usas NodeLocal DNSCache con Cloud DNS, el clúster usa la dirección IP del servidor de nombres 169.254.20.10, como se muestra en el siguiente diagrama:

NodeLocal DNSCache con la arquitectura de Cloud DNS

Como resultado, la dirección IP del servicio kube-dns puede ser diferente de la dirección IP del servidor de nombres que usan tus Pods. Se espera esta diferencia en las direcciones IP, ya que la dirección IP del servidor de nombres 169.254.20.10 es necesaria para que Cloud DNS funcione correctamente.

Para verificar las direcciones IP, ejecuta los siguientes comandos:

  1. Consulta la dirección IP del servicio kube-dns:

    kubectl get svc -n kube-system kube-dns -o jsonpath="{.spec.clusterIP}"
    

    El resultado es la dirección IP de kube-dns, como 10.0.0.10:53.

  2. Abre una sesión de shell en tu Pod:

    kubectl exec -it POD_NAME -- /bin/bash
    
  3. En la sesión de shell del Pod, lee el contenido del archivo /etc/resolv.conf:

    cat /etc/resolv.conf
    

    El resultado es 169.254.20.10

Política de red con NodeLocal DNSCache

Si usas la política de red con NodeLocal DNSCache y no usas Cloud DNS ni GKE Dataplane V2, debes configurar reglas para permitir que tus cargas de trabajo y los Pods node-local-dns envíen consultas de DNS.

Usa una regla ipBlock en tu manifiesto para permitir la comunicación entre los Pods y kube-dns.

En el siguiente manifiesto, se describe una política de red que usa una regla ipBlock:

spec:
  egress:
  - ports:
    - port: 53
      protocol: TCP
    - port: 53
      protocol: UDP
    to:
    - ipBlock:
        cidr: KUBE_DNS_SVC_CLUSTER_IP/32
  podSelector: {}
  policyTypes:
    - Egress

Reemplaza KUBE_DNS_SVC_CLUSTER_IP por la dirección IP del servicio kube-dns. Puedes obtener la dirección IP del servicio kube-dns mediante el siguiente comando:

kubectl get svc -n kube-system kube-dns -o jsonpath="{.spec.clusterIP}"

Problemas conocidos

Tiempo de espera de DNS en ClusterFirstWithHostNet dnsPolicy cuando se usa NodeLocal DNSCache y GKE Dataplane V2

En los clústeres que usan GKE Dataplane V2 y NodeLocal DNSCache, los Pods con hostNetwork establecido en true y dnsPolicy configurados en ClusterFirstWithHostNet no pueden alcanzar los backends de DNS del clúster. Los registros DNS pueden contener entradas similares a las siguientes:

nslookup: write to 'a.b.c.d': Operation not permitted

;; connection timed out; no servers could be reached

El resultado indica que las solicitudes de DNS no pueden llegar a los servidores de backend.

Una solución alternativa es configurar los siguientes dnsPolicy y dnsConfig para los pods hostNetwork:

spec:
 dnsPolicy: "None"
 dnsConfig:
   nameservers:
     - KUBE_DNS_UPSTREAM
   searches:
     - cluster.local
     - svc.cluster.local
     - NAMESPACE.svc.cluster.local
     - c.PROJECT_ID.internal
     - google.internal
   options:
     - name: ndots
       value: "5"

Reemplaza lo siguiente:

  • NAMESPACE: Es el espacio de nombres del Pod hostNetwork.
  • PROJECT_ID: El ID del proyecto de Google Cloud.
  • KUBE_DNS_UPSTREAM: El ClusterIP del servicio ascendente de kube-dns. Puedes obtener este valor mediante el siguiente comando:

    kubectl get svc -n kube-system kube-dns-upstream -o jsonpath="{.spec.clusterIP}"
    

Las solicitudes de DNS del Pod ahora pueden llegar a kube-dns y omitir NodeLocal DNSCache.

Errores de tiempo de espera de NodeLocal DNSCache

En los clústeres con NodeLocal DNSCache habilitado, los registros pueden contener entradas similares a las siguientes:

[ERROR] plugin/errors: 2 <hostname> A: read tcp <node IP: port>-><kubedns IP>:53: i/o timeout

El resultado incluye la dirección IP del servicio de IP del clúster kube-dns-upstream. En este ejemplo, no se recibió la respuesta a una solicitud de DNS desde kube-dns en 2 segundos. Esto podría deberse a alguno de los siguientes motivos:

  • Un problema de conectividad de red subyacente.
  • Aumentos significativos de las consultas de DNS desde la carga de trabajo o debido al escalamiento vertical del grupo de nodos.

Como resultado, los Pods kube-dns existentes no pueden controlar todas las solicitudes a tiempo. La solución alternativa es aumentar la cantidad de réplicas de kube-dns mediante el ajuste de los parámetros del ajuste de escala automático.

Escala kube-dns

Puedes usar un valor menor para nodesPerReplica a fin de asegurarte de que se creen más pods de kube-dns a medida que se escalan los nodos del clúster. Recomendamos configurar un valor max explícito para garantizar que la máquina virtual (VM) del plano de control de GKE no se sobrecargue debido a una gran cantidad de pods de kube-dns que observan la API de Kubernetes.

Puedes configurar max en la cantidad de nodos del clúster. Si el clúster tiene más de 500 nodos, establece max en 500.

¿Qué sigue?