CloudFormationを使用して、EC2 Image Builder入門

CloudFormationを使用して、EC2 Image Builder入門

CloudFormationを使用して、EC2 Image Builder入門

本ページではEC2 Image Builderを取り上げます。

Image Builder は、シンプルなグラフィカルインターフェイス、組み込みの自動化、および AWS が提供するセキュリティ設定により、イメージを最新でセキュアなものにするための労力を大幅に軽減します。Image Builder を使えば、イメージをアップデートするためのステップを手動で実施したり、独自の自動化パイプラインを構築したりする必要はなくなります。

EC2 Image Builder

今回はImage Builder入門ということで、Apacheをインストール・有効化したAMIを作成します。
そしてこのAMIを使用して、自動的にEC2インスタンスを作成します。

構築する環境

Diagram of introduction to EC2 Image Builder using CloudFormation.

Image Builderを使用して、Linux用のAMIを作成します。
このAMIはApacheをインストール・有効化したものです。

このAMIを使用して、EC2インスタンスを作成します。
インスタンスのOSはAmazon Linux 2とします。
このインスタンスはパブリックサブネットに配置し、パブリックアドレスをアタッチします。

本ページでは、自動的にImage Builderパイプラインを実行し、それを受けて、自動的にEC2インスタンスを構築することを目指します。
そのために、いくつかLambda関数を使用します。

1つ目の関数の働きは、SSM Parameter Storeに作成されたAMIのIDを登録することです。
2つ目の関数の働きは、EventBridge用のカスタムイベントを作成することです。
この2つの関数は、Image Builderパイプラインが正常に完了した際に、SNSを通じて実行されます。

3つ目の関数の働きは、Image Builderパイプラインを開始することです。
この関数はCloudFormationカスタムリソースに関連づけて、CloudFormationスタック作成時に自動的に実行されます。

4つ目の関数の働きは、CloudFormation WaitConditionへ成功シグナルを発信することです。
この関数はEventBridgeルールに関連づけて、関数2によってイベントが作成されたことをトリガーとして実行されます。

なお全関数のランタイム環境はPython3.8です。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-fa/tree/main/145

テンプレートファイルのポイント解説

Image Builder

Image Builderを構築する上で、以下の5つのリソースを作成する必要があります。

  • コンポーネント
  • レシピ
  • インフラストラクチャ設定およびIAMロール
  • ディストリビューション設定
  • パイプライン

コンポーネント

AWS公式では、コンポーネントを以下の通りに説明しています。

Image Builder uses the AWS Task Orchestrator and Executor (AWSTOE) component management application to orchestrate complex workflows. Build and test components that work with the AWSTOE application are based on YAML documents that define the scripts to customize or test your image.

Manage components with Image Builder

つまりコンポーネントとは、AMIビルド時にインストールするパッケージや、テスト内容を定義するものです。

Resources:
  Component:
    Type: AWS::ImageBuilder::Component
    Properties:
      Data: |
        schemaVersion: 1.0
        phases:
          - name: build
            steps:
              - name: InstallAndEnableApache
                action: ExecuteBash
                inputs:
                  commands:
                    - yum update -y
                    - yum install -y httpd
                    - systemctl start httpd
                    - systemctl enable httpd
                    - ec2-metadata -i > /var/www/html/index.html
      Name: !Sub "${Prefix}-Component"
      Platform: !Ref ImageBuilderPlatform
      SupportedOsVersions:
        - !Ref ImageBuilderSupportedOsVersion
      Version: !Ref ImageBuilderVersion
Code language: YAML (yaml)

コンポーネントに関する詳細は以下のページをご確認ください。

https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-components.html

本ページでは、ポイントのみ取り上げます。

Dataプロパティでコンポーネント用のYAMLドキュメントを設定できます。
今回はactionにExecuteBashを指定することで、Bashコマンドを実行するように指定します。
inputs内にApacheのインストール・有効化用のコマンドを指定します。
AMIビルド用のEC2インスタンスのIDをindex.htmlに書き込み、ルートディレクトリに配置します。

PlatformプロパティはコンポーネントのOSを設定します。
今回は「Linux」を指定します。

SupportedOsVersionsプロパティで、このコンポーネントがサポートするOSやバージョンを指定します。
今回は「Amazon Linux 2」を指定します。

