Aller au contenu principal

Construire des OMI Outscale avec Packer

Dans le domaine du DevOps, la construction d'images de machines virtuelles (VM) est une étape fondamentale pour garantir l'efficacité et la reproductibilité des environnements de production et de développement. Aujourd'hui, je vais partager avec vous un guide détaillé sur la manière de construire des OMI Outscale en utilisant deux outils populaires dans l'univers DevOps : Packer et Ansible.

Quelques explications

Packer, un outil open-source développé par HashiCorp, permet de créer des images de machine virtuelle pour différentes plateformes à partir d'une source unique de configuration. Il est reconnu pour sa flexibilité et son efficacité, offrant une approche automatisée et cohérente dans la création d'images.

D'autre part, Ansible, un outil d'automatisation de configuration puissant, se distingue par sa simplicité et sa facilité d'utilisation. Grâce à sa nature déclarative, Ansible permet de configurer les VM de manière précise et reproductible.

L'intégration de Packer et Ansible dans le processus de construction d'OMI Outscale présente de nombreux avantages. Non seulement elle automatise le processus, rendant la création d'images rapide et moins sujette aux erreurs humaines, mais elle assure également une cohérence dans les configurations à travers différents environnements. Cette approche est particulièrement utile pour les équipes qui cherchent à optimiser leurs workflows de déploiement et à maintenir des standards élevés en matière de qualité et de sécurité.

Pour installer ces deux produits, suivez ces liens : Packer et Ansible

Comprendre le Builder BSU d'Outscale

Maintenant que nous avons installé les outils nécessaires, il est temps de nous concentrer sur un composant clé de notre processus de création d'images VM : le builder BSU d'Outscale. Le builder BSU, ou Block Storage Unit, est un élément spécifique à Outscale qui joue un rôle important dans la création d'images personnalisées pour les VM Outscale, les OMI.

Le builder BSU d'Outscale fonctionne en provisionnant une instance de VM sur laquelle il effectue toutes les configurations nécessaires. Une fois la configuration terminée, il crée une image de cette VM, incluant toutes les modifications apportées. Cette image peut ensuite être réutilisée pour déployer de nouvelles instances de VM, garantissant ainsi une uniformité et une reproductibilité dans vos déploiements.

Pour intégrer le builder BSU dans votre processus de construction avec Packer, il est nécessaire de comprendre et de configurer correctement votre fichier de template Packer. Ce fichier définit la manière dont Packer et le builder BSU interagissent pour créer votre image. Voici un exemple de base pour illustrer cette interaction :

source "outscale-bsu" "exemple" {
  // Paramètres du builder BSU, comme l'ID de l'image source, le type d'instance, etc.
}

build {
  sources = ["source.outscale-bsu.exemple"]

  // Ici, vous pouvez ajouter des provisioners, comme Ansible, pour configurer l'instance.
}

Ce code est un point de départ pour utiliser le builder BSU avec Packer. Il démontre la structure de base d'un fichier de configuration Packer utilisant le builder BSU d'Outscale.

Préparation de l'Environnement de Travail

Avant de plonger dans le vif du sujet avec la rédaction de notre code Packer et l'intégration d'Ansible, il est crucial de préparer adéquatement notre environnement de travail. Cette étape garantit que tous les composants nécessaires sont en place et configurés correctement pour un processus de construction d'image fluide et sans erreur.

La première étape consiste à s'assurer que les outils que nous avons installés, Ansible et Packer, sont configurés correctement. Pour Ansible, cela signifie vérifier que les playbooks et les rôles sont bien structurés et accessibles. Pour Packer, assurez-vous que le chemin d'accès au binaire est bien défini dans votre environnement, permettant son exécution depuis n'importe quel répertoire.

Faites très attention à la configuration d'Ansible, comme par exemple avec l'utilisation d'un inventaire codé dans ce fichier de config. Cela risque d'interférer dans la création de l'OMI. Pour vérifier lancez cette commande :

