Blog

AMIの作成を自動化して、サーバーを立ててみる

はじめに

こんにちは、会員システムグループの上原です。
先日、社内ISUCONを開催し、参加者から好評の声をいただくことができました。
当日どんな感じだったのか気になる方は以下のブログ記事をご覧ください。https://engineering.nifty.co.jp/blog/21057
本イベントでは参加者にハンズオンで使用するサーバーを配布しました。参加者の人数とクォータ制限の観点から、数百台のサーバーをマルチアカウント・マルチリージョンで展開する必要があったのですが、手動でやるのは面倒だったので、可能な限り自動化してみました。

目標

  • 数百台の同じ設定を入れ込んだサーバーを複数のAWSアカウント・複数のリージョンで簡単に立ち上げたい

従来の方法

同じ設定のサーバーを大量に立ち上げるためにまずはAMIを作成し、そのAMIを元にサーバーを起動する方法が思いつきます。
具体的には以下の手順になります。
  • UbuntuやAmazon LinuxなどのOSが入っているAMIからEC2インスタンスを立ち上げる
  • sshやセッションマネージャなどでサーバにログインし、EC2インスタンスに必要なソフトウェア・設定を入れ込む
  • EC2インスタンスをAMI化する
  • 作成したカスタムAMIを使って複数アカウント・複数リージョンにサーバーを立てる

従来の方法の問題点とその解決策

従来の方法の問題は、AMIを作成するためだけにEC2インスタンスを起動しコマンドを打ちこみイメージを作成する必要があるところです。
ですが、手作業だと抜け漏れやミスが発生しやすく、何しろ面倒です。
そこで、AMIを自動的に作成する方法はないかどうか探してみたところ見つけたのが、Amazon EC2 Image Builderというサービスです!

Amazon EC2 Image Builderとは?

Amazon EC2 Image BuilderとはAWSのフルマネージドサービスで、AMIを自動で生成・検証・配布してくれるサービスです。
手順をYAMLファイルに書いておけばその手順をもとにAMIを作成・検証し、AMIを他リージョン・他アカウントにも共有・コピーして使えるようにしてくれます。
より詳しく知りたい方は以下のBlack Beltのpdfがわかりやすいので参考にしてください。
https://pages.awscloud.com/rs/112-TZM-766/images/20200825_BlackBelt_EC2imagebuilder.pdf

ハンズオン

  • 今回はお試しとしてslコマンドを入れたサーバーを5台同時に立ててみます
    • 使用するOSはUbuntu 22.04
      • 公式のAMI(ami-0d52744d6551d851e)を使用する
    • AMIは自アカウントのap-northeast-1とus-east-1に展開します
      • ちなみに、今回のterraformのコードをいじると別のアカウントにも展開できるようにすることもできます
    • 作成したAMIを使ってEC2インスタンスをap-northeastに5台起動します
  • 今回使うコードはこちらのレポジトリに配置しています。

Amazon EC2 Image Builderでパイプラインを作成する

ここではAWS EC2 Image Builderをterraformを使って立ててみます
  • レポジトリをcloneします
  • terraform実行に必要なS3バケットや認証情報を入れてください
  • terraform initで初期化、terraform applyでAWS環境に反映します
  • 実行が終わればEC2 Image Builderのパイプラインが作られた状態になります

コンソールに入って設定を見てみる

  • AWS コンソールにログインし、EC2 Image Builderでイメージパイプラインを表示します
  • 以下のように作成したパイプラインが表示されるはずです
  • パイプラインの中を見ると、パイプラインで出力したイメージ(AMI)・作成手順・配布設定・トリガーの設定を見ることができます
  • レシピはどのようにAMIを構築するか指定します
    • ベースとなるイメージをUbuntuに指定し、slコマンドをインストールする手順をコンポーネントに記述します
  • ディストリビューション設定をクリックし、image-builder-testの中身を見ると以下の通りになっています
    • ap-northeast-1とus-east-1に作成したAMIを展開するように設定されています

パイプラインを実行し、AMIを作成する

  • 手動でパイプラインを実行します。イメージパイプラインからimage-builder-testにチェックを入れてパイプラインを実行するをクリックします
  • パイプラインの出力イメージに作成中のイメージが追加されます
  • 出力イメージをクリックすると作成状況がわかります
  • 作成中はEC2 Image BuilderがEC2を起動して作業をしています
  • 完了になればAMIがap-northeast-1とus-east-1に作成されているはずです

EC2を起動する

  • terraformコードで今回作成したAMIを参照してEC2を5台起動できるようにしているので、ec2ディレクトリに移動しterraform applyで反映させます
  • EC2コンソールでサーバーが5台起動していることがわかります
  • セッションマネージャでログインするとslコマンドがインストールされてることがわかります
  • このようにAMIの作成手順や設定を記述しパイプラインを実行することで、AMIの作成・配布を自動化できます
    • 設定を変更し、もう一度パイプラインを実行すればAMIを更新してくれます

お片付け

  • terraform destroyでEC2 Image BuilderとEC2を破棄します
  • コンソール画面でバージニア北部と東京リージョンに作成されたAMIの登録解除を行い、スナップショットを削除します

EC2 Image Builderのterraformのコード説明

  • もし気になる方向けにterraformのコードの中身を簡単に説明します

Image Pipeline

  • AMIを生成・配布するための自動実行されるパイプラインです
    • CodePipelineのPipelineと同じやつです
  • 1つのパイプラインから1つのAMIができます
  • terraformの設定の中身はレシピとインフラ設定、配布設定のarnを指定しているだけです
    • その他スケジュールで定期的にパイプラインを実行することもできます
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_image_pipeline

Recipes

  • レシピはAMIをどのように作っていくか記述していきます
  • ここでslをインストールするように指示する自作のコンポーネントを指定します
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_image_recipe

Components

  • コンポーネントはAMIを作成するためにどのようなコマンドを実行するかを記述します
  • AWSが公式に出しているコンポーネントもあります
  • 他のレシピからも参照できる再利用可能なコンポーネントです
  • 中身はYAMLで記述します
    • ビルドフェーズでaptを使ってslをインストールしますテストフェーズで正常動作するか検証することができ、今回はwhichを使ってslコマンドが存在するか検証します
    • yamlに記述するnameにスペースがあるとエラーになるので注意してください
    • 引数を受け取って処理させることも可能です(今回は引数を受け取りません)
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_component

infrastructure Configuration

  • Image BuilderがAMIを作成するために立ち上げるEC2の設定を記述します
  • Image Builderが起動するEC2には以下のポリシーが必要です
    • arn:aws:iam::aws:policy/EC2InstanceProfileForImageBuilder
    • arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
  • SSM agentとSSMが疎通できる環境でないとImage Builderは使えないです
    • セキュリティグループでインターネットへの外向きのアクセスを全開放にして、サブネットをパブリックに、起動時にパブリックIPが自動的につくように設定すると簡単に疎通できると思います
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_infrastructure_configuration

Distribution Configuration

  • 作成したAMIをどのアカウント・どのリージョンに展開するか記述します
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_distribution_configuration
  • 1リージョンごとに設定を入れます
    • terraformだとdynamicという構文を使うとfor文で一気に設定を入れることができます
    • ami_tagsでamiのtagを指定できます
    • target_account_idにAMIをコピーして配置したいIDを指定します
      • 他のAWSアカウントでも可能ですが、ここで指定したアカウントにクロスアカウントアクセス用のロールを作成する必要があります
    • 逆にコピーせず共有したい時にはlaunch_permissionでIDを指定しましょう
https://docs.aws.amazon.com/imagebuilder/latest/userguide/cross-account-dist.html

最後に

今回は社内ISUCONで参加者にサーバーを配布するために使用したAmazon EC2 Image Builderをご紹介しました。
このサービスを使うと、AMIの作成を自動化することができ非常に便利です。
もしよろしければ使ってみてください。

We are hiring!

ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です!
ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! カジュアル面談も受け付けています! Tech TalkやMeetUpも開催しております!
こちらもお気軽にご応募ください!