In this section, we will proceed to build an AMI Pipeline via EC2 Image Builder.
EC2 Image Builder is a service that simplifies the creation, maintenance, validation, and distribution of Linux/Windows Images.

Upon completing this section, we will be able to:
To proceed with infrastructure deployment, we will use the AWS CloudFormation service via the AWS Console or AWS CLI.
| Component | Value (Required) |
|---|---|
| Stack Name | pattern3-pipeline |
| Template | pattern3-pipeline.yml - download in the Template section below |
| BaselineVpcStack | pattern3-base |
Please download the template here:
The template takes the following parameters:
| Parameter | Default | Meaning |
|---|---|---|
BaselineVpcStack | (required) | Stack name of the Base Infrastructure section, used to fetch VPC and Private Subnet |
MasterAMI | /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 | SSM Public Parameter pointing to the latest Amazon Linux 2023 AMI |
Ver | 1.0.0 | Version of the Component and Image Recipe |
BuildInstanceType | t3.medium | Instance type used for building the AMI |
EnableInspectorScanning | false | Enable vulnerability scanning with Amazon Inspector for the output AMI |
Here are the initialization steps via AWS CLI:
aws cloudformation create-stack --stack-name pattern3-pipeline --template-body file://pattern3-pipeline.yml --parameters ParameterKey=BaselineVpcStack,ParameterValue=pattern3-base --capabilities CAPABILITY_IAM --region ap-southeast-2

Wait for the Stack to complete creation. This step is fairly quick, taking about 1 to 2 minutes, as we are just creating the definition of the pipeline and not building the AMI yet.
aws cloudformation wait stack-create-complete --stack-name pattern3-pipeline --region ap-southeast-2
Verify that the CloudFormation Stack has been successfully created with the StackStatus as CREATE_COMPLETE.
aws cloudformation describe-stacks --stack-name pattern3-pipeline --region ap-southeast-2 --query "Stacks[0].StackStatus" --output text

Pattern3ImagePipeline (the pipeline ARN) and Pattern3ParentImageId.aws cloudformation describe-stacks --stack-name pattern3-pipeline --region ap-southeast-2 --query "Stacks[0].Outputs" --output table

You can check which Amazon Linux 2023 AMI is being used as the Parent Image with the following command. This value should match the Pattern3ParentImageId in the Outputs:
aws ssm get-parameter --name /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 --region ap-southeast-2 --query "Parameter.Value" --output text

If you deployed using CloudFormation, you can skip the manual steps below and proceed directly to Execute Builder Pipeline.
This section is for those who want to deeply understand each component of an AMI Pipeline. We will perform the following steps sequentially:
Due to the nature of the S3 service, when naming an S3 Bucket, we must follow certain rules specified at this URL.
uuidgen | awk -F- '{print tolower($1$2$3)}'
([guid]::NewGuid().ToString('N')).Substring(0,12).ToLower()

pattern3-logging combined with the generated UUID, and block all public access. This bucket only stores internal logs, so there is no reason to expose it to the Internet.BUCKET="pattern3-logging-$(uuidgen | awk -F- '{print tolower($1$2$3)}')"
echo "Bucket: $BUCKET"
aws s3 mb "s3://${BUCKET}" --region ap-southeast-2
aws s3api put-public-access-block --bucket "$BUCKET" --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true" --region ap-southeast-2
$BUCKET = "pattern3-logging-" + ([guid]::NewGuid().ToString('N')).Substring(0,12).ToLower()
Write-Output "Bucket: $BUCKET"
aws s3 mb "s3://$BUCKET" --region ap-southeast-2
aws s3api put-public-access-block --bucket $BUCKET --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true" --region ap-southeast-2

Please note down the bucket name, you will need it in the IAM Role creation step and when configuring logging for the pipeline.
More details about creating an S3 bucket can be found at Creating a bucket.
This IAM Role will be used for EC2 Image Builder acting as an instance profile for the temporarily created EC2 instance. This EC2 instance will perform the OS Patching task.
The following is the process to create an IAM Role:
Roles and click the Create role button.
AWS service and set Use case to EC2, then click Next.
Add permissions screen, search for and select the following policies:Next to go to the Name, review, and create screen.pattern3-recipe-instance-role along with a detailed description.
Create role.pattern3-recipe-instance-role.Permissions tab, click Add permissions and select Create inline policy.
<S3_BUCKET_NAME> with the S3 Bucket name from the previous step.{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "WriteBuildLogs",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::<S3_BUCKET_NAME>/*"
},
{
"Sid": "DescribeBucket",
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::<S3_BUCKET_NAME>"
}
]
}

Next.Create policy to finish.
Pay attention to the scope of permissions in the specification above. The build instance only needs to write logs to one exact bucket, so the policy only opens s3:PutObject on that bucket. Avoid using "Action": "s3:*" or attaching the managed policy AmazonS3FullAccess, as that grants broader permissions than actually needed.
We will need an EC2 Security Group for the temporary EC2 instance. The Security Group does not require any Inbound Rule; however, the default Outbound Rule is needed so the build instance can access the Internet via NAT Gateway to download patches.

Create security group.pattern3-pipeline-instance-security-group and a description.pattern3-base Stack.Create security group to initialize.

We will proceed to create a Component of the EC2 Image Builder service.
Create component button.Linux.Amazon Linux 2023.pattern3-pipeline-ConfigureOSComponent.1.0.0.Component to update the OS with latest package versions.
The illustration may show Amazon Linux 2. Please select Amazon Linux 2023, because Amazon Linux 2 has reached its end of support.
Definition document section, select Define document content.name: ConfigureOS
description: Update the operating system to the latest available packages
schemaVersion: 1.0
phases:
- name: build
steps:
- name: UpdateOS
action: UpdateOS

Create component button to proceed with initialization.
In this lab, we simply define an UpdateOS action to update all packages of the operating system. On Amazon Linux 2023, UpdateOS will run dnf instead of yum as on Amazon Linux 2, but the component specification remains unchanged. You can refer to other action modules at Action modules reference.
Before defining the Builder Pipeline, we must have a Builder Recipe.
Create image recipe button.pattern3-pipeline-ImageRecipe.1.0.0.Pattern3 Configure OS Recipe.Select managed images, then:Amazon Linux.Quick start (Amazon-managed).Use latest available OS version so each build fetches the latest AL2023 version.

Do not select Enter custom AMI ID and enter a fixed AMI ID. A fixed AMI ID will gradually become outdated and may be marked as deprecated by AWS, causing the pipeline to start from an obsolete image. Choosing a managed image along with Use latest available OS version ensures each build starts from the latest Amazon Linux 2023 release, adhering to the spirit of a patching lab.
Volume type to gp3 for lower cost and faster performance than gp2.Owned by me filter.
Create recipe button to proceed with initialization.
The Infrastructure Configuration describes where the AMI is built: instance type, VPC, subnet, security group, and where to write logs. This is an independent resource that must be created before creating the pipeline.
Create infrastructure configuration.pattern3-pipeline-InfraConfig.Build infrastructure for pattern3 image pipeline.pattern3-recipe-instance-role created earlier.
t3.medium.pattern3-base Stack, choose a Private Subnet, and select the pattern3-pipeline-instance-security-group security group.
If you leave the VPC and subnet blank, Image Builder will use the account’s default VPC and default subnet. The lab will still build the AMI, but the build instance will not reside in the infrastructure you created in section 2, and the architecture will no longer match the diagram. Please select them explicitly.
Terminate instance on failure enabled.
Create infrastructure configuration.The build instance must reside in a Private Subnet with outbound Internet access via NAT Gateway. This instance needs to connect to Systems Manager and the Amazon Linux 2023 repository to download patches. If placed in an isolated subnet, the pipeline will hang at the Building step and then fail because the SSM Agent cannot register.
Retrieve the VPC ID and Subnet ID from the Outputs of the pattern3-base Stack:
aws cloudformation describe-stacks --stack-name pattern3-base --region ap-southeast-2 --query "Stacks[0].Outputs" --output table
In the left navigation pane, select Image pipelines, then click Create pipeline.
General section:
pattern3-pipeline-ImagePipeline.Pattern 3 pipeline to update OS.
Manual.The page defaults to On schedule, running automatically every week. You must change it to Manual, for two reasons: in section 5 we will trigger the pipeline via Systems Manager, and a periodically running pipeline will silently create a new AMI and EBS Snapshot every week, incurring charges even after you finish learning.
Recipe section:
pattern3-pipeline-ImageRecipe from the list.Use latest version available so the pipeline automatically uses the latest recipe version. If you want to fix it, choose Specify recipe version then 1.0.0.Workflow section: keep Use default workflows.

Select a configuration, then choose pattern3-pipeline-InfraConfig created in the previous step.Distribution settings section: keep Create with default settings. The AMI will be created in the current Region ap-southeast-2, just as the Distribution details line shows.

Advanced settings section, expand if you wish to tweak. For the lab you can keep everything as default:
ResourceType = awsstudygroup-000099-imagebuilder.5 consecutive failures. This policy only applies to scheduled runs, not manual Run pipeline.Disabled, keeping it as is works fine. Choose Enabled if you want Image Builder to collect metadata via SSM Inventory to check component compatibility.Disabled. To enable vulnerability scanning, you must activate security scanning settings at the account level first, which utilizes Amazon Inspector and is out of the scope of this lab.Click Create pipeline at the bottom of the page.
With a t3.medium, the build process takes about 20 to 30 minutes. You can choose a smaller instance type to save costs, but the build time will be longer. Most of the time is spent on standard Image Builder steps like initializing the instance, running the component, taking a snapshot, and registering the AMI.

Once the specification process is complete, we proceed to test the Builder Pipeline.

In the Image pipelines list, select the pipeline just created, click the Actions button and select Run pipeline.

Once execution is complete, we will check whether the new AMI has been initialized or not.

If using the AWS CLI, you can run the pipeline and monitor its status as follows:
# Get the pipeline ARN directly from Image Builder, works for both creation methods
PIPELINE_ARN=$(aws imagebuilder list-image-pipelines --region ap-southeast-2 --query "imagePipelineList[?name=='pattern3-pipeline-ImagePipeline'].arn | [0]" --output text)
BUILD_ARN=$(aws imagebuilder start-image-pipeline-execution --image-pipeline-arn "$PIPELINE_ARN" --region ap-southeast-2 --query "imageBuildVersionArn" --output text)
aws imagebuilder get-image --image-build-version-arn "$BUILD_ARN" --region ap-southeast-2 --query "image.state" --output json
The status will progress through PENDING, BUILDING, TESTING, DISTRIBUTING, and then AVAILABLE. Once it reaches AVAILABLE, you retrieve the new AMI ID using:
aws imagebuilder get-image --image-build-version-arn "$BUILD_ARN" --region ap-southeast-2 --query "image.outputResources.amis[0].image" --output text
# Get the pipeline ARN directly from Image Builder, works for both creation methods
$PIPELINE_ARN = aws imagebuilder list-image-pipelines --region ap-southeast-2 --query "imagePipelineList[?name=='pattern3-pipeline-ImagePipeline'].arn | [0]" --output text
$BUILD_ARN = aws imagebuilder start-image-pipeline-execution --image-pipeline-arn "$PIPELINE_ARN" --region ap-southeast-2 --query "imageBuildVersionArn" --output text
aws imagebuilder get-image --image-build-version-arn "$BUILD_ARN" --region ap-southeast-2 --query "image.state" --output json
The status will progress through PENDING, BUILDING, TESTING, DISTRIBUTING, and then AVAILABLE. Once it reaches AVAILABLE, you retrieve the new AMI ID using:
aws imagebuilder get-image --image-build-version-arn "$BUILD_ARN" --region ap-southeast-2 --query "image.outputResources.amis[0].image" --output text
EC2 Image Builder uses an Automation Document from the Systems Manager service to complete the initialization process. We can access Systems Manager to track this process as well as check the status of the ImageBuilderBuildImageDocument document.
Refer to more details about monitoring an Automation Document at Running automations.
Each successful pipeline run will generate an AMI along with an EBS Snapshot. These resources are not deleted by CloudFormation when you delete the Stack, and the snapshot will continue to incur costs. The Resource Cleanup section provides instructions on how to delete them.
Now, we will transition to the next section detailing the Build Automation deployment with the Systems Manager service.