ansible-config dump --only-changed
CONFIG_FILE() = None

Prérequis pour le Builder BSU

En ce qui concerne le builder BSU d'Outscale, quelques prérequis sont nécessaires :

  • Identifiants Outscale : Assurez-vous d'avoir vos identifiants API Outscale, à portée de main. Ces identifiants sont essentiels pour permettre à Packer de communiquer avec l'environnement Outscale.

    export OUTSCALE_ACCESSKEYID="xxxxxxxxx"
    export OUTSCALE_SECRETKEYID="xxxxxxxxxxxxxxx"
    
  • Image Source : Choisissez une image source appropriée sur Outscale pour servir de base à votre construction. Cette image sera le point de départ sur lequel Packer et Ansible appliqueront leurs configurations.

Écriture du Code Packer

Après avoir préparé notre environnement, il est temps de se concentrer sur la rédaction du fichier de configuration pour Packer. Packer utilise le format HCL (HashiCorp Configuration Language), un langage de configuration structuré et facile à lire, pour définir les tâches de construction d'image. Voici comment vous pouvez structurer votre fichier de configuration Packer pour utiliser le builder BSU d'Outscale.

Structure de Base du Fichier HCL pour Packer

Un fichier de configuration Packer en HCL est composé de trois sections principales : source, build et provisioner. Voici un exemple simple pour illustrer cette structure :

packer {
  required_plugins {
    outscale = {
      version = ">= 1.0.0"
      source  = "github.com/outscale/outscale"
    }
    ansible = {
      source  = "github.com/hashicorp/ansible"
      version = "~> 1"
    }
  }
  required_version = ">= 1.7.0, < 2.0.0"
}

source "outscale-bsu" "exemple" {
  // Paramètres spécifiques au builder BSU, tels que l'ID de l'image source, le type d'instance, etc.
}

build {
  sources = ["source.outscale-bsu.exemple"]

  // Ici, vous pouvez ajouter des 'provisioners', comme Ansible, pour configurer l'instance.
}

Configuration du Builder BSU

Dans la section source, vous définissez les paramètres spécifiques au builder BSU d'Outscale. Cela inclut des informations comme l'ID de l'image source, le type d'instance et d'autres paramètres de configuration. Par exemple :

source "outscale-bsu" "ubuntu_2204" {
  region = var.region
  vm_type = "tinav5.c2r4p2"
  ssh_username = "outscale"
  communicator = "ssh"
  ssh_interface = "public_ip"
  ssh_keypair_name = var.keypair_name
  source_omi = var.omi_source
  omi_name = "ubuntu_2204_steph"
  ssh_private_key_file = "~/.ssh/id_ed25519"
  launch_block_device_mappings {
      delete_on_vm_deletion = true
      device_name = "/dev/sda1"
      volume_size = "40"
      volume_type = "gp2"
  }
}

Voici une explication détaillée de chaque partie du code :

  • region = var.region : Spécifie la région dans laquelle l'instance VM sera créée, en utilisant une variable region. Les variables permettent de personnaliser les configurations sans hardcoder les valeurs directement dans le fichier.

  • vm_type = "tinav5.c2r4p2" : Définit le type d'instance VM à utiliser. Dans ce cas, tinav5.c2r4p2 signifie un VM de génération 5 utilisant 2 CPU et 4 Go de mémoire et in indice de performance à 2. Plus d'infos ici

  • communicator = "ssh" : Définit le moyen de communication avec la VM, ici via SSH.

  • ssh_username = "outscale" : Indique le nom d'utilisateur SSH pour se connecter à l'instance VM. Ici, outscale est utilisé.

  • ssh_interface = "public_ip" : Indique que Packer doit se connecter à l'instance VM en utilisant son adresse IP publique.

  • ssh_keypair_name = var.keypair_name : Fournit le nom de la paire de clés SSH à utiliser pour se connecter à l'instance, en utilisant une variable keypair_name.

  • source_omi = var.omi_source : Spécifie l'ID de l'image source (Outscale Machine Image, OMI) à utiliser pour la construction, en utilisant une variable omi_source.

  • omi_name = "ubuntu_2204_steph" : Nomme l'image résultante. Ici, l'image sera nommée ubuntu_2204_steph.

  • ssh_private_key_file = "~/.ssh/id_ed25519" : Indique le chemin du fichier contenant la clé privée SSH utilisée pour se connecter à l'instance.

  • launch_block_device_mappings { ... } : Configure les paramètres du disque de l'instance. Dans ce bloc :

    • delete_on_vm_deletion = true : Assure que le volume est supprimé lorsque l'instance VM est terminée.
    • device_name = "/dev/sda1" : Définit le nom du périphérique pour le volume.
    • volume_size = "40" : Définit la taille du volume en gigaoctets.
    • volume_type = "gp2" : Indique le type de volume, gp2 étant un type de SSD général.

En résumé, ce bloc de configuration Packer crée une instance VM Outscale basée sur une image spécifique, en utilisant des paramètres définis comme la région, le type d'instance, les configurations SSH et les configurations de disque. Une fois l'instance lancée et configurée (potentiellement avec des scripts de provisionnement supplémentaires non montrés ici), Packer capture cette configuration dans une nouvelle image OMI, nommée ubuntu_2204_steph.

Les variables :

variable "region" {
  type =  string
  default = "eu-west-2"
}

variable "keypair_name" {
  type =  string
  default = "terraform-keypair-import-file"
}

variable "omi_source" {
  type =  string
  default = "ami-a3ca408c" # Une Ubuntu 2204
}

Je code l'OMI en dur plutôt que de lancer une recherche sur la dernière Ubuntu disponible. Dans les bonnes pratiques, on utilise jamais de pointeur de type latest pour garantir la reproductibilité des résultats !

Intégration des Provisioners

Dans la section build, vous référencez la source que vous avez définie et vous pouvez y ajouter des provisioners. Les provisioners sont utilisés pour configurer l'instance VM une fois qu'elle est lancée. Pour Ansible, cela peut ressembler à :

build {
  name    = "ubuntu_2204-steph"
  sources = ["source.outscale-bsu.ubuntu_2204"]

  provisioner "shell" {
    inline = [
      "cloud-init status --wait",
    ]
  }
  provisioner "ansible" {
    playbook_file = "./packer-playbook.yml"
  }
}

Cette configuration permet à Packer de lancer une instance VM en utilisant les paramètres définis dans la source BSU, puis d'exécuter un playbook Ansible pour configurer cette instance. Voici le code du playbook :

---
- name: Install
  hosts: default
  gather_facts: true
  roles:
    - role: stephrobert.bootstrap
      vars:
        bootstrap_timeout: 10
    - role: stephrobert.motd
      vars:
        motd_banner: welcome
        motd_disable_default_motd: true
  tasks:
    - name: Upgrade packages
      ansible.builtin.apt:
        force_apt_get: true
        update_cache: true
        upgrade: true
        cache_valid_time: 3600
      become: true
    - name: Install local-all
      ansible.builtin.apt:
        name:
          - locales-all
        state: present
      become: true

Lancement de la construction de l'OMI

Une fois que nous avons configuré notre environnement avec Packer et Ansible et compris le fonctionnement du builder BSU d'Outscale, nous sommes prêts à lancer la construction de l'image VM. Ce processus est au cœur de l'automatisation et de la standardisation de nos environnements de déploiement.

Avant de lancer la construction, il faut initialiser le code Packer :

packer init .

Vérifiez ensuite la syntaxe du code Packer :

packer validate ubuntu.pkr.hcl

Pour lancer la construction de l'image VM, nous utilisons la commande packer build avec le fichier de configuration Packer (HCL). Dans notre cas, avec le fichier nommé ubuntu.pkr.hcl, la commande serait :

packer build ubuntu.pkr.hcl
ubuntu_2204-steph.outscale-bsu.ubuntu_2204: output will be in this color.

...

Build 'ubuntu_2204-steph.outscale-bsu.ubuntu_2204' finished after 3 minutes 32 seconds.

==> Wait completed after 3 minutes 32 seconds

==> Builds finished. The artifacts of successful builds are:
--> ubuntu_2204-steph.outscale-bsu.ubuntu_2204: OMIs were created:
eu-west-2: ami-0dcb71d6

Cette commande déclenche plusieurs étapes :

  1. Initialisation de l'Instance VM : Packer utilise les configurations définies dans le bloc source (outscale-bsu) pour lancer une instance VM dans la région et le type d'instance spécifiés.
  2. Exécution des Provisioners : Si des provisioners, comme Ansible, sont spécifiés dans le fichier de configuration, Packer les exécute. Dans notre cas, Ansible configurerait l'instance en exécutant le playbook spécifié.
  3. Capture de l'Image : Une fois la configuration terminée, Packer capture l'état de l'instance VM sous forme d'une nouvelle image OMI, avec les configurations appliquées. Ici, elle se nomme ami-0dcb71d6.

Vérifions qu'elle existe bien avec la cli AWS :

aws ec2 describe-images --image-ids ami-0dcb71d6
{
    "Images": [
        {
            "Architecture": "x86_64",
            "ImageId": "ami-0dcb71d6",
            "ImageLocation": "300446419788/ubuntu_2204_steph",
...
            "Name": "ubuntu_2204_steph",
            "RootDeviceName": "/dev/sda1",
            "RootDeviceType": "ebs",
            "VirtualizationType": "hvm"
        }
    ]
}

Il ne reste plus qu'à la tester, le plus simple avec du code Terraform.

Débogage et Optimisation

Lorsque vous rencontrez des erreurs dans vos scripts Packer, voici quelques conseils pour les résoudre :

  • Logs Verbose : Packer offre une option qui permet d'exécuter le build en mode débogage, fournissant des logs détaillés. Utilisez cette option pour mieux comprendre où et pourquoi une erreur se produit.

    PACKER_LOG=1 packer build ubuntu.pkr.hcl
    

Pour les scripts Ansible, voici quelques astuces pour optimiser vos playbooks :

  • Idempotence : Assurez-vous que vos playbooks sont idempotents, c'est-à-dire qu'ils peuvent être exécutés plusieurs fois sans modifier l'état final de la VM si celui-ci est déjà atteint.
  • Utilisation de Rôles : Structurez vos playbooks en utilisant des rôles pour faciliter la réutilisation et la maintenance.
  • Tests et Validation : Testez vos playbooks sur des environnements locaux, construis avec Vagrant pax exemple, avant de les intégrer dans le processus de construction d'image Packer.

Bonnes Pratiques

La construction d'images VM avec Packer et Ansible est un processus complexe, qui peut être grandement amélioré par l'adoption de certaines meilleures pratiques. Voici quelques-unes des plus importantes à garder à l'esprit :

  • Utilisez un système de contrôle de version comme Git pour vos fichiers de configuration Packer et vos playbooks Ansible. Cela facilite le suivi des modifications et la collaboration.
  • Le processus d'optimisation est un cycle continu. N'hésitez pas à revenir sur votre configuration, à tester différentes approches et à chercher des moyens d'améliorer la performance et la fiabilité de vos builds.

Conclusion

La construction d'images VM avec Packer et Ansible est une compétence précieuse dans le domaine du DevOps. Elle non seulement augmente l'efficacité et la reproductibilité des déploiements, mais encourage également une approche plus systématique et fiable de la gestion de l'infrastructure.

J'espère que ce guide vous aura été utile et vous aura donné les outils et les connaissances nécessaires pour maîtriser cette technique. Comme toujours, je vous encourage à expérimenter, à explorer et à continuer à apprendre pour devenir encore plus compétent dans vos pratiques DevOps.