Sortie de Terraform 0.9

Source: LinuxFR – les dépêches
Liens: Sortie de Terraform 0.9
Sortie de Terraform 0.9

Le 15 mars 2017 a été annoncée la sortie de la version 0.9 de Terraform par HashiCorp (vagrant, consul, nomad, etc).

Terraform est un outil d’Infrastructure as Code qui permet de décrire et créer son infrastructure sous forme d’un code source déclaratif. Il est en partie équivalent à des outils tels puppet, ansible ou chef (pour la partie infrastructure).

Pour ce faire il s’appuie sur un ensemble de providers permettant de manipuler des ressources Amazon Web Services, Google Cloud, OpenStack, mais aussi Docker, Nomad, etc. La liste est longue et continue régulièrement à s’agrandir.

Sommaire

Exemple

Pour mieux comprendre, voici deux petits exemples de ce qui peut être réalisé.

Le premier crée une instance dans un cloud OpenStack en y attachant un volume de données :

resource "openstack_blockstorage_volume_v1" "myvol" {
  name = "myvol"
  size = 1
}

resource "openstack_compute_instance_v2" "volume-attached" {
  name            = "volume-attached"
  image_id        = "ad091b52-742f-469e-8f3c-fd81cadf0743"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  network {
    name = "my_network"
  }

  volume {
    volume_id = "${openstack_blockstorage_volume_v1.myvol.id}"
  }
}

Le deuxième définit une image pour Docker et crée un conteneur avec elle :

# Configure the Docker provider
provider "docker" {
  host = "tcp://127.0.0.1:2376/"
}

# Create a container
resource "docker_container" "foo" {
  image = "${docker_image.ubuntu.latest}"
  name  = "foo"
}

resource "docker_image" "ubuntu" {
  name = "ubuntu:latest"
}

Nouveautés de la 0.9

Provisionneurs à la destruction

Depuis les débuts de Terraform, un système de provisionneurs permet d’exécuter des actions locales ou distantes lors de la création d’une ressource. Par exemple, vous voulez qu’un script shell soit exécuté à la création d’un serveur ; désormais vous pouvez aussi réaliser cette action à la destruction. Cela peut permettre à un nœud de cluster d’envoyer un message indiquant qu’il le quitte juste avant que le nœud soit supprimée.

Voici un exemple où un membre d’un cluster consul indique qu’il quitte le cluster au moment de la destruction :

resource "aws_instance" "consul" {
  # ... other fields

  provisioner "remote-exec" {
    command = "consul leave"
    when = "destroy"
  }
}

Verrouillage de l’état

Afin de pouvoir savoir quelles actions doivent êtres réalisées à chaque exécution, Terraform sauvegarde l’état courant de l’infrastructure dans un fichier. Avec cette solution il n’était pas possible d’exécuter simultanément (par exemple par deux personnes différentes) plusieurs fois Terraform. Pour prévenir ce problème, il fallait s’appuyer sur des outils externes du type de Terragrunt.

Désormais, Terraform est capable de poser un verrou au niveau de l’état, que l’infrastruture soit stockée localement (dans un fichier), sur AWS S3 ou dans Consul. D’autres supports vont être ajoutés dans les versions 0.9.x ainsi que des fonctionnalités avancées de verrouillage.

C’était attendu avec impatience, non que Terragrunt ne fasse pas son boulot, mais cela va permettre de réduire le nombre d’outils mis en œuvre pour réaliser les actions de base.

Provisionneurs interruptibles

Terraform a toujours su s’arrêter proprement sur un Ctrl-c. Mais pour rester dans un état cohérent il devait attendre que la tâche courante termine. Certaines tâches prenant parfois plusieurs minutes cela n’était pas optimal (par exemple, création d’une instance de base de données chez Amazon). Désormais Terraform va rendre la main sans attendre et marquer l’instance comme tainted ce qui forcera sa recréation à la prochaine exécution.

