how-to-install-and-manage Help

Terraform

Terraform est un outil d'infrastructure en tant que code (IaC) open-source développé par HashiCorp. Il permet aux utilisateurs de définir et de provisionner des infrastructures de datacenter dans un langage de configuration déclaratif (connu sous le nom de HashiCorp Configuration Langage - HCL), ou en utilisant le JSON.

Nous allons utiliser terraform pour déployer notre infrastructure. Sur toute la partie hyperviseurs et VM terraform sera utilisé.

Terraform dialoguera principalement avec Xen Orchestra pour la gestion des VMs et des hyperviseurs.

Provider

Pour le provider, nous avons utilisé le provider qui est fournis avec Xen orchestra.

Pour l'importer dans terraform, nous avons créé un fichier main.tf qui regroupe toutes les informations liées au provider de XenOrchestra.

main.tf

# Pour chercher le module via `tofu init` terraform { required_providers { xenorchestra = { source = "vatesfr/xenorchestra" } } } # Les variables liées à l'authentification provider "xenorchestra" { # Must be ws or wss url = var.XOA_URL username = var.XOA_USER password = var.XOA_PASSWORD insecure = true }

Liaison à XenOrchestra

La première étape est de générer des identifiants sur XenOrchestra qui seront dédiés à terraform. Il est important de créer un compte générique à terraform pour que dans les logs de XenOrchestra. Il peut y avoir la possibilité d'identifier les actions réalisées par terraform et celle qui n'ont pas été éxécuté par terraform.

Une fois l'utilisateur créé dans XenOrchestra, il faut créer les variables de connexions.

variable.tf

variable "XOA_URL" { description = "URL de xen orchestra" type = string } variable "XOA_PASSWORD" { description = "PASS XO" type = string } variable "XOA_USER" { description = "Utilisateur dédié à terraform XO" type = string }

Ensuite, nous utiliserons les variables d'environnement pour définir les variables

En se rendant dans le projet gitlab terraform. Puis SettingsCI/CDVariables. On cliquera sur add variable

variable-tf-gitlab

Et on fera cette étape pour le mot de passe et l'URL.

Configuration de l'environnement pour XO

Pour une vm, nous avons besoin de data pour définir l'environnement du cluster à utiliser.

Dans XCP-NG plusieurs informations sont nécessaires pour l'environnement du cluster. Il faut une pool qui définira l'ensemble d'hôtes où pourra être déployé la VM. Ensuite, il faut le réseau qui sera utilisé par la VM, le template utilisé pour la VM. Et enfin la pool de stockage pour la VM.

Tout ceci a été renseigné dans le fichier xen_orchestra.tf

# Permet de définir la pool de stockage data "xenorchestra_sr" "storage" { for_each = var.deploy_vm name_label = each.value.name_sr } # Permet de finir la pool XCPNG data "xenorchestra_pool" "pool" { for_each = var.deploy_vm name_label = each.value.pool } # Permet de définir le template à utiliser par la vm data "xenorchestra_template" "vm_template" { for_each = var.deploy_vm name_label = each.value.template pool_id = data.xenorchestra_pool.pool[each.key].id } # Permet de définir le réseau à utiliser data "xenorchestra_network" "network" { for_each = var.deploy_vm name_label = each.value.network pool_id = data.xenorchestra_pool.pool[each.key].id }

Création de la VM

Ensuite, il fallait créer un template pour terraform avec toutes les ressources nécessaires pour la création de la VM.

VM

Tout cela a été défini dans le fichier

vm.tf

resource "xenorchestra_vm" "vm" { for_each = var.deploy_vm name_label = each.value.name name_description = "Deployed by Terraform" memory_max = each.value.ram cpus = each.value.cpus template = data.xenorchestra_template.vm_template[each.key].id cloud_config = templatefile("cloud-init.tftpl", { host = each.value.name user = "nixos" }) cloud_network_config = templatefile("cloud_network_config.tftpl", { ipv4 = each.value.ipv4 ipv4_gw = each.value.ipv4_gw dns01 = each.value.dns1 dns02 = each.value.dns2 }) hvm_boot_firmware = "uefi" network { network_id = data.xenorchestra_network.network[each.key].id } auto_poweron = true disk { size = each.value.disk sr_id = data.xenorchestra_sr.storage[each.key].id name_label = "${each.value.name}-disk" } tags = [ each.value.tags_function, each.value.tags_os, each.value.tags_backup ] }

