Acerca de kube-dns para GKE

Si ejecutas aplicaciones en clústeres Estándar, kube-dns es el proveedor de DNS predeterminado que te ayuda a habilitar el descubrimiento y la comunicación de servicios. En este documento, se describe cómo administrar DNS con kube-dns, incluida su arquitectura, configuración y prácticas recomendadas para optimizar la resolución de DNS en tu entorno de GKE.

Este documento está dirigido a desarrolladores, administradores y arquitectos responsables de administrar DNS en GKE. Para obtener contexto sobre los roles y las tareas comunes en Google Cloud, consulta Roles y tareas comunes del usuario de GKE y las tareas.

Antes de comenzar, asegúrate de estar familiarizado con los servicios deKubernetes y los conceptos generales de DNS.

Comprende la arquitectura de kube-dns

kube-dns opera dentro de tu clúster de GKE para habilitar la resolución de DNS entre Pods y servicios.

En el siguiente diagrama, se muestra cómo interactúan tus Pods con el servicio kube-dns:

Figura 1: Diagrama que muestra cómo los Pods envían consultas de DNS al servicio de "kube-dns", que está respaldado por Pods de "kube-dns". Los Pods de `kube-dns` controlan la resolución de DNS interna y reenvían las consultas externas a los servidores DNS ascendentes.

Componentes clave

kube-dns incluye los siguientes componentes clave:

  • Pods de kube-dns: Estos Pods ejecutan el software del servidor kube-dns. Varias réplicas de estos Pods se ejecutan en el espacio de nombres kube-system y proporcionan alta disponibilidad y redundancia.
  • Servicio kube-dns: En la siguiente tabla, se comparan los límites de escalabilidad y configuración de las versiones heredadas y basadas en CoreDNS de kube-dns:
    Función Heredado (kube-dns 1.35 y versiones anteriores) kube-dns en CoreDNS (1.36 y versiones posteriores)
    Conocimiento de extremos Conoce hasta 1,000 extremos por servicio. Si un servicio tiene más de 1,000 Pods, kube-dns no conoce los extremos adicionales. Conoce todos los extremos. Esta versión usa EndpointSlices para garantizar la exactitud y mejorar la eficiencia de los servicios grandes.
    Servidores de nombres ascendentes Limitado a 3 Admite hasta 15
    Conexiones TCP salientes simultáneas Limitado a 200 Admite hasta 1,500
  • kube-dns-autoscaler: Este Pod ajusta la cantidad de réplicas de kube-dns en función del tamaño del clúster, que incluye la cantidad de nodos y núcleos de CPU. Este enfoque ayuda a garantizar que kube-dns pueda controlar las cargas variables de consultas de DNS.

Resolución de DNS interna

Cuando un Pod necesita resolver un nombre de DNS dentro del dominio del clúster, como myservice.my-namespace.svc.cluster.local, se produce el siguiente proceso:

  1. Configuración de DNS del Pod: El kubelet de cada nodo configura el archivo /etc/resolv.conf del Pod. Este archivo usa el ClusterIP del servicio kube-dns como servidor de nombres.
  2. Consulta de DNS: El Pod envía una consulta de DNS al servicio kube-dns.
  3. Resolución de nombres:

    • GKE versión 1.36 o posterior: La implementación basada en CoreDNS usa EndpointSlices para que kube-dns conozca todos los Pods de un servicio. Esto mejora la exactitud y la eficiencia de los servicios a gran escala.
    • GKE versión 1.35 o anterior: kube-dns resuelve nombres en función de la API de Cloud Endpoints anterior, que está limitada a 1,000 extremos. Si un servicio tiene más de 1,000 Pods de respaldo, kube-dns no conoce los extremos adicionales.
  4. Comunicación: Luego, el Pod usa la dirección IP resuelta para comunicarse con el servicio de destino.

Resolución de DNS externa

Cuando un Pod necesita resolver un nombre de DNS externo o un nombre que está fuera del dominio del clúster, kube-dns actúa como un agente de resolución recursivo. Reenvía la consulta a los servidores DNS ascendentes que están configurados en su ConfigMap archivo. También puedes configurar agentes de resolución personalizados para dominios específicos, que también se conocen como dominios stub. Esta configuración indica a kube-dns que reenvíe las solicitudes de esos dominios a servidores DNS ascendentes específicos.

