Aller au contenu

Débuter avec Terraform

Dans cet article

Information

Terraform est un outil d'infrastructure en tant que code (Infrastructure as Code) développé par HashiCorp. L'état souhaité de l'infrastructure est décrit dans des fichiers de configuration écrits en HCL, et Terraform met les ressources réelles en adéquation avec cette description en appelant l'API du fournisseur de services via un module dédié appelé "provider". Chaque opération effectuée est enregistrée dans un fichier d'état (state file), de sorte que l'outil sait ce qui existe déjà et n'applique que les modifications manquantes lors de l'exécution suivante. Terraform permet de prévisualiser les changements avant de les appliquer, de conserver la configuration sous contrôle de version et de reproduire des environnements identiques, ce qui en fait un moyen pratique de gérer des serveurs, des réseaux et des services, quel que soit leur hébergeur.

Lorsque vous ne gérez qu'un seul serveur, le commander manuellement est plus rapide. Une fois que vous en avez quinze, créés à des moments différents par différents administrateurs, personne ne se souvient pourquoi l'un tourne sous Ubuntu 20.04 alors que la machine voisine est sous la 22.04. Un fichier de configuration conserve cet historique de manière autonome, et il vous permet également de recréer le même environnement sans avoir à reconstruire une séquence de clics de mémoire.

Avec notre provider, le flux de travail est le suivant. Le fichier liste le preset, l'emplacement, le système d'exploitation et le plan de trafic, après quoi terraform apply passe la commande et attend la fin du déploiement. L'exécuter à nouveau ne duplique rien, car Terraform se souvient des ressources qu'il a créées. La commande terraform plan affiche les changements à venir sans en effectuer aucun.

Le provider fonctionne avec l'ensemble du catalogue, y compris les VPS, VDS, serveurs dédiés et serveurs GPU, les adresses IP supplémentaires, les clés SSH et les zones DNS. La référence complète pour les ressources et les sources de données est disponible sur le Terraform Registry et dans le dépôt hostkey-cloud/terraform-provider-hostkey-com. Ce qui suit est le scénario de base : la commande d'un serveur virtuel.

Ce dont vous avez besoin pour travailler avec Terraform

  • Un compte dans le panneau de contrôle Invapi avec des fonds sur le solde, car la commande d'un serveur est une opération payante ;
  • une clé API ;
  • une clé SSH ;
  • Terraform 1.0 ou version supérieure.

Attention

Le compte doit posséder au moins un serveur. Invapi n'ouvre pas de session pour un compte sans services, et l'authentification échouera avec le message No appropriate servers found. Si le compte est nouveau, commandez le premier serveur via le panneau de contrôle et créez les suivants avec Terraform.

Étape 1. Installer Terraform

Terraform fonctionne sur Linux, macOS et Windows, et vous pouvez l'installer de deux manières : soit via un gestionnaire de paquets, soit manuellement en téléchargeant et en décompressant le binaire précompilé.

Windows

Téléchargez l'archive, décompressez terraform.exe dans un dossier dédié tel que C:\terraform, et ajoutez ce dossier à la variable d'environnement Path.

Fermez et rouvrez ensuite le terminal, car la nouvelle valeur de Path ne sera pas appliquée avant cela. Pour vérifier l'installation :

terraform -v

Linux

wget https://releases.hashicorp.com/terraform/1.15.8/terraform_1.15.8_linux_amd64.zip
unzip ./terraform_1.15.8_linux_amd64.zip
sudo mv ./terraform /usr/local/bin
terraform -v

macOS

brew install terraform
terraform -v

Étape 2. Créer une clé API

La clé est créée dans le panneau de contrôle Invapi. Cliquez sur votre nom d'utilisateur en haut à droite et sélectionnez API keys :

Cliquez sur Add new et remplissez le formulaire.

Champ Valeur
Name 5 à 30 caractères, lettres latines, chiffres, _ et - uniquement
Restrict a new API key only for the server Any
IP ACL Laissez vide pour autoriser l'accès depuis n'importe quelle adresse
Set login notification method None
Active Selected

Le champ Restrict a new API key only for the server lie la clé à un service unique, et le provider doit pouvoir commander de nouveaux serveurs, la valeur doit donc être Any.

Le champ IP ACL limite l'accès aux adresses listées. Cela améliore la sécurité, cependant, avec une adresse IP dynamique, la clé cessera de fonctionner dès que l'adresse changera ; laissez donc le champ vide pour débuter, et pour l'intégration continue, listez les adresses de vos serveurs de build.

Cliquez sur Create. La clé ne s'affiche qu'une seule fois.

Attention

Enregistrez la clé immédiatement, car nous ne conservons que son hash et la valeur ne peut pas être récupérée. Si vous la perdez, vous devrez en créer une nouvelle.

Étape 3. Préparer la configuration

Exemple de configuration

Des exemples de configuration prêts à l'emploi sont disponibles dans le dépôt du provider. Pour une configuration de base, consultez l'exemple examples/basic.

Créez un répertoire de projet, par exemple hostkey-terraform. Les fichiers de configuration utilisent l'extension .tf et leurs noms sont arbitraires, car Terraform fusionne chaque fichier .tf du répertoire en une configuration unique. Notre exemple utilise trois fichiers.

main.tf

Le premier bloc définit le provider et la version requise de Terraform.

terraform {
  required_providers {
    hostkey = {
      source  = "hostkey-cloud/hostkey-com"
      version = "~> 0.2"
    }
  }
  required_version = ">= 1.0"
}

provider "hostkey" {}

Remarque

À partir de la version 0.2, le provider est publié séparément pour chaque système de facturation. Le package hostkey-com fonctionne avec invapi.hostkey.com, il n'y a donc pas d'endpoint API à choisir et le bloc provider reste vide.

Vient ensuite la vérification du catalogue. Ces blocs ne créent aucun ressource et ne sont pas facturés, ils demandent simplement à l'API les listes des presets et des plans de trafic disponibles pour la commande :

data "hostkey_presets" "selected" {
  location = var.location
  name     = var.preset_name
}

data "hostkey_traffic_plans" "for_preset" {
  location    = var.location
  instance_id = data.hostkey_presets.selected.presets[0].id
}

output "catalog_preset" {
  value = data.hostkey_presets.selected.presets
}

output "catalog_traffic_plans" {
  value = data.hostkey_traffic_plans.for_preset.traffic_plans
}

Cette vérification est utile pour deux raisons. Le provider exige une correspondance exacte du nom, et le catalogue contient des noms de plans de trafic similaires, par exemple 3 TB / 1 Gbps VM et 3Tb traffic (1Gbps) VM. De plus, le contenu du catalogue dépend de l'emplacement et évolue avec le temps ; un preset disponible aujourd'hui peut ne plus l'être demain.

Le serveur lui-même est décrit ensuite :

resource "hostkey_server" "web" {
  preset_name       = var.preset_name
  location_name     = var.location
  traffic_plan_name = var.traffic_plan_name
  deploy_period     = "monthly"

  os_name   = "Ubuntu 22.04"
  root_pass = var.root_pass
  ssh_key   = file(pathexpand(var.ssh_public_key_path))

  power_state = "on"

  cancellation_type   = 1
  cancellation_reason = "terraform"

  tags = {
    env = "demo"
  }

  timeouts {
    create = "90m"
    update = "90m"
    delete = "30m"
  }
}

Le bloc timeouts définit le temps pendant lequel Terraform attend la fin d'une opération. Le déploiement prend généralement quelques minutes, mais si l'attente est interrompue par un timeout, la commande reste payée alors que Terraform perd sa trace.

L'argument cancellation_type réglé sur 1 annule le service immédiatement, tandis que 0 le laisse fonctionner jusqu'à la fin de la période payée.

Remarque

L'argument hostname est délibérément omis de l'exemple. Lorsqu'il est omis, le provider génère un nom unique tel que tf-44067425, et le service apparaît sous ce nom dans le panneau de contrôle. Le nom à l'intérieur du système d'exploitation peut différer, car Invapi ne le transmet pas à l'invité ; la seule façon de le vérifier est d'exécuter hostname sur le serveur lui-même.

La clé SSH dans le stockage du compte est créée séparément :

resource "hostkey_ssh_key" "deploy" {
  name = "tf-deploy"
  key  = file(pathexpand(var.ssh_public_key_path))
}

Ceci n'est pas la même chose que l'attribut ssh_key de hostkey_server. L'attribut du serveur écrit la clé sur la machine lors de l'installation du système d'exploitation, tandis que la ressource hostkey_ssh_key stocke la clé dans le compte pour une utilisation ultérieure.

Le fichier se termine par des blocs output. Après la commande, Terraform affiche l'adresse du serveur, son identifiant et le numéro de facture, et terraform output main_ipv4 permet de récupérer l'adresse à tout moment ultérieurement, ce qui est pratique pour les processus automatisés :

output "server_id" {
  value = hostkey_server.web.id
}

output "main_ipv4" {
  value = hostkey_server.web.main_ipv4
}

output "invoice" {
  value = hostkey_server.web.invoice
}

variables.tf

variable "location" {
  type    = string
  default = "FI"
}

variable "preset_name" {
  type    = string
  default = "vm.v2-pico"
}

variable "traffic_plan_name" {
  type    = string
  default = "3 TB / 1 Gbps VM"
}

variable "root_pass" {
  type      = string
  sensitive = true
}

variable "ssh_public_key_path" {
  type    = string
  default = "~/.ssh/id_ed25519.pub"
}

terraform.tfvars

Ce fichier contient le mot de passe, il n'est donc pas envoyé au contrôle de version :

root_pass = "StrongPass1%"

# Les valeurs par défaut peuvent être écrasées ici
# location          = "NL"
# preset_name       = "vm.v3-pico"
# traffic_plan_name = "5 TB / 1 Gbps VM"

Attention

Le mot de passe root doit comporter entre 8 et 30 caractères et contenir une lettre majuscule, une lettre minuscule, un chiffre et l'un des caractères suivants : %, -, _, +. Les caractères @ et # ne sont pas autorisés. Le mot de passe est stocké dans le fichier d'état Terraform et est envoyé en texte clair dans l'e-mail de préparation du serveur ; changez-le une fois le serveur déployé.

Étape 4. Initialiser le provider

La clé est transmise via une variable d'environnement afin qu'elle ne figure pas dans les fichiers du projet :

$env:HOSTKEY_API_KEY = "your-key"

Sur l'invite de commande Windows, utilisez set HOSTKEY_API_KEY=your-key, et sur Linux et macOS export HOSTKEY_API_KEY="your-key". La variable ne s'applique qu'à la session actuelle du terminal.

Remarque

La clé est déjà nécessaire lors de l'étape de planification (plan), car le provider compare les noms de la configuration avec le catalogue et échouera sans accès à l'API.

Ensuite, le provider doit être téléchargé :

terraform init

Terraform télécharge le provider et crée un fichier .terraform.lock.hcl avec la version exacte. Ce fichier est envoyé sur le dépôt, car il garantit que tous les membres du projet disposent de la même version installée.

Étape 5. Valider la configuration

La syntaxe est vérifiée sans appeler l'API :

terraform validate

Une vérification réussie affiche Success! The configuration is valid.

Vient ensuite le plan, qui montre les changements à venir sans en effectuer aucun :

terraform plan

La ligne de résumé. Attendez-vous à Plan: 2 to add, 0 to change, 0 to destroy, soit le serveur et la clé SSH.

Les identifiants résolus. Le provider remplit preset_id, os_id et traffic_plan_id à côté des noms, et si un nom n'est pas trouvé dans le catalogue, le plan échoue avant toute facturation.

Le catalogue. La section Changes to Outputs liste les presets et les plans de trafic, et les valeurs dans la configuration doivent être écrites exactement de la même manière.

Étape 6. Commander le serveur

terraform apply

Terraform affiche le plan une nouvelle fois et demande une confirmation ; tapez yes et appuyez sur Enter.

Attention

La commande est payée à partir de ce moment. Ne fermez pas la fenêtre du terminal et n'interrompez pas la commande, sinon la commande restera dans le panneau de contrôle alors que Terraform en aura perdu la trace.

La clé SSH est créée en premier, puis la commande du serveur commence, et Terraform a déterminé cet ordre de lui-même grâce aux dépendances.

Après cela, apparaissent les lignes Still creating..., rafraîchies toutes les dix secondes, pendant que le provider interroge l'API et attend la fin de l'installation. Pendant ce temps, le serveur est visible dans le panneau de contrôle :

Une fois terminé, les valeurs sont affichées. Il est utile de vérifier l'accès SSH en utilisant l'adresse reçue :

La clé spécifiée dans l'attribut ssh_key est déjà présente sur le serveur, aucune demande de mot de passe n'est donc requise. Le nouveau serveur apparaît dans le panneau de contrôle à côté de ceux commandés manuellement :

Étape 7. Modifier la configuration

Les modifications se répartissent en trois catégories :

  • Modifications sûres. Les tags et l'état d'alimentation sont appliqués à un serveur en cours d'exécution, et le plan les affiche comme update in-place.

  • Réinstallation du système d'exploitation. Modifier os_name, soft_name, root_pass ou ssh_key réinstalle le système d'exploitation sur le même serveur, ce qui signifie que toutes les données sur le disque sont perdues.

  • Une nouvelle commande. Modifier preset_name, location_name, traffic_plan_name ou deploy_period signifie que le serveur précédent est annulé et qu'un nouveau est commandé, vous serez donc facturé à nouveau. Le plan marque ces changements comme forces replacement.

Attention

Les modifications entraînant une réinstallation apparaissent dans le plan comme update in-place, exactement de la même manière qu'un changement de tag inoffensif. Le provider affiche un avertissement distinct concernant la perte de données ; avant de confirmer, il est donc utile de lire non seulement le plan, mais aussi les avertissements.

Étape 8. Détruire les ressources

terraform destroy

terraform destroy supprime toutes les ressources qui sont dans l'état Terraform actuel pour cette configuration. Terraform affichera la liste des ressources à supprimer et demandera une confirmation. Entrez yes et appuyez sur Enter.

Si vous devez supprimer une seule ressource, vous pouvez la spécifier avec -target. Par exemple :

terraform destroy -target=hostkey_server.web

Ici, web est le nom de la ressource provenant du bloc resource "hostkey_server" "web", et non l'ID du serveur du panneau de contrôle.

Une autre option consiste à supprimer la ressource des fichiers .tf et de lancer :

terraform apply

Terraform verra que la ressource n'est plus présente dans la configuration et la supprimera de l'infrastructure.

L'annulation du service est effectuée via Invapi, et la méthode d'annulation est déterminée par le paramètre cancellation_type : 1 annule le service immédiatement, tandis que 0 l'annule à la fin de la période payée.

Information

Avec une annulation immédiate (cancellation_type = 1), la partie inutilisée de la période payée est créditée sur le solde du compte proportionnellement au temps réel pendant lequel le service a fonctionné.

Importer des serveurs existants

Les serveurs commandés via le panneau de contrôle peuvent être placés sous la gestion de Terraform. L'identifiant est pris dans la colonne ID de la liste des serveurs :

terraform import hostkey_server.web 19463

Après l'importation, l'état contient les données réelles, c'est-à-dire l'identifiant, l'adresse, le statut et l'état d'alimentation. Les arguments de commande ne sont pas transférés depuis le panneau de contrôle, ils doivent donc être décrits manuellement dans la configuration. Le premier terraform apply après un import n'entraîne pas de réinstallation.

Dépannage

Remarque

No appropriate servers found lors de l'exécution du plan. Vérifiez que le compte possède au moins un service, car Invapi n'ouvre pas de session pour un compte sans services.

Remarque

Catalog name resolve failed. Le preset, le système d'exploitation ou le nom du plan de trafic spécifié n'est pas présent dans le catalogue pour l'emplacement sélectionné. Listez les valeurs disponibles via les sources de données hostkey_presets et hostkey_traffic_plans et mettez la configuration en adéquation avec elles.

Remarque

État pending:<invoice>. La commande est payée mais le déploiement n'est pas terminé, généralement parce que la connexion a été coupée. Exécuter à nouveau terraform apply reprend l'attente et ne passe pas une nouvelle commande. Si la facture n'est pas payée, réglez-la et relancez terraform apply. Le statut en direct du service est visible dans le panneau de contrôle.

Information

Vous trouverez plus d'informations sur Terraform lui-même dans la documentation officielle de HashiCorp, et les arguments spécifiques des ressources et des sources de données sont documentés dans le Terraform Registry.