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.