Loading search data...

Prendre en main Hashicorp Terraform

Terraform, fais parti des meilleurs outils devops et en particulier de l’infrastructure-as-code. Mais pourquoi ?

Tout simplement car il est agnostique : Un logiciel est dit agnostique en termes de protocole lorsqu'il est indépendant des protocoles de communication.

En effet, Terraform est un outil indépendant à la plateforme visée. On peut aussi bien provisionner des machines dans le cloud (AWS, Azure, GCP, …) que sur du onprem (VmWare, Libvirt, )

Donc si jour vous voulez changer de fournisseur il suffira pratiquement juste à changer la partie déclarant le provider.

Rappel

Rappel : L’infrastructure as code (IaC) désigne le processus qui implique la mise à disposition d’environnements à l’aide d’un code contenant la configuration désirée.

Dans le cas de Terraform, le langage utilisé pour définir l’infrastructure est connu sous le nom de HashiCorp Configuration Langage (HCL).

De plus couplé à un système de gestion de code, comme git, plus un gestionnaire de configuration, comme Ansible, et vous avez tout pour faire un parfait gitops. Vous serez capable de reconstruire toute votre infrastructure à l’identique après une catastrophe, un changement de fournisseur, …

Mise en pratique

Je vous propose ici de découvrir comment utiliser Terraform avec libvirt. Je vous conseille de monter cet environnement de dev qui contient tout ce qu’il faut.

Installer et configurer Terraform

Il suffit juste un petit curl et ca fonctionne.

wget https://releases.hashicorp.com/terraform/0.14.5/terraform_0.14.5_linux_amd64.zip
unzip terraform_0.14.5_linux_amd64.zip
sudo mv terraform /usr/local/bin

On lance la commande pour contrôler que tout fonctionne :

terraform --version

Terraform v0.14.5

terraform init

La deuxième commande permet de créer les répertoires qui vont nous servir à installer le plugin libvirt.

Installer le plugin libvirt

Si vous avez pris mon environnement de dev rien à installer, ca fonctionne de suite. Sinon il faudra installer libvirt et mkisofs (on va utiliser cloud-init).

La c’est un peu plus compliqué. En effet libvirt n’est pas fourni par hashicorp mais par un développeur répondant au nom de Duncan Mac-Vicar P.

Plutôt que de récupérer un binaire nous allons le compiler:

git clone https://github.com/dmacvicar/terraform-provider-libvirt.git
cd terraform-provider-libvirt
make
mkdir -p ~/.local/share/terraform/plugins/registry.terraform.io/hashicorp/libvirt/0.6.3/linux_amd64/
cp terraform-provider-libvirt ~/.local/share/terraform/plugins/registry.terraform.io/hashicorp/libvirt/0.6.3/linux_amd64

On relance la commande terraform init et normalement il va installer ce plugin.

cd  ..
terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/template...
- Finding latest version of hashicorp/libvirt...
- Installing hashicorp/template v2.2.0...
- Installed hashicorp/template v2.2.0 (signed by HashiCorp)
- Installing hashicorp/libvirt v0.6.3...
- Installed hashicorp/libvirt v0.6.3 (unauthenticated)
...
Terraform has been successfully initialized!

La cli terraform

La CLI de terraform permet entre autre de :

  • init : La commande init va initialiser le répertoire de travail et vérifier que les plugins utilisés sont correctement installé.
  • plan : La commande plan permet de créer un plan d’exécution. Terraform va indiquer quelles actions il doit effectuer pour arriver au résultat décrit dans le fichier de configuration.
  • apply : L’infrastructure voulue est mise en place.
  • console : Cette commande est permet de faire du débogage, avant de créer un plan ou de l’appliquer.
  • destroy: L’infrastructure est détruite

Création de la première machine

On va voir un exemple permettant de créer une machine ubuntu en utilisant cloud-init pour sa configuration.

mkdir test-terraform
cd test-terraform

Les fichiers de configuration

Créer le fichier libvirt.tf. C’est le fameux fichier utilisant le langage HCL

 variables that can be overriden
variable "hostname" { default = "staticip" }
variable "domain" { default = "example.com" }
variable "ip_type" { default = "static" } # dhcp is other valid type
variable "memoryMB" { default = 1024*1 }
variable "cpu" { default = 1 }
variable "prefixIP" { default = "192.168.122" }
variable "octetIP" { default = "31" }


 instance the provider
provider "libvirt" {
  uri = "qemu:///system"
}

 fetch the latest ubuntu release image from their mirrors
resource "libvirt_volume" "os_image" {
  name = "${var.hostname}-os_image"
  pool = "default"
  source = "https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img"
  format = "qcow2"
}

 Use CloudInit ISO to add ssh-key to the instance