Dans ce fichier, nous retrouvons toutes les informations liées à la création de la VM. On y retrouve le nom de la VM, la description, la mémoire, le nombre de CPU, le template, le cloud-config, le réseau, le disque, etc.

TFVARS

Il n'était pas possible de marquer toutes les informations directement dans le fichier vm.tf. C'est pour cela que nous avons utilisé des boucles for et un fichier tfvars afin de provisionner toutes les VMs.

terraform.tfvars

deploy_vm = { # NTP servers ntp-1 = { name = "ntp-uranium-01" vm_template = "nixos-24.11" pool = "uranium" cpus = 1 ram = 1073741824 disk = 10737418240 name_sr = "ssd-uranium" network = "PA-NET" tags_function = "ntp" tags_os = "nixos-24.11" tags_backup = "do-not-backup" ipv4 = "10.50.75.1/16" ipv4_gw = "10.50.255.254" dns1 = "8.8.8.8" dns2 = "1.1.1.1" } }

Voici un exemple uniquement pour une VM, ensuite il suffit de copier-coller le block et de changer les informations pour chaque VM.

Template cloud init

Pour le cloud init, nous avons utilisé un fichier template qui sera utilisé pour la création de la VM. Ce fichier nous permet de définir le nom de la VM et l'utilisateur qui sera utilisé pour la connexion. Le template terraform nous permettra de générer un fichier cloud init unique pour chaque VM.

cloud-init.tftpl

#cloud-config hostname: ${host} user: ${user} ssh_authorized_keys: - ${ssh_key}

Puis la meme chose, mais pour la configuration réseau

network: version: 2 ethernets: enX0: dhcp4: no addresses: - ${ipv4} gateway4: ${ipv4_gw} nameservers: addresses: - ${dns01} - ${dns02}

Utilisation de terraform

Pour utiliser terraform, il suffit de lancer les commandes suivantes:

tofu init tofu plan tofu apply -auto-approve

tofu init permet d'initialiser le projet terraform tofu plan permet de voir les changements qui seront effectués tofu apply -auto-approve permet d'appliquer les changements

Voici une démonstration vidéo

CI/CD avec Gitlab

Pour automatiser le déploiement de l'infrastructure avec Terraform, nous avons utilisé GitLab CI/CD. Nous avons créé un fichier .gitlab-ci.yml qui contient les étapes nécessaires pour déployer l'infrastructure. Et utiliser le store terraform de gitlab pour stocker l'état de l'infrastructure.

Initialiser le store terraform de gitlab

Pour initialiser le store terraform de gitlab, il faut se rendre dans le projet gitlab terraform. Et copier l'id du projet dans le fichier main.tf dans la section terraform comme ceci :

terraform { required_providers { xenorchestra = { source = "vatesfr/xenorchestra" } } backend "http" { address = "https://gitlab.innovalia.cc/api/v4/projects/<ID_PROJET>/terraform/state" } }

Une fois cela fait il faut lancer la commande tofu init pour initialiser le store terraform de gitlab.

state-terraform.png

Fichier .gitlab-ci.yml

Pour automatiser le déploiement de l'infrastructure avec Terraform, nous avons créé un fichier .gitlab-ci.yml. Ce fichier contient les étapes nécessaires pour déployer l'infrastructure à chaque commit sur la branche main.

gitlab-ci.yml

image: alpine:3.20 before_script: - apk add jq curl - curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh - chmod +x ./install-opentofu.sh && ./install-opentofu.sh --install-method apk --opentofu-version 1.10.2 stages: - validate - plan - apply variables: TF_IN_AUTOMATION: "true" TOFU_LOG: "TRACE" validate: stage: validate script: - tofu init - tofu validate plan: stage: plan script: - tofu init - tofu plan -out=tfplan artifacts: paths: - tfplan apply: stage: apply when: manual script: - tofu init - tofu apply -auto-approve tfplan

Ce fichier permet de déployer l'infrastructure à chaque fois qu'il y a un commit sur la branche main.

Execution de la pipeline

tofu-exec-ci.png
Last modified: 13 July 2025