Utiliser Terraform ou OpenTofu pour créer des VM sur Proxmox
Monter son environnement grâce à du code
Suite à un article portant sur l'utilisation de Terraform pour créer des LXC pour Proxmox, je souhaite approfondir le sujet en abordant cette fois la création de machines virtuelles.
L'objectif de ce document est de guider le déploiement de machines virtuelles sur un hôte Proxmox à partir d'un modèle créé à l'aide de Packer. Pour étendre ces déploiements à une plus grande échelle, il suffira de dupliquer les blocs de code et d'ajuster les valeurs en conséquence.
Prérequis : Une connaissance préalable de Terraform, des droits d'administration sur Proxmox, et la capacité à effectuer des manipulations sans contraintes majeures. J'utilise également OpenTofu, compatible avec Terraform sans modification de code au moment de la rédaction de cet article.
L'environnement de travail pour cet article est le suivant :
- un serveur Proxmox 8.1.x
- un éditeur de code
- Terraform 1.6.x ou Open Tofu 1.6.x
Préparation de l'environnement de travail
Avant de commencer le déploiement automatisé avec Terraform ou OpenTofu, assurez-vous que votre environnement est correctement configuré en suivant ces étapes :
- Installation de Terraform ou OpenTofu :
- Dans un terminal, procédez à l'installation de Terraform en suivant les indications de la documentation officielle d'HashiCorp, adaptées à votre système d'exploitation. De même, pour OpenTofu, référez-vous à ce lien de documentation pour obtenir toutes les informations nécessaires. Assurez-vous que Terraform ou OpenTofu est correctement installé en vérifiant la version :
$ terraform version
.
- Dans un terminal, procédez à l'installation de Terraform en suivant les indications de la documentation officielle d'HashiCorp, adaptées à votre système d'exploitation. De même, pour OpenTofu, référez-vous à ce lien de documentation pour obtenir toutes les informations nécessaires. Assurez-vous que Terraform ou OpenTofu est correctement installé en vérifiant la version :
- Accès à Proxmox :
- Assurez-vous d'avoir un accès à votre hôte Proxmox via un navigateur web.
- Vérifiez aussi l'accès via SSH pour des opérations en ligne de commande.
- Identifiants pour Proxmox : Disposez des identifiants de l'utilisateur "root" ou d'un autre utilisateur ayant des privilèges élevés sur Proxmox pour créer des machines virtuelles et gérer le stockage.
Avec ces prérequis en place, vous êtes prêt à automatiser le déploiement de machines virtuelles avec Terraform ou OpenTofu.
Préparation de Proxmox
Pour simplifier les opérations dans vos environnements de test et raccourcir ce document, vous pouvez utiliser le compte root@pam
créé lors de l'installation de Proxmox. Ce compte possède tous les privilèges. Pour une gestion plus fine, la création d'un token pour le compte root est conseillée.
Le code Terraform complet
Enfin, voici le code complet que j'utilise pour créer des VM sur Proxmox avec Terraform ou OpenTofu. Le code est assez complet, j'aime bien avoir le maximum d'informations et d'attributs pour préciser au maximum mes ressources.
Fichier "provider.tf" :
### provider.tf
terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = ">=0.41.0"
}
}
}
provider "proxmox" {
api_token = var.pve_api_token
endpoint = var.pve_host_address
insecure = true
tmp_dir = var.tmp_dir
}
Fichier "variables.tf" :
### variables.tf
variable "clone_node_name" {
type = string
}
variable "clone_vm_id" {
type = number
}
variable "cloudinit_dns_domain" {
type = string
}
variable "cloudinit_dns_servers" {
type = list(string)
}
variable "cloudinit_ssh_keys" {
type = list(string)
}
variable "cloudinit_user_account" {
type = string
}
variable "datastore_id" {
type = string
}
variable "disk_file_format" {
type = string
}
variable "node_name" {
type = string
}
variable "pve_api_token" {
type = string
}
variable "pve_host_address" {
type = string
}
variable "tmp_dir" {
type = string
}
variable "vm_bridge_lan" {
type = string
}
variable "vm_cpu_cores_number" {
type = number
}
variable "vm_cpu_type" {
type = string
}
variable "vm_description" {
type = string
}
variable "vm_disk_size" {
type = number
}
variable "vm_id" {
type = number
}
variable "vm_memory_max" {
type = number
}
variable "vm_memory_min" {
type = number
}
variable "vm_name" {
type = string
}
variable "vm_socket_number" {
type = number
}
Fichier "variables.auto.tfvars", c'est ce fichier qu'il faut modifier pour que vous puissiez avoir un conteneur correspondant à votre besoin :
### variables.auto.tfvars
clone_node_name = "pve_host"
clone_vm_id = 99999
cloudinit_dns_domain = "your.domain.net"
cloudinit_dns_servers = ["9.9.9.9"]
cloudinit_ssh_keys = ["ssh-ed25519 changeme"]
cloudinit_user_account = "jho"
datastore_id = "local"
disk_file_format = "raw"
node_name = "pve"
pve_api_token = "terrabot@pve!token_name=token_secret"
pve_host_address = "https://pve:8006"
tmp_dir = "/tmp"
vm_bridge_lan = "vmbr0"
vm_cpu_cores_number = 2
vm_cpu_type = "x86-64-v2-AES"
vm_description = "Managed by terraform."
vm_disk_size = 64
vm_id = 9993
vm_memory_max = 8192
vm_memory_min = 4096
vm_name = "tf_example"
vm_socket_number = 1
Fichier "vm.tf" : J'utilise Cloud-Init pour faciliter la configuration de la machine au niveau réseau. Si vous ne souhaitez pas utiliser Cloud-Init, supprimez le bloc "{ initialization }
" :
### vm.tf
resource "proxmox_virtual_environment_vm" "vm1_example" {
description = var.vm_description
keyboard_layout = "fr"
machine = "q35"
migrate = true
name = var.vm_name
node_name = var.node_name
scsi_hardware = "virtio-scsi-single"
started = true
tablet_device = false
vm_id = var.vm_id
clone {
datastore_id = var.datastore_id
full = true
node_name = var.clone_node_name
retries = 2
vm_id = var.clone_vm_id
}
agent {
enabled = true
trim = true
}
cpu {
cores = var.vm_cpu_cores_number
numa = true
sockets = var.vm_socket_number
type = var.vm_cpu_type
}
disk {
datastore_id = var.datastore_id
discard = "on"
file_format = var.disk_file_format
interface = "scsi0"
iothread = true
size = var.vm_disk_size
}
initialization {
datastore_id = var.datastore_id
dns {
domain = var.cloudinit_dns_domain
servers = var.cloudinit_dns_servers
}
ip_config {
ipv4 {
address = "172.16.241.10/16"
gateway = "172.16.0.1"
}
}
user_account {
keys = var.cloudinit_ssh_keys
username = var.cloudinit_user_account
}
}
memory {
dedicated = var.vm_memory_max
floating = var.vm_memory_min
}
network_device {
bridge = var.vm_bridge_lan
model = "virtio"
}
operating_system {
type = "l26"
}
startup {
order = "1"
up_delay = "20"
down_delay = "20"
}
serial_device {}
}
Dans ces fichiers, des valeurs sont à modifier et doivent correspondre à vos besoins. Relisez bien chaque fichier et adaptez-les selon votre infrastructure. J'ai maximisé l'utilisation de variables pour faciliter les ajustements.