Solucionar problemas de kube-dns en GKE


Si usas kube-dns para el descubrimiento de servicios, es posible que se produzcan errores de conexión, como dial tcp: i/o timeout o no such host. Estos errores suelen indicar que hay problemas con los pods de kube-dns en el espacio de nombres kube-system, como configuraciones incorrectas, limitaciones de recursos o problemas de conectividad de red que afectan a estos pods.

Usa esta página para diagnosticar y resolver problemas habituales específicos de la implementación de kube-dns, lo que te ayudará a asegurar una resolución de DNS fiable para tus cargas de trabajo.

Esta información es importante para los administradores y operadores de la plataforma, que son responsables de mantener los componentes principales del clúster, como kube-dns, y para los desarrolladores de aplicaciones, cuyas aplicaciones dependen de él para conectarse con otros servicios del clúster. Para obtener más información sobre los roles habituales y las tareas de ejemplo a las que hacemos referencia en el contenido, consulta Roles y tareas habituales de los usuarios de GKE. Google Cloud

Identificar la fuente de los problemas de DNS en kube-dns

En las siguientes secciones se explica cómo diagnosticar por qué kube-dns tiene problemas para resolver consultas.

Comprobar si los pods de kube-dns se están ejecutando

Los pods de Kube-DNS son fundamentales para la resolución de nombres en el clúster. Si no se están ejecutando, es probable que tengas problemas con la resolución de DNS.

Para verificar que los pods de kube-dns se están ejecutando sin reinicios recientes, consulta el estado de estos pods:

kubectl get pods -l k8s-app=kube-dns -n kube-system

El resultado debería ser similar al siguiente:

NAME                   READY          STATUS          RESTARTS       AGE
kube-dns-POD_ID_1      5/5            Running         0              16d
kube-dns-POD_ID_2      0/5            Terminating     0              16d

En este resultado, POD_ID_1 y POD_ID_2 representan identificadores únicos que se añaden automáticamente a los pods de kube-dns.

Si el resultado muestra que alguno de tus pods kube-dns no tiene el estado Running, sigue estos pasos:

  1. Usa los registros de auditoría de actividad del administrador para investigar si se han producido cambios recientes, como actualizaciones de la versión del clúster o del grupo de nodos, o cambios en el ConfigMap de kube-dns. Para obtener más información sobre los registros de auditoría, consulta el artículo Registros de auditoría de GKE. Si detectas cambios, revierte los cambios y vuelve a consultar el estado de los pods.

  2. Si no encuentras ningún cambio reciente relevante, investiga si se produce un error de falta de memoria en el nodo en el que se ejecuta el pod kube-dns. Si ves un error similar al siguiente en los mensajes de registro de Cloud Logging, significa que estos pods están experimentando un error de falta de memoria:

    Warning: OOMKilling Memory cgroup out of memory
    

    Este mensaje indica que Kubernetes ha terminado un proceso debido a un consumo excesivo de recursos. Kubernetes programa los pods en función de las solicitudes de recursos, pero permite que los pods consuman hasta sus límites de recursos. Si los límites son superiores a las solicitudes o no hay límites, el uso de recursos del pod puede superar los recursos del sistema.

    Para resolver este error, puedes eliminar las cargas de trabajo problemáticas o definir límites de memoria o CPU. Para obtener más información sobre cómo definir límites, consulta el artículo Gestión de recursos para pods y contenedores de la documentación de Kubernetes. Para obtener más información sobre los eventos de falta de memoria, consulta Solucionar problemas de eventos de falta de memoria.

  3. Si no encuentras ningún mensaje de error de falta de memoria, reinicia el despliegue de kube-dns:

    kubectl rollout restart deployment/kube-dns --namespace=kube-system
    

    Después de reiniciar la implementación, comprueba si tus pods kube-dns están en ejecución.

Si estos pasos no funcionan o todos tus pods kube-dns tienen el estado Running, pero sigues teniendo problemas con el DNS, comprueba que el archivo /etc/resolv.conf esté configurado correctamente.

