Comment automatiser le déploiement d’infrastructures avec Terraform ?

Image de Quentin BASSEMAYOUSSE
Quentin BASSEMAYOUSSE

Administrateur systèmes et réseaux

L’informatique a été développée dans l’optique de faciliter et automatiser les tâches fastidieuses telles que les calculs, le traitement d’informations et son stockage. Cependant, la mise en place d’un système informatique est encore faite de façon manuelle. Une méthode longue et fastidieuse en cas d’infrastructure importante. Des outils, comme Terraform, ont donc été créés afin de faciliter cette tâche de déploiement.

GUIDE

À quoi sert Terraform ?

Terraform est un outil de ligne de commande open-source, développé en Golang par HashiCorp. Il permet d’automatiser le déploiement d’infrastructures compatibles sur plusieurs clouds (AWS, Azure, Flexibleengine, etc..). Cette automatisation est possible car Terraform décrit l’infrastructure sous forme de code “infrastructure as a code”, et utilise un langage nommé HCL (Hashicorp Configuration Language). Cette méthode de déploiement est dite “déclarative”, c’est-à-dire exécuter ce qu’on a décrit, mais ne rien faire si la ressource est déjà existante. Cette méthode est contraire à la méthode impérative qui demande d’énoncer les différentes étapes, et ne regarde pas l’existant.

Fonctionnement de terraform

fonctionnement-Terraform-YPSI-SAS

Source : Devopssec

L’automatisation des tâches avec les modules

Il existe plusieurs manières d’utiliser Terraform. Avec la manière simple, on renseigne directement les valeurs dans les blocs de ressource. Cette façon de faire est rapide à mettre en place, mais pas réutilisable pour tous les projets, puisqu’il faudra l’adapter en conséquence.

resource "flexibleengine_compute_instance_v2" "basic" { 
name = "basic"
image_id = "ad091b52-742f-469e-8f3c-fd81cadf0743"
flavor_id = "3"
key_pair = "my_key_pair_name"
security_groups = ["default"]
network { name = "my_network" }
tags = { foo = "bar" this = "that" }
}

Pour pallier aux lacunes de la méthode précédente, on utilise des modules. Cela suppose qu’on sépare la configuration de chaque ressource pour les rendre indépendantes, et on variabilise ces dernières pour les centraliser dans un root module.

Les modules ont l’avantage de pouvoir être stockés sur un logiciel de versionning tel que gitlab, et être spécifiés directement dans le code sans les avoirs en local. Cela va faciliter le partage au sein d’une équipe technique.

