Unlocking the Potential of VM Image Generation with HashiCorp Packer
Written on
Introduction to HashiCorp Packer: A Game Changer in VM Image Creation
HashiCorp Packer is a robust tool designed for the creation of tailored virtual machine images across numerous platforms such as KVM, VMWare, Vagrant, Docker, AWS, Azure, and Google Cloud. For DevOps engineers, Packer stands out as an essential resource.
One of its primary advantages is the ability to generate images for various platforms while minimizing the complexities associated with platform-specific requirements. This means you can produce uniform machine images from a single source configuration, regardless of the underlying platform.
Packer operates across multiple operating systems, including Linux, macOS, Windows, FreeBSD, NetBSD, OpenBSD, and Solaris.
How Packer Functions
Packer utilizes a configuration or template file to dictate how the images are constructed. This configuration can be in either JSON or HashiCorp Configuration Language (HCL2).
The image creation process with Packer follows these steps:
- Packer initiates an instance using a base image or ISO, whether locally, on a remote server, or in the cloud.
- It runs configuration tools, such as Ansible or custom scripts, to set up the instance to the desired specifications.
- Finally, it generates the image and retrieves it from ESXi or the host on which the image was created.
For KVM, Packer employs QEMU to build the image, while for VMWare—our primary focus here—it leverages a VMWare ESXi server.
In this guide, I will demonstrate how to use Packer to create a Rocky Linux 8.6 operating system image compatible with both KVM and VMWare, serving as a golden image suitable for various environments and applications. With minor adjustments, this procedure can easily be adapted for additional platforms.
Installing Packer
You can find installation instructions and packages at the designated URL.
Sample Packer Template/Configuration File
This configuration file is a fully operational template for building Rocky Linux 8.6 compatible with both KVM/QEMU and VMWare.
variable "root_user" {
type = string
default = "root"
sensitive = true
}
variable "root_pw" {
type = string
default = "myExamplePw289@@"
sensitive = true
}
variable "vmware_user" {
type = string
}
variable "vmware_host" {
type = string
}
variable "vmware_pw" {
type = string
sensitive = true
}
variable "out_dir" {
type = string
default = "images"
}
variable "version" {
type = string
}
locals {
version = "rocky-8.6–1.0"
iso_name = "Rocky-8.6-x86_64-dvd1.iso"
iso_checksum = "sha256:1d48e0af63d07ff4e582a1819348e714c694e7fd33207f48879c2bc806960786"
}
source "qemu" "lvm-resize" {
iso_url = local.iso_name
iso_checksum = local.iso_checksum
output_directory = var.out_dir
shutdown_command = "shutdown -P now"
disk_compression = true
disk_size = "7500M"
memory = 1024
format = "qcow2"
accelerator = "kvm"
http_directory = "kickstarts"
ssh_username = var.root_user
ssh_password = var.root_pw
ssh_timeout = "30m"
vnc_bind_address = "0.0.0.0"
vnc_port_min = "5900"
vnc_port_max = "5909"
vm_name = "{{ build_name }}-${var.version}.qcow2"
net_device = "virtio-net"
disk_interface = "virtio"
boot_wait = "5s"
headless = true
boot_command = [" text inst.ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/lvm-resize.ks"]
qemu_img_args {
convert = ["-o", "compat=0.10"] # compatibility with older centos6 hypervisors
}
}
source "vmware-iso" "lvm-resize-vmware" {
format = "ovf"
guest_os_type = "centos-64"
iso_url = local.iso_name
iso_checksum = local.iso_checksum
output_directory = var.out_dir
vm_name = "{{ build_name }}-${var.version}"
vmdk_name = "{{ build_name }}-${var.version}-disk"
disk_type_id = "thin"
keep_registered = false
disk_size = 102400
memory = 4096
cpus = 4
http_directory = "kickstarts"
http_port_min = 8000
http_port_max = 8009
headless = false
boot_wait = "5s"
remote_host = var.vmware_host
remote_username = var.vmware_user
remote_password = var.vmware_pw
remote_type = "esx5"
skip_compaction = false
shutdown_command = "shutdown -P now"
ssh_port = "22"
ssh_timeout = "30m"
ssh_username = var.root_user
ssh_password = var.root_pw
vnc_bind_address = "0.0.0.0"
vnc_port_min = 5900
vnc_port_max = 5909
vnc_disable_password = true
boot_command = [
" text net.ifnames=0 biosdevname=0 ip=10.89.91.241::10.89.90.1:255.255.254.0:vmware:eth0:none ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/lvm-resize-vmware.ks"
]
vmx_data = {
"ethernet0.addressType" = "generated"
"ethernet0.networkName" = "VM Network"
"ethernet0.present" = "TRUE"
"ethernet0.startConnected" = "TRUE"
}
}
In the above example, the ISO can be stored locally or specified as a remote URL for Packer to download. For expediency during testing, I opted for a local ISO.
If you wish to monitor the installation progress for QEMU/KVM builds, you can connect to the VM being built using VNC. Packer will provide the port number for this connection.
For VMWare ESXi settings, I keep the credentials in a separate file for security purposes.
{
"vmware_host": "10.89.91.99",
"vmware_user": "root",
"vmware_pw": "MyAm@z1ngP@ssw0rd"
}
This is the kickstart file utilized for image creation, structured for templating.
Building the Images
To initiate the image creation, execute the command.
This video demonstrates how to utilize HashiCorp Packer for building a custom Ubuntu 22.04 image in VMware vSphere.
Conclusion
HashiCorp's Packer serves as an excellent solution for generating images across various platforms. Utilizing a tool like Packer allows for the creation of comprehensive golden images that document every aspect of the image-building process, making it an efficient and repeatable endeavor.
For further insights, consider watching the following video:
This video provides a detailed walkthrough on building a golden image pipeline with HCP Packer.