Comprueba que /etc/resolv.conf esté configurado correctamente

Revisa el archivo /etc/resolv.conf de los pods que tienen problemas con el DNS y asegúrate de que las entradas que contiene sean correctas:

  1. Consulta el archivo /etc/resolv.conf del pod:

    kubectl exec -it POD_NAME -- cat /etc/resolv.conf
    

    Sustituye POD_NAME por el nombre del pod que tiene problemas con el DNS. Si hay varios pods que tienen problemas, repite los pasos de esta sección con cada uno de ellos.

    Si el archivo binario del pod no admite el comando kubectl exec, es posible que este comando falle. Si esto ocurre, crea un Pod sencillo para usarlo como entorno de prueba. Este procedimiento te permite ejecutar un pod de prueba en el mismo espacio de nombres que el pod problemático.

  2. Comprueba que la dirección IP del servidor de nombres del archivo /etc/resolv.conf sea correcta:

    • Los pods que usen una red de host deben usar los valores del archivo /etc/resolv.conf del nodo. La dirección IP del servidor de nombres debe ser 169.254.169.254.
    • En el caso de los pods que no usan una red de host, la dirección IP del servicio kube-dns debe ser la misma que la dirección IP del servidor de nombres. Para comparar las direcciones IP, sigue estos pasos:

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

        kubectl get svc kube-dns -n kube-system
        

        El resultado debería ser similar al siguiente:

        NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
        kube-dns   ClusterIP   192.0.2.10   <none>        53/UDP,53/TCP   64d
        
      2. Anota el valor de la columna IP de clúster. En este ejemplo, es 192.0.2.10.

      3. Compara la dirección IP del servicio kube-dns con la dirección IP del archivo /etc/resolv.conf:

        # cat /etc/resolv.conf
        
        search default.svc.cluster.local svc.cluster.local cluster.local c.PROJECT_NAME google.internal
        nameserver 192.0.2.10
        options ndots:5
        

        En este ejemplo, los dos valores coinciden, por lo que una dirección IP de servidor de nombres incorrecta no es la causa del problema.

        Sin embargo, si las direcciones IP no coinciden, significa que el campo dnsConfig se ha configurado en el manifiesto del pod de la aplicación.

        Si el valor del campo dnsConfig.nameservers es correcto, investiga tu servidor DNS y asegúrate de que funciona correctamente.

        Si no quieres usar el servidor de nombres personalizado, elimina el campo y realiza un reinicio gradual del pod:

        kubectl rollout restart deployment POD_NAME
        

        Sustituye POD_NAME por el nombre de tu pod.

  3. Verifica las entradas de search y ndots en /etc/resolv.conf. Asegúrate de que no haya errores ortográficos ni configuraciones obsoletas y de que la solicitud fallida apunte a un servicio que exista en el espacio de nombres correcto.

Realizar una petición de DNS

