DNS Multi-Proveedor con Terraform y DNSControl
Despliega zonas DNS en DNScale y Hetzner DNS para redundancia usando Terraform o DNSControl.
Ejecutar tu DNS a través de un solo proveedor significa un solo punto de fallo. Si ese proveedor se cae — ya sea por una interrupción, un ataque DDoS o una mala configuración — tus dominios quedan inaccesibles. El DNS multi-proveedor elimina ese riesgo sirviendo la misma zona desde dos proveedores independientes simultáneamente.
Esta guía recorre la configuración de DNScale y Hetzner DNS como proveedores duales usando Terraform o DNSControl. Ambas herramientas te permiten definir registros una vez y enviarlos a ambos proveedores, manteniendo todo sincronizado sin duplicación manual.
Por qué DNS multi-proveedor
DNS es la base de todo servicio de Internet que ejecutas. Una interrupción del proveedor no solo significa que tu sitio web es inaccesible — significa que el correo deja de fluir, las APIs se vuelven inaccesibles y los servicios que dependen de registros SRV o TXT se rompen.
El DNS multi-proveedor funciona delegando tu dominio a servidores de nombres de ambos proveedores. Los resolvers en todo el mundo consultarán el conjunto de servidores de nombres que responda, así que si un proveedor está caído, el otro sigue sirviendo respuestas.
¿Cuándo tiene sentido el multi-proveedor?
- Dominios de producción donde el tiempo de inactividad tiene un costo real
- Entornos de cumplimiento que requieren redundancia
- Servicios globales donde la cobertura del proveedor varía por región
¿Cuándo es excesivo? Para dominios de desarrollo, herramientas internas o dominios donde unos minutos de inactividad son aceptables, un solo proveedor con buen uptime generalmente es suficiente.
Cómo funciona
El concepto es directo:
- Define tus registros una vez en Terraform o DNSControl
- Envía registros idénticos a DNScale y Hetzner DNS
- Configura los registros NS en tu registrador apuntando a servidores de nombres de ambos proveedores
- Los resolvers consultan cualquier proveedor — el que responda primero gana
┌──────────────┐
│ Registrador│
│ │
│ Registros NS:│
│ ns1.dnscale │
│ ns2.dnscale │
│ hydrogen.ns │ ← Hetzner
│ oxygen.ns │ ← Hetzner
└──────┬───────┘
│
▼
┌──────────────┐ ┌──────────────┐
│ DNScale │ │ Hetzner DNS │
│ │ │ │
│ example.com │ │ example.com │
│ A, MX, TXT │ │ A, MX, TXT │
│ (idénticos) │ │ (idénticos) │
└──────────────┘ └──────────────┘
▲ ▲
│ ┌──────────┐ │
└────│ Resolver │────┘
└──────────┘
Consulta cualquieraAmbos proveedores tienen los mismos registros. Tu herramienta de IaC es la única fuente de verdad, y ambos proveedores son simplemente espejos de esa verdad.
Requisitos previos
Necesitarás:
- Una cuenta de DNScale con una clave API — Obtener tu clave API
- Una cuenta de Hetzner DNS con un token API — Hetzner DNS Console
- Terraform (v1.0+) o DNSControl (v4.0+) instalados
- Un dominio que controles con acceso para configurar registros NS en el registrador
Terraform: Configuración multi-proveedor
Terraform hace que el DNS multi-proveedor sea limpio con su soporte nativo para múltiples proveedores y bucles for_each. Defines tus registros una vez en un bloque locals y los creas en ambos proveedores.
Configuración de proveedores
# providers.tf
terraform {
required_providers {
dnscale = {
source = "dnscaleou/dnscale"
version = "~> 1.0"
}
hetznerdns = {
source = "timohirt/hetznerdns"
version = "~> 2.2"
}
}
}
provider "dnscale" {
api_key = var.dnscale_api_key
}
provider "hetznerdns" {
apitoken = var.hetzner_dns_token
}# variables.tf
variable "dnscale_api_key" {
description = "DNScale API key"
type = string
sensitive = true
}
variable "hetzner_dns_token" {
description = "Hetzner DNS API token"
type = string
sensitive = true
}
variable "domain" {
description = "Domain to manage"
type = string
default = "example.com"
}Definir registros una vez
La clave del DNS multi-proveedor con Terraform es definir tus registros en un solo lugar. Usa locals para crear un conjunto de registros compartido:
# records.tf
locals {
dns_records = {
# Registros A
"root-a" = {
name = "@"
type = "A"
value = "203.0.113.10"
ttl = 3600
}
"www-a" = {
name = "www"
type = "CNAME"
value = "example.com."
ttl = 3600
}
# Correo
"mx-primary" = {
name = "@"
type = "MX"
value = "mail.example.com."
ttl = 3600
priority = 10
}
"mail-a" = {
name = "mail"
type = "A"
value = "203.0.113.20"
ttl = 3600
}
# SPF
"spf" = {
name = "@"
type = "TXT"
value = "v=spf1 mx -all"
ttl = 3600
}
# IPv6
"root-aaaa" = {
name = "@"
type = "AAAA"
value = "2001:db8::1"
ttl = 3600
}
}
}Crear en ambos proveedores
# dnscale.tf
resource "dnscale_zone" "primary" {
name = var.domain
}
resource "dnscale_record" "all" {
for_each = local.dns_records
zone_id = dnscale_zone.primary.id
name = each.value.name
type = each.value.type
content = each.value.value
ttl = each.value.ttl
priority = lookup(each.value, "priority", null)
}# hetzner.tf
resource "hetznerdns_zone" "secondary" {
name = var.domain
ttl = 3600
}
resource "hetznerdns_record" "all" {
for_each = local.dns_records
zone_id = hetznerdns_zone.secondary.id
name = each.value.name
type = each.value.type
value = each.value.value
ttl = each.value.ttl
}Para registros MX en Hetzner DNS, la prioridad generalmente se incluye en el campo
value(por ejemplo,"10 mail.example.com."). Puede que necesites ajustar el formato dependiendo de la versión del proveedor. Consulta la documentación del proveedor Terraform de Hetzner DNS para detalles específicos.
Aplicar
export TF_VAR_dnscale_api_key="your-dnscale-key"
export TF_VAR_hetzner_dns_token="your-hetzner-token"
terraform init
terraform plan # Revisar cambios para ambos proveedores
terraform apply # Enviar a ambos simultáneamenteTerraform crea recursos en ambos proveedores en paralelo, así que un solo apply actualiza todo. Para una inmersión más profunda sobre el proveedor de DNScale específicamente, consulta la guía del proveedor Terraform.
DNSControl: Configuración multi-proveedor
DNSControl tiene soporte nativo multi-proveedor integrado. Puedes adjuntar múltiples proveedores DNS a un solo dominio, y DNSControl envía registros idénticos a todos ellos en un solo comando.
Credenciales
// creds.json
{
"dnscale": {
"TYPE": "DNSCALE",
"api_key": "your-dnscale-key"
},
"hetzner": {
"TYPE": "HETZNER",
"api_token": "your-hetzner-token"
}
}Mantén creds.json fuera del control de versiones:
echo "creds.json" >> .gitignoreConfiguración
La función DnsProvider() de DNSControl acepta múltiples proveedores para un solo dominio. Los registros se envían automáticamente a todos los proveedores adjuntos:
// dnsconfig.js
var REG_NONE = NewRegistrar("none");
var DSP_DNSCALE = NewDnsProvider("dnscale");
var DSP_HETZNER = NewDnsProvider("hetzner");
D("example.com", REG_NONE,
DnsProvider(DSP_DNSCALE),
DnsProvider(DSP_HETZNER),
// Registros A
A("@", "203.0.113.10", TTL(3600)),
A("mail", "203.0.113.20", TTL(3600)),
// IPv6
AAAA("@", "2001:db8::1", TTL(3600)),
// CNAME
CNAME("www", "example.com.", TTL(3600)),
// Correo
MX("@", 10, "mail.example.com.", TTL(3600)),
// SPF
TXT("@", "v=spf1 mx -all", TTL(3600)),
END);Eso es todo. Ambos proveedores están listados en el mismo dominio, y DNSControl se encarga del resto.
Previsualizar y aplicar
# Ver qué cambiaría en ambos proveedores
dnscontrol preview
# Aplicar cambios a ambos proveedores
dnscontrol pushLa salida de preview muestra los cambios por proveedor, para que puedas verificar que tanto DNScale como Hetzner recibirán los registros correctos antes de aplicar.
Para más detalles sobre DNSControl con DNScale, consulta la guía de DNSControl.
Mantener los registros sincronizados
El mayor riesgo con el DNS multi-proveedor es la divergencia — registros que se dessincronizan entre proveedores. Tu herramienta de IaC resuelve esto al ser la única fuente de verdad.
IaC como fuente de verdad
Nunca edites registros directamente en los paneles de DNScale o Hetzner. Todos los cambios pasan por tu configuración de Terraform o DNSControl. Esto asegura que ambos proveedores siempre tengan registros idénticos.
Pipeline CI/CD
Automatiza los despliegues para que los registros se envíen a ambos proveedores en cada merge a main:
# .github/workflows/dns.yml
name: DNS Deploy
on:
push:
branches: [main]
paths: ["dns/**"]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Apply DNS changes
working-directory: dns/
env:
TF_VAR_dnscale_api_key: ${{ secrets.DNSCALE_API_KEY }}
TF_VAR_hetzner_dns_token: ${{ secrets.HETZNER_DNS_TOKEN }}
run: |
terraform init
terraform apply -auto-approveDetección de divergencia
Ejecuta verificaciones periódicas para detectar cambios manuales o inconsistencias de API:
# Terraform: detectar divergencia
terraform plan -detailed-exitcode
# Código de salida 2 significa divergencia detectada
# DNSControl: preview mostrará cualquier diferencia
dnscontrol previewPrograma esto en CI (por ejemplo, un cron job diario) y alerta ante diferencias inesperadas.
Delegación NS en tu registrador
Después de desplegar registros en ambos proveedores, actualiza los registros NS en tu registrador de dominio para incluir servidores de nombres de DNScale y Hetzner.
Un conjunto NS típico se ve así:
ns1.dnscale.eu
ns2.dnscale.eu
hydrogen.ns.hetzner.com
oxygen.ns.hetzner.com
helium.ns.hetzner.deLos nombres exactos de servidores de nombres de DNScale dependen de tu cuenta. Verifica los detalles de tu zona en el panel de DNScale para los servidores de nombres asignados.
Configura todos estos como registros NS en tu registrador. La mayoría de los registradores permiten agregar tantos servidores de nombres como necesites.
Verificar delegación
Después de actualizar los registros NS (permite hasta 48 horas para la propagación), verifica con:
dig NS example.com +shortDeberías ver servidores de nombres de ambos proveedores en la respuesta. También puedes verificar que cada proveedor responde correctamente:
# Consultar DNScale directamente
dig @ns1.dnscale.eu example.com A +short
# Consultar Hetzner directamente
dig @hydrogen.ns.hetzner.com example.com A +shortAmbos deberían devolver la misma dirección IP.
Limitaciones y consideraciones
DNSSEC
DNSSEC multi-proveedor es complejo. Cada proveedor firma la zona con sus propias claves, así que necesitas:
- Que ambos proveedores soporten DNSSEC multi-firmante (RFC 8901) — no es ampliamente soportado aún
- Que un proveedor sea el firmante y transfiera zonas firmadas al otro
- Omitir DNSSEC en zonas multi-proveedor hasta que mejore el soporte multi-firmante
Para la mayoría de las configuraciones, omitir DNSSEC en zonas multi-proveedor es la opción pragmática. Si DNSSEC es un requisito obligatorio, considera usar un solo proveedor con garantías sólidas de uptime. Consulta la guía de DNSSEC para configuración DNSSEC de un solo proveedor.
Alineación de TTL
Mantén los TTLs idénticos en ambos proveedores. TTLs diferentes significan que los resolvers almacenan en caché los registros por duraciones distintas dependiendo de qué proveedor consultaron, lo que lleva a comportamiento inconsistente.
Retrasos de propagación
Cuando aplicas cambios, ambos proveedores los procesan independientemente. Hay una breve ventana (generalmente segundos, a veces minutos) donde un proveedor tiene los registros nuevos y el otro aún sirve los antiguos. Para la mayoría de los casos de uso esto es aceptable — solo evita hacer cambios que se romperían si se aplican parcialmente.
Tipos de registros específicos del proveedor
Limítate a tipos de registros estándar que ambos proveedores soporten: A, AAAA, CNAME, MX, TXT, SRV, CAA, NS. Las extensiones específicas del proveedor o tipos de registros propietarios no serán portables.
Próximos pasos
- Gestión de DNS con Terraform — inmersión más profunda en el proveedor Terraform de DNScale
- Gestión de DNS con DNSControl — configuración completa de DNSControl
- Configuración de DNSSEC — configurar DNSSEC para zonas de un solo proveedor
- Balanceo Global de Resolución DNS — distribución geográfica de tráfico entre nodos DNS