Versionはこのコンポーネントのバージョンを指定します。
今回は「1.0.0」とします。

レシピ

AWS公式では、イメージレシピを以下の通りに説明しています。

An EC2 Image Builder recipe defines the base image to use as your starting point to create a new image, along with the set of components that you add to customize your image and verify that everything works as expected.

Manage recipes

つまりレシピとは、AMIのベースとなるイメージや適用するコンポーネントを指定するものです。

Resources:
  ImageRecipe:
    Type: AWS::ImageBuilder::ImageRecipe
    Properties:
      Components:
        - ComponentArn: !Ref Component
      Name: !Sub "${Prefix}-ImageRecipe"
      ParentImage: !Ref ImageBuilderParentImage
      Version: !Ref ImageBuilderVersion
Code language: YAML (yaml)

Componentsプロパティに、レシピに適用するコンポーネントを設定します。
こちらに先ほど確認したコンポーネントを指定します。

ParentImageプロパティで、ベースとなるAMIを設定します。
今回はARM版のAmazon Linux 2のAMI(arn:aws:imagebuilder:ap-northeast-1:aws:image/amazon-linux-2-arm64/x.x.x)を指定します。

Versionはこのレシピのバージョンを指定します。
今回は「1.0.0」とします。

インフラストラクチャ設定

AWS公式では、インフラストラクチャ設定を以下の通りに説明しています。

You can use infrastructure configurations to specify the Amazon EC2 infrastructure that Image Builder uses to build and test your EC2 Image Builder image.

Manage EC2 Image Builder infrastructure configuration

つまりインフラストラクチャ設定とは、AMIビルド用のEC2インスタンスに関して設定するものです。

Resources:
  InfrastructureConfiguration:
    Type: AWS::ImageBuilder::InfrastructureConfiguration
    Properties:
      InstanceProfileName: !Ref ImageBuilderRoleProfile
      InstanceTypes:
        - !Ref InstanceType
      Name: !Sub "${Prefix}-InfrastructureConfiguration"
      SnsTopicArn: !Ref Topic
Code language: YAML (yaml)

InstanceTypesプロパティで、AMIビルド用のEC2インスタンスのタイプを設定できます。
今回はARMタイプのt4g.nanoを指定します。

SnsTopicArnプロパティでSNSの通知先を指定できます。

When the image status reaches one of the following states, Image Builder publishes a message:

AVAILABLE

FAILED

Amazon SNS integration in Image Builder

今回は本プロパティにSNSトピックを指定することによって、Image Builderパイプラインが完了し、AMIが使用可能になった際に、後述するLambda関数を実行します。

InstanceProfileNameプロパティで、Image Builder用のSLRを指定します。

Resources:
  ImageBuilderRoleProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref ImageBuilderRole

  ImageBuilderRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - ec2.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/EC2InstanceProfileForImageBuilder
Code language: YAML (yaml)

詳細につきましては、以下のページをご確認ください。

https://docs.aws.amazon.com/imagebuilder/latest/userguide/image-builder-setting-up.html

ディストリビューション設定

AWS公式では、ディストリビューション設定を以下の通りに説明しています。

Specify the name and description of your output AMI.

Authorize other AWS accounts, organizations, and OUs to launch the AMI from the owner’s account. The owner account is billed for charges that are associated with the AMI.

Manage EC2 Image Builder distribution settings

つまりディストリビューション設定とは、ビルドされたイメージの配信リージョン等を設定するものです。

Resources:
  DistributionConfiguration:
    Type: AWS::ImageBuilder::DistributionConfiguration
    Properties:
      Distributions:
        - Region: !Ref AWS::Region
          AmiDistributionConfiguration: {}
      Name: !Sub "${Prefix}-DistributionConfiguration"
Code language: YAML (yaml)

Distributionsプロパティで配信設定が行えます。
Regionプロパティに本スタックを作成するap-northeast-1リージョンを指定します。

なお今回はAmiDistributionConfigurationプロパティは何も設定しませんが、この項目を明示しなければ本リソース作成に失敗します。
ですから本プロパティに「{}」を指定します。

パイプライン

AWS公式では、パイプラインを以下の通りに説明しています。

Image Builder image pipelines provide an automation framework for creating and maintaining custom AMIs and container images.

Manage EC2 Image Builder pipelines using the console

つまりパイプラインは、AMIをビルドするために、パッケージインストールやテスト等の一連の流れを自動的に実行します。

Resources:
  ImagePipeline:
    Type: AWS::ImageBuilder::ImagePipeline
    Properties:
      DistributionConfigurationArn: !Ref DistributionConfiguration
      ImageRecipeArn: !Ref ImageRecipe
      InfrastructureConfigurationArn: !Ref InfrastructureConfiguration
      Name: !Sub "${Prefix}-ImagePipeline"
      Status: ENABLED
Code language: YAML (yaml)

今まで確認した各リソースを指定します。
具体的には、レシピ・インフラストラクチャ設定・ディストリビューション設定です。

(参考) SNS

Resources:
  Topic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: !Ref FunctionArn1
          Protocol: lambda
        - Endpoint: !Ref FunctionArn2
          Protocol: lambda
      TopicName: !Ref Prefix

  SNSPermission1:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref Function1
      Action: lambda:InvokeFunction
      Principal: sns.amazonaws.com
      SourceArn: !Ref Topic

  SNSPermission2:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref Function2
      Action: lambda:InvokeFunction
      Principal: sns.amazonaws.com
      SourceArn: !Ref Topic
Code language: YAML (yaml)

Image Builderパイプライン完了後に、SNSを通じて、その旨を各リソースに通知することができます。
今回は2つのLambda関数を実行させます。

SNSを通じてLambda関数を実行する方法については、以下のページをご確認ください。

あわせて読みたい
SNSからLambdaを呼び出す 【SNSからLambdaを呼び出す】 以下のページでSNSについて取り上げました。 https://awstut.com/2022/07/30/introduction-to-sns-with-cfn-email 上記のページでは、サブ...

(参考) Lambda

関数1

Resources:
  ParameterAmi:
    Type: AWS::SSM::Parameter
    Properties:
      Name: !Sub "${Prefix}-Ami"
      Type: String
      Value: " "

  Function1:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Environment:
        Variables:
          PARAMETER: !Ref ParameterAmi
      Code:
        ZipFile: |
          import boto3
          import json
          import os

          parameter = os.environ['PARAMETER']
          client = boto3.client('ssm')

          def lambda_handler(event, context):
            message = json.loads(event["Records"][0]["Sns"]["Message"])
            ami = message['outputResources']['amis'][0]['image']

            response = client.put_parameter(
              Name=parameter,
              Value=ami,
              Type='String',
              Overwrite=True
            )
            print(response)
      FunctionName: !Sub "${Prefix}-function-01"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole1.Arn

  FunctionRole1:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: UpdateSSMParameter
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - ssm:PutParameter
                Resource:
                  - !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${ParameterAmi}"
Code language: YAML (yaml)

SNSによって呼び出されるLambda関数の1つです。
この関数の目的は、ビルドされたAMIのIDをSSM Parameter Storeに保存することです。

関数2

Resources:
  Function2:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          import boto3
          import datetime
          import json
          import os

          event_bus_name = os.environ['EVENT_BUS_NAME']
          detail_type = os.environ['DETAIL_TYPE']
          source = os.environ['SOURCE']

          client = boto3.client('events')

          def lambda_handler(event, context):
            detail = json.dumps({})

            entry = {
              'Time': datetime.datetime.now(),
              'Source': source,
              'Resources': [],
              'DetailType': detail_type,
              'Detail': detail,
              'EventBusName': event_bus_name
            }
            print(entry)

            response = client.put_events(
              Entries=[entry,]
            )
            print(response)
      Environment:
        Variables:
          EVENT_BUS_NAME: !Ref EventBusName
          DETAIL_TYPE: image-builder-finish-event
          SOURCE: !Ref Prefix
      FunctionName: !Sub "${Prefix}-function-02"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole2.Arn

  FunctionRole2:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: !Sub "${Prefix}-PutEventsPolicy"
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - events:PutEvents
                Resource: !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:event-bus/${EventBusName}"
Code language: YAML (yaml)

SNSによって呼び出されるLambda関数の1つです。
この関数の目的は、EventBridgeのカスタムイベントを生成することです。

