Instalación y Configuración de CoreDNS

CoreDNS es un servidor DNS flexible y extensible escrito en Go, que sirve como el servidor DNS por defecto en Kubernetes y puede desplegarse como servidor DNS de propósito general en Linux. Su arquitectura basada en plugins permite componerlo para cualquier caso de uso: autoridad, resolución recursiva, caché, reenvío y descubrimiento de servicios. Esta guía cubre la instalación de CoreDNS, configuración de plugins, zonas personalizadas e integración con Kubernetes.

Requisitos Previos

  • Servidor Linux (Ubuntu 22.04/Debian 12 o CentOS 9/Rocky 9)
  • Mínimo 512 MB de RAM (1 GB recomendado)
  • Puerto 53 disponible (no conflictos con systemd-resolved u otro DNS local)
  • Acceso root al servidor

Instalación de CoreDNS

# Obtener la última versión de CoreDNS
COREDNS_VERSION="1.11.1"

# Descargar el binario precompilado
wget "https://github.com/coredns/coredns/releases/download/v${COREDNS_VERSION}/coredns_${COREDNS_VERSION}_linux_amd64.tgz"
tar xzf "coredns_${COREDNS_VERSION}_linux_amd64.tgz"

# Instalar el binario
install -m 755 coredns /usr/local/bin/coredns

# Verificar la instalación y los plugins incluidos
coredns --version
coredns -plugins

# Crear usuario de sistema para CoreDNS
useradd -r -d /etc/coredns -s /bin/false coredns

# Crear directorios de configuración
mkdir -p /etc/coredns /var/lib/coredns
chown coredns:coredns /var/lib/coredns

# Asignar capacidad para binding en puerto 53 sin root
setcap cap_net_bind_service=+ep /usr/local/bin/coredns

Configuración Básica con Corefile

El Corefile es el archivo de configuración principal de CoreDNS:

cat > /etc/coredns/Corefile << 'EOF'
# Servidor DNS principal - atiende todas las consultas en el puerto 53
. {
    # Reenviar consultas no resueltas localmente a servidores upstream
    forward . 1.1.1.1 8.8.8.8 {
        protocol udp
        max_concurrent 1000
    }

    # Caché de respuestas para mejorar el rendimiento
    cache {
        success 9984 300  # Cachear respuestas exitosas hasta 300 segundos
        denial  9984 30   # Cachear respuestas NXDOMAIN 30 segundos
    }

    # Logs de errores (no loguear cada query para reducir I/O)
    errors

    # Métricas de Prometheus en el puerto 9153
    prometheus :9153

    # Health check endpoint en el puerto 8080
    health :8080 {
        lameduck 5s
    }

    # Listo para tráfico
    ready :8181
}
EOF

chown coredns:coredns /etc/coredns/Corefile

Crea el servicio systemd:

cat > /etc/systemd/system/coredns.service << 'EOF'
[Unit]
Description=CoreDNS - DNS Server
Documentation=https://coredns.io
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=coredns
Group=coredns
ExecStart=/usr/local/bin/coredns -conf /etc/coredns/Corefile
ExecReload=/bin/kill -SIGUSR1 $MAINPID
Restart=on-failure
RestartSec=5s
LimitNOFILE=1048576
LimitNPROC=512

[Install]
WantedBy=multi-user.target
EOF

# Deshabilitar systemd-resolved si está en el puerto 53
# (en Ubuntu, systemd-resolved ocupa el puerto 53 por defecto)
systemctl disable --now systemd-resolved
rm -f /etc/resolv.conf
echo "nameserver 127.0.0.1" > /etc/resolv.conf

systemctl daemon-reload
systemctl enable --now coredns

# Probar la resolución DNS
dig @127.0.0.1 google.com
dig @127.0.0.1 google.com AAAA

Plugin de Caché

Optimiza la caché de CoreDNS para alto rendimiento:

cat > /etc/coredns/Corefile << 'EOF'
. {
    forward . 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 {
        policy round_robin
        health_check 5s
    }

    # Caché optimizada para producción
    cache {
        success 10000 600 300   # max_items ttl min_ttl
        denial  5000  30  5     # max_items ttl min_ttl
        prefetch 10 1m 10%      # Precarga proactiva al llegar al 10% del TTL
    }

    errors
    prometheus :9153
    health :8080
}
EOF

Reenvío de Consultas

Configura reenvío selectivo por dominio:

cat > /etc/coredns/Corefile << 'EOF'
# Dominio interno de la empresa - resolver con servidor interno
empresa.local {
    forward . 10.0.0.10 10.0.0.11
    cache 60
    errors
}

# Consultas para Kubernetes - resolver con kube-dns
cluster.local {
    forward . 10.96.0.10
    cache 30
}

# Todo lo demás - reenviar a DNS público con DoT
. {
    forward . tls://1.1.1.1 tls://1.0.0.1 {
        tls_servername cloudflare-dns.com
        health_check 5s
    }
    cache {
        success 9984 300
        denial  9984 30
    }
    errors
    prometheus :9153
    health :8080
}
EOF

# Recargar configuración sin reiniciar el servicio
systemctl reload coredns
# o enviar señal al proceso
kill -SIGUSR1 $(pgrep coredns)

Gestión de Zonas

Configura CoreDNS como servidor autoritativo para una zona:

# Crear archivo de zona en formato RFC 1035
cat > /etc/coredns/zones/db.empresa.local << 'EOF'
$ORIGIN empresa.local.
$TTL 300

@   IN  SOA ns1.empresa.local. admin.empresa.local. (
            2024011501 ; Serial (YYYYMMDDNN)
            3600       ; Refresh
            900        ; Retry
            604800     ; Expire
            300 )      ; Minimum TTL

; Servidores de nombres
@   IN  NS  ns1.empresa.local.
@   IN  NS  ns2.empresa.local.

; Registros A del propio servidor NS
ns1 IN  A   10.0.0.10
ns2 IN  A   10.0.0.11

; Registros de la infraestructura
web     IN  A   10.0.1.10
web     IN  A   10.0.1.11
api     IN  A   10.0.2.10
db      IN  A   10.0.3.10
mail    IN  A   10.0.4.10
mail    IN  MX  10 mail.empresa.local.

; Alias CNAME
www     IN  CNAME   web.empresa.local.
app     IN  CNAME   api.empresa.local.
EOF

# Añadir el bloque de zona al Corefile
cat >> /etc/coredns/Corefile << 'EOF'

# Zona autoritativa para empresa.local
empresa.local {
    file /etc/coredns/zones/db.empresa.local {
        reload 10s  # Recargar el archivo si cambia
    }
    errors
    log
}
EOF

# Verificar la configuración
coredns -conf /etc/coredns/Corefile -dns.port 5300 &
dig @127.0.0.1 -p 5300 web.empresa.local
dig @127.0.0.1 -p 5300 empresa.local MX
kill %1

Integración con Kubernetes

En Kubernetes, CoreDNS se gestiona como un Deployment en el namespace kube-system:

# Ver la configuración actual de CoreDNS en Kubernetes
kubectl get configmap coredns -n kube-system -o yaml

# Editar la configuración de CoreDNS en Kubernetes
kubectl edit configmap coredns -n kube-system

# Corefile típico de Kubernetes
# .:53 {
#     errors
#     health {
#         lameduck 5s
#     }
#     ready
#     kubernetes cluster.local in-addr.arpa ip6.arpa {
#         pods insecure
#         fallthrough in-addr.arpa ip6.arpa
#         ttl 30
#     }
#     prometheus :9153
#     forward . /etc/resolv.conf {
#         max_concurrent 1000
#     }
#     cache 30
#     loop
#     reload
#     loadbalance
# }

# Añadir reenvío para dominio interno al Corefile de Kubernetes
kubectl patch configmap coredns -n kube-system --patch '
data:
  Corefile: |
    empresa.local:53 {
        forward . 10.0.0.10
    }
    .:53 {
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }
'

# Reiniciar CoreDNS para aplicar cambios
kubectl rollout restart deployment coredns -n kube-system

Políticas de Resolución Personalizadas

# Plugin "rewrite" para renombrar consultas DNS
cat >> /etc/coredns/Corefile << 'EOF'

# Redirigir consultas antiguas al nuevo dominio
old.empresa.com {
    rewrite name suffix .old.empresa.com .empresa.local
    forward . 127.0.0.1
}
EOF

# Plugin "hosts" para resolución estática (como /etc/hosts)
. {
    hosts /etc/coredns/custom-hosts {
        10.0.1.50  legacy-app.empresa.local
        10.0.1.51  old-db.empresa.local
        fallthrough
    }
    # ... resto de la configuración
}

Solución de Problemas

# Habilitar logging detallado de consultas (útil para depuración, no para producción)
# Añadir el plugin "log" al bloque deseado en el Corefile:
# . {
#     log  # Loguea cada consulta
#     ...
# }

# Ver logs del servicio
journalctl -u coredns -f

# Probar resolución desde el servidor
dig @127.0.0.1 google.com
dig @127.0.0.1 empresa.local NS
dig @127.0.0.1 web.empresa.local

# Verificar que el puerto 53 está escuchando
ss -ulnp | grep 53

# Validar el Corefile antes de recargar
coredns -conf /etc/coredns/Corefile -validate

# Ver métricas en tiempo real
curl -s http://localhost:9153/metrics | grep coredns_cache

# Comprobar el health check
curl http://localhost:8080/health
curl http://localhost:8181/ready

Conclusión

CoreDNS ofrece una solución DNS moderna y extremadamente flexible gracias a su arquitectura de plugins, que permite construir desde un simple forwarder con caché hasta un servidor autoritativo completo con integración Kubernetes. Su diseño eficiente en Go y el soporte nativo de métricas Prometheus lo hacen ideal tanto para entornos de contenedores como para infraestructuras Linux tradicionales.