Usar kube-dns

En esta página se describe cómo implementa Google Kubernetes Engine (GKE) el descubrimiento de servicios mediante kube-dns, el proveedor de DNS predeterminado de los clústeres de GKE.

En los clústeres de Autopilot, no puedes modificar la configuración predeterminada de kube-dns.

Arquitectura

Cuando creas un clúster, GKE despliega automáticamente pods de kube-dns en el espacio de nombres kube-system. Los pods acceden al despliegue de kube-dns a través de un servicio correspondiente que agrupa los pods de kube-dns y les asigna una única dirección IP (ClusterIP). De forma predeterminada, todos los pods de un clúster usan este servicio para resolver consultas de DNS. En el siguiente diagrama se muestra la relación entre los pods y el servicio kube-dns.

Relación de los pods de kube-dns con el servicio kube-dns.

kube-dns se escala para satisfacer las demandas de DNS del clúster. Este escalado lo controla kube-dns-autoscaler, un pod que se despliega de forma predeterminada en todos los clústeres de GKE. kube-dns-autoscaler ajusta el número de réplicas de la implementación de kube-dns en función del número de nodos y núcleos del clúster.

kube-dns admite hasta 1000 endpoints por servicio sin encabezado.

Cómo se configura el DNS de los pods

El kubelet que se ejecuta en cada nodo configura el etc/resolv.conf del pod para usar la ClusterIP del servicio kube-dns. En el siguiente ejemplo de configuración se muestra que la dirección IP del servicio kube-dns es 10.0.0.10. Esta dirección IP es diferente en otros clústeres.

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

kube-dns es el servidor de nombres acreditado del dominio del clúster (cluster.local) y resuelve nombres externos de forma recursiva. Los nombres cortos que no estén totalmente cualificados, como myservice, se completan primero con rutas de búsqueda locales.

Añadir resoluciones personalizadas para dominios stub

Puedes modificar el ConfigMap de kube-dns para definir dominios stub como parte de la infraestructura de DNS de tus clústeres.

Los dominios stub te permiten configurar resoluciones personalizadas por dominio para que kube-dns reenvíe las solicitudes de DNS a servidores de DNS upstream específicos al resolver estos dominios.

El siguiente ejemplo de manifiesto de ConfigMap para kube-dns incluye una stubDomains configuración que define resoluciones personalizadas para el dominio example.com.

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",
        "1.1.1.1",
        "1.0.0.1"
      ]
    }

Ejecuta el siguiente comando para abrir un editor de texto:

kubectl edit configmap kube-dns -n kube-system

Sustituye el contenido del archivo por el manifiesto y, a continuación, cierra el editor de texto para aplicar el manifiesto al clúster.

Servidores de nombres upstream

Si modificas el ConfigMap de kube-dns para incluir upstreamNameservers, kube-dns reenviará todas las solicitudes DNS, excepto *.cluster.local, a esos servidores. Esto incluye metadata.internal y *.google.internal, que no se pueden resolver en el servidor upstream.

Si habilitas Workload Identity Federation para GKE o cualquier carga de trabajo que dependa de la resolución de metadata.internal, para conservar la resolución de nombres de *.internal, añade un stubDomain al ConfigMap.

data:
  stubDomains: |
    {
      "internal": [
        "169.254.169.254"
      ]
    }
  upstreamNameservers: |
    ["8.8.8.8"]

Solución de problemas

Para obtener información sobre cómo solucionar problemas de kube-dns, consulta las siguientes páginas:

Limitaciones

Consulta las siguientes secciones para obtener información sobre las limitaciones de kube-dns.

Límite de búsqueda de dominio

Hay un límite de 32 dominios de búsqueda de DNS para /etc/resolv.conf. Si defines más de 32 dominios de búsqueda, no se podrá crear el pod y se mostrará el siguiente error:

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.

Este mensaje de error lo devuelve kube-apiserver en respuesta a un intento de creación de un pod.

Para solucionar este problema, quite las rutas de búsqueda adicionales de la configuración.

Ten en cuenta el límite de upstreamNameservers

Kubernetes impone un límite de hasta tres valores upstreamNameservers. Si defines más de tres upstreamNameservers, verás el siguiente error en Cloud Logging en los registros de implementación de kube-dns:

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

