AWS Certified CloudOps Engineer - Associate

AMIs and EC2 Image Builder

What an AMI actually contains, where the line between baking and bootstrapping sits, how an EC2 Image Builder pipeline turns a base image into a tested and distributed golden AMI, and the difference between deprecating, disabling, and deregistering an image.

Intermediate 26 minutes 6 Learning Objectives
  1. Describe what an AMI contains and which properties are fixed at creation time
  2. Decide what belongs baked into an image and what belongs in launch-time bootstrapping
  3. Explain the five EC2 Image Builder resources and how a pipeline assembles them into a build
  4. Predict what happens when the test stage of an Image Builder pipeline fails
  5. Compare deprecating, disabling, and deregistering an AMI, and choose the right one for a given requirement
  6. State what is required to share an AMI backed by encrypted snapshots with another account

An Auto Scaling group adds an instance during a traffic spike. The instance boots in about 40 seconds, then spends 8 more minutes in user data: patching the OS, pulling three agents, and compiling a dependency. By the time it passes its health check, the spike is over. Worse, the instance that launched last Tuesday installed slightly different package versions from the one that launched today, because both resolved "latest" against a repository that moved in between.

Both problems have the same fix. Do that work once, before the launch, and store the result as an image.

What an AMI actually is

An Amazon Machine Image is not a file you can download. It is a record in EC2 that points at one or more EBS snapshots and carries the metadata needed to turn those snapshots into a bootable instance:

  • The block device mapping: which snapshot becomes the root volume, what size it is, which additional volumes attach, and whether they delete on termination.
  • The boot and platform metadata: architecture (x86_64 or arm64), virtualization type, root device type, and boot mode.
  • Launch permissions: which accounts, organizations, or OUs may launch from it.

Two consequences follow from that structure, and both show up on the exam.

An AMI is Regional. The snapshots live in one Region, so the AMI ID is meaningful only in that Region. To launch the same image in a second Region you copy it there, and the copy gets a different AMI ID. This is why a CloudFormation template that hardcodes an AMI ID breaks the moment someone deploys it elsewhere.

You do not pay for the AMI, you pay for its snapshots. The AMI record itself is free. Every AMI you have ever created is quietly billing you for the snapshot storage behind it, which is why the cleanup section at the end of this lesson matters more than it sounds.

An AMI is also fixed at these properties. You cannot change an x86_64 AMI into an arm64 one, or convert an instance-store-backed AMI into an EBS-backed one. When you need a different combination, you build a new image.

Bake or bootstrap: the decision that shapes everything else

Every piece of configuration a server needs can arrive one of two ways. Baking puts it in the image at build time. Bootstrapping applies it at launch time through user data, a Systems Manager association, or a configuration management tool.

Nothing forces you to pick one. The useful question is which half of your configuration goes where.

Bake into the AMIBootstrap at launch
Launch time costZero, the work already happenedPaid on every single launch
ConsistencyByte-identical across every instanceDepends on what upstream repositories serve that minute
Changing itRebuild the image and replace instancesChange the script, next launch picks it up
Per-environment valuesForces a separate image per environmentHandled naturally
AuditabilityOne image ID answers "what is on this box"You have to reconstruct it from logs

The decision rule that falls out of that table: bake what is slow and stable, bootstrap what is fast and varies. OS patches, agents, runtimes, and compiled dependencies are slow and stable, so they belong in the image. The database endpoint, the environment name, and the instance's role in the cluster are fast and vary per deployment, so they belong in user data or Parameter Store.

An image built this way is usually called a golden AMI: a hardened, patched, pre-loaded base that every workload in the organization launches from.

Here is the misconception this section exists to kill: "a golden AMI means everything is in the image." Push it that far and you end up rebuilding an image to change a log level, and maintaining one image per environment per application. The image is a starting line, not a finished server.

Why hand-built golden AMIs stop working

The first golden AMI is easy. Launch an instance, patch it, install what you need, run create-image, write the AMI ID in a wiki page.

The second month is where it falls apart. New CVEs land, so the image needs a rebuild, and the person who built it is on leave and never wrote down step 4. Nobody tested the new image before an Auto Scaling group started launching from it. The image exists in us-east-1 only, and the DR Region needs it too. There is no record of what changed between version 3 and version 4.

Those failures are not about laziness. They are what happens when a build process lives in someone's memory instead of in a file. EC2 Image Builder exists to move it into files.

The five Image Builder resources

Image Builder splits an image build into five resources, and once you see what each one owns, the service stops feeling large.

