CoreDNS dedicado para DNS interno / split‑horizon
Este directorio contiene los manifiestos para desplegar un CoreDNS propio (namespace coredns) que sirve como DNS interno para resoluciones split‑horizon y control de rutas en la VPN (split‑tunnel).
Con este CoreDNS:
- Los FQDN internos (p. ej.
portal.apolo.c2et.net) resuelven a la VIP interna192.168.200.10cuando el cliente usa el DNS interno192.168.200.11→ el tráfico va por la VPN/LAN. - Los FQDN “externos” (p. ej.
admin.firewall.c2et.net) pueden apuntar a la VIP pública192.168.0.100desde el mismo DNS interno (útil para pruebas) o gestionarse sólo en el DNS público. - El resto de nombres se reenvían a los resolvers del nodo (
/etc/resolv.conf).
Estructura
./coredns
├── configmap-coredns.yaml # Corefile con ‘hosts’, forward y cache
├── deploy-coredns.yaml # Deployment (réplicas, probes y mounts)
├── kustomization.yaml # Kustomize para aplicar todo el conjunto
├── namespace.yaml # Namespace dedicado: coredns
└── svc-coredns.yaml # Service LoadBalancer (UDP/TCP 53) → 192.168.200.11
Despliegue
Requisitos: MetalLB operativo en la red 192.168.200.0/24 para anunciar
192.168.200.11.
# Desde ./kubernetes/coredns
kubectl apply -k .
# Verificar
kubectl -n coredns get all
kubectl -n coredns get svc coredns-custom -o wide # Debe mostrar External IP: 192.168.200.11
kubectl -n coredns logs deploy/coredns-custom -f # Comprobar ‘health’/errores
Configuración (Corefile)
El Corefile se define en configmap-coredns.yaml:
.:53 {
log
errors
health
reload
hosts {
# === APOLO (GPS táctico) ===
192.168.200.10 backend.apolo.c2et.net
192.168.200.10 portal.apolo.c2et.net
192.168.200.10 colossus.apolo.c2et.net
192.168.200.13 chat.apolo.c2et.net
192.168.200.13 muc.chat.apolo.c2et.net
192.168.200.12 streaming.apolo.c2et.net
192.168.200.14 meeting.apolo.c2et.net
# === ARGOS (videovigilancia) ===
192.168.200.15 mqtt.argos.interna
192.168.200.16 mediamtx.argos.interna
192.168.200.10 s3.argos.interna
192.168.200.10 minio.argos.interna
192.168.200.10 panel.argos.c2et.net
# === External ===
192.168.0.100 admin.firewall.c2et.net
192.168.0.100 k8s.c2et.net
192.168.0.100 admin.powervault1.c2et.net
192.168.0.100 admin.powervault2.c2et.net
192.168.0.100 ceph.c2et.net
fallthrough
}
forward . /etc/resolv.conf
cache 120
# prometheus 0.0.0.0:9153 # (opcional) exportar métricas
}
Puntos clave
hosts: mapa de FQDN → IP (A/AAAA estáticos). Añade/edita aquí tus entradas internas.fallthrough: si un nombre no está enhosts, la consulta pasa al siguiente plugin.forward . /etc/resolv.conf: reenvía el resto de consultas a los resolvers del nodo.cache 120: cache de respuestas para mejorar latencia.reload: CoreDNS recarga el Corefile cuando cambia el ConfigMap montado.
Modificar el Corefile ⇒
kubectl -n coredns apply -f configmap-coredns.yaml(CoreDNS recarga solo). Si fuera necesario, unrollout restartdel deployment.
Integración con la VPN (split‑tunnel)
Para que los clientes usen las VIP internas cuando están en la VPN:
-
Empuja el DNS interno por la VPN:
- DNS del cliente:
192.168.200.11(este Service). - Asegúrate de que la interfaz de la VPN enruta el DNS interno (por ejemplo con
AllowedIPs = 192.168.200.11/32en WireGuard).
- DNS del cliente:
-
Split‑horizon: este CoreDNS responde con IPs internas (192.168.200.x). Si el cliente no usa este DNS, resolverá contra el público y saldrá por Internet (lo cual está bien si quieres que el Ingress lo bloquee por whitelist).
-
Ingress‑nginx (contexto relacionado):
-
Services del controller con
externalTrafficPolicy: Localpara preservar IP origen. -
Anotación de whitelist en los Ingress de apps: sólo redes permitidas (LAN/VPN), por ejemplo:
nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.200.0/24,192.168.0.0/24,192.168.4.0/24" -
Evitar abrir
10.244.0.0/16. Si tu gateway VPN es un Pod y el Ingress ve IP de Pod, permitir sólo su /32 o mover la VPN ahostNetwork: truepara usar IP estable del nodo.
-
Operación
Escalado y HA
deploy-coredns.yamlfijareplicas: 2con probes de liveness/readiness.- El Service
LoadBalancer(UDP/TCP 53) anuncia 192.168.200.11 vía MetalLB.
Actualizar entradas
- Edita
configmap-coredns.yaml(bloquehosts). kubectl -n coredns apply -f configmap-coredns.yaml.- Verifica con consultas (ver abajo).
Reinicio controlado (si lo precisas)
kubectl -n coredns rollout restart deploy/coredns-custom
kubectl -n coredns rollout status deploy/coredns-custom
Métricas (opcional)
- Descomenta la línea
prometheus 0.0.0.0:9153y expón unServiceMonitorsi usas Prometheus.
Pruebas y verificación
Resolución directa contra CoreDNS interno
# Desde un cliente en VPN/LAN
nslookup portal.apolo.c2et.net 192.168.200.11
nslookup admin.firewall.c2et.net 192.168.200.11
# o con dig
dig +short portal.apolo.c2et.net @192.168.200.11
Resultado esperado: portal.apolo.c2et.net → 192.168.200.10.
Camino por la VIP interna (SNI correcto)
curl -I https://portal.apolo.c2et.net \
--resolve portal.apolo.c2et.net:443:192.168.200.10
Logs de CoreDNS e Ingress
# CoreDNS
kubectl -n coredns logs deploy/coredns-custom -f | grep -iE "error|timeout"
# Ingress (para ver IP origen preservada)
kubectl -n ingress-nginx logs -l app.kubernetes.io/name=ingress-nginx --tail=100
Mantenimiento y buenas prácticas
- Versiona cambios en
hostsy acompaña con una nota de por qué se enruta cada FQDN a cada VIP. - Mantén separadas las entradas internas (192.168.200.x) y las externas (192.168.0.100) para claridad.
- Si la VPN está en Pods y rota IPs, considera moverla a
hostNetwork: trueo asignarle IP estática (Multus) para whitelistear un /32 estable en Ingress. - Revisa periódicamente que MetalLB siga anunciando
192.168.200.11y que no haya conflictos ARP en la red.
Comandos útiles
# Aplicar todo
kubectl apply -k .
# Ver estado
kubectl -n coredns get pods -o wide
kubectl -n coredns get svc coredns-custom -o wide
# Probar resolución desde un Pod del clúster
kubectl -n coredns run -it --rm dnsutils --image=ghcr.io/k8s-at-home/dnsutils:latest -- sh -lc \
"dig portal.apolo.c2et.net @192.168.200.11 +short"
Notas
- Este CoreDNS no sustituye al CoreDNS del clúster para kube‑services; su objetivo es servir nombres internos de la organización y controlar el camino de acceso (VPN/LAN vs. Internet).
- Si necesitas TTLs personalizados en respuestas estáticas, puedes extender el bloque
hostscon opciones (TTL, etc.).