Cuando esto ocurre, kube-dns se comporta como si no tuviera ningún upstreamNameservers configurado. Para solucionar este problema, quite el upstreamNameservers adicional de la configuración.

Limitaciones de rendimiento con kube-dns

Si experimentas una latencia alta con las búsquedas de DNS o errores de resolución de DNS con el proveedor kube-dns predeterminado, puede deberse a lo siguiente:

  • Realizar peticiones de DNS frecuentes en tu carga de trabajo
  • Implementar una densidad de pods por nodo más alta.
  • Superar el límite de 20 consultas por segundo (CPS) de cada pod kube-dns.
  • Ejecutar kube-dns en máquinas virtuales de acceso puntual o interrumpibles, lo que puede provocar eliminaciones de nodos inesperadas y problemas de resolución de DNS posteriores.

Para mejorar los tiempos de búsqueda de DNS, puedes elegir una de las siguientes opciones:

  • Evita ejecutar componentes críticos del sistema, como kube-dns, en Spot VMs o máquinas virtuales interrumpibles. Si usas máquinas virtuales de acceso puntual o interrumpibles para el DNS, pueden producirse fallos y tu clúster puede dejar de funcionar.
  • Como práctica recomendada, crea al menos un grupo de nodos compuesto por VMs estándar (no Spot ni interrumpibles) para alojar componentes críticos del sistema, como kube-dns. Para asegurarte de que las cargas de trabajo críticas solo se programen en el grupo de nodos fiable y evitar que se ejecuten en máquinas virtuales de acceso puntual o interrumpibles, puedes usar marcas y tolerancias para máquinas virtuales de acceso puntual.
  • Habilita NodeLocal DNSCache.
  • Aumenta la escala de 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íncrona. Las funciones dns.resolve* siempre realizan una consulta DNS asíncrona en la red.

Registros DNS de servicio

kube-dns solo crea registros DNS para los servicios que tienen Endpoints.

TTL grande de los servidores upstream de DNS

Si kube-dns recibe una respuesta DNS de un resolvedor DNS upstream con un TTL grande o "infinito", mantiene este valor de TTL para la entrada DNS en la caché. La entrada nunca caduca y podría crear una discrepancia entre la entrada y la dirección IP real resuelta para el nombre TTL.

GKE resuelve este problema en las siguientes versiones del plano de control. Para ello, asigna un valor TTL máximo de 30 segundos a cualquier respuesta DNS que tenga un TTL superior a 30 segundos:

  • 1.21.14-gke.9100
  • 1.22.15-gke.2100
  • 1.23.13-gke.500
  • 1.24.7-gke.500
  • 1.25.2-gke.500 o posterior

Este comportamiento es similar a NodeLocal DNSCache.

Registrar métricas de kube-dns o dnsmasq

Puede obtener métricas sobre las consultas de DNS en el clúster de GKE. Es una forma rápida de obtener métricas de kube-dns o dnsmasq sin modificar la implementación.

  1. Lista los pods del despliegue de kube-dns.

    $ kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    

    La salida será similar a la siguiente:

    NAME                        READY     STATUS    RESTARTS   AGE
    kube-dns-548976df6c-98fkd   4/4       Running   0          48m
    kube-dns-548976df6c-x4xsh   4/4       Running   0          47m
    
  2. Elige un Pod y asigna su nombre a una variable.

    POD="kube-dns-548976df6c-98fkd"
    
  3. Configura la redirección de puertos para el pod de kube-dns elegido.

    $ kubectl port-forward pod/${POD} -n kube-system 10054:10054 10055:10055
    

    La salida será similar a la siguiente:

    Forwarding from 127.0.0.1:10054 -> 10054
    Forwarding from 127.0.0.1:10055 -> 10055
    
  4. Para obtener las métricas, ejecuta el siguiente comando curl en el endpoint.

    $ curl http://127.0.0.1:10054/metrics; curl http://127.0.0.1:10055/metrics

    El puerto 10054 contiene métricas de dnsmasq y el puerto 10055 contiene métricas de kube-dns.

    La salida será similar a la siguiente:

    kubedns_dnsmasq_errors 0
    kubedns_dnsmasq_evictions 0
    kubedns_dnsmasq_hits 3.67351e+06
    kubedns_dnsmasq_insertions 254114
    kubedns_dnsmasq_max_size 1000
    kubedns_dnsmasq_misses 3.278166e+06
    
    

Siguientes pasos