ImageBuilderでカスタムAMIを作成

# ImageBuilderでカスタムAMIを作成

## はじめに

昔、IaCの先駆けといいますか、PapetやChefを使用したことがあります。
その後、Ansibleが主流となった経緯を体験してきました。
PapetやChefでは自動構築する処理を書くのですが、それを「レシピ」と呼んでいました。
Ansibleではプレイブックと呼ぶようになったので、しばらく「レシピ」という言葉は聞かなくなりました。

今回、AWSでもAnsibleのようなIaCサービス、ImageBuilderを使用する必要があり、事前検証を行いました。
ここで久々に「レシピ」という言葉に出会ったのですが、Chefの頃のレシピとは少々位置づけが違っているように感じ、ImageBuilderの理解に時間がかかってしまいました。

最終的にはこのImageBuilderの検証で行った手順をTerraform化し、マネジメントコンソールから設定するのではなく、IaC(Terraform)でIaC(imageBuilder)を構成することも検討予定ですが、まずはImageBuilderとはどのようなサービスなのか、どんなものが作成されるのか、こちらを検証してみることにしました。

## どこから手を付ける？

ImageBuilderへアクセスするとこのような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/ae65f026-2189-f6e7-242d-a1f6e00f3804.png)

「イメージパイプラインを作成する」というボタンが目立ちますが、闇雲に試してみたところ、ここからスタートするのは少々難しいと感じました。
ではどこから構築するか。
イメージパイプラインはイメージレシピと、イメージレシピを構成するコンポーネントが必要になることがわかりました。
下から攻める、まずはコンポーネントから用意していくことにしました。

## コンポーネント

コンポーネントはその名の通り、どのようなコンポーネントをどのように準備するのかを記載します。
今回はAMIにZabbix AgentとSplunkをインストールした状態で作成したいので、Zabbix Agent用とSplunk用の2つのコンポーネントを作成します。

「コンポーネントを作成する」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/2c1cbff3-1ec5-a95a-11da-a75e8ca9f82e.png)

コンポーネントの各パラメータですが、以下のように指定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/6b39db8d-85d4-54a5-7ef3-7fc4c9a0d0a5.png)

タイプ＝ビルド
互換性のあるOSバージョン＝Amazon Linux 2
コンポーネント名＝ZabbixAgent
コンポーネントのバージョン＝1.0.0

実際の処理はこの下にある、「定義ドキュメント」に記載します。
どのように書くべきか、まずは記述イメージを沸かせるために、「例を使用する」をクリックしてみます。
AWSが用意しているサンプルが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/769ccb9a-f24a-cba5-70f8-29895ab0264f.png)

このサンプルを見つつ、自分がどのような処理でコンポーネント(今回はZabbixAgent)をインストールするのかを記述します。
(以下、さらっと書いていますが、何度も何度も試行錯誤して出来上がった定義ドキュメントです)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/09d04515-9d23-30f0-b483-3e18e92aeca4.png)

同様の手順で、Splunk用のコンポーネントも作成しておきます。

## イメージレシピ

次に、どのコンポーネントを使用するのかを定義するイメージレシポを作成します。
「イメージレシピを作成」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/15ca9161-bf93-4393-f229-9f00c88cbcb8.png)

イメージレシピの基本的な情報となる名前とバージョンを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/a1269205-d792-3b84-a58d-5b0f5ce87a36.png)

ベースとなるイメージを指定します。
今回はAmazon Linux 2を使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/e67e946c-ee6e-9517-d8fc-202ad7b545eb.png)

Amazon Linux 2をどのような状態で使用するのかを指定できます。
常に最新の状態のAIMを使用したい場合もあるでしょうが、以下のように、バージョンを指定しておくことも可能です。
業務で使用する場合は常に最新のものというよりは、動作検証のとれた、確実に動くバージョンを使用したい場合もあると思いますので、そういう場合にとても役に立つ設定だと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/50c2b819-be58-4d09-700b-397b1da28f84.png)

インスタンスの設定は今回は利用しませんでしたので未指定で進めます。
(SSMエージェントの削除は指定しても良かったかもしれません)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/6fbfee4b-9821-c21d-dc77-e1f6891ef219.png)

作業ディレクトリも特に理由がなければ変更せずこのままで進めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/b8500056-8f1e-776e-9fcf-6c55da98b5db.png)

次に、肝となるコンポーネントの指定です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/3fc3bba9-87cf-5687-ed42-358bf9b49396.png)

ここで、AWSが用意しているコンポーネントや、事前に作成したコンポーネントを選択します。
選択肢から、「ユーザ所有」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/98130eaa-f3e7-0824-3063-08669508031c.png)

すると、事前に作成したコンポーネントが表示されるので、カスタムAMIにどのコンポーネントをインストールするのかを指定します。
今回はZabbixAgentとSplunkHFを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/5df20d19-b02a-e4eb-d182-51e783edbe7e.png)

テストコンポーネントも同様にAWSが用意されたコンポーネントなどが選択可能です。
今回はテストコンポーネントは使用しませんので、コンポーネントの選択は行わずに進めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/3f5ea162-6c04-f1b8-c382-6fa1a87a2e0a.png)

ストレージボリューム、タグについても必要に応じて設定します。
設定が終わったら、最後に「レシピを作成する」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/2668e0cd-e7bf-2f41-d893-3c6f7ac00ba2.png)


## イメージパイプライン

コンポーネント、イメージレシピの準備ができましたので、いよいよイメージパイプラインを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/f9f258a7-3389-fcd4-8582-073e9b93a6ef.png)

イメージパイプライン名を入力し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/b4099970-67d9-7cfe-ac69-82b6df5f2d6a.png)

ビルドスケジュールは今回は検証のため「手動」とし、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/c983c4f2-fd31-eeb5-ea82-f65dd2554784.png)

必要に応じてタグを入力し、「次へ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/ad2ff793-5c08-5388-a61e-21df5db1e6a7.png)

イメージレシピの指定になりますが、事前に作成してあるので、「既存のレシピを使用する」を選択します。
ここで新しいレシピを作成することも可能です。
ImageBuilderに慣れていればここから作成したほうが楽かもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/1c9d9662-359d-d2e6-dcc6-6c558107ebcd.png)

事前に作成しておいたイメージレシピを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/7c83be8c-798b-6e0c-cc46-1096f413adba.png)

すると、画面には、選択したイメージレシピの情報が表示されます。
先程設定したように、ZabbixAgentとSplunkHFの2つのコンポーネントが含まれていることがわかります。
内容を確認し、「次へ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/227f93eb-bc69-083d-3add-e0b116511fb5.png)

インフラストラクチャ設定では今回は便宜上、「サービスデフォルトを使用」とします。
なお、このインフラストラクチャ設定は後ほど変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/139d11bf-cc3b-4040-ed48-ffdc048640e9.png)

ディストリビューション設定もデフォルトのまま進めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/1a3f54be-1976-3c2e-433d-1edd5d57ddde.png)

以上の設定の内容を最後に確認し、「パイプラインを作成する」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/fa54eaf3-57be-640c-a79c-2b0efe35e1fc.png)

## インフラストラクチャ設定の変更

作成したイメージパイプラインですが、このままでは実行時にエラーになる箇所と、少々カスタマイズしたほうが良い箇所がありますので、そちらを変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/abed0f11-858e-6118-9329-0102fa76252c.png)


### IAMロールの変更

この変更は、どのようなコンポーネントを定義しているのかに左右されます。
今回の検証ではZabbixAgentで必要な媒体はインターネットから取得しています。
SplunkHFは特定のバージョンを利用したいこともあり、S3バケット内に媒体を保管しておき、コンポーネント内でS3から媒体を取得する処理にしています。
このイメージパイプラインのインフラストラクチャ設定で定義されているIAMロールはS3へのアクセス権限が不足していますので、このまま実行するとエラーになります。

インフラストラクチャの「編集」をクリックし、IAMロールの下にある、「新しいロールを作成する」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/1276e9f6-4ed7-bb71-5d7d-d43612a0f8fb.png)

ロール名の検索欄に「EC2」と入力すると、現在インフラストラクチャ設定で使用されている「EC2InstanceProfileForImageBuilder」が現れますので、ロール名をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/4e893c6d-f072-2c8f-f200-c899689c3dad.png)

このロールにS3のアクセスポリシーをアタッチします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/a796a394-bf95-a117-7a8a-ac8f04ce32d9.png)

余計な権限は与えないのがAWSのポリシー。
今回はS3バケットから情報が取り出せれば良いので、「AmazonS3ReadOnlyAccess」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/dabc83bc-eaef-976c-5e66-9db48565dfbf.png)

これでS3へのアクセス権限が付与されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/55d323d3-f8cf-5fde-1c5c-22eafd5ff157.png)

### インスタンスタイプの変更

イメージパイプラインのインフラストラクチャ設定に戻ります。
ここにある、インスタンスタイプが未指定の状態です。
このままでも問題はないのですが実際に実行すると4xlargeなど、高スペックのインスタンスが使用されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/c754761b-00d6-7439-626f-4e2752e5dcf9.png)

パイプラインの実行が終われば自動的にインスタンスは終了するのでそこまで費用にこだわらなくてもよいのかもしれませんが、少しでも費用を抑えるために、低スペックのインスタンスを指定しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/6938931b-c818-35b7-fa64-178f86aa1bc0.png)

## 動作確認

以上で基本的なImageBuilderの設定が終わりました。
実際に実行し、カスタムAMIが作成されるか確認してみます。

今回のイメージパイプラインは手動で設定していますので、イメージパイプラインを画面から実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/fffc1f4c-1856-7c6a-0dd5-e5f292763a4c.png)

しばらく時間がかかりますが、エラーがなければ出力イメージのステータスが「使用可能」になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/9cdc44e8-e227-bd58-b040-392af97ecf35.png)

あとは、完成したこのAMIを使用して、EC2インスタンスを起動するだけです。
実際に起動したEC2インスタンスを確認すると、ZabbixAgentが起動していますし、S3から取得したSplunkHFの媒体も/tmpに存在しています。


## おわりに

ImageBuilderの構成の理解に少々時間がかかりました。
あとはコンポーネントの中身。
こちらは何度か試行錯誤しながら形にしていくことになりますので、こちらも少々時間がかかります。
それでも、一度カスタムAMIが完成してしまえば、あとは安定して同じ状態のAMIを使用してEC2のインスタンスやコンテナを起動することができます。
これまで、ChefやAnsibleで自動構築を経験してきましたが、AWSでも同じようなことができるということを実際に経験することができました。
Ansible等に触れたことがある方であれば理解は早いと思います。
AnsibleのRoleのように、コンポーネントを分割して構成する構成が良いです。
コンポーネントをバージョンアップしたのであれば、それに付随してイメージレシピもどのバージョンのコンポーネントを使用するのかを設定変更すれう必要がありますが、関係のないコンポーネントに影響が及ぶことにはなりません。

例えば、SplunkHFのコンポーネントを修正し、バージョンを「1.0.1」に変更した場合、イメージレシピ内のコンポーネントのバージョン指定も変更する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589067/e8108319-240f-9dcc-a226-cac17c400876.png)

修正したコンポーネントはイメージレシピンはすべてバージョン管理されて保存されているため、いつでも過去のバージョンを使用してカスタムAMIを作成することもできます。

一度使い方を理解してしまえば、かなり面白いサービスだなと感じることができました。
これはImageBuilderにだけ言える話ではなく、AWSの他のサービスについても同じようなことが言えると思います。

サービス数が多いのですべてを検証してみることはできませんが、今後も積極的に検証し理解を深めていき、有志とも情報を共有して行きたいと感じた、今回の検証でした。