TL;DR
Remember that Lambda function I built to work around EC2 Image Builder’s Distribution Settings wiping your Launch Template config? You can bin it. AWS have updated the Distribution Settings behaviour and it now preserves your existing Launch Template settings when it creates a new version. The custom Lambda updater is no longer required.
A quick recap
In Half Baked Images I walked through the pain of integrating EC2 Image Builder with Terraform-managed Auto Scaling Groups. The core issue was that when EC2 Image Builder distributed a new AMI and updated your Launch Template, it created a new version containing only the AMI ID and account ID. Everything else, i.e. instance profile, security groups, key pair, block device mappings was gone.
The result? Your ASG would scale up instances with no instance profile, no security groups, and none of the configuration you’d carefully defined. Not ideal.
My solution was a two-parter:
- Use an SSM Parameter as the source of truth for the AMI ID, updated by Image Builder’s Distribution Settings.
- Deploy a custom Lambda function, triggered by EventBridge, that would read the latest AMI ID from SSM and create a proper new Launch Template version. One that actually included all the important bits.
It worked. It was reliable. But it was also plumbing that shouldn’t have been necessary.
What changed?
AWS have updated the EC2 Image Builder Distribution Settings behaviour. The documentation now states:
When
launchTemplateConfigurationsare present during the distribution process, Image Builder creates a new version of the launch template that includes all of the original settings from the template, and the new AMI ID from the build.
The important bit there: All of the original settings from the template.
That’s the bit that was missing before. Previously, Image Builder would create a new Launch Template version with only the AMI ID, effectively a blank template with a picture attached. Now it carries forward your existing configuration and simply swaps in the new AMI ID.
This is exactly the behaviour I expected when I first configured the launch_template_configuration block in my distribution config. It’s what most people would reasonably expect. And now it actually works that way.
What does this mean practically?
If you followed my original approach, you can simplify things significantly.
What you can remove
- The Lambda function that created new Launch Template versions with the full configuration.
- The EventBridge rule that triggered that Lambda on successful image builds.
- The associated IAM roles and policies for the Lambda function.
- Any CloudWatch log groups you set up for the Lambda.
That’s a decent chunk of infrastructure that existed purely to work around a limitation that no longer exists.
What you should keep
- The SSM Parameter approach is still a good pattern. Having a single source of truth for your AMI ID that both Terraform and Image Builder can reference is clean and avoids the bootstrapping headaches I described in the original post.
- The lifecycle ignore on the SSM Parameter value in Terraform, this is still needed so Terraform doesn’t fight with Image Builder over who owns that value.
What to add back
You can now use the launch_template_configuration block in your distribution config with confidence:
resource "aws_imagebuilder_distribution_configuration" "dist" {
name = "${var.project}-dist"
distribution {
region = var.region
ami_distribution_configuration {
name = "${var.project}-{{imagebuilder:buildDate}}"
description = "Custom built AL2023 image"
ami_tags = {
OS = "AmazonLinux2023"
Hardened = "true"
Name = "${var.project}-{{imagebuilder:buildDate}}"
}
}
launch_template_configuration {
launch_template_id = aws_launch_template.my_lt.id
account_id = local.account_id
set_default_version = true
}
}
}
Note the set_default_version = true… this tells Image Builder to set the newly created version as the default. Combined with the preserved settings, this means your ASG will pick up the new AMI on the next scale event without any Lambda glue in the middle.
Updated lab
I’ve updated the autoscaling_with_imagebuilder lab to reflect this. The Lambda updater and its associated EventBridge rule have been removed. The distribution config now handles the Launch Template update natively, as it always should have.
If you previously deployed the lab with the Lambda approach, you can safely remove those resources and update your distribution configuration. The SSM Parameter pattern remains, it’s still useful for the Terraform bootstrapping needs.
Thoughts
I’ll be honest, this is a satisfying update to write. The original solution worked, and I do think it was a reasonable approach given the constraints at the time. But it always felt like I was compensating for something that should have been a native capability.
The fact that AWS have addressed this is a good sign. It suggests they listened to the feedback (and I suspect I wasn’t the only one who ran into this). It also validates the frustration I had - if the fix was to make Distribution Settings preserve existing config, then the previous behaviour was the problem, not my expectations.
One less Lambda in the world. Now if AWS could just make their Lifecycle Policies stop nuking AMIs that are still in use, I might be able to retire the other Lambda too. A man can dream.
Additional Resources
- Half Baked Images - original blog post
- Half Baked Lifecycles - follow up blog post
- Updated Auto Scaling Group with EC2 Image Builder Lab
- EC2 Image Builder - Configure AMI distribution with a launch template
This post is part of my AWS technical blog series. Found this helpful? Connect with me on LinkedIn or check back here for more AWS content and discussions.