I have been working with a friend on learning Terraform to manage his new and growing, AWS environment. One of the challenges I gave him was to use Terraform to manage the AMI updates that Packer creates or to initiate an update if the source AMI is newer than the current state.
Terraform doesn’t have Packer provider so this requires using other resources built into Terraform to accomplish a working and trackable state.
Maintain current AMIs based on source AMI and userdata updates and rebuild the AMI as needed when the source, or gold image, AMI is updated, or you update your userdata, using Packer to accomplish customization.
I accomplished this by abusing the null_resource provider and local-exec provisioner.
First, let’s go find the AMI we need as the source:
This returns an ami-id of ami-0c007ac192ba0744b (as of 20210114 in AWS region us-east-2). These AMIs are updated by Canonical periodically, and there will be a new ami-id.
Now that we have an ami-id, we can add that as a trigger to execute changes to null_resource. This has a second trigger to check on the userdata file that will be used to do customization:
So basically I have the following directory structure that is relevant. You will probably also have backend resource, perhaps some requirements, etc.
Implementation via Jenkins or other CI/CD systems is left to you to figure out.
I have items running in multiple regions and each region has its own AMIs (and resulting ami-ids). The above has been pared down a bit for brevity.
You can use the aws provider to connect to multiple regions concurrently:
Of course you can do other things to make it even more dynamic using data calls for aws_caller_identity within the region you are working against and applying it programmatically but I’ll leave that to you for now.