Una vez que hayas confirmado que /etc/resolv.conf está configurado correctamente y que el registro DNS es correcto, usa la herramienta de línea de comandos dig para realizar búsquedas de DNS desde el pod que informa de errores de DNS:

  1. Consulta directamente un pod abriendo un shell en él:

    kubectl exec -it POD_NAME -n NAMESPACE_NAME -- SHELL_NAME
    

    Haz los cambios siguientes:

    • POD_NAME: nombre del pod que informa de errores de DNS.
    • NAMESPACE_NAME: el espacio de nombres al que pertenece el pod.
    • SHELL_NAME: el nombre del shell que quieras abrir. Por ejemplo, sh o /bin/bash.

    Es posible que este comando falle si tu pod no permite el comando kubectl exec o si el pod no tiene el archivo binario dig. Si esto ocurre, crea un Pod de prueba con una imagen que tenga instalado dig:

    kubectl run "test-$RANDOM" ti --restart=Never --image=thockin/dnsutils - bash
    
  2. Comprueba si el pod puede resolver correctamente el servicio DNS interno del clúster:

    dig kubernetes
    

    Como el archivo /etc/resolv.conf apunta a la dirección IP del servicio kube-dns, cuando ejecutas este comando, el servidor DNS es el servicio kube-dns.

    Deberías ver una respuesta DNS correcta con la dirección IP del servicio de la API de Kubernetes (a menudo, algo parecido a 10.96.0.1). Si ves SERVFAIL o no recibes ninguna respuesta, suele significar que el pod kube-dns no puede resolver los nombres de servicio internos.

  3. Comprueba si el servicio kube-dns puede resolver un nombre de dominio externo:

    dig example.com
    
  4. Si tienes problemas con un pod de kube-dns concreto que responde a consultas de DNS, comprueba si ese pod puede resolver un nombre de dominio externo:

     dig example.com @KUBE_DNS_POD_IP
    

    Sustituye KUBE_DNS_POD_IP por la dirección IP del pod kube-dns. Si no sabes el valor de esta dirección IP, ejecuta el siguiente comando:

     kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
    

    La dirección IP se encuentra en la columna IP.

    Si la resolución del comando se realiza correctamente, verás status: NOERROR y los detalles del registro A, como se muestra en el siguiente ejemplo:

     ; <<>> DiG 9.16.27 <<>> example.com
     ;; global options: +cmd
     ;; Got answer:
     ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31256
     ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
    
     ;; OPT PSEUDOSECTION:
     ; EDNS: version: 0, flags:; udp: 512
     ;; QUESTION SECTION:
     ;example.com.                   IN      A
    
     ;; ANSWER SECTION:
     example.com.            30      IN      A       93.184.215.14
    
     ;; Query time: 6 msec
     ;; SERVER: 10.76.0.10#53(10.76.0.10)
     ;; WHEN: Tue Oct 15 16:45:26 UTC 2024
     ;; MSG SIZE  rcvd: 56
    
  5. Salir del shell:

    exit
    

Si falla alguno de estos comandos, realiza un reinicio gradual de la implementación de kube-dns:

kubectl rollout restart deployment/kube-dns --namespace=kube-system

Una vez que hayas completado el reinicio, vuelve a probar los comandos dig y comprueba si ahora funcionan. Si siguen fallando, haz una captura de paquetes.

Hacer una captura de paquetes

Haz una captura de paquetes para verificar si los pods de kube-dns reciben las consultas de DNS y responden a ellas correctamente:

  1. Conéctate mediante SSH al nodo que ejecuta el pod kube-dns. Por ejemplo:

    1. En la consola de Google Cloud , ve a la página Instancias de VM.

      Ir a Instancias de VM

    2. Busca el nodo al que quieras conectarte. Si no sabes el nombre del nodo de tu pod kube-dns, ejecuta el siguiente comando:

      kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
      

      El nombre del nodo aparece en la columna Nodo.

    3. En la columna Conectar, haz clic en SSH.

  2. En el terminal, inicia toolbox, una herramienta de depuración preinstalada:

    toolbox
    
  3. En la petición de raíz, instala el paquete tcpdump:

    apt update -y && apt install -y tcpdump
    
  4. Con tcpdump, haz una captura de paquetes de tu tráfico DNS:

    tcpdump -i eth0 port 53" -w FILE_LOCATION
    

    Sustituye FILE_LOCATION por la ruta a la ubicación donde quieras guardar la captura.

  5. Revisa la captura de paquetes. Comprueba si hay paquetes con direcciones IP de destino que coincidan con la dirección IP del servicio kube-dns. De esta forma, se asegura de que las solicitudes de DNS lleguen al destino correcto para la resolución. Si no ves que el tráfico DNS llega a los pods correctos, puede que haya una política de red que esté bloqueando las solicitudes.

Comprobar si hay una política de red

En ocasiones, las políticas de red restrictivas pueden interrumpir el tráfico DNS. Para comprobar si existe una política de red en el espacio de nombres kube-system, ejecuta el siguiente comando:

