Proxmox, Terraform et Ansible

Submitted by hacyran on Sun, 08/15/2021 - 09:35

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:

  1. cloner la machine template: bouton droit, puis Clone, et sélectionner ensuite le mode Full Clone plutôt que Linked Clone.
  2. 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.
  3. 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, ...
  4. 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.

Terraform Proxmox Certificate Error

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.