Gestion des environnements

Si vous avez de multiples environnements pour votre projet (par exemple staging, pre-production, production) rien n’était fait jusqu’à présent pour vous faciliter la vie. Comme dit plus haut, Terraform stocke l’état de l’infrastructure dans un fichier. Mais qui dit multiples environnements dit multiples fichiers d’états à partir d’un même code et probablement de multiples fichiers de variables pour stocker des credentials différents par environnement. Et ce n’était tout simplement pas géré.

Avant la version 0.9 nous utilisions une surcouche à base de Makefile pour gérer tout ceci :

apply:
    $(TERRAFORM_BIN) apply -state=$(call getenv).tfstate -var environment=$(call getenv) -var-file=$(call getenv).tfvars

Ce qui permettait de faire (je vous ai masqué un peu les détails) make apply env=staging ou make apply env=production.

Certes ça fonctionne, mais c’est mieux de l’éviter pour se concentrer sur des choses de plus grande valeur et pour gagner en fiabilité.

Avec la 0.9 il est donc possible d’avoir de multiples environnements :

$ terraform env list
  default
* mitchellh-test

$ terraform env select default
Switched to environment "default"!

$ terraform env delete mitchellh-test
Deleted environment "mitchellh-test"!

Et une nouvelle interpolation ${terraform.env} permet de connaitre l’environnement dans les fichiers Terraform :

resource "aws_instance" "example" {
  count = "${terraform.env == "default" ? 5 : 1}"

  tags { Name = "web - ${terraform.env}" }

  # ... other fields
}

Réorganisation du stockage distant de l’état

Nous avons vu plus haut le nouveau verrouillage des fichiers d’état, y compris pour le stockage distant.

Le stockage des états à distance a été revu en profondeur pour un usage plus agréable et une meilleure confiance. Par exemple, si un stockage distant est configuré, Terraform en ligne de commande va l’utiliser de préférence au fichier d’état local.

DataSources pour Ignition

C’est un point qui n’est pas présent dans le billet de sortie de la version 0.9, mais il fait partie des améliorations que nous utilisons en production depuis quelques temps.

Nous utilisons Terraform pour instancier des clusters CoreOS. Les machines nécessitant souvent quelques actions initiales (par exemple formater et monter un disque) nous utilisons pour cela Ignition qui au premier boot va configurer ces éléments plutôt bas niveau. Or le support d’Ignition était loin d’être parfait, avec certains comportements plutôt désagréables.
Avec la version 0.9 la manière de gérer Ignition a été fortement améliorée.

Voici un exemple réel (un poil allégé tout de même) montrant la configuration d’un serveur qui va installer un service systemd directement au premier démarrage :

# Définition de l'unité systemd se trouvant dans le fichier data/elasticsearch.service
data "ignition_systemd_unit" "elasticsearch" { 
  name    = "elasticsearch.service" 
  content = "${file("${path.module}/data/elasticsearch.service")}"
}

# Définition d'un serveur supportant elasticsearch
resource "aws_instance" "es_srv" {
  # ... paramètres de l'instance, taille, etc

  # Indique la configuration à appliquer au premier boot
  user_data = "${data.ignition_config.es_srv.rendered}"
}

# Configuration systemd (ou autre)
data "ignition_config" "es_srv" {
  systemd = [
    "${data.ignition_systemd_unit.elasticsearch.id}",
  ]
}

Open Source

Le développement de Terraform est ouvert. Terraform (ainsi que les autres outils de HashiCorp) fait partie de ces projets où il est facile d’échanger avec l’équipe de développeurs que ce soit pour rapporter des bugs ou pour proposer des améliorations.
Le projet est sous Mozilla Public License 2

Suite des développements

Le développement de la 0.9.1 est déjà en route, avec entre autres un nouveau provider pour kubernetes, l’orchestrateur de conteneurs par Google qui a bien le vent en poupe en ce moment.

Lire les commentaires

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *