Aller au contenu

Custom Cloud Image

When working with cloud, it could be interesting to prepare a custom image, containing all the necessary tools pre-installed. For exemple, having an image ready to run inside the GNS-3 simulator or for an OpenStack Cloud.

HashiCorp Packer In this documentation we will use the Packer Tool from Hashicorp. Packer is an open-source tool developed by HashiCorp that automates the process of building identical machine images for multiple platforms from a single source configuration. It is a lightweight and portable tool that can be used to create machine images for a variety of cloud providers, including AWS, Azure, and Google Cloud Platform. Packer can also be used to create machine images for local development environments, such as Vagrant and VirtualBox.

Installing Packer

The installation is straight forward, just follow the documentation.

Building of custom Cloud Image

The process to build a custom image locally on your machine is:

  • Declare all the required VM configurations in an HCL (Hashicorp configuration language) or a JSON file. Let’s call it the Packer template.
  • To build the VM image, execute Packer with the Packer template..
  • Packer takes a remote connection to the server (SSH).
  • Then it configures the server based on the provisioner you specified in the Packer template (Shell script, Ansible, Chef, etc).
  • Deletes the running instance.

Template files

The high level template structure is the following:

  • Variables : Default value that can be overridden during run time
  • Source : Define the image builder plugin
  • Build : Defines provisioners and post processors

Example

In this exemple we build an QEMU Ubuntu 22.04 LTS image, using ansible to deploy an OpenDaylight controller inside this image.

Settings

The first step is to create the “Cloud-Init” files and generate the ISO image to boot the image. In this example the file is called packer_qemu.seed.pkr.hcl :

source "file" "user_data" {
  content = <<EOF
#cloud-config
ssh_pwauth: True
keyboard:
    layout: fr_CH
ssh:
  install-server: true
  allow-pw: true
packages_update: true
packages:
  - qemu-guest-agent
  - python3-pip

late-commands:
  - sudo apt update && sudo apt install -y traceroute
  - pip3 install -U urllib3 requests

users:
  - name: ubuntu
    plain_text_passwd: ubuntu
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    lock_passwd: false
interactive-sections:
  - network
EOF
  target  = "user-data"
}

source "file" "meta_data" {
  content = <<EOF
{"instance-id":"odl.tenant-local","local-hostname":"odl"}
EOF
  target  = "meta-data"
}

build {
  sources = ["sources.file.user_data", "sources.file.meta_data"]

  provisioner "shell-local" {
    inline = ["genisoimage -output cidata.iso -input-charset utf-8 -volid cidata -joliet -r user-data meta-data"]
  }
}

The second file contains the image description and the initial configuration, this file is called packer_qemu.qcow2.pkr.hcl:

packer {
  required_plugins {
    vagrant = {
      version = "1.0.9"
      source  = "github.com/hashicorp/qemu"
    }
    ansible = {
      version = "1.0.4"
      source  = "github.com/hashicorp/ansible"
    }
  }
}

source "qemu" "ubuntu" {
  format           = "qcow2"
  disk_image       = true
  disk_size        = "8G"
  headless         = true
  iso_checksum     = "file:https://cloud-images.ubuntu.com/focal/current/SHA256SUMS"
  iso_url          = "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img"
  qemuargs         = [["-m", "1G"], ["-smp", "8"], ["-cdrom", "cidata.iso"], ["-serial", "mon:stdio"]]
  shutdown_command = "echo 'packer' | sudo -S shutdown -P now"
  ssh_password     = "ubuntu"
  ssh_username     = "ubuntu"
  vm_name          = "ubuntu_packer_odl.qcow2"
  output_directory = "output"
}

build {
  sources = ["source.qemu.ubuntu"]
  provisioner "shell" {
    inline = [ "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for Cloud-Init...'; sleep 1; done" ]
  }
  provisioner "ansible" {
    playbook_file = "./opendaylight/install_opendaylight.yml"
  }
}

Creation of the image

Once the settings are done, type the following commands to generate the QEMU Image:

packer init packer_qemu.qcow2.pkr.hcl
packer build packer_qemu.seed.pkr.hcl
packer build packer_qemu.qcow2.pkr.hcl

The generated image will be in the ./output directory and is ready to use.

Note

You could have warning when running ansible as provisioner. You need the latest version of Ansible and also pip3.

References


Dernière mise à jour: 24 November 2023