

# EC2 Image Builder を使用して、Amazon ECS に最適化されたカスタム AMI を構築する
<a name="image-builder-tutorial"></a>

AWS では、コンテナ ワークロードを実行するための要件および推奨事項であらかじめ設定されている、Amazon ECS に最適化された AMI の使用をお勧めしています。ソフトウェアの追加には AMI のカスタマイズが必要になる場合があります。EC2 Image Builder は、サーバーイメージの作成、管理、デプロイに使用できます。アカウントで作成されるカスタムイメージの所有権は、お客様に保持されます。EC2 Image Builder パイプラインを使用してイメージの更新やシステムパッチを自動化したり、スタンドアロンコマンドを使用して定義済みの設定リソースでイメージを作成することができます。

イメージのレシピを作成します。レシピには親画像とその他の追加コンポーネントが含まれます。さらに、カスタマイズした AMI を配信するパイプラインを作成します。

イメージのレシピを作成します。Image Builder イメージレシピは、ベースイメージとベースイメージに適用するコンポーネントを定義し、必要な構成の出力イメージを生成するためのドキュメントです。さらに、カスタマイズした AMI を配信するパイプラインを作成します。詳細については、「*EC2 Image Builder ユーザーガイド*」の「[EC2 Image Builder の仕組み](https://docs.aws.amazon.com/imagebuilder/latest/userguide/how-image-builder-works.html)」を参照してください。

EC2 Image Builder の「親イメージ」として、次の Amazon ECS に最適化された AMI のいずれかの使用をお勧めします。
+ Linux
  + Amazon ECS 最適化 AL2023 x86
  + Amazon ECS 最適化 Amazon Linux 2023 (arm64) AMI
  + Amazon ECS 最適化 Amazon Linux 2 カーネル 5 AMI
  + Amazon ECS 最適化 Amazon Linux 2 x86 AMI
+ Windows
  + Amazon ECS 最適化 Windows 2022 Full x86
  + Amazon ECS 最適化 Windows 2022 Core x86
  + Amazon ECS 最適化 Windows 2019 Full x86
  + Amazon ECS 最適化 Windows 2019 Core x86
  + Amazon ECS 最適化 Windows 2016 Full x86

利用可能な最新バージョンを使用することをお勧めします。パイプラインでは親イメージにセマンティックバージョニングを使用します。これにより、自動スケジューリングされたジョブの依存関係の更新を検出しやすくなります。詳細については、「*EC2 Image Builder ユーザーガイド*」の「[セマンティックバージョニング](https://docs.aws.amazon.com/imagebuilder/latest/userguide/ibhow-semantic-versioning.html)」を参照してください。

AWS は、Amazon ECS に最適化された AMI イメージを、セキュリティパッチと新しいコンテナエージェントバージョンで定期的に更新しています。AMI ID をイメージレシピの親イメージとして使用する場合、親イメージの更新がないかを定期的に確認する必要があります。更新がある場合は、更新した AMI を使用して新しいバージョンのレシピを作成する必要があります。これにより、カスタムイメージに最新バージョンの親イメージが組み込まれます。新しく作成した AMI を使用して Amazon ECS クラスターの EC2 インスタンスを自動的に更新するワークフローを作成する方法については、「[AMI 強化パイプラインを作成して ECS インスタンスフリートの更新を自動化する方法](https://aws.amazon.com/blogs/security/how-to-create-an-ami-hardening-pipeline-and-automate-updates-to-your-ecs-instance-fleet/)」を参照してください。

マネージド EC2 Image Builder パイプラインを通じて公開された親イメージの Amazon リソースネーム (ARN) を指定することもできます。Amazon は、マネージドパイプラインを通じて、Amazon ECS 最適化 AMI イメージを定期的に公開します。これらのイメージはパブリックアクセス可能です。イメージにアクセスするには、適切なアクセス許可が必要です。Image Builder レシピで AMI の代わりにイメージ ARN を使用すると、パイプラインは実行のたびに最新バージョンの親イメージを自動的に使用します。この方法により、更新のたびに新しいレシピバージョンを手動で作成する必要がなくなります。

## Amazon ECS に最適化された AMI のクリーンアップ
<a name="cleanup-ecs-optimized-ami"></a>

Amazon ECS に最適化された AMI を親イメージとして使用する場合は、一時的な問題を防ぐためにイメージをクリーンアップする必要があります。Amazon ECS に最適化された AMI は、Amazon ECS エージェントが自動起動してコンテナインスタンスとして Amazon ECS に登録するように事前設定されています。適切なクリーンアップを行わずにベースイメージとして使用すると、カスタム AMI で問題が発生する可能性があります。

今後の使用のためにイメージをクリーンアップするには、次のコマンドを実行して ecs-init パッケージと Docker プロセスを停止するコンポーネントを作成します。

```
sudo systemctl stop ecs
sudo systemctl stop docker
```

イメージの保存時に一緒に保存されないように、すべてのログファイルを現在のインスタンスから削除します。[EC2 Image Builder のセキュリティのベストプラクティス](https://docs.aws.amazon.com/imagebuilder/latest/userguide/security-best-practices.html)のスクリプト例を使用して、インスタンスから各種ファイルをクリーンアップします。

Amazon ECS 固有のデータをクリーンアップするには、次のコマンドを実行します。

```
sudo rm -rf /var/log/ecs/*
sudo rm /var/lib/ecs/data/agent.db
```

カスタム Amazon ECS 最適化 AMI を作成する方法については、AWS ナレッジセンターの「[How do I create a custom AMI from an Amazon ECS-optimized AMI?](https://forums.aws.amazon.com/knowledge-center/ecs-create-custom-amis/)」を参照してください。

## イメージ ARN と Infrastructure as Code (IaC) の使用
<a name="infrastructure-as-code-arn"></a>

EC2 Image Builder コンソール、Infrastructure as Code (例: CloudFormation)、または AWS SDK を使用してレシピを設定できます。レシピで親イメージを指定する場合、EC2 AMI ID、Image Builder イメージ ARN、AWS Marketplace プロダクト ID、またはコンテナイメージを指定できます。AWS は、Amazon ECS 最適化 AMI の AMI ID と Image Builder イメージ ARN の両方を公開します。イメージの ARN 形式は以下の通りです。

```
arn:${Partition}:imagebuilder:${Region}:${Account}:image/${ImageName}/${ImageVersion}
```

`ImageVersion` の形式は以下のようになっています。{{[メジャー]}}、{{[マイナー]}}、{{[パッチ]}}を最新の値に置き換えます。

```
<{{major}}>.<{{minor}}>.<{{patch}}>
```

`major`、`minor`、`patch` を特定の値に置き換えたり、イメージのバージョンレス ARN を使用することができます。これにより、パイプラインは常に親イメージの最新バージョンに更新された状態に保たれます。バージョンレス ARN では、ワイルドカード形式「x.x.x」でイメージバージョンを表現します。この方法により、Image Builder サービスは最新バージョンのイメージに自動的に解決されます。バージョンレス ARN を使用すると、参照先は常に利用可能な最新のイメージを示すため、デプロイ内のイメージを最新の状態に維持するプロセスが効率化されます。コンソールでレシピを作成すると、EC2 Image Builder は親イメージの ARN を自動的に識別します。IaC を使用してレシピを作成する場合、ARN を特定して目的のイメージバージョンを選択するか、バージョンレス ARN を使用して使用可能な最新のイメージを示す必要があります。フィルタリングにより条件に合致するイメージのみを表示する自動スクリプトを作成することをお勧めします。次の Python スクリプトは、Amazon ECS 最適化 AMI のリストを取得する方法を示しています。

このスクリプトは、`owner` と `platform` の 2 つのオプション引数を受け付けます。デフォルト値はそれぞれ「Amazon」と「Windows」です。owner 引数の有効値は、`Self`、`Shared`、`Amazon`、`ThirdParty` です。プラットフォーム引数の有効値は、`Windows` と `Linux` です。たとえば、`owner` 引数を `Amazon` に設定し、`platform` を `Linux` に設定してスクリプトを実行すると、スクリプトは Amazon ECS 最適化イメージを含む、Amazon によって公開されたイメージのリストを生成します。

```
import boto3
import argparse

def list_images(owner, platform):
    # Create a Boto3 session
    session = boto3.Session()
    
    # Create an EC2 Image Builder client
    client = session.client('imagebuilder')

    # Define the initial request parameters
    request_params = {
        'owner': owner,
        'filters': [
            {
                'name': 'platform',
                'values': [platform]
            }
        ]
    }

    # Initialize the results list
    all_images = []

    # Get the initial response with the first page of results
    response = client.list_images(**request_params)

    # Extract images from the response
    all_images.extend(response['imageVersionList'])

    # While 'nextToken' is present, continue paginating
    while 'nextToken' in response and response['nextToken']:
        # Update the token for the next request
        request_params['nextToken'] = response['nextToken']

        # Get the next page of results
        response = client.list_images(**request_params)

        # Extract images from the response
        all_images.extend(response['imageVersionList'])

    return all_images

def main():
    # Initialize the parser
    parser = argparse.ArgumentParser(description="List AWS images based on owner and platform")
    
    # Add the parameters/arguments
    parser.add_argument("--owner", default="Amazon", help="The owner of the images. Default is 'Amazon'.")
    parser.add_argument("--platform", default="Windows", help="The platform type of the images. Default is 'Windows'.")

    # Parse the arguments
    args = parser.parse_args()

    # Retrieve all images based on the provided owner and platform
    images = list_images(args.owner, args.platform)

    # Print the details of the images
    for image in images:
        print(f"Name: {image['name']}, Version: {image['version']}, ARN: {image['arn']}")

if __name__ == "__main__":
    main()
```

## CloudFormation でのイメージ ARN の使用
<a name="arn-with-cloudformation"></a>

Image Builder のイメージレシピは、出力イメージの意図した構成を実現するために必要な親イメージとコンポーネントを指定するブループリントです。`AWS::ImageBuilder::ImageRecipe` リソースを使用します。`ParentImage` 値をイメージ ARN に設定します。パイプラインが常に最新バージョンのイメージを使用するように、目的のイメージのバージョンレス ARN を使用してください。例えば、`arn:aws:imagebuilder:us-east-1:aws:image/amazon-linux-2023-ecs-optimized-x86/x.x.x`。以下の `AWS::ImageBuilder::ImageRecipe` リソースの定義は、Amazon マネージドイメージ ARN を使用しています。

```
ECSRecipe:
    Type: AWS::ImageBuilder::ImageRecipe
    Properties:
      Name: MyRecipe
      Version: '1.0.0'
      Components:
        - ComponentArn: [<The component arns of the image recipe>]
      ParentImage: "arn:aws:imagebuilder:us-east-1:aws:image/amazon-linux-2023-ecs-optimized-x86/x.x.x"
```

これらの [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-imagerecipe.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-imagerecipe.html) リソースの詳細については、「*AWS CloudFormation ユーザーガイド*」を参照してください。

`AWS::ImageBuilder::ImagePipeline` リソースの `Schedule` プロパティを設定することで、パイプラインでの新しいイメージの作成を自動化できます。スケジュールには開始条件と cron 式が含まれています。詳細については、*AWS CloudFormation ユーザーガイド*の [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-imagepipeline.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-imagepipeline.html) をご参照ください。

 `AWS::ImageBuilder::ImagePipeline`次の例では、パイプラインで毎日協定世界時 (UTC) の午前 10 時にビルドを実行しています。以下の `Schedule` 値を設定します。
+ `PipelineExecutionStartCondition` を `EXPRESSION_MATCH_AND_DEPENDENCY_UPDATES_AVAILABLE` に設定します。ビルドは、セマンティックバージョンでワイルドカード「x」を使用する親イメージやコンポーネントなどの依存リソースが更新された場合にのみ開始されます。これにより、ビルドにはそれらのリソースの最新の更新が確実に組み込まれます。
+ ScheduleExpression を cron 式 `(0 10 * * ? *)` に設定します。

```
ECSPipeline:
    Type: AWS::ImageBuilder::ImagePipeline
    Properties:
      Name: my-pipeline
      ImageRecipeArn: <arn of the recipe you created in previous step>
      InfrastructureConfigurationArn: <ARN of the infrastructure configuration associated with this image pipeline>
      Schedule:
        PipelineExecutionStartCondition: EXPRESSION_MATCH_AND_DEPENDENCY_UPDATES_AVAILABLE
        ScheduleExpression: 'cron(0 10 * * ? *)'
```

## Terraform でのイメージ ARN の使用
<a name="arn-with-terraform"></a>

Terraform でパイプラインの親イメージとスケジュールを指定する方法は、AWS CloudFormation での方法と同様です。`aws_imagebuilder_image_recipe` リソースを使用します。`parent_image` 値をイメージ ARN に設定します。パイプラインが常に最新バージョンのイメージを使用するように、目的のイメージのバージョンレス ARN を使用してください。詳細については、Terraform ドキュメントの [https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_image_recipe#argument-reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_image_recipe#argument-reference) を参照してください。

`aws_imagebuilder_image_pipeline resource` のスケジュール設定ブロックで、`schedule_expression` 引数の値を任意の cron 式に設定してパイプラインの実行頻度を指定し、`pipeline_execution_start_condition` を `EXPRESSION_MATCH_AND_DEPENDENCY_UPDATES_AVAILABLE` に設定します。詳細については、Terraform ドキュメントの [https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_image_pipeline#argument-reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_image_pipeline#argument-reference) を参照してください。