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 d’approvisionnement 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 serveur membre d’une grappe d’envoyer un message indiquant qu’il va quitter la grappe juste avant que cela ne soit effectif.
Voici un exemple où un membre d’une grappe de serveurs Consul indique qu’il quitte la grappe 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 prises en charge vont être ajoutées 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.
Approvisionnements 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 se 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, pré‐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 identifiants 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 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 préférentiellement 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 grappes de serveurs CoreOS. Les machines nécessitant souvent quelques actions initiales (par exemple, formater et monter un disque) nous utilisons pour cela Ignition qui au premier amorçage va configurer ces éléments plutôt bas niveau. Or, la prise en charge d’Ignition était loin d’être parfaite, 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 prenant en charge 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 bogues ou pour proposer des améliorations.
Le projet est sous licence publique Mozilla version 2.
Suite des développements
Le développement de la version 0.9.1 est déjà en route, avec entre autres un nouveau provider pour Kubernetes, l’orchestrateur de conteneurs de Google qui a bien le vent en poupe en ce moment.