Automate image building with packer¶
Packer, crafted by HashiCorp, offers an efficient, reusable, and reproducible approach to automate image creation.
Continuous Deployment (CD) and Infrastructure as a Service (IaaS) offer a plethora of handy tools for seamless updates, rollbacks, and overall infrastructure management. The cornerstone of a well-maintained infrastructure lies in the ability to restart it entirely from scratch. This entails having a straightforward and reproducible method to reconfigure your virtual machines, precisely what Packer facilitates.
Basic requirement¶
You need to configure your OpenStack CLI as described in the dedicated section. The examples provided are based on this configuration, so if you have any specific configurations, you'll need to adjust accordingly.
Packer utilizes SSH to connect to the virtual machine, so you should run Packer in a network where SSH is open from your client.
Official documentation¶
Official documentation can be found on packer documentation website.
Installation¶
On Mac OS¶
$ brew install packer
$ mkdir -p ~/packer/example
$ cd ~/packer/example
$
On ubuntu 24.04¶
$ sudo apt install packer
$ mkdir -p ~/packer/example
$ cd ~/packer/example
$
Quick start¶
Cloud@VirtualData provide a basic packer skeleton to simplify packer
usage. In "Advanced usage" section will we go
further. You can simply fork the gitlab repository and clone your fork.
The basic skeleton provide you some key features :
- multiple source choice : allow you to choose which OS and cloud you want to use. It's especially useful if you want to have a federated services on multiple cloud infrastructure
- formatted image name : each images will be formatted following the schema
os-name
-flavor
-timestamp
- common [pre|post]configure scripts : some configuration must be done on every image you want to have, this could be configuring ntp, installing monitoring packages, ...
Skeleton hierarchy¶
.pkr.hcl
is the packer file extension. It uses hcl
format.
The files
directory contains all file that will be uploaded on images during creation.
common
directory will be uploaded for any kind of images, flavor
directory will
only be uploaded when creating a specific flavor image.
The scripts
directory contains all scripts that will be run through on virtual
machine during creation.
The same-idea than files
is applied here for subdirectory.
Finally, variables
will contain packer variables
declaration for services. Per
example, operating system name, flavor, ...
$ tree -A
.
├── build.pkr.hcl
├── files
│ ├── common
│ │ └── empty
│ ├── core
│ │ └── empty
│ └── service-1
│ ├── empty
│ └── service.cfg
├── scripts
│ ├── common
│ │ ├── empty
│ │ ├── post-configure.sh
│ │ └── pre-configure.sh
│ └── profiles
│ ├── core.sh
│ ├── empty
│ └── service-1.sh
├── sources.pkr.hcl
├── variables
│ ├── empty
│ └── service-1.pkr.hcl
└── variables.pkr.hcl
Using skeleton¶
As example, we will create a web server image with our skeleton. The server will
be based on alma-9x
OS and the flavor will be web
.
Note
packer use a standard user to log into the virtual machine during
installation. This mean that you can't directly put a file in /etc
and
you need to prefix all command which need root access with sudo -E
in your
scripts.
files/flavor¶
You need to create a flavor
directory the a empty
file. empty
file is just
needed to push on git server the directory. If you don't want to use git (which
is not recommended), you don't need to create empty
file.
All file will be uploaded on /tmp/common
and /tmp/flavor
. You can manipulate
them with flavor.sh
script.
$ mkdir -p ./files/web
$ touch ./files/web/empty
$
scripts/profiles/flavor.sh¶
You need to create a flavor.sh
script that will be run on the virtual machine.
$ cat > ./scripts/profiles/web.sh <<EOF
#!/bin/sh
# WARNING : packer use a standard user account to connect to the virtual machine
# You need to prefix all your command with `sudo -E`
sudo -E dnf -y install nginx
EOF
variables/service.pkr.hcl¶
This file will be used to overwrite default value of variables flavor
and
operating-system
. As the default operating-system is alma-9x
we don't need to
overwrite this value.
$ cat > variables/alma-9x-web.pkr.hcl << EOF
flavor = "web"
EOF
Build a specific service¶
By default, alma-9x-core image will be generated. To create another image based
on different operating system or flavor, you have to create your own file directory,
scripts and variables/flavor.pkr.hcl
. Per example, to generate a alma-9x-web
images you should build with the following command.
$ packer init .
$ packer build --var-file variables/alma-9x-web.pkr.hcl .
[...]
$ openstack image list \
--os-cloud virtualdata
+--------------------------------------+--------------------------+--------+
| ad15a094-2dab-4024-b37d-e5b38858df72 | alma-9x-web-202404301725 | active |
+--------------------------------------+--------------------------+--------+
Advanced usage¶
Define openstack plugins for packer¶
Packer offers an OpenStack plugin for interacting with OpenStack-based clouds as Cloud@VirtualData.
$ cat > ~/packer/example/config.pkr.hcl << EOF
packer {
required_plugins {
openstack = {
version = ">= 1.1.1"
source = "github.com/hashicorp/openstack"
}
}
}
EOF
Define sources¶
The initial step with Packer involves defining the sources for your build. The source section encompasses:
image_name
: the name of the generated imagessh_username
: the default username utilized by the distributionsource_image
: the ID of the GenericCloud image on the cloudflavor
: the flavor employed for building the imagecloud
: the--os-cloud
value within your clouds.yaml filenetworks
: a list of network IDs
The provided source section will utilize an Almalinux 9 Generic Cloud as the source image on Cloud@VirtualData, resulting in the creation of an image named "alma-9x-my-image."
$ cat >> ~/packer/example/main.pkr.hcl << EOF
source "openstack" "alma-9x" {
image_name = "alma-9x-my-image"
ssh_username = "almalinux"
source_image = "901c99e8-2f6a-4cfa-879d-a48144322fbc"
flavor = "m1.small"
cloud = "virtualdata"
networks = [
"39aa90ca-163b-4630-9671-9439fefe516f"
]
}
EOF
Building procedure¶
The build section define the list of action that will be done to generate your image.
Sources¶
By default, you only need a sources
section. With the following build
section, Packer will only create a new image without performing any additional
actions, which is essentially useless.
$ cat > ~/packer/example/main.pkr.hcl << EOF
build { # Be careful, build section is close on "Run building" section
sources = ["source.openstack.alma-9x"]
EOF
Provisioner¶
Provisioners are plugins that can be used to configure VMs. In this documentation,
we will explore two provisioners: file
and shell
.
file provisioner¶
The File provisioner will copy a local file to the VM in a specific directory.
With the following section, we will create a file called myfile.cfg
on your
local machine and place it in the /etc
directory on the VM.
$ cat > ~/packer/example/myfile.cfg << EOF
[section]
key = value
EOF
$ cat >> ~/packer/example/main.pkr.hcl <<EOF
provisioner "file" {
destination = "/etc/"
source = "./myfile.cfg"
}
EOF
shell provisioner¶
The Shell provisioner will run a command on the VM after it is up. This section
will create a script called configure.sh
that will create a /etc/myscript.cfg
file on the VM.
$ cat > ~/packer/example/configure.sh << EOF
#!/bin/sh
sudo sh -c 'hostname > /etc/myscript.cfg'
EOF
$ cat >> ~/packer/example/main.pkr.hcl <<EOF
provisioner "shell" {
script = "configure.sh"
}
EOF
Run building¶
To build a new image called alma-9x-my-image
, you just need to start
packer build
as follows:
Warning
Be careful, as Packer logs into the machine as a standard user, you don't have direct root access. In your scripts, you must prefix all commands with sudo to allow the script to be run as root.
$ cat >> ~/packer/example/main.pkr.hcl <<EOF
} # We close build section
EOF
$ packer build .
[...]