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.
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
.