Fév 24 2022

Gérez les Entrées DNS avec Terraform

Publié par à 7:40 sous DevOps,Terraform

Terraform aide à construction des infrastructures as code. De plus en plus d’hébergeurs Internet offrent désormais des plugins Terraform permettant de gérer les zones DNS. Gandi est l’un d’entre eux, avec OVH et bien d’autres. Testons la version 2 qui vient juste de sortir, et voyons comment créer les enregistrements DNS sur Gandi depuis un dépôt Git.

DNS avec Terraform


Le Provider DNS Terraform Gandi

Le provider Terraform de Gandi se déclare dans un fichier, habituellement provider.tf. Vous pouvez y ajouter l’API key Gandi nécessaire pour s’authentifier et enregistrer des ressources. Elle peut être générée depuis leur site web dans « Paramètres utilisateur », « Gestion du compte utilisateur et paramètres de sécurité » sous l’onglet Sécurité.
Pour des raisons évidentes de sécurité, il est recommandé de créer la clé d’API key dans la variable d’environnement GANDI_KEY. Je laisse comme ceci dans provider.tf dans le cadre du test.

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

provider "gandi" {
  key = "XXXXXXXXXXXXXXXXXXX"
}


Fichier des Enregistrements DNS

Gandi fait des sauvegardes automatiques des entrées DNS dans un format de fichier simple, dans lequel j’ai puisé mon inspiration pour le fichier d’enregistrements DNS. Appelons-le domaine.txt où « domaine » votre nom de domaine. Voici un exemple avec 3 entrées DNS.

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


Nous devons déclarer le domaine en tant que variable que nous utiliserons par la suite, dans variable.tf.

variable domain {
  default = "mydomain.com"
}


Code Terraform des Entrées DNS

Voici un fichier Terraform minimaliste main.tf qui lit le fichier contenant les entrées DNS, et crée un nouvel enregistrement à partir de chaque ligne.

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]]
}


Vous pouvez apprécier la puissance de Terraform qui peut faire beaucoup de choses en quelques lignes de code.

Notez que je supprime les espaces multiples – replace(e, « /\\s+/ »,  » « ) – en séparant les lignes car la fonction split crée un élément vide si elle traite deux espaces. J’ignore aussi les lignes vides. Ensuite nous bouclons sur chaque ligne pour créer des enregistrements DNS avec une ressource de type gandi_livedns_record.
Ca fonctionne avec les entrées A et les CNAME.

Nous pourrions appliquer des traitements différents pour chaque type d’enregistrement en créant des tableaux distincts, ou pour ignorer les autres type 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"])


Nous pourrions ensuite boucler sur A_records pour créer les entrées A, et traiter les CNAME dans un deuxième block de ressources.
D’autres possibilités: gérer les CNAME à valeurs multiples, les enregistrements TXT, etc …


Plan et Application de la Création des Entrées DNS

Exécutez terraform plan pour vérifier ce que terraform compte changer. Il devrait afficher que 3 resources seront créées. lancez terraform apply pour créer les entrées 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.


Côté performances, j’ai testé la création de 200 entrées, et cela a pris 2’57 » depuis une assez mauvaise connexion. Oui, c’est un peu lent comme ca repose sur l’appel d’une API REST pour chaque entrée. La création d’une entrée supplémentaire sera très rapide par contre.
Un terraform plan a pris 1’31 » pour rafraichir ces 200 entrées.

Bien sûr, vous pourrez toujours éviter l’étape de refresh avec terraform plan -refresh=false qui prend moins d’une seconde.
Le plan peut être sauvegardé dans un fichier temporaire, qui peut être chargé lorsqu’on applique les changements.

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

No responses yet

Comments RSS

Leave a Reply