Skip to content

Commit

Permalink
Update image ID in launch template with instance refresh
Browse files Browse the repository at this point in the history
* Modifies the Lambda that triggers an instance refresh, to first update
  the image ID to the latest AMI. This ensures the instances will be
  using the most up to date AMI
* This has been placed within the instance refresh lambda, because it
  will require an instance refresh anyway to actually update the
  instances, and allows it to happen at the chosen instance refresh
  cron
* The AutoScaling group's launch template version has also been changed
  to '$Latest', rather than a specific version so that we don't need to
  keep that up to date with the latest version
  • Loading branch information
Stretch96 committed Jan 6, 2025
1 parent 9d3dca5 commit afd37d3
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ This project creates and manages resources within an AWS account for infrastruct
| [aws_iam_policy.ecs_cluster_infrastructure_ecs_asg_diff_metric_ecs_describe_cluster_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.ecs_cluster_infrastructure_ecs_asg_diff_metric_kms_encrypt](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.ecs_cluster_infrastructure_ecs_asg_diff_metric_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.ecs_cluster_infrastructure_instance_refresh_allow_describe_images](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.ecs_cluster_infrastructure_instance_refresh_allow_instance_refresh](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.ecs_cluster_infrastructure_instance_refresh_kms_encrypt](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.ecs_cluster_infrastructure_instance_refresh_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
Expand Down Expand Up @@ -236,6 +237,7 @@ This project creates and manages resources within an AWS account for infrastruct
| [aws_iam_role_policy_attachment.ecs_cluster_infrastructure_ecs_asg_diff_metric_asg_describe_asg_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.ecs_cluster_infrastructure_ecs_asg_diff_metric_ecs_describe_cluster_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.ecs_cluster_infrastructure_ecs_asg_diff_metric_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.ecs_cluster_infrastructure_instance_refresh_allow_describe_images](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.ecs_cluster_infrastructure_instance_refresh_allow_instance_refresh](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.ecs_cluster_infrastructure_instance_refresh_kms_encrypt](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.ecs_cluster_infrastructure_instance_refresh_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
Expand Down
2 changes: 1 addition & 1 deletion data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ data "aws_ami" "ecs_cluster_ami" {
filter {
name = "name"
values = [
"al2023-ami-ecs-hvm-${local.infrastructure_ecs_cluster_ami_version}"
local.infrastructure_ecs_cluster_ami_name_filter
]
}

Expand Down
18 changes: 17 additions & 1 deletion ecs-cluster-infrastructure-instance-refresh-lambda.tf
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ resource "aws_iam_role_policy_attachment" "ecs_cluster_infrastructure_instance_r
policy_arn = aws_iam_policy.ecs_cluster_infrastructure_instance_refresh_allow_instance_refresh[0].arn
}

resource "aws_iam_policy" "ecs_cluster_infrastructure_instance_refresh_allow_describe_images" {
count = local.infrastructure_ecs_cluster_instance_refresh_lambda_schedule_expression != "" ? 1 : 0

name = "${local.resource_prefix}-ecs-cluster-infrastructure-instance-refresh-allow-describe-images"
policy = templatefile("${path.root}/policies/ec2-describe-images.json.tpl", {})
}

resource "aws_iam_role_policy_attachment" "ecs_cluster_infrastructure_instance_refresh_allow_describe_images" {
count = local.infrastructure_ecs_cluster_instance_refresh_lambda_schedule_expression != "" ? 1 : 0

role = aws_iam_role.ecs_cluster_infrastructure_instance_refresh_lambda[0].name
policy_arn = aws_iam_policy.ecs_cluster_infrastructure_instance_refresh_allow_describe_images[0].arn
}

resource "aws_iam_policy" "ecs_cluster_infrastructure_instance_refresh_kms_encrypt" {
count = local.infrastructure_ecs_cluster_instance_refresh_lambda_schedule_expression != "" && local.infrastructure_kms_encryption ? 1 : 0

Expand Down Expand Up @@ -98,7 +112,9 @@ resource "aws_lambda_function" "ecs_cluster_infrastructure_instance_refresh" {

environment {
variables = {
asgName = aws_autoscaling_group.infrastructure_ecs_cluster[0].name
asgName = aws_autoscaling_group.infrastructure_ecs_cluster[0].name
launchTemplateName = aws_launch_template.infrastructure_ecs_cluster[0].name
amiVersion = local.infrastructure_ecs_cluster_ami_name_filter
}
}

Expand Down
2 changes: 1 addition & 1 deletion ecs-cluster-infrastructure.tf
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ resource "aws_autoscaling_group" "infrastructure_ecs_cluster" {

launch_template {
id = aws_launch_template.infrastructure_ecs_cluster[0].id
version = aws_launch_template.infrastructure_ecs_cluster[0].latest_version
version = "$Latest"
}

vpc_zone_identifier = local.infrastructure_ecs_cluster_publicly_avaialble ? [
Expand Down
50 changes: 50 additions & 0 deletions lambdas/ecs-asg-instance-refresh/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,59 @@
import os

asgName = os.environ['asgName']
launchTemplateName = os.environ['launchTemplateName']
amiVersion = os.environ['amiVersion']

def lambda_handler(event, context):
asgClient = boto3.client('autoscaling')
ec2Client = boto3.client('ec2')

# Update launch template to use the latest AMI
response = ec2Client.describe_images(
Owners=['amazon'],
Filters=[
{'Name': 'name', 'Values': [amiVersion]},
{'Name': 'state', 'Values': ['available']},
{'Name': 'architecture', 'Values': ['x86_64']}
]
)

images = sorted(
response['Images'],
key=lambda x: x['CreationDate'],
reverse=True
)
if not images:
raise Exception("No AMIs found!")

latest_ami_id = images[0]['ImageId']
print(f"Latest ECS-optimized AMI: {latest_ami_id}")

try:
template_response = ec2Client.describe_launch_template_versions(
LaunchTemplateName=launchTemplateName,
Versions=["$Latest"]
)
template_data = template_response['LaunchTemplateVersions'][0]['LaunchTemplateData']
except Exception as e:
print(f"Error retrieving launch template: {e}")
raise

template_data['ImageId'] = latest_ami_id

try:
new_version_response = ec2Client.create_launch_template_version(
LaunchTemplateName=launchTemplateName,
SourceVersion="$Latest",
LaunchTemplateData=template_data
)
new_version_number = new_version_response['LaunchTemplateVersion']['VersionNumber']
print(f"Created new version: {new_version_number}")
except Exception as e:
print(f"Error creating new launch template version: {e}")
raise

# Start instance refresh
try:
response = asgClient.start_instance_refresh(
AutoScalingGroupName=asgName,
Expand Down
1 change: 1 addition & 0 deletions locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ locals {
enable_infrastructure_ecs_cluster = var.enable_infrastructure_ecs_cluster && local.infrastructure_vpc
infrastructure_ecs_cluster_name = "${local.resource_prefix}-infrastructure"
infrastructure_ecs_cluster_ami_version = var.infrastructure_ecs_cluster_ami_version
infrastructure_ecs_cluster_ami_name_filter = "al2023-ami-ecs-hvm-${local.infrastructure_ecs_cluster_ami_version}"
infrastructure_ecs_cluster_ebs_docker_storage_volume_device_name = "/dev/xvdcz"
infrastructure_ecs_cluster_ebs_docker_storage_volume_size = var.infrastructure_ecs_cluster_ebs_docker_storage_volume_size
infrastructure_ecs_cluster_ebs_docker_storage_volume_type = var.infrastructure_ecs_cluster_ebs_docker_storage_volume_type
Expand Down
12 changes: 12 additions & 0 deletions policies/ec2-describe-images.json.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeImages"
],
"Resource": "*"
}
]
}

0 comments on commit afd37d3

Please sign in to comment.