One common use of Packer is to build a new AMI based on a source AMI. One approach to this task has been to use the “Inject artifact ID during build” feature in Terraform Enterprise, however Packer integration with Terraform Enterprise has been deprecated. This article will describe how to use Packer features to accomplish this same task, as well as the ability to create AMIs in different regions using AMI filters.
Preparing and identifying the base AMI
To begin, assume there is some AMI that is provided, possibly from the marketplace or one that is built using a template base.json
. The AMI either has, or was created with, tags or other identifying properties. In this example the configuration is that base.json
creates an AMI with tag:artifact
set to a unique value that can be found later.
Creating the derived AMI template
Create a new template, which will be referred to as derived.json
here. This configuration will use source_ami_filter
to identify the source AMI. In this example the previously created tag:artifact
will be used, but any suitable filter may be employed. A complete code listing for the builders
section of the template is provided after describing the steps.
First, be sure to disable “Inject artifact ID during build” if this setting in Terraform Enterprise was previously used.
Set region
in both build templates to the same region. The filter inherently searches in the region in which the build occurs, therefore the source AMI should be in the same region as the region used when creating the new, derived AMI.
Use the ami_regions
configuration option to copy the base build to additional regions if that is desired.
In the derived build, add an appropriate source_ami_filter
that will locate the AMI built by the base build. Again, a complete builders
example is provided below. In the filter shown, most_recent
has also been set to true
, which is usually desired, but, again, any suitable filter can be used. The options for the filter are those valid for the DescribeImages
AWS API request.
Again add ami_regions
to the derived build if that is desired, which will copy the build into the regions just as in the base build. Typically the region
and ami_regions
parameters will be set to the same values in base.json
and derived.json
.
Example builders
in derived.json
All of the above described entries in derived.json
are summarized in the builders
section example provided below. Note that the variables used will need to be set; in particular base_ami
, which is the tag value used in base.json
when creating the source AMI.
"builders": [
{
"type": "amazon-ebs",
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}",
"region": "us-west-1",
"instance_type": "t2.micro",
"ssh_username": "ec2-user",
"ami_name": "{{user `name`}}_{{timestamp}}",
"ami_description": "{{user `name`}}-ami",
"ami_regions": ["us-east-2"],
"source_ami_filter": {
"filters": {
"tag:artifact": "{{user `base_ami`}}"
},
"most_recent": true
},
"tags": {
"Name": "{{user `name`}}_{{timestamp}}",
"artifact": "{{user `name`}}"
}
}
],
Extending builds to multiple regions
Variations of this example can provide configurations where builds are be performed in different regions. As described above, both builds occur in the same region and copied to other AMI regions, however this is not a requirement.
With the tag filter in place and the source AMI copied to all other regions, the derived AMI could be built in any region the source AMI was copied to without changes to the filter. In this case, the region
in derived.json
would differ from base.json
, but would be a value contained in the ami_regions
option in base.json
.
This can be useful if the source AMI needs to exist in multiple regions but the derived AMI only needs to exist in a subset of those regions.