詳細については、以下のページをご確認ください。

あわせて読みたい
EventBridgeを使って2つのLambda関数を連携させる 【EventBridgeを使って2つのLambda関数を連携させる】 EventBridgeはフルマネージドのイベントバスサービスです。 Amazon EventBridge は、コードを作成せずに、AWS の...

関数3

Resources:
  CustomResource:
    Type: Custom::CustomResource
    Properties:
      ServiceToken: !GetAtt Function3.Arn

  Function3:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Environment:
        Variables:
          IMAGE_PIPELINE_ARN: !Ref ImagePipelineArn
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import os

          image_pipeline_arn = os.environ['IMAGE_PIPELINE_ARN']
          client = boto3.client('imagebuilder')

          CREATE = 'Create'
          response_data = {}

          def lambda_handler(event, context):
            try:
              if event['RequestType'] == CREATE:
                response = client.start_image_pipeline_execution(
                  imagePipelineArn=image_pipeline_arn
                )
                print(response)

              cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)

            except Exception as e:
              print(e)
              cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
      FunctionName: !Sub "${Prefix}-function-03"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole3.Arn

  FunctionRole3:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: UpdateSSMParameter
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - imagebuilder:StartImagePipelineExecution
                Resource:
                  - !Ref ImagePipelineArn
Code language: YAML (yaml)

この関数は、CloudFormationカスタムリソースに関連づけます。

カスタムリソースに関する詳細は、以下のページをご確認ください。

あわせて読みたい
CloudFormationカスタムリソース入門 【CloudFormationカスタムリソースの挙動を確認する構成】 CloudFormationの機能の1つにカスタムリソースがあります。 カスタムリソースを使用すると、テンプレートにカ...

この関数の目的は、CloudFormationスタック作成時に、Image Builderパイプラインを開始することです。

関数4

Resources:
  WaitConditionHandle:
    Type: AWS::CloudFormation::WaitConditionHandle

  WaitCondition:
    Type: AWS::CloudFormation::WaitCondition
    Properties:
      Handle: !Ref WaitConditionHandle
      Timeout: !Ref WaitConditionTimeout

  EventsRule:
    Type: AWS::Events::Rule
    Properties:
      EventBusName: !Ref EventBusName
      EventPattern:
        source:
          - !Ref Prefix
      Name: !Sub "${Prefix}-EventsRule"
      State: ENABLED
      Targets:
        - Arn: !GetAtt Function4.Arn
          Id: !Ref Function4

  EventsRulePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref Function4
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt EventsRule.Arn

  Function4:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Environment:
        Variables:
          SIGNAL_URL: !Ref WaitConditionHandle
      Code:
        ZipFile: |
          import boto3
          import json
          import os
          import urllib3
          import uuid

          signal_url = os.environ['SIGNAL_URL']

          def lambda_handler(event, context):
            body = json.dumps({
                "Status": "SUCCESS",
                "Reason": "AMI Building Successed",
                "UniqueId": str(uuid.uuid4()),
                "Data": "Lambda Deploy Package Setup Successed"
            })
            http = urllib3.PoolManager()
            http.request('PUT', signal_url, body=body)
      FunctionName: !Sub "${Prefix}-function-04"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole4.Arn

  FunctionRole4:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Code language: YAML (yaml)

CloudFormationを使用して、Image BuilderでAMIを作成し、このAMIを使用してEC2インスタンスを作成する場合、ポイントは作成する順序です。
最初にImage Builderリソースを作成し、次にパイプラインを実行してAMIをビルドし、最後にEC2インスタンスを作成します。

そのためにCloudFormation WaitConditionを使用して、リソースの作成タイミングを制御します。
WaitConditionを使用して、EC2インスタンスの作成を待機させます。

先述の通り、CloudFormationカスタムリソースによって、Lambda関数3が実行されて、Image Builderパイプラインが開始されます。
SNSを通じて、Lambda関数2が実行されて、EventBridgeカスタムイベントが生成されます。
このイベントがEventBridgeルールを満たしているため、同ルールに関連づくLambda関数4が実行がトリガーされます。
この関数によって、WaitConditionに成功シグナルが通知されて、待機が解除されます。
このように、WaitConditionを使用することによって、EC2インスタンスが作成されるタイミングを、AMIが作成された後に制御できます。

