Amazon Web Services ブログ

ECS-optimized AMI Build Recipes を用いて、カスタム Amazon Machine Image (AMI) を作成する

Amazon Elastic Container Service (Amazon ECS) 上でコンテナワークロードを実行しているお客様は、AWS Fargate を利用するか、Amazon ECS-optimized AMI を用いて Elastic Compute Cloud (EC2) を利用するか、選択できます。これまでにお客様から寄せられた要望 (issue #176) の中には、独自の ECS Amazon Machine Image (AMI) を作成できるようにしてほしい、というものがありました。

本日、私たちは ECS-optimized AMI Build Recipes をオープンソースプロジェクトとして公開しました。そのビルドスクリプトでは、HashiCorp 社の packer レシピを使用して AMI をビルドします。

ユースケース

独自のカスタム ECS AMI をビルドすることで、様々なユースケースを実現できます。

  1. より軽量な AMI。お客様の中には、EBS ボリュームのコストを削減するために、ECS インスタンスにより小さな EBS ボリュームを作成したいと考える方がいます。
  2. ECS コンテナインスタンスにプリインストールされたソフトウェア。お客様の中には、クラウド上のインスタンスに、特定のソフトウェアやパッケージをインストールする要件 (例 : 監視、セキュリティエージェント) をお持ちの方がいます。このレシピでは、独自の AMI にソフトウェアをパッケージ化することで、プロビジョニングや標準化を高速化できます。
  3. 事前にキャッシュされたコンテナ。ECS タスクの起動時間を短縮したいお客様のために、ECS インスタンスに docker イメージを事前キャッシュ可能になりました。これにより、コンテナレジストリからインスタンスに初期イメージのプル時間を短縮できます。これは、イメージサイズが極めて大きい場合に有効です。

アーキテクチャ

下図に、ビルドのプロセスを示します。

  1. SSH キーペアと適切なセキュリティグループが設定された新しい EC2 インスタンスをプロビジョニングします。(デフォルトでは、packer は 0.0.0.0/0 からの SSH トラフィックを許可するルールを作成しますが、これはカスタマイズ可能です。)
  2. EC2 インスタンスにソフトウェアをインストールし、オペレーティングシステムの構成変更を行います。これには、関連する ECS ソフトウェアパッケージとその依存関係が含まれます。
  3. インスタンスは、パッケージ化される前に、インスタンス固有の情報を一掃する「一般化」プロセスを経ます。
  4. インスタンスを停止し、関連するタグ情報を適用した AMI をインスタンスから作成します。
  5. このプロセスで作成したリソースを削除します。(EC2 インスタンスを終了し、セキュリティグループとキーペアを削除します。)

事前準備

手順

まず、Amazon ECS AMI の github リポジトリをローカル環境にクローンし、amazon-ecs-ami ディレクトリに移動します。

git clone https://github.com/aws/amazon-ecs-ami
cd amazon-ecs-ami

このブログ記事では、us-east-1 の AWS リージョンで Amazon Linux 2 AMI をビルドしていきますが、どの AWS リージョンでも同様にビルドできます。

スクリプトは、以下のアーキテクチャの AMI のビルドをサポートしています。

  • al1 – Amazon Linux 64-bit (x86)
  • al2 – Amazon Linux 2 64-bit (x86)
  • al2arm – Amazon Linux 2 64-bit (Arm)
  • al2gpu – Amazon Linux 2 GPU-optimized
  • al2inf – Amazon Linux 2 (Inferentia)

make コマンドを実行します。(REGION は必須です。)

REGION=us-east-1 make al2

このスクリプトは、お使いの環境に適したバージョンの packer と Packer Plugin Amazon をダウンロードします。ここで、variables.pkr.hcl にあるグローバルなデフォルト値と、各アーキテクチャ用の特定の設定ファイル (ここでは al2.pkr.hcl) にある追加のデフォルト値を使用します。これらすべてのデフォルト値は、ニーズや要件に応じてカスタマイズできます。

ここで、EC2 インスタンスが us-east-1 のデフォルト VPC で起動します。このビルドでは、新しいキーペアとセキュリティグループを作成します。

インスタンスが起動し、SSH でアクセス可能になると、ソフトウェアのインストールやインスタンスの設定変更など、いくつかのステップを経ます。進捗状況はコンソール上に表示されます。

以下に、インスタンスで行われる操作の概要を示します。

  • Message of the Day (MOTD) バナーを変更します
  • Docker をインストールします
  • ecs-init パッケージをインストールします
  • ecs exec 機能を有効化するために AWS Systems Manager Agent (SSM Agent) をインストールします
  • ec2-user を docker Unix グループに追加します
  • 起動時に ecsamazon-ecs-volume-pluginamazon-ssm-agent サービスが起動していることを確認します
  • インスタンスから特定の情報を削除します

すべての変更点の包括的なリストは、github リポジトリで確認できます。

その後、インスタンスを停止し、レシピはインスタンスから AMI (とバックアップのスナップショット) を作成します。

一連のプロセスが完了すると、レシピは EC2 インスタンスを終了し、セキュリティグループとキーペアを削除します。

遮断された環境 (エアギャップ)

レシピが実行するスクリプトでは、インスタンスを実行している VPC の外部にあるリポジトリから、多くのパッケージやソフトウェアをダウンロードします。お客様の中には、ソフトウェアダウンロードのための自由なインターネットアクセスを禁止するような、厳しいセキュリティ要件をお持ちの方もいます。このレシピは、そのような要件にも対応しています。

そのようなユースケースでは、variables.pkr.hcl該当箇所で、変数を true に設定する必要があります。

variable "air_gapped" {
  type = string
  description = "If this build is for an air-gapped region, set to 'true'"
  default = "true"
}

もし他のソフトウェアパッケージをインストールしたいのであれば、addinional-packages ディレクトリにダウンロード、保存する必要があります。そうすることで、レシピがインスタンスにそれらのソフトウェアパッケージをコピー、インストールします。

後片付け

この記事の中で作成したリソースを削除するには、AMI を登録解除し、スナップショットを削除する必要があります。そのためには、以下のコマンドを実行してください。

AMI_ID=$(aws ec2 describe-images \
  --filters "Name=tag:Name,Values='Packer Builder'" \
  --query 'Images[*].[ImageId]' \
  --region us-east-1 \
  --output text)

SNAPSHOT_ID=$(aws ec2 describe-images \
  --filters "Name=tag:Name,Values='Packer Builder'" \
  --query 'Images[].BlockDeviceMappings[].Ebs.SnapshotId' \
  --region us-east-1 \
  --output text)

aws ec2 deregister-image --image-id $AMI_ID --region us-east-1
aws ec2 delete-snapshot --snapshot-id $SNAPSHOT_ID --region us-east-1

まとめ

この記事では、ECS-optimized AMI Build Recipes の使用方法、そのプロセスで作成されるリソース、固有の要件に応じてスクリプトをさらにカスタマイズする方法の詳細について、紹介しました。

ECS-optimized AMI Build Recipes は、オープンソースかつ共同のコミュニティプロジェクトなので、あなたの参加、フィードバックをお待ちしています。ぜひ Amazon ECS AMI github リポジトリで issue の議論を確認し、プルリクエストを通じて貢献してみてください。

翻訳はソリューションアーキテクト渡辺が担当しました。原文はこちらです。