resource "libvirt_cloudinit_disk" "commoninit" {
          name = "${var.hostname}-commoninit.iso"
          pool = "default"
          user_data = data.template_file.user_data.rendered
          network_config = data.template_file.network_config.rendered
}


data "template_file" "user_data" {
  template = file("${path.module}/cloud_init.cfg")
  vars = {
    hostname = var.hostname
    fqdn = "${var.hostname}.${var.domain}"
  }
}

data "template_file" "network_config" {
  template = file("${path.module}/network_config_${var.ip_type}.cfg")
  vars = {
    domain = var.domain
    prefixIP = var.prefixIP
    octetIP = var.octetIP
  }
}


 Create the machine
resource "libvirt_domain" "domain-ubuntu" {
  # domain name in libvirt, not hostname
  name = "${var.hostname}-${var.prefixIP}.${var.octetIP}"
  memory = var.memoryMB
  vcpu = var.cpu

  disk {
       volume_id = libvirt_volume.os_image.id
  }
  network_interface {
       network_name = "default"
  }

  cloudinit = libvirt_cloudinit_disk.commoninit.id

  # IMPORTANT
  # Ubuntu can hang is a isa-serial is not present at boot time.
  # If you find your CPU 100% and never is available this is why
  console {
    type        = "pty"
    target_port = "0"
    target_type = "serial"
  }

  graphics {
    type = "spice"
    listen_type = "address"
    autoport = "true"
  }
}

terraform {
  required_version = ">= 0.12"
}

output "ips" {
  #value = libvirt_domain.domain-ubuntu
  #value = libvirt_domain.domain-ubuntu.*.network_interface
  # show IP, run 'terraform refresh' if not populated
  value = libvirt_domain.domain-ubuntu.*.network_interface.0.addresses
}

Créer les deux fichiers cloud_init.cfg et network_config.cfg

cloud-config
hostname: ${hostname}
fqdn: ${fqdn}
manage_etc_hosts: true
users:
  - name: ubuntu
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: users, admin
    home: /home/ubuntu
    shell: /bin/bash
    lock_passwd: false
    ssh-authorized-keys:
      - ${file("/home/ubuntu/.ssh/id_rsa.pub")}
 only cert auth via ssh (console access can still login)
ssh_pwauth: false
disable_root: false
chpasswd:
  list: |
     ubuntu:linux
  expire: False
packages:
    - qemu-guest-agent
    - python3
 every boot
bootcmd:
    - [ sh, -c, 'echo $(date) | sudo tee -a /root/bootcmd.log' ]
 run once for setup
runcmd:
    - [ sh, -c, 'echo $(date) | sudo tee -a /root/runcmd.log' ]
 written to /var/log/cloud-init-output.log
final_message: "The system is finall up, after $UPTIME seconds"

le second :

version: 2
ethernets:
  ens3:
    dhcp4: true

Provisionning

Il suffit de lancer les commandes :

terrarform plan
terraform apply

Répondez yes à la commande apply.

Controlons si la vm a bien été provisionné :

sudo virsh list --all
 Id   Name                                        State
------------------------------------------------------------
 29   staticip-192.168.122.31                     running

Oui elle bien up ! Maintenant il suffit de lancer se connecter à la vm

ssh 192.168.122.31

On va controler le resultat de la commande cloud_init :

cat /var/log/cloud-init-output.log
Cloud-init v. 20.4.1-0ubuntu1~18.04.1 running 'init-local' at Thu, 04 Feb 2021 10:30:15 +0000. Up 7.43 seconds.
Cloud-init v. 20.4.1-0ubuntu1~18.04.1 running 'init' at Thu, 04 Feb 2021 10:30:17 +0000. Up 9.54 seconds.
ci-info: ++++++++++++++++++++++++++++++++++++++Net device info++++++++++++++++++++++++++++++++++++++
....
Processing triggers for ureadahead (0.100.0-21) ...
Processing triggers for systemd (237-3ubuntu10.44) ...
Thu Feb 4 10:30:34 UTC 2021
Cloud-init v. 20.4.1-0ubuntu1~18.04.1 running 'modules:final' at Thu, 04 Feb 2021 10:30:22 +0000. Up 14.06 seconds.
The system is finall up, after 25.96 seconds

Génial !!!

Voila maintenant détruisez la :

Décomissionnement

terraform destroy

A bientot !


Alimenter un blog comme celui-ci est aussi passionnant que chronophage. En passant votre prochaine commande (n'importe quel autre article) via ce lien, je recevrai une petite commission sans que cela ne vous coûte plus cher. Cela ne me permet pas de gagner ma vie, mais de couvrir les frais inhérents au fonctionnement du site. Merci donc à vous!

Mots clés :

devops, tutorials,

Autres Articles