詳細につきましては、以下のページをご確認ください。

あわせて読みたい
CFNのWaitConditionを使用して、Lambdaデプロイパッケージのビルドを待つ 【CFNのWaitConditionを使用して、Lambdaデプロイパッケージのビルドを待つ】 CloudFormationを使用して、Lambda関数を作成することを考えます。 以下のページでご紹介...

上記のページでは、Lambda関数を作成する際に、関数本体と、デプロイパッケージを作成する順序を制御する方法を取り上げています。
Lambda関数用のデプロイパッケージとElastic Beanstalk用のソースバンドルとの違いはありますが、考え方は全く同じです。

EC2インスタンス

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Sub "{{resolve:ssm:${ParameterAmi}}}"
      InstanceType: !Ref InstanceType
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          GroupSet:
            - !Ref InstanceSecurityGroup
          SubnetId: !Ref PublicSubnet1
Code language: YAML (yaml)

ImageIdプロパティでAMIを指定します。
今回は先述のSSM Parameter Storeに保存されているAMI IDを動的参照します。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html

先ほども確認した通り、EC2インスタンスを作成するタイミングは、CloudFormation WaitConditionで調整しています。
つまり必ずSSM Parameter StoreにAMI IDが保存されていることが保証されているということです。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • コンポーネント:fa-145-Component
  • レシピ:fa-145-ImageRecipe
  • インフラストラクチャ設定:fa-145-InfrastructureConfiguration
  • ディストリビューション設定:fa-145-DistributionConfiguration
  • パイプライン:fa-145-ImagePipeline
  • EC2インスタンス:i-0547b207bb21f2ee0

作成されたリソースをAWS Management Consoleから確認します。

コンポーネントを確認します。

Detail of Image Builder 1.

正常にコンポーネントが作成されています。
Contentを見ると、YAMLファイルの中身を確認することができます。

レシピを確認します。

Detail of Image Builder 2.

正常にレシピが作成されています。
先ほど確認したコンポーネントが指定されていることわかります。

インフラストラクチャ設定を確認します。

Detail of Image Builder 3.

AMIビルド用のインスタンスタイプや、SNSトピックが指定されています。
このSNS通知を通じて、2つのLambda関数が実行されます。

ディストリビューション設定を確認します。

Detail of Image Builder 4.

主にリージョンが設定されていることがわかります。

パイプラインを確認します。

Detail of Image Builder 5.

正常にパイプラインが作成されていることがわかります。

Output Imagesを見ると、このパイプラインは実行されて、AMIが作成されたことがわかります。
つまりCloudFormationカスタムリソースに関連づいているLambda関数3によって、本パイプラインが自動的に実行されたということです。

パイプラインの実行の詳細を確認します。

Detail of Image Builder 6.

ワークフロー全体のステータスはCompletedです。
合計7つのステップがありましたが、全てSkipped・Completedというステータスです。

サンプルとして1番目のステップの詳細を確認します。

Detail of Image Builder 7.

今回のAMIビルド用に一時的に生成されたEC2インスタンスのIDが確認できます。
このインスタンスのIDは「i-009be6f511f325923」でした。

ビルドされたAMIを確認します。

Detail of Image Builder 8.

今回作成されたAMIのIDは「ami-0885558857f153fa9」です。

SSM Parameter Storeを確認します。

Detail of SSM 1.

確かにParameter StoreにAMI IDが保存されています。
つまりSNS経由でLambda関数1が実行されたということです。

EC2インスタンスを確認します。

Detail of EC2 1.

AMI IDの値を見ると、Image BuilderでビルドされたAMIです。
つまりLambda関数2および4によって、EC2インスタンス作成のタイミングを調整し、ビルドされたAMIを使用してインスタンスが作成されたということです。

動作確認

最後にこのインスタンスにアクセスします。

$ curl http://3.112.218.190
instance-id: i-009be6f511f325923
Code language: Bash (bash)

インスタンスから応答がありました。
このIDはAMIビルド用に使われたインスタンスのものです。
このことから確かにImage BuilderによってビルドされたAMIであることがわかります。

まとめ

Image Builderを使用して、AMIを作成しました。
そしてこのAMIを使用して、自動的にEC2インスタンスを作成しました。