kubectl get networkpolicy -n kube-system

Si encuentras una política de red, revísala y asegúrate de que permita la comunicación DNS necesaria. Por ejemplo, si tienes una política de red que bloquea todo el tráfico de salida, la política también bloqueará las solicitudes DNS.

Si el resultado es No resources found in kube-system namespace, significa que no tienes ninguna política de red y puedes descartar que sea la causa del problema. Investigar los registros puede ayudarte a encontrar más puntos de fallo.

Habilitar el registro temporal de consultas DNS

Para ayudarle a identificar problemas como respuestas de DNS incorrectas, habilite temporalmente el registro de depuración de las consultas de DNS. Para habilitar las consultas, crea un pod basado en un pod kube-dns. Los cambios que se hagan en el despliegue de kube-dns se revertirán automáticamente.

Habilitar el registro temporal de consultas de DNS es un procedimiento que requiere muchos recursos, por lo que te recomendamos que elimines el pod que crees en cuanto hayas recogido una muestra de registros adecuada.

Para habilitar el registro temporal de consultas DNS, sigue estos pasos:

  1. Recupera un pod de kube-dns y almacénalo en una variable llamada POD:

    POD=$(kubectl -n kube-system get pods --selector=k8s-app=kube-dns -o jsonpath="{.items[0].metadata.name}")
    
  2. Crea un Pod llamado kube-dns-debug. Este pod es una copia del pod almacenado en la variable POD, pero con el registro de dnsmasq habilitado. Este comando no modifica el pod kube-dns original:

    kubectl apply -f <(kubectl get pod -n kube-system ${POD} -o json | jq -e '
    
    (
    
    (.spec.containers[] | select(.name == "dnsmasq") | .args) += ["--log-queries"]
    
    )
    
    | (.metadata.name = "kube-dns-debug")
    
    | (del(.metadata.labels."pod-template-hash"))
    
    ')
    
  3. Inspecciona los registros:

    kubectl logs -f --tail 100 -c dnsmasq -n kube-system kube-dns-debug
    

    También puede ver las consultas en Cloud Logging.

  4. Cuando hayas terminado de ver los registros de consultas de DNS, elimina el kube-dns-debug Pod:

    kubectl -n kube-system delete pod kube-dns-debug
    

Investigar el pod kube-dns

Consulta cómo reciben y resuelven las consultas DNS los pods de kube-dns con Cloud Logging.

Para ver las entradas de registro relacionadas con el pod kube-dns, sigue estos pasos:

  1. En la Google Cloud consola, ve a la página Explorador de registros.

    Ir a Explorador de registros

  2. En el panel de consultas, introduce el siguiente filtro para ver los eventos relacionados con el contenedor kube-dns:

    resource.type="k8s_container"
    resource.labels.namespace_name="kube-system"
    resource.labels.pod_name:"kube-dns"
    resource.labels.cluster_name="CLUSTER_NAME"
    resource.labels.location="CLUSTER_LOCATION"
    

    Haz los cambios siguientes:

    • CLUSTER_NAME: el nombre del clúster al que pertenece el pod kube-dns.
    • CLUSTER_LOCATION: la ubicación de tu clúster.
  3. Haz clic en Realizar una consulta.

  4. Revisa el resultado. En el siguiente ejemplo se muestra un posible error que puede aparecer:

    {
       "timestamp": "2024-10-10T15:32:16.789Z",
       "severity": "ERROR",
       "resource": {
          "type": "k8s_container",
          "labels": {
          "namespace_name": "kube-system",
          "pod_name": "kube-dns",
          "cluster_name": "CLUSTER_NAME",
          "location": "CLUSTER_LOCATION"
          }
       },
       "message": "Failed to resolve 'example.com': Timeout."
    },
    

    En este ejemplo, kube-dns no ha podido resolver example.com en un tiempo razonable. Este tipo de error puede deberse a varios problemas. Por ejemplo, el servidor upstream podría estar configurado incorrectamente en el ConfigMap de kube-dns o podría haber un tráfico de red elevado.

Si no tienes habilitado Cloud Logging, consulta los registros de Kubernetes:

Pod=$(kubectl get Pods -n kube-system -l k8s-app=kube-dns -o name | head -n1)
kubectl logs -n kube-system $Pod -c dnsmasq
kubectl logs -n kube-system $Pod -c kubedns
kubectl logs -n kube-system $Pod -c sidecar

Investigar los cambios recientes en el ConfigMap kube-dns

Si de repente se producen errores de resolución de DNS en tu clúster, una de las causas puede ser un cambio de configuración incorrecto en el ConfigMap de kube-dns. En concreto, los cambios en la configuración de los dominios stub y las definiciones de los servidores upstream pueden provocar problemas.

Para comprobar si hay actualizaciones de la configuración del dominio de stub, sigue estos pasos:

  1. En la Google Cloud consola, ve a la página Explorador de registros.

    Ir a Explorador de registros

  2. En el panel de consultas, introduce la siguiente consulta:

    resource.labels.cluster_name="clouddns"
    resource.type="k8s_container"
    resource.labels.namespace_name="kube-system"
    labels.k8s-pod/k8s-app="kube-dns" jsonPayload.message=~"Updated stubDomains to"
    
  3. Haz clic en Realizar una consulta.

  4. Revisa el resultado. Si ha habido alguna actualización, el resultado será similar al siguiente:

    Updated stubDomains to map[example.com: [8.8.8.8 8.8.4.4 1.1.3.3 1.0.8.111]]
    

    Si ves una actualización, despliega el resultado para obtener más información sobre los cambios. Verifica que los dominios de stub y sus servidores DNS upstream correspondientes se hayan definido correctamente. Si las entradas son incorrectas, se pueden producir errores de resolución en esos dominios.

Para comprobar si se han producido cambios en el servidor upstream, sigue estos pasos:

  1. En la Google Cloud consola, ve a la página Explorador de registros.

    Ir a Explorador de registros

  2. En el panel de consultas, introduce la siguiente consulta:

    resource.labels.cluster_name="clouddns"
    resource.type="k8s_container" resource.labels.namespace_name="kube-system"
    labels.k8s-pod/k8s-app="kube-dns" jsonPayload.message=~"Updated upstreamNameservers to"
    
  3. Haz clic en Realizar una consulta.

  4. Revisa el resultado. Si se ha producido algún cambio, el resultado será similar al siguiente:

    Updated upstreamNameservers to [8.8.8.8]
    

    Despliega el resultado para obtener más información sobre los cambios. Verifica que la lista de servidores DNS ascendentes sea precisa y que se pueda acceder a estos servidores desde tu clúster. Si estos servidores no están disponibles o están mal configurados, es posible que falle la resolución general de DNS.

Si has comprobado si hay cambios en los dominios stub y los servidores upstream, pero no has encontrado ningún resultado, busca todos los cambios con el siguiente filtro:

resource.type="k8s_cluster"
protoPayload.resourceName:"namespaces/kube-system/configmaps/kube-dns"
protoPayload.methodName=~"io.k8s.core.v1.configmaps."

Revisa los cambios que se hayan hecho para ver si han provocado el error.

Contactar con Cloud Customer Care

Si has seguido los pasos de las secciones anteriores, pero sigues sin poder diagnosticar la causa del problema, ponte en contacto con el servicio de atención al cliente de Cloud.

Resolver los problemas más habituales

Si has experimentado un error o un problema específico, sigue los consejos que se indican en las secciones siguientes.

Problema: tiempos de espera de DNS intermitentes

Si observas que se agota el tiempo de espera de la resolución de DNS de forma intermitente cuando aumenta el tráfico de DNS o cuando empieza el horario de apertura, prueba las siguientes soluciones para optimizar el rendimiento de DNS:

  • Comprueba el número de pods de kube-dns que se ejecutan en el clúster y compáralo con el número total de nodos de GKE. Si no hay suficientes recursos, te recomendamos que aumentes la escala de los pods de kube-dns.

  • Para mejorar el tiempo medio de búsqueda de DNS, habilita NodeLocal DNS Cache.

  • La resolución de DNS a nombres externos puede sobrecargar el pod kube-dns. Para reducir el número de consultas, ajusta el ajuste ndots en el archivo /etc/resolv.conf. ndots representa el número de puntos que deben aparecer en un nombre de dominio para resolver una consulta antes de la consulta absoluta inicial.

    El siguiente ejemplo es el archivo /etc/resolv.conf de un pod de aplicación:

    search default.svc.cluster.local svc.cluster.local cluster.local c.PROJECT_ID.internal google.internal
    nameserver 10.52.16.10
    options ndots:5
    

    En este ejemplo, kube-dns busca cinco puntos en el dominio consultado. Si el pod hace una llamada de resolución de DNS para example.com, los registros serán similares al siguiente ejemplo:

    "A IN example.com.default.svc.cluster.local." NXDOMAIN
    "A IN example.com.svc.cluster.local." NXDOMAIN
    "A IN example.com.cluster.local." NXDOMAIN
    "A IN example.com.google.internal." NXDOMAIN
    "A IN example.com.c.PROJECT_ID.internal." NXDOMAIN
    "A IN example.com." NOERROR
    

    Para solucionar este problema, cambie el valor de ndots a 1 para buscar solo un punto o añada un punto (.) al final del dominio que consulte o utilice. Por ejemplo:

    dig example.com.
    

Problema: las consultas de DNS fallan de forma intermitente desde algunos nodos

Si observas que las consultas de DNS fallan de forma intermitente desde algunos nodos, es posible que se produzcan los siguientes síntomas:

  • Cuando ejecutas comandos dig en la dirección IP del servicio kube-dns o en la dirección IP del pod, las consultas de DNS fallan de forma intermitente con tiempos de espera.
  • No se pueden ejecutar comandos dig desde un pod en el mismo nodo que el pod kube-dns.

Para solucionar este problema, siga estos pasos:

  1. Realiza una prueba de conectividad. Define el pod o el nodo problemático como origen y la dirección IP del pod kube-dns como destino. De esta forma, puedes comprobar si tienes las reglas de cortafuegos necesarias para permitir este tráfico.
  2. Si la prueba no se realiza correctamente y una regla de cortafuegos bloquea el tráfico, usa Cloud Logging para consultar los cambios manuales que se hayan hecho en las reglas de cortafuegos. Busca los cambios que bloquean un tipo de tráfico específico:

    1. En la Google Cloud consola, ve a la página Explorador de registros.

      Ir a Explorador de registros

    2. En el panel de consultas, introduce la siguiente consulta:

      logName="projects/project-name/logs/cloudaudit.googleapis.com/activity"
      resource.type="gce_firewall_rule"
      
    3. Haz clic en Realizar una consulta. Usa el resultado de la consulta para determinar si se ha realizado algún cambio. Si detecta algún error, corríjalo y vuelva a aplicar la regla de firewall.

      Asegúrate de no hacer cambios en ninguna regla de cortafuegos automatizada.

  3. Si no se ha realizado ningún cambio en las reglas de cortafuegos, comprueba la versión del grupo de nodos y asegúrate de que sea compatible con el plano de control y otros grupos de nodos que funcionen. Si alguno de los grupos de nodos del clúster tiene una versión anterior a la del plano de control en más de dos versiones secundarias, puede que esto esté causando problemas. Para obtener más información sobre esta incompatibilidad, consulta La versión de Node no es compatible con la versión del plano de control.

  4. Para determinar si las solicitudes se envían a la IP de servicio kube-dns correcta, captura el tráfico de red en el nodo problemático y filtra por el puerto 53 (tráfico DNS). Captura el tráfico de los pods de kube-dns para ver si las solicitudes llegan a los pods previstos y si se resuelven correctamente.

Siguientes pasos