Packer now supports HCL2, so I rewrote my existing JSON format code
![]()
table of contents
This is Teraoka, an infrastructure engineer.
Packer has received a long-awaited update.
It finally supports HCL2!
This time, I tried rewriting the existing code written in Json based on HCL2, so
I would like to summarize it while comparing each code.
What is Packer?
A CLI tool for creating multi-cloud compatible golden images
Tools that create this type of golden image are
very compatible with Immutable Infrastructure and blue-green deployments, and
are useful in environments where servers are frequently created and destroyed, such as with AutoScaling.
Development continues at HashiCorp and it is written in Golang.
Terraform is also a well-known tool, so many people may be familiar with it.
supports
not only major cloud services such as AWS, GCP, and Azure, but Although it supports a large number of services (called builders in Packer),
its advantage is that you can write code in a common format to describe the process across all builders.
Previously, it was only possible to write in JSON format, but
from version 1.5 onwards, HCL2 format is supported.
At the time of writing this article (March 31, 2020), it is still in beta, so
it may be best to thoroughly test it before using it in a production environment.
What is HCL
It stands for HashiCorp Configuration Language and was also developed by HashiCorp.
While its implementation is Json-compatible, it is a proprietary language that allows for unique descriptions that are completely different from Json. It
is intended for use with command line tools and has long been supported by Terraform, so it
will likely be familiar to anyone who writes tf files.
There are two versions, HCL1 and HCL2, with HCL2 currently being the mainstream.
Writing a Packer template (Json)
Packer creates images by writing something called a template, but
I would like to write the template contents in HCL2 while comparing them with JSON format.
First, let's look at what is written in JSON format.
{ "builders": [ { "type": "amazon-ebs", "region": "{{user `region`}}", "source_ami_filter": { "filters": { "name": "{{user `ami_name`}}}*" }, "owners": [ "self" ], "most_recent": true }, "instance_type": "{{user `instance_type`}}", "ssh_username": "{{user `ssh_username`}}", "ami_name": "{{user `ami_name`}}_{{timestamp}}", "tags": { "Name": "{{user `ami_name`}}_{{timestamp}}" }, "iam_instance_profile": "{{user `iam_instance_profile`}}" } ], "provisioners": [ { "type": "shell", "inline": [ "sudo yum -y update" ] } ] }
Parts such as {{user `ami_name`}} are variables and
the values to be stored are written in a separate file.
{ "ssh_username": "ec2-user", "region": "ap-northeast-1", "instance_type": "t3.micro", "ami_name": "ami-packer-test", "iam_instance_profile": "role-packer-test" }
Using this template file
$ packer build main.json -var-file=variables.json
By executing the command,
you can build the image while reading the values to be stored in variables from variables.json.
If you build according to the contents of the template above,
- Search for the base AMIID using the contents written in source_ami_filter
- Start the build process based on the AMI that matches the search
- Launch a new EC2 instance from the base AMI
- Create a temporary key pair to log in to your EC2 instance
- Log in to the instance via SSH and execute the process described in the provisioners
- Stop the EC2 instance
- Get an AMI from a stopped instance
- Delete the instance after the acquisition is complete
This is a series of processes.
Since an IAM role can be used to obtain AMI information,
the IAM role required for execution is set in advance
on the EC2 instance that runs the packer command The permissions required for the IAM role are summarized below.
https://packer.io/docs/builders/amazon.html
Writing a Packer template (HCL2)
So what would happen if we rewrote the above JSON in HCL2?
First, we write the values to be stored in the variables.
We will use the following two files.
variables.pkrvars.hcl
ssh_username = "ec2-user" region = "ap-northeast-1" instance_type = "t3.micro" ami_name = "ami-packer-test" iam_instance_profile = "role-packer-test"
variables.pkr.hcl
variable "ssh_username" { type = string description = "SSH User Name" } variable "region" { type = string description = "AWS Region" } variable "instance_type" { type = string description = "EC2 Instance Type" } variable "ami_name" { type = string description = "EC2 AMI Name" } variable "iam_instance_profile" { type = string description = "EC2 IAM Instance Profile" }
Write the value to be stored in the variable in variables.pkrvars.hcl.
In JSON, it is "value name: value", but in HCL2 it is "value name = value".
To express variables in HCL2, we use variable.
Just like in programming languages, there is a concept of types, and
example we are using all string type variables.
- Number type
- List type (list)
- Map type (map)
- Boolean type (bool)
etc
Next, we will write the actual build processing part.
We will use the following two files.
sources.pkr.hcl
## Source source "amazon-ebs" "example" { region = var.region ami_name = "${var.ami_name}_{{timestamp}}" instance_type = var.instance_type iam_instance_profile = var.iam_instance_profile ssh_username = var.ssh_username source_ami_filter { owners = ["self"] most_recent = true filters { virtualization-type = "hvm" name = "${var.ami_name}*" root-device-type = "ebs" } } tags { Name = "${var.ami_name}_{{timestamp}}" } }
build.pkr.hcl
## Build build { sources = [ "source.amazon-ebs.example" ] provisioner "shell" { inline = [ "sudo yum -y update" ] } }
As you can see, with the JSON format, what was written in one file
can be divided into separate files for source and build.
Another feature of HCL2 is that you can insert comments in the middle of the code.
Variables can be referenced using "var.variable name".
In build.pkr.hcl, the source settings are read
and the provisioner section writes the process to be executed during the build.
The sources section is a list type, so multiple sources can be specified as shown below.
sources = [ "source.amazon-ebs.example", "source.amazon-ebs.example2" ]
When you run the build, go to the directory where the template file is located and run
$ packer build -var-file=variables.pkrvars.hcl ./
This will load and execute all files in the current directory
Current issues
Packer has a validate command that checks syntax, but
this is not available when written in HCL.
I look forward to future updates.
https://github.com/hashicorp/packer/issues/8538
summary
Packer is a useful tool for practicing DevOps using cloud services.
It's easy to incorporate into your CI/CD flow, and the configuration of Packer itself is very simple, so
we encourage everyone to give it a try.
0