ResourceAnswers the questionContains
Image recipeWhat goes in the image?Base image, ordered list of components, instance-level settings such as the root volume size
ComponentHow is one customization performed?An AWSTOE YAML document with phases and steps: install a package, harden a setting, run a test
Infrastructure configurationWhere is the image built?Instance types, subnet, security groups, IAM instance profile, SNS topic, S3 log bucket, terminate-on-failure
Distribution settingsWhere does the finished image go?Target Regions, output AMI name, KMS key, accounts and OUs to share or copy to, launch template configuration
Image pipelineWhen does this run?A recipe plus an infrastructure configuration plus distribution settings, plus a schedule

Two of these deserve a closer look.

Components are where your actual customization lives. A component is a plain YAML document that AWSTOE runs on the build instance, and it comes in two flavors: build components customize the instance before the snapshot, and test components validate the instance after it. AWS publishes managed components for common jobs, including update-linux and the STIG and CIS hardening sets, and you write your own for anything specific to you.

name: InstallAndVerifyNginx
description: Install nginx and confirm it answers on port 80
schemaVersion: 1.0
phases:
  - name: build
    steps:
      - name: InstallNginx
        action: ExecuteBash
        inputs:
          commands:
            - dnf install -y nginx
            - systemctl enable nginx
  - name: validate
    steps:
      - name: ConfirmBinary
        action: ExecuteBash
        inputs:
          commands:
            - nginx -v

The phase names are not decoration. Image Builder decides when a component runs by which phases it defines: a component runs in the build stage if it defines build or validate, and it runs in the test stage if it defines test and nothing else. A component cannot straddle the two, and you cannot chain a value produced in build into a test step, because those stages run on different instances.

Infrastructure configuration is the resource people forget until a build fails. The build instance runs in your VPC, which means it needs a subnet with a route to reach package repositories, a security group that permits that traffic, and an instance profile with the Image Builder permissions. It is also where the troubleshooting switch lives: by default the build instance terminates when a build fails, and turning that off keeps the instance alive so you can log in and read the AWSTOE logs.

What one pipeline run actually does

Walk one build end to end, because the ordering explains several exam answers.

  1. Build stage. Image Builder launches an EC2 instance from the base image, inside the subnet from your infrastructure configuration. AWSTOE runs the build phase of every build component in recipe order, then the validate phase of each. If any step fails, the build stops here.
  2. Snapshot. With the customizations applied, Image Builder stops the instance and takes a snapshot, producing the candidate image.
  3. Test stage. For an AMI workflow, Image Builder launches a new instance from that candidate image and runs the test phase of every component in the recipe. This is a real launch of the real artifact, not a re-check of the build instance, which is why it catches a first-boot service that fails to start.
  4. Distribution. Only if every test passed does Image Builder copy the AMI into each Region in your distribution settings, apply the configured KMS key, set launch permissions, and optionally update a launch template to point at the new AMI ID.

That last option is worth pausing on. Distribution can write the new AMI ID into a specific version of an EC2 launch template, so an Auto Scaling group pointed at that template's $Latest or $Default version picks up the new image without anyone editing anything.

The service itself is free. You pay for the EC2 build and test instances while they run, the EBS snapshots the images occupy, S3 log storage, Amazon Inspector if you turn on vulnerability scanning during the build, and ECR storage for container image outputs.

Scheduling: build on a clock, or build on a change

A pipeline can run on demand, on a cron schedule, or in response to an EventBridge rule. The schedule has a second setting that carries most of the value, and it is a common exam target.

  • Run at the scheduled time, always. Every scheduled slot produces a build, whether or not anything upstream changed. You get a fresh image on a fixed cadence and pay for a build each time.
  • Run at the scheduled time only if dependency updates are available. Image Builder checks whether the base image or any component has a newer semantic version, and skips the build if nothing moved.

The second option only works if your recipe uses semantic versioning for the base image and components, which in the console means choosing "use latest available OS version" and "use latest version available" rather than pinning an exact version string. Pin everything to fixed versions and Image Builder has nothing to compare, so it either rebuilds every time or never detects an update, depending on how the recipe is written.

A weekly pipeline set to build only on dependency updates is the shape most teams want: no image churn during a quiet week, and a fresh patched image the moment AWS publishes a new base AMI.

Distributing and sharing the result

Distribution settings handle the cross-Region and cross-account work that people otherwise do by hand.

