Soluciona problemas de kube-dns en GKE


En esta página, se muestra cómo resolver problemas con kube-dns en Google Kubernetes Engine (GKE).

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

Los errores como dial tcp: i/o timeout, no such host o Could not resolve host suelen indicar problemas con la capacidad de kube-dns para resolver consultas.

Si ves uno de esos errores, pero no conoces la causa, usa las siguientes secciones para encontrarla. Las siguientes secciones están organizadas para comenzar con los pasos que tienen más probabilidades de ayudarte, así que prueba cada sección en orden.

Verifica si los Pods de kube-dns se están ejecutando

Los pods de kube-dns son fundamentales para la resolución de nombres dentro del clúster. Si no se ejecutan, 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 es similar a este:

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 agregan automáticamente a los Pods de kube-dns.

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

  1. Usa los registros de auditoría de actividad del administrador para investigar si hubo cambios recientes, como actualizaciones de 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 Información sobre el registro de auditoría de GKE. Si encuentras cambios, revierte los cambios y vuelve a ver el estado de los Pods.

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

    Warning: OOMKilling Memory cgroup out of memory
    

    Para resolver este error, consulta Mensaje de error: "Warning: OOMKilling Memory cgroup out of memory".

  3. Si no encuentras ningún mensaje de error de OOM, reinicia la Deployment de kube-dns:

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

    Después de reiniciar la Deployment, verifica si tus pods de kube-dns se están ejecutando.

Si estos pasos no funcionan o todos tus Pods de kube-dns tienen un estado de Running, pero aún tienes problemas de DNS, verifica que el archivo /etc/resolv.conf esté configurado correctamente.

Verifica que /etc/resolv.conf esté configurado de forma correcta

Revisa el archivo /etc/resolv.conf de los pods que tienen problemas de 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
    

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

    Si el binario de Pod no admite el comando kubectl exec, es posible que este comando falle. Si esto sucede, crea un Pod simple 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. Verifica que la dirección IP del servidor de nombres en el archivo /etc/resolv.conf sea correcta:

    • Los pods que usan una red del 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 de kube-dns debe ser la misma que la dirección IP del servidor de nombres. Para comparar las direcciones IP, completa los siguientes pasos:

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

        kubectl get svc kube-dns -n kube-system
        

        El resultado es similar a este:

        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 de 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 hay un campo dnsConfig 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 funcione correctamente.

        Si no quieres usar el servidor de nombres personalizado, quita el campo y realiza un reinicio continuo del Pod:

        kubectl rollout restart deployment POD_NAME
        

        Reemplaza POD_NAME por el nombre del Pod.

  3. Verifica las entradas search y ndots en /etc/resolv.conf. Asegúrate de que no haya errores de ortografía, configuraciones inactivas y que la solicitud con errores apunte al servicio existente en el espacio de nombres correcto.

Realiza una búsqueda de DNS

Después de confirmar 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 errores de DNS:

  1. Para consultar un Pod directamente, abre una shell dentro de él:

    kubectl exec -it POD_NAME -n NAMESPACE_NAME -- SHELL_NAME
    

    Reemplaza lo siguiente:

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

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

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

    dig kubernetes
    

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

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

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

    dig example.com
    
  4. Si tienes dificultades con un Pod de kube-dns en particular que responde a las consultas de DNS, verifica si ese Pod puede resolver un nombre de dominio externo:

     dig example.com @KUBE_DNS_POD_IP
    

    Reemplaza KUBE_DNS_POD_IP por la dirección IP del Pod de kube-dns. Si no conoces 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. Sal de la shell:

    exit
    

Si alguno de estos comandos falla, realiza un reinicio continuo de la Deployment de kube-dns:

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

Después de completar el reinicio, vuelve a intentar los comandos dig y comprueba si ahora se ejecutan correctamente. Si el problema persiste, realiza una captura de paquetes.

Cómo tomar una captura de paquetes

Realiza una captura de paquetes para verificar si los Pods de kube-dns reciben y responden correctamente las consultas de DNS:

  1. Usa SSH para conectarte 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. Ubica el nodo al que deseas conectarte. Si no conoces el nombre del nodo en tu Pod de 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 la terminal, inicia toolbox, una herramienta de depuración preinstalada:

    toolbox
    
  3. En el mensaje raíz, instala el paquete tcpdump:

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

    tcpdump -i eth0 port 53" -w FILE_LOCATION
    

    Reemplaza FILE_LOCATION por la ruta de acceso a la que deseas guardar la captura.

  5. Revisa la captura de paquetes. Verifica si hay paquetes con direcciones IP de destino que coincidan con la dirección IP del servicio kube-dns. Esto garantiza que las solicitudes de DNS lleguen al destino correcto para la resolución. Si no ves el tráfico de DNS en los Pods correctos, es posible que haya una política de red que bloquee las solicitudes.

Cómo verificar si hay una política de red

En ocasiones, las políticas de red restrictivas pueden interrumpir el tráfico de DNS. Para verificar 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 de 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 de DNS.

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

Habilita el registro temporal de consultas de DNS

Para ayudarte a identificar problemas, como respuestas de DNS incorrectas, habilita temporalmente el registro de depuración de las consultas de DNS.

