Terraform

IaC → Réconcilier le monde des Ops et celui des Devs

  • Versions / historique
  • Collaboration

Deux grandes familles d’outils : provisionnement et configuration.

Les outils de configuration sont Ansible, Puppet, etc.

Terraform est un outil de provisionnement.

Fonctionnalités

  • Langage déclaratif HCL
  • Gestion implicite des dépendances (même si ça peut être forcé)
  • Gestion de l’état via le state à conserver intact (sous peine de ne plus avoir de configuration dynamique)
  • Nous pouvons importer des ressources existantes dans le state

Providers : interface entre Terraform et les fournisseurs de service.

Resources : composants de l’infrastructure.

Data : informations sur les ressources (réutilisables)

Variables : paramètres de configuration.

Outputs : exposer des informations sur les ressources.

Debug : export TF_LOG=DEBUG/INFO/WARN/ERROR

HCL

  • Langage typé + objets
  • Support d’expressions ternaires
  • Fonctions de base pour manipuler des chaînes de caractères, valeurs numériques ou des sets.

Utilisation de Terraform

Structure du projet avec des noms de fichier recommandés : README.md, main.hcl.tf, providers.hcl.tf, terraform.tfvars (à ne pas versionner, on peut avoir des secrets dedans), variables.hcl.tf, et un dossier pour des modules réutilisables.

Les variables sont accessibles via var.ma_variable.

Une variable se définir avec une valeur par défaut, un type et une description (un paramètre spécial sensitive = truepeut être précisé).

Remarque : penser à utiliser un outil type Vault pour gérer les données sensibles (mdp, AK/SK, etc.)

Utilisation des datas :

data "outscale_subnet" "some_value" {
  filter {
    # ...
  }
}

Exemple d’output :

output "public_ip" {
  value = my_vm.bastion-a.public_ip
}

Commandes en CLI :

  • terraform init pour initier un projet.
  • terraform plan pour afficher le plan prévu pour l’exécution (selon les scripts HCL fournit).
  • terraform apply les modifications que nous aurons pu voir avec terraform_plan.
  • terraform destroy supprime les ressources créées via apply.

Documentation du provider Outscale : https://registry.terraform.io/providers/outscale/outscale/latest/docs.

Remarque : utiliser une variable d’environnement pour définir une variable Terraform via export TF_VAR_my_var=”${SOME_VAR_OR_VALUE}".

Gestion de l’état :

  • Stocker l’historique des changements sur notre infrastructure.
  • Peux-être hébergé sur un stockage objet.

Provisioners :

  • Besoins spécifiques de configuration et de gestion des ressources Terraform
  • local-exec (exécution locale)
  • remote-exec (exécution sur un hôte distant, par exemple une VM qu’on vient de créer)
  • file (spécifiquement pour du transfert de fichiers)
  • Attention : si le provisioner d’une ressource dépend d’une autre ressource, il faut bien prendre en compte la précédence dans la création de ces ressources. Par exemple, pour se connecter à une Machine Virtuelle en SSH, on a besoin de son adresse IP. Or celle-ci lui est ajoutée après création de la Machine Virtuelle (en principe, ces contraintes doivent être gérées par le provider).

Remarque : dans la plupart des cas, il sera plus logique d’utiliser un outil de configuration à la place du provisioner de Terraform.

Gestion du cycle dans Terraform :

  • Terraform gère normalement l’ordre de précédence des ressources en fonction des dépendances qui existent entre elle (à noter qu’une part de ce travail est à la charge du provider).
  • Contrôler la création, la destruction et le remplacement (par exemple, sauver une Public IP utilisé ailleurs; remplacer une ressource à sa suppression, par exemple pour un processus de mise à jour).
  • Déclencher des pré- et post-conditions à l’application de la recette.

Les modules

Ils permettent de réutiliser un même jeu de règles à plusieurs endroits.

L’arborescence du module est similaire à celle du projet Terraform (hormis le dossier “module”).

Dans une ressource, on bénéficie d’un paramètre «source» pour utiliser un module.

Il est possible de retrouver des modules opensource parmis les ressources de Hashicorp, sur Github, etc.

Il est possible de déclarer des variables « privées », locales au module. Elles permettent de réutiliser les paramètres ou récupérer des données spécifiques au module, et ainsi de réutiliser du code.

Utilisation :

  • Les arguments que prend le module au moment de son instanciation sont les variables déclarées dans le variables.hcl.t du module.
  • Les valeurs que l’on veut exporter hors du module doivent être dans des règles output.
  • Au moment d’utiliser le module, on va utiliser un bloc module avec l’ensemble des paramètres nécessaires au module.

Les workspaces

C’est la possibilité de réutiliser le même code pour plusieurs environnement, via des variables.

Les imports

Permettent de récupérer des ressources hors de notre projet Terraform, et d’en récupérer toutes les informations pour les appliquer sur une ressource de notre projet.

par exemple

resource "outscale_vm" "test" { }
terraform import outscale_vm.test i-abcdef01
resource "outscale_vm" "test" {
  tags {
    name "Env"
    value "local"
  }
}
terraform apply

Ici, on a récupéré toutes les caractéristiques de la Machine Virtuelle i-abcdef01 dans notre outscale_vm.test et ainsi de créer une Machine Virtuelle qui reprend ces caractéristiques.

Monter un environnement complet avec Terraform

Objectif :

  • Utiliser un module portant le projet, qui sera réutilisé dans deux environnements différents : staging et prod.

Notes :

  • Le provider doit être défini au moment où on utiliser le module (donc pas dans le module).
  • Les variables sont définis dans le module, mais leur valeur est attribuée au moment d’utiliser le module (± « instanciation ») : dans le dossier de chaque environnement, au moment d’instancier le module, on fournit la valeur que doivent prendre les variables.
  • La clé privée est générée pour chaque environnement, et doit avoir un nom différent en fonction de l’environnement : le code permettant de générer la clé privée est dans le module, mais il est utilisé depuis le dossier de l’environnement, et le nom de la clé est fournit en paramètre.
  • Le nom des ressources réseau dépend également de l’environnement pour lequel elles sont déployées (donc le code dans le module, le nom en paramètre du module).

Remarque : pour pouvoir faciliter la manipulation des ressources, prévoir un output des IP publiques des différents environnements.

Bonnes pratiques

  • Versionner son code HCL
  • Attention à la sécurité des données (e.g. sensitive, etc.) des environnements, etc.