Within your own account, distribution copies the AMI into each target Region. Across accounts you have two different options, and the difference is about ownership:

  • Launch permissions let another account launch from your AMI. You still own the image, you still pay for the snapshots, and the other account pays only for the instances it launches. Revoke the permission and their future launches stop.
  • Target accounts and OUs create a copy of the AMI in each target account. That account owns its copy and pays for its snapshots, and the copy survives anything you do to the original.

Encryption adds one requirement that trips up more people than any other part of AMI sharing. An AMI whose snapshots are encrypted with the default AWS managed key cannot be shared at all, because you cannot edit that key's policy. Sharing an encrypted AMI means encrypting its snapshots with a customer managed KMS key and granting the target accounts permission to use that key. The usual fix is a copy: copy the AMI to itself, specifying your own KMS key, then share the copy.

Two smaller behaviors worth knowing. You do not have to share the underlying snapshots separately, because EC2 grants launch access to them on your behalf. And your user-defined tags do not travel with a shared AMI, so the receiving account sees an untagged image.

Retiring an image: three verbs that are not synonyms

An organization that builds a weekly golden AMI has 52 images a year, per Region, per OS. Cleaning them up is a real operational task, and AWS gives you three distinct actions that learners routinely blur together.

DeprecateDisableDeregister
Can new instances launch from it?Yes, if the launcher knows the AMI IDNo, launches failNo
Auto Scaling groups and launch templatesKeep workingKeep referencing it, and their launches failTheir launches fail
Visible in listingsHidden from users, visible to the ownerHidden by default, visible only to the owner with --include-disabledGone
SharingUnaffectedAll launch permissions removed, AMI becomes privateGone
ReversibleYes, cancel the deprecation dateYes, re-enable, but sharing is not restoredNo, except from the Recycle Bin if a retention rule matched
Snapshots still billedYesYes, and they cannot be deleted while the AMI is disabledOnly if you left them behind
Running instancesUnaffectedUnaffectedUnaffected

Read that table as an escalation ladder. Deprecate is a signal: stop choosing this image, but nothing breaks. Disable is a stop: launches fail, and you can undo it. Deregister is deletion.

The numbers AWS asks about directly: you can set a deprecation date up to 10 years out for a private AMI, public AMIs default to deprecation 2 years after creation, and the only way to move a public AMI's deprecation later is to make it private by sharing it with specific accounts.

Then there is the cost trap. Deregistering an AMI does not delete its backing snapshots by default. A team that deregisters 40 stale AMIs and expects the storage bill to drop is in for a surprise, because the snapshots are still there. Pass --delete-associated-snapshots on the deregister call, or clean them up afterwards. A snapshot referenced by more than one AMI is kept regardless.

You do not have to do any of this by hand. Image Builder lifecycle policies apply deprecate, disable, and delete actions to the images a pipeline produced, using age-based and count-based rules with exclusion rules to protect images you must keep. Amazon Data Lifecycle Manager covers the same ground for EBS-backed AMIs generally, including AMIs you did not build with Image Builder.

Exam tips

  • "Stop launches now, and let us undo it later" is disable. "Mark as out of date but keep it working" is deprecate. "Delete it" is deregister. Options that mix the effects are the distractors.
  • If a stem says an Auto Scaling group is still launching from an old image after the team deprecated it, that is the expected behavior, not a bug. Deprecation hides an AMI from listings; it never blocks a launch by ID.
  • Deregistering does not stop the snapshot bill on its own. Any answer that treats deregistration as a complete cleanup is wrong.
  • Encrypted AMI sharing needs a customer managed KMS key plus a grant to the target account. If the stem mentions the default AWS managed key, the sharing cannot work, and the answer involves copying with your own key.
  • An Image Builder pipeline that fails its tests distributes nothing. If a question asks why a new AMI never appeared in the DR Region, a failed test component is a prime suspect, alongside the Region simply not being in the distribution settings.
  • "Build only when the base image is patched" is the dependency-update schedule setting, and it depends on semantic versioning in the recipe.
  • Image Builder itself is free. Charges come from the build and test instances, snapshots, logs, Inspector, and ECR.
  • Watch for the bake-versus-bootstrap split in scenario stems. Long launch times point at baking; per-environment configuration points at bootstrapping.

The idea to carry forward is that an image is a build artifact with a version, a test suite, and an expiry, not a server someone once configured. That framing is what makes the whole domain coherent: the image is built from a file, tested before it ships, distributed by policy, and retired on schedule.

Everything in this lesson assumed the unit you ship is a machine. The next lesson swaps that assumption. When the machine already exists and only the application changes, you ship a container image instead, and almost every idea here reappears in a smaller and faster form.