resource "flexibleengine_compute_instance_v2" "instances" {
availability_zone = var.availability_zone
count = var.instance_count
name = var.instance_count > 1 ? format("%s-%d", var.instance_name, count.index + 1) : var.instance_name
flavor_name = var.flavor_name
key_pair = var.key_name
user_data = var.user_data
security_groups = [flexibleengine_networking_secgroup_v2.sg-instances.name]
network {
uuid = var.network_id.0
}
dynamic "block_device" {
for_each = var.block_devices
content {
uuid = block_device.value.uuid != "" ? block_device.value.uuid : null
source_type = block_device.value.source_type
destination_type = block_device.value.destination_type
volume_size = block_device.value.volume_size
volume_type = block_device.value.volume_type
boot_index = block_device.value.boot_index
delete_on_termination = block_device.value.delete_on_termination ? block_device.value.delete_on_termination : null
}
}

On peut pousser le processus de variabilisation jusqu’au root module :

module "module-bastion" {
source = "../modules/bastion"
access_protocol = var.bastion_access_protocol
port_ssh = var.bastion_port_ssh
access_address = var.bastion_access_address
sg_name = "sg-${var.client}-${var.contexte}-bastion"
instance_name = "ecs-${var.client}-${var.contexte}-bastion"
instance_count = var.bastion_instance_count
availability_zone = var. bastion_availability_zone
flavor_name = var.bastion_flavor_name
key_name = module.module-keypair.keypair_id
security_groups = ["sg-${var.client}-${var.contexte}-bastion"]
subnet_id = module.module-network.subnet_ids
network_id = module.module-network.network_ids
new_eip = var.bastion_new_eip
eip_bandwidth = var.bastion_eip_bandwidth

Ainsi, on a juste à remplir un fichier de variable avec les valeurs que l’on veut, par exemple le nombre de serveurs à déployer, la quantité de RAM et CPU ou encore la capacité des disques ainsi que le type. De cette manière, lors du déploiement d’une nouvelle infrastructure, on reprend les modules déjà existants en changeant simplement la valeur des variables dans le root module.

bastion_new_eip = true
bastion_eip_bandwidth = 8
bastion_os_name = "OBS Ubuntu 18.04"
bastion_os_region = "eu-west-0"
bastion_access_protocol = "tcp"
bastion_port_ssh = "22"
bastion_access_address = "0.0.0.0/0"
bastion_instance_count = 1
bastion_availability_zone = "eu-west-0a"
bastion_flavor_name = "s3.small.1"
bastion_os_volume_size = 40
bastion_os_volume_delete_on_termination = true
bastion_os_volume_type = "SATA"

Il est également possible de faire appel à des ressources déjà existantes sur le cloud, grâce à la fonction “data” pour intégrer une nouvelle machine à un réseau existant.

data "flexibleengine_vpc_subnet_v1" "networks" {
name = var.network_name
}

On remarquera que cette technique demande plus d’organisation, il est recommandé de séparer le root module du module. Ainsi, on ne touche pas à ce dernier et on modifie le premier pour le faire correspondre à notre besoin. Ici, les fichiers à modifier sont dans le dossier “infra” et le module auquel on ne touche pas se situe dans le fichier “module”. Il faut noter également que les variables ont besoin d’être définies (ici dans les fichiers variables.tf), afin que Terraform puisse avoir un référentiel de celles-ci ainsi que leurs types (string, number, bool, etc..).

TITRE : CAPTURE D'ÉCRAN TERRAFORM

module-terraform-YPSI-SAS

Les étapes de déploiement

Avant de déployer l’infrastructure, Terraform propose des commandes pour vérifier le bon fonctionnement des ressources décrites:

  • Terraform init : initialise le fichier courant où se trouve le fichier de configuration ;
  • Terraform validate : permet de vérifier la syntaxe du code ;
  • Terraform plan : vérifie la cohérence avec les éléments existants et affiche les changements de l’infrastructure ;
  • Terraform apply : applique le code.

 

Lorsque l’infrastructure est déployée, Terraform crée un fichier d’état où toute l’infrastructure qui a été déployée est décrite. Cela permet à Terraform de comparer les changements qui ont été faits dans la description et ce qui a été déployé, afin de ne pas tout redéployer. Aussi, si des modifications concernant des ressources déployées avec Terraform ont été apportées sur la console de l’hébergeur cloud, elles peuvent être ajoutées automatiquement en rafraîchissant le fichier d’état.

Terraform permet également de détruire toute l’infrastructure ou des ressources ciblées de façon automatique en se basant sur le fichier d’état.

Les avantages et les inconvénients de son utilisation

AVANTAGES

Déploie rapidement des infrastructures complexes

Open source

Beaucoup de documentations en ligne

INCONVÉNIENTS

Demande du temps pour préparer les modules

Pas de marche arrière possible pendant le déploiement

Fonction de collaboration et de sécurité payante

Vous avez encore un doute sur l’efficacité de Terraform ? Nous avons confronté pour vous lors du YPSI CHALLENGE, la méthode manuelle et celle automatique (avec Terraform) de déploiement d’une infrastructure cloud. N’hésitez pas à y jeter un coup d’oeil afin de définitivement faire votre choix.

Contact de l’auteur : quentin.bassemayousse@ypsi.fr

Suivez-nous

Laisser un commentaire