Mar 21 2022

Administre las Entradas de DNS con Terraform

Published by at 22:50 under Devops,Terraform

Terraform ayuda a construir la infraestructura as code. Cada vez más servidores web ahora ofrecen plugins de Terraform para administrar zonas DNS. Gandi es uno de ellos, junto con OVH y muchos otros. Probemos la versión 2 que se acaba de lanzar y veamos cómo crear registros DNS en Gandi desde un repositorio de Git.


El Provider de DNS Terraform Gandi

El proveedor Terraform de Gandi se declara en un archivo, por lo general, provider.tf. Puede agregar la clave API de Gandi necesaria para autenticar y registrar recursos. Se puede generar desde su sitio web en «Configuración de usuario», «Administración de cuentas de usuario y configuración de seguridad» en la pestaña Seguridad.
Por obvias razones de seguridad, se recomienda crear la clave de la clave API en la variable de entorno GANDI_KEY. Lo dejo así en provider.tf como parte de la prueba.

terraform {
  required_providers {
    gandi = {
      version = "~> 2.0"
      source   = "go-gandi/gandi"
    }
  }
}

provider "gandi" {
  key = "XXXXXXXXXXXXXXXXXXX"
}


Archivo de registros DNS

Gandi realiza copias de seguridad automáticas de las entradas de DNS en un formato de archivo simple, en el que me inspiré para el archivo de registros de DNS. Llamémoslo dominio.txt donde «dominio» es su nombre de dominio. Aquí hay un ejemplo con 3 entradas DNS.

www1 300 IN A 127.0.0.1
www2 300 IN A 127.0.0.1
www  300 IN CNAME www1


Debemos declarar el dominio como una variable que usaremos más adelante, en variable.tf.

variable domain {
  default = "mydomain.com"
}


Código Terraform de Entradas DNS

Aquí hay un archivo main.tf de Terraform minimalista que lee el archivo que contiene las entradas de DNS y crea un nuevo registro de cada línea.

data "local_file" "dns_file" {
  filename = "./${var.domain}.txt"
}

locals {
  # Convertit le fichier en tableau
  dns_records = toset([ for e in split("\n", data.local_file.dns_file.content) :
                        replace(e, "/\\s+/", " ") if e != "" ])
}
  
resource "gandi_livedns_record" "record" {
  for_each =  local.dns_records
  zone     =  var.domain
  name     =  split(" ",each.value)[0]
  type     =  split(" ",each.value)[3]
  ttl      =  split(" ",each.value)[1]
  values   = [split(" ",each.value)[4]]
}


Puede apreciar el poder de Terraform, que puede hacer mucho con solo unas pocas líneas de código.

Tenga en cuenta que estoy eliminando varios espacios – replace(e, «/\\s+/», » «) – al dividir las líneas porque la función de división crea un elemento vacío si procesa dos espacios. También ignoro las líneas en blanco. Luego recorremos cada línea para crear registros DNS con un recurso de tipo gandi_livedns_record.
Funciona con entradas A y CNAME.

Podríamos aplicar diferentes tratamientos para cada tipo de registro creando tablas separadas o ignorando otros tipos de DNS:

dns_records   = [ for e in split("\n", data.local_file.dns_file.content) :
                  replace(e, "/\\s+/", " ") if e != "" ]
A_records     = toset([for e in local.dns_records : e if split(" ",e)[3] == "A"])
CNAME_records = toset([for e in local.dns_records : e if split(" ",e)[3] == "CNAME"])


Luego podríamos recorrer A_records para crear las entradas A y procesar los CNAME en un segundo bloque de recursos.
Otras posibilidades: manejo de CNAMEs multivalor, registros TXT, etc…


Plan y Aplicación de Creación de Entradas de DNS

Ejecute terraform plan para comprobar lo qué terraform se va a modificar. Debería mostrar que se crearán 3 recursos. ejecute terraform apply para crear las entradas de DNS.

$ terraform plan

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # gandi_livedns_record.record["www 300 IN CNAME www1"] will be created
  + resource "gandi_livedns_record" "record" {
      + href   = (known after apply)
      + id     = (known after apply)
      + name   = "www"
      + ttl    = 300
      + type   = "CNAME"
      + values = [
          + "www1",
        ]
      + zone   = "domain.com"
    }

  [...]

Plan: 3 to add, 0 to change, 0 to destroy.


En cuanto al rendimiento, probé la creación de 200 entradas y tardé 2’57» con una conexión bastante mala. Sí, es un poco lento ya que se basa en llamar a una API REST para cada entrada. Sin embargo, crear una entrada adicional será muy rápido.
Un terraform plan tardó 1’31» en actualizar estas 200 entradas.

Por supuesto, siempre puede omitir el paso de actualización terraform plan -refresh=false que demora menos de un segundo.
El plan se puede guardar en un archivo temporal, que se puede cargar al aplicar los cambios.

$ terraform plan -refresh=false -out=plan.file
$ terraform apply plan.file

No responses yet

Comments RSS

Leave a Reply