Este es un procedimiento que consume muchos recursos, por lo que te recomendamos que inhabilites este registro después de recopilar una muestra adecuada de registros.

Investiga el Pod de kube-dns

Revisa cómo los Pods de kube-dns reciben y resuelven consultas de DNS con Cloud Logging.

Para ver las entradas de registro relacionadas con el Pod kube-dns, completa los siguientes pasos:

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

    Ir al Explorador de registros

  2. En el panel de consultas, ingresa el siguiente filtro para ver los eventos relacionados con el contenedor de 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"
    

    Reemplaza lo siguiente:

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

  4. Revise el resultado. En el siguiente ejemplo de resultado, se muestra un posible error que podrías ver:

    {
       "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 pudo resolver example.com en un tiempo razonable. Este tipo de error puede deberse a varios problemas. Por ejemplo, es posible que el servidor upstream esté configurado de forma incorrecta en el ConfigMap de kube-dns o que haya mucho tráfico de red.

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

Investiga los cambios recientes en el ConfigMap de kube-dns

Si, de repente, encuentras fallas de resolución de DNS en tu clúster, una razón puede ser un cambio de configuración incorrecto en el ConfigMap de kube-dns. En particular, los cambios de configuración en los dominios de stub y las definiciones de los servidores upstream pueden causar problemas.

Para verificar si hay actualizaciones en la configuración del dominio stub, completa los siguientes pasos:

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

    Ir al Explorador de registros

  2. En el panel de consulta, ingresa 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 Ejecutar consulta.

  4. Revise el resultado. Si hubo alguna actualización, el resultado es 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, expande el resultado para obtener más información sobre los cambios. Verifica que los dominios de stub y sus servidores DNS ascendentes correspondientes estén definidos correctamente. Las entradas incorrectas aquí pueden provocar fallas de resolución para esos dominios.

Para verificar si hay cambios en el servidor upstream, completa los siguientes pasos:

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

    Ir al Explorador de registros

  2. En el panel de consulta, ingresa 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 Ejecutar consulta.

  4. Revise el resultado. Si hubo algún cambio, el resultado es similar al siguiente:

    Updated upstreamNameservers to [8.8.8.8]
    

    Expande 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 verificaste si hay cambios en los dominios stub y los servidores upstream, pero no encontraste ningún resultado, verifica 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 enumeran para ver si fueron la causa del error.

Comunícate con Atención al cliente de Cloud

Si seguiste las secciones anteriores, pero aún no puedes diagnosticar la causa del problema, comunícate con Atención al cliente de Cloud.

Soluciona problemas habituales

Si experimentas un error o un problema específico, sigue los consejos de las siguientes secciones.

Problema: Tiempos de espera intermitentes de DNS

Si observas tiempos de espera intermitentes de resolución de DNS que ocurren cuando hay un aumento en el tráfico de DNS o cuando comienzan las horas de atención, prueba las siguientes soluciones para optimizar el rendimiento de tu DNS:

  • Verifica la cantidad de Pods de kube-dns que se ejecutan en el clúster y compárala con la cantidad total de nodos de GKE. Si no hay suficientes recursos, considera aumentar la escala de los Pods de kube-dns.

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

  • La resolución de DNS a nombres externos puede sobrecargar el Pod kube-dns. Para reducir la cantidad de consultas, ajusta el parámetro de configuración ndots en el archivo /etc/resolv.conf. ndots representa la cantidad 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 que se consulta. Si el Pod realiza una llamada de resolución de DNS para example.com, tus registros se verá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 resolver este problema, cambia el valor de ndots a 1 para buscar solo un punto o agrega un punto (.) al final del dominio que consultas o usas. 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 veas los siguientes síntomas:

  • Cuando ejecutas comandos dig a la dirección IP del servicio de kube-dns o a 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 resolver este problema, realiza los siguientes pasos:

  1. Realiza una prueba de conectividad. Establece el Pod o el nodo problemático como la fuente y el destino como la dirección IP del Pod kube-dns. Esto te permite verificar si tienes las reglas de firewall necesarias para permitir este tráfico.
  2. Si la prueba no se realiza correctamente y una regla de firewall bloquea el tráfico, usa Cloud Logging para enumerar los cambios manuales que se realizaron en las reglas de firewall. Busca cambios que bloqueen un tipo específico de tráfico:

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

      Ir al Explorador de registros

    2. En el panel de consulta, ingresa la siguiente consulta:

      logName="projects/project-name/logs/cloudaudit.googleapis.com/activity"
      resource.type="gce_firewall_rule"
      
    3. Haz clic en Ejecutar consulta. Usa el resultado de la consulta para determinar si se realizaron cambios. Si notas algún error, corrígelo y vuelve a aplicar la regla de firewall.

      Asegúrate de no realizar cambios en ninguna regla de firewall automática.

  3. Si no se realizaron cambios en las reglas de firewall, verifica la versión del grupo de nodos y asegúrate de que sea compatible con el plano de control y otros grupos de nodos en funcionamiento. Si alguno de los grupos de nodos del clúster tiene más de dos versiones secundarias anteriores a la versión del plano de control, es posible que esto genere problemas. Para obtener más información sobre esta incompatibilidad, consulta La versión del nodo no es compatible con la versión del plano de control.

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

¿Qué sigue?