Configura el DNS del Pod

En GKE, el agente kubelet de cada nodo configura los parámetros de DNS para los Pods que se ejecutan en ese nodo.

Configura el archivo /etc/resolv.conf

Cuando GKE crea un Pod, el agente kubelet modifica el archivo /etc/resolv.conf del Pod. Este archivo configura el servidor DNS para la resolución de nombres y especifica los dominios de búsqueda. De forma predeterminada, kubelet configura el Pod para que use el servicio de DNS interno del clúster, kube-dns, como su servidor de nombres. También propaga los dominios de búsqueda en el archivo. Estos dominios de búsqueda te permiten usar nombres no calificados en las consultas de DNS. Por ejemplo, si un Pod consulta myservice, Kubernetes primero intenta resolver myservice.default.svc.cluster.local, luego myservice.svc.cluster.local y, luego, otros dominios de la lista search.

En el siguiente ejemplo, se muestra una configuración /etc/resolv.conf predeterminada:

nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local c.my-project-id.internal google.internal
options ndots:5

Este archivo tiene las siguientes entradas:

  • nameserver: Define el ClusterIP del servicio kube-dns.
  • search: Define los dominios de búsqueda que se agregan a los nombres no calificados durante las búsquedas de DNS.
  • options ndots:5: Establece el umbral para cuando GKE considera que un nombre está completamente calificado. Un nombre se considera completamente calificado si tiene cinco o más puntos.

Los Pods configurados con hostNetwork: true heredan su configuración de DNS del host y no consultan kube-dns directamente, a menos que usen la dnsPolicy ClusterFirstWithHostNet.

Personaliza kube-dns

kube-dns proporciona una resolución de DNS predeterminada sólida. Puedes adaptar su comportamiento para necesidades específicas, como mejorar la eficiencia de la resolución o usar agentes de resolución de DNS preferidos. Los dominios stub y los servidores de nombres ascendentes se configuran modificando el ConfigMap de kube-dns en el espacio de nombres kube-system.

Modifica el ConfigMap de kube-dns

Para modificar el ConfigMap de kube-dns, haz lo siguiente:

  1. Abre el ConfigMap para editar:

    kubectl edit configmap kube-dns -n kube-system
    
  2. En la sección data, agrega los campos stubDomains y upstreamNameservers de la siguiente manera:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      labels:
        addonmanager.kubernetes.io/mode: EnsureExists
      name: kube-dns
      namespace: kube-system
    data:
      stubDomains: |
        {
          "example.com": [
            "8.8.8.8",
            "8.8.4.4"
          ],
          "internal": [ # Required if your upstream nameservers can't resolve GKE internal domains
            "169.254.169.254" # IP of the metadata server
          ]
        }
      upstreamNameservers: |
        [
          "8.8.8.8", # Google Public DNS
          "8.8.4.4" # Google Public DNS Backup
        ]
    
  3. Guarda el ConfigMap. kube-dns vuelve a cargar la configuración de forma automática.

Dominios de stub

Los dominios stub te permiten definir agentes de resolución de DNS personalizados para dominios específicos. Cuando un Pod consulta un nombre dentro de ese dominio stub, kube-dns reenvía la consulta al agente de resolución especificado en lugar de usar su mecanismo de resolución predeterminado.

Incluye una sección stubDomains en el ConfigMap de kube-dns.

En esta sección, se especifican el dominio y los servidores de nombres ascendentes correspondientes. Luego, kube-dns reenvía las consultas de nombres dentro de ese dominio a los servidores designados. Por ejemplo, puedes enrutar todas las consultas de DNS para internal.mycompany.com a 192.168.0.10, agregar "internal.mycompany.com": ["192.168.0.10"] a stubDomains.

Cuando configuras un agente de resolución personalizado para un dominio stub, como example.com, kube-dns reenvía todas las solicitudes de resolución de nombres para ese dominio, incluidos los subdominios como *.example.com, a los servidores especificados.

Servidores de nombres ascendentes

Puedes configurar kube-dns para que use servidores de nombres ascendentes personalizados para resolver nombres de dominio externos. Esta configuración indica a kube-dns que reenvíe todas las solicitudes de DNS, excepto las solicitudes para el dominio interno del clúster (*.cluster.local), a los servidores ascendentes designados. Es posible que tus servidores ascendentes personalizados no puedan resolver dominios internos como metadata.internal y *.google.internal. Si habilitas Workload Identity Federation for GKE o tienes cargas de trabajo que dependen de estos dominios, agrega un dominio stub para internal en el ConfigMap. Usa 169.254.169.254, la dirección IP del servidor de metadatos, como el agente de resolución para este dominio stub.

Administra una Deployment personalizada de kube-dns

En un clúster Estándar, kube-dns se ejecuta como una Deployment. Una implementación personalizada de kube-dns significa que tú, como administrador del clúster, puedes controlar la Deployment y personalizarla según tus necesidades, en lugar de usar la implementación predeterminada que proporciona GKE.

Motivos para una implementación personalizada

Considera una implementación personalizada de kube-dns por los siguientes motivos:

  • Asignación de recursos: Ajusta los recursos de CPU y memoria para los Pods de kube-dns para optimizar el rendimiento en clústeres con tráfico de DNS alto.
  • Versión de la imagen: Usa una versión específica de la imagen de kube-dns o cambia a un proveedor de DNS alternativo como CoreDNS.
  • Configuración avanzada: Personaliza los niveles de registro, las políticas de seguridad y el comportamiento de almacenamiento en caché de DNS.

Ajuste de escala automático para implementaciones personalizadas

El kube-dns-autoscaler integrado funciona con la Deployment kube-dns predeterminada. Si creas una Deployment personalizada de kube-dns, el escalador automático integrado no la administra. Por lo tanto, debes configurar un escalador automático independiente que esté configurado específicamente para supervisar y ajustar el recuento de réplicas de tu Deployment personalizado. Este enfoque implica crear e implementar tu propia configuración de escalador automático en tu clúster.

Cuando administras una Deployment personalizada, eres responsable de todos sus componentes, como mantener actualizada la imagen del escalador automático. El uso de componentes desactualizados puede provocar una degradación del rendimiento o fallas de DNS.

Para obtener instrucciones detalladas sobre cómo configurar y administrar tu propia kube-dns implementación, consulta Configura una implementación personalizada de kube-dns Deployment.

Solucionar problemas

Para obtener información sobre la solución de problemas de kube-dns, consulta las siguientes páginas:

Optimiza la resolución de DNS

En esta sección, se describen los problemas comunes y las prácticas recomendadas para administrar DNS en GKE.

Límite de dominios de búsqueda dnsConfig de un Pod

Kubernetes limita la cantidad de dominios de búsqueda de DNS a 32. Si intentas definir más de 32 dominios de búsqueda en el dnsConfig de un Pod, el kube-apiserver no creará el Pod y mostrará un error similar al siguiente:

The Pod "dns-example" is invalid: spec.dnsConfig.searches: Invalid value: []string{"ns1.svc.cluster-domain.example", "my.dns.search.suffix1", "ns2.svc.cluster-domain.example", "my.dns.search.suffix2", "ns3.svc.cluster-domain.example", "my.dns.search.suffix3", "ns4.svc.cluster-domain.example", "my.dns.search.suffix4", "ns5.svc.cluster-domain.example", "my.dns.search.suffix5", "ns6.svc.cluster-domain.example", "my.dns.search.suffix6", "ns7.svc.cluster-domain.example", "my.dns.search.suffix7", "ns8.svc.cluster-domain.example", "my.dns.search.suffix8", "ns9.svc.cluster-domain.example", "my.dns.search.suffix9", "ns10.svc.cluster-domain.example", "my.dns.search.suffix10", "ns11.svc.cluster-domain.example", "my.dns.search.suffix11", "ns12.svc.cluster-domain.example", "my.dns.search.suffix12", "ns13.svc.cluster-domain.example", "my.dns.search.suffix13", "ns14.svc.cluster-domain.example", "my.dns.search.suffix14", "ns15.svc.cluster-domain.example", "my.dns.search.suffix15", "ns16.svc.cluster-domain.example", "my.dns.search.suffix16", "my.dns.search.suffix17"}: must not have more than 32 search paths.

El kube-apiserver muestra este mensaje de error en respuesta a un intento de creación de Pod. Para resolver este problema, quita las rutas de búsqueda adicionales de la configuración.

Límite de nameservers ascendentes para kube-dns

Las versiones heredadas de kube-dns (versión 1.35 y anteriores) limitan la cantidad de upstreamNameservers a tres. Si defines más de tres, Cloud Logging muestra un error similar al siguiente:

Invalid configuration: upstreamNameserver cannot have more than three entries (value was &TypeMeta{Kind:,APIVersion:,}), ignoring update

En este caso, kube-dns ignora la configuración de upstreamNameservers y continúa usando la configuración válida anterior. Para resolver este problema, quita los upstreamNameservers adicionales del ConfigMap de kube-dns.

Escala verticalmente kube-dns

En los clústeres Estándar, puedes usar un valor menor para nodesPerReplica de modo que se creen más Pods de kube-dns cuando los nodos del clúster se escalen verticalmente. Recomendamos configurar un valor explícito para el campo max para garantizar que la máquina virtual (VM) del plano de control de GKE no se sobrecargue debido a la gran cantidad de Pods de kube-dns que observan la API de Kubernetes.

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

Puedes modificar la cantidad de kube-dns réplicas editando el kube-dns-autoscaler ConfigMap.

kubectl edit configmap kube-dns-autoscaler --namespace=kube-system

El resultado es similar a este:

linear: '{"coresPerReplica":256, "nodesPerReplica":16,"preventSinglePointFailure":true}'

La cantidad de réplicas de kube-dns se calcula con la siguiente fórmula:

replicas = max( ceil( cores * 1/coresPerReplica ) , ceil( nodes * 1/nodesPerReplica ) )

Para escalar verticalmente, cambia el valor del campo nodesPerReplica a un valor más pequeño y, luego, incluye un valor para el campo max.

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"preventSinglePointFailure":true}'

Con esta configuración se crea 1 pod kube-dns por cada 8 nodos en el clúster. Un clúster de 24 nodos tiene 3 réplicas y un clúster de 40 nodos tiene 5 réplicas. Si el clúster supera los 120 nodos, la cantidad de réplicas de kube-dns no aumenta más allá de 15, el valor del campo max.

Para garantizar un nivel de modelo de referencia de la disponibilidad de DNS en el clúster, establece un recuento mínimo de réplicas para el campo kube-dns.

El resultado del ConfigMap de kube-dns-autoscaler con el campo min configurado es similar al siguiente:

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"min": 5,"preventSinglePointFailure":true}'

Mejora los tiempos de búsqueda de DNS

Varios factores pueden causar una latencia alta con las búsquedas de DNS o fallas de resolución de DNS con el proveedor de kube-dns predeterminado. Las aplicaciones pueden experimentar estos problemas como errores getaddrinfo EAI_AGAIN, que indican una falla temporal en la resolución de nombres. Los siguientes son algunos de los motivos:

  • Búsquedas de DNS frecuentes en tu carga de trabajo
  • Alta densidad de Pods por nodo
  • Ejecución de kube-dns en VMs Spot o VMs interrumpibles, lo que puede provocar eliminaciones inesperadas de nodos
  • Límites de conexión: Las versiones heredadas de kube-dns (GKE versión 1.35 y anteriores) están limitadas a 200 conexiones TCP simultáneas. kube-dns en CoreDNS (GKE versión 1.36 y posteriores) quita estos límites fijos para las conexiones entrantes y proporciona una capacidad significativamente mayor para las conexiones salientes.

Para mejorar los tiempos de búsqueda de DNS, haz lo siguiente:

  • Evita ejecutar componentes críticos del sistema, como kube-dns en VMs Spot o VMs interrumpibles. Crea al menos un grupo de nodos que tenga VMs estándar y que no tenga VMs Spot ni VMs interrumpibles. Usa taints y tolerancias para garantizar que las cargas de trabajo críticas se programen en estos nodos confiables.
  • Habilita NodeLocal DNSCache. NodeLocal DNSCache almacena en caché las respuestas de DNS directamente en cada nodo, lo que reduce la latencia y la carga en el servicio kube-dns. Si habilitas NodeLocal DNSCache y usas políticas de red con reglas de denegación predeterminadas, agrega una política para permitir que las cargas de trabajo envíen consultas de DNS a los Pods node-local-dns.
  • Escala verticalmente kube-dns.
  • Asegúrate de que tu aplicación use funciones basadas en dns.resolve* en lugar de funciones basadas en dns.lookup, ya que dns.lookup es síncrono.
  • Usa nombres de dominio completamente calificados (FQDN), por ejemplo, https://google.com./ en lugar de https://google.com/.

Las fallas de resolución de DNS pueden ocurrir durante las actualizaciones del clúster de GKE debido a las actualizaciones simultáneas de los componentes del plano de control, incluido kube-dns. Por lo general, estas fallas afectan a un pequeño porcentaje de nodos. Prueba de forma exhaustiva las actualizaciones del clúster en un entorno que no sea de producción antes de aplicarlas a los clústeres de producción.

Garantiza la visibilidad del servicio

kube-dns solo crea registros DNS para los servicios que tienen extremos. Si un servicio no tiene extremos, kube-dns no crea registros DNS para ese servicio.

Administra las discrepancias de TTL de DNS

Si kube-dns recibe una respuesta de DNS de un agente de resolución de DNS ascendente con un TTL grande o infinito, conserva este valor de TTL. Este comportamiento puede crear una discrepancia entre la entrada almacenada en caché y la dirección IP real.

GKE resuelve este problema en versiones específicas del plano de control, como 1.21.14-gke.9100 y posteriores o 1.22.15-gke.2100 y posteriores. Estas versiones establecen un valor de TTL máximo en 30 segundos para cualquier respuesta de DNS que tenga un TTL superior. Este comportamiento es similar a NodeLocal DNSCache.

Visualiza las métricas de kube-dns

Puedes recuperar métricas sobre las consultas de DNS directamente desde los Pods de kube-dns. La forma en que recuperas estas métricas depende de tu versión de GKE.

GKE versión 1.36 y posteriores

Si tu clúster ejecuta la versión 1.36 o posterior de GKE (kube-dns en CoreDNS), puedes supervisar el rendimiento de DNS con paneles predefinidos en Cloud Monitoring o recuperar métricas de forma manual desde los Pods.

Visualiza métricas en la Google Cloud consola

  1. En la Google Cloud consola de, ve a la página Paneles.
  2. Selecciona el panel GKE DNS Observability - Cluster View.

Como alternativa, puedes consultar estas métricas directamente en la Google Cloud consola de si vas a Monitoring > Explorador de métricas y buscas los nombres de métricas específicos.

Recupera métricas de forma manual

Para recuperar métricas del Pod de forma manual, haz lo siguiente:

  1. Busca los Pods de kube-dns.

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    
  2. Redirecciona el puerto 9153 a uno de los Pods.

    kubectl port-forward pod/POD_NAME -n kube-system 9153:9153
    

    Reemplaza POD_NAME por el nombre de uno de los Pods de kube-dns del resultado anterior.

  3. Accede a las métricas.

    curl http://127.0.0.1:9153/metrics
    

GKE versión 1.35 y anteriores

Esta versión de kube-dns usa Pods de varios contenedores. Para recuperar métricas, haz lo siguiente:

  1. Busca los Pods de kube-dns en el espacio de nombres kube-system.

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    
  2. Redirecciona a los puertos 10055 (para el contenedor kube-dns) y 10054 (para el contenedor dnsmasq):

    #For the kube-dns container
    kubectl port-forward pod/POD_NAME -n kube-system 10055:10055
    #For the dnsmasq container
    kubectl port-forward pod/POD_NAME -n kube-system 10054:10054
    

    Reemplaza POD_NAME por el nombre de uno de los Pods de kube-dns del resultado anterior. Ejecuta estos comandos de redireccionamiento de puertos en sesiones de terminal independientes.

  3. Accede a las métricas.

    #Metrics from the kube-dns container
    curl http://127.0.0.1:10055/metrics
    
    #Metrics from the dnsmasq container
    curl http://127.0.0.1:10054/metrics
    

¿Qué sigue?