L'objectif de cet article est préparer un environnement Proxmox destiné à servir de provider à Terraform.
Le principe est le suivant: Terraform va s'adresser à l'API de Proxmox, définie par l'URL https://<serveur>:8006/api2/json , pour créer des machines virtuelles ou des conteneurs LXC sous forme de ressources (terminologie Terraform). Dans le cas d'une machine virtuelle, on peut démarrer sur une ISO avec un fichier kickstart pour installer l'OS from scratch, ou partir d'un template. Dans les deux cas, l'API cloud-init pourra être utilisée pour assigner une configuration réseau à la machine virtuelle, un utilisateur, une clef SSH, ...
Préparation
Clefs SSH
On peut utiliser une clef existante où en générer une spécialement pour cet usage: ssh-keygen -t rsa -b 2048 -C "Terraform admins" -P "P4ssPhr4s3" -f terraform_admins
Pour la suite de l'article, il sera plus facile d'ajouter notre clef à l'agent SSH: ssh-add terraform_admins
VM Template
Voir:
- https://pve.proxmox.com/wiki/Cloud-Init_Support
- https://pve.proxmox.com/wiki/Cloud-Init_Support#_cloud_init_specific_options
- https://pve.proxmox.com/wiki/Cloud-Init_FAQ#Creating_a_custom_cloud_image
Il s'agit ici d'installer un distribution Debian sur une machine virtuelle type (4 vprocs, 16GB disque, 2GB RAM) , sans la configurer autrement qu'en définissant un mot de passe pour l'utilisateur root, et en installant les packages sudo qemu-guest-agent et cloud-init. Une fois cette machine installée, on l'éteint, on l'archive, et on la convertit en template Proxmox (bouton droit, convert to template).
Pour déployer cette image depuis Proxmox, il faudra:
- cloner la machine template: bouton droit, puis Clone, et sélectionner ensuite le mode Full Clone plutôt que Linked Clone.
- depuis le menu "Hardware", ajouter à la machine clonée un disque de type Cloud-Init Drive. Ce disque ne servant qu'à l'initialisation de la machine, on pourra le supprimer plus tard, et on peut par conséquent le créer en IDE sur le disque local.
- indiquer les éléments de configuration du menu Cloud-Init: utilisateur par défaut, mot de passe, configuration IP, clef SSH d'accès distant, ...
- finalement, démarrer la machine clonée et vérifier que tout est en place
Terraform
Installation sur une machine devop: https://docs.hacyran.net/node/1
On va maintenant pouvoir automatiser le déploiement précédent. Pour cela, on se "munit" d'une machine équipée de Terraform et qui servira aussi de base pour Ansible.
Provider
Il faut pouvoir indiquer à Terraform qu'on utilisera un serveur Proxmox pour déployer notre infrastructure. On crée donc le fichier proxmoxlab.tf avec le contenu suivant:
terraform {
required_providers {
proxmox = {
source = "telmate/proxmox"
version = ">=1.0.0"
}
}
}
provider "proxmoxlab" {
pm_user = "root@pam"
pm_password = "xXxXxXxX"
pm_api_url = "https://10.42.10.2:8006/api2/json"
pm_log_enable = true
pm_log_file = "terraform-provider-proxmoxlab.log"
pm_log_levels = {
_default = "debug"
_capturelog = ""
}
}
Première création d'une VM
On est prêt à tester un premier déploiement. Le contenu suivant est à enregistrer dans un fichier main.cf:
/* Uses cloud-init options from Proxmox 6.3 */
resource "proxmox_vm_qemu" "cloudinit-test" {
name = "tftest1"
desc = "tf description"
target_node = "proxmoxlab"
# vmid defaults to next available id
vmid = 2001
clone = "CIDebian10TMPL"
# If false, linked clone
full_clone = "false"
# qemu-guest-agent is installed in the template
agent = 1
# The destination resource pool for the new VM
# pool = "pool0"
/* Adds a disk
disk {
storage = "Rapid-fixed"
type = "virtio"
size = "8G"
cache = "writeback"
}
*/
# See: https://github.com/Telmate/terraform-provider-proxmox/issues/282
boot = "order=scsi0;ide2;net0"
# CPU settings
cores = 2
sockets = 1
vcpus = 0
# Memory settings
memory = 1024
# Do not set ballooning (and check why afterward)
balloon = 0
# Network settings
network {
model = "virtio"
bridge = "vmbr0"
firewall = "false"
}
# Display settings
vga {
type = "virtio"
memory = 0
}
# Preprovision (cloud-init)
os_type = "cloud-init"
# use a cloud-init configuration file
# cicustom = "user=local:snippets/write_file.yml"
# or use Proxmox variables
ciuser = "administrateur"
cipassword = "changeme"
ipconfig0 = "ip=10.42.11.13/16,gw=10.42.10.254"
searchdomain = "hacyran.net"
nameserver = "10.42.10.252"
# add this key to /root/.ssh/authorized_keys
sshkeys = <<EOF
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDM1NVDUjz5Of666AULV2Dw/Sfu47rduT0m0rqiacoxsSIjCT2Ucfy3hKBE5kxGUwlW0mMJus+4HauPy+qtjULHmcX3fV0VSljzUa8U+7o79cNpv3IGchPOtc2fPrufSojV4gg4te9cgZBCO34Wr5EjUBY0YT8p2UDSD+W++SLTy5fk4nwOmC54Ea7J8NcUBBIufKCIUEF0KQiCr4yBuMO/ZlGregHXIsKmU+jFA95NbDiIkkzHb0/jihVcSNQ9NQkM7dDNAIb5rkC+RPdo+Ky5Y4Imnn0h1BiTX+x+NCpj6f6kkGNf4rIp7U3d9KMxo6BzJM/9+zylWmKCFvNuvEdN Terraform admins
EOF
}
Les options utilisables sont décrites sur cette page: https://registry.terraform.io/providers/Telmate/proxmox/latest/docs/resources/vm_qemu
Si on active l'option cicustom, on peut utiliser le stockage "local" de Proxmox (ou n'importe quel autre stockage) en activant l'option "snippets". On bénéficie alors d'un répertoire /var/lib/vz/snippets où ranger ces fichiers de configuration Cloud-init.
On peut alors essayer les commandes suivantes:
- terraform init (va télécharger le plugin proxmox et initialiser le répertoire)
- terraform plan (résoud le déploiement et affiche ce qui sera effectué)
- terraform apply (effectue le plan affiché précédemment)
- terraform destroy (supprime la machine virtuelle)
Cloud-Init
https://cloudinit.readthedocs.io/en/latest/topics/examples.html#yaml-examples
Pour afficher le contenu de la configuration cloud-init, il suffit d'indiquer la commande: qm cloudinit dump <vmid> user
Ansible
Fichier inventaire
Voir: https://www.linkbynet.com/produce-an-ansible-inventory-with-terraform
On souhaite que la création d'une nouvelle machine virtuelle déclence l'ajout de cette machine à l'inventaire Ansible (/etc/ansible/hosts).
Troubleshoot
Certificat serveur
A la première tentative de connexion au serveur Proxmox, le certificat ne reflètait pas un récent changement d'adresse IP. On a pu le regénérer grace à la commande proxmox: pvecm updatecerts --force.
A la deuxième tentative, le certificat n'étant pas signé par une autorité de certification reconnue, il a fallu ajouter le contenu du fichier /etc/pve/pve-root-ca.pem (sur le serveur) au contenu du fichier /etc/ssl/certs/ca-certificates.crt.

A partir de ce moment, la commande "terraform plan" a pu aboutir.
Erreurs Proxmox
cannot delete 'balloon' - not set in current configuration! cannot delete 'vcpu' - not set in current configuration! cannot delete 'vga' - not set in current configuration!
Ces registres ne faisant pas partie de l'image template, la configuration terraform génère ces erreurs bégnines dans le log de Proxmox.
Could not generate persistent MAC address for tap2001i0: No such file or directory
On a aussi eu le cas où la VM n'avait pas assez de mémoire (1024MB) pour exécuter cloud-init.