EC2 Image Builder で Ansible playbook を実行してみた
どうも今年の目標はベンチプレス150kgのオンジーです。
AnsibleのplaybookをEC2 Image Builderで使ってみました。
なおAnsible、Image Builderの基本的な使い方についてはある程度知っている前提で書かれています。最後に入門記事のリンクを載せていますのでご参考ください。
やってみた
AWSが公開しているサンプルを使って実行してみます。
内容としてはAmazon Linux2にapacheをインストールしてHello worldと書かれたトップページを作成するというシンプルなものです。
playbookの中身
my-playbook.ymlの中身です。
- name: Apache Hello World hosts: 127.0.0.1 gather_facts: false connection: local tasks: - name: Install Apache yum: name: httpd state: latest - name: Create a default page shell: echo "<h1>Hello world from EC2 Image Builder and Ansible</h1>" > /var/www/html/index.html - name: Enable Apache service: name=httpd enabled=yes state=started
従来のAnsibleではsshやWinRMでリモートホストにアクセスしミドルウェアのインストールや設定ファイルの更新を行いますが
Image Builder 内で Ansible を実行する際はAMIを作成するEC2上で実行することになるのでローカルホスト上で実行するように設定する必要があります。
次の部分がローカルでの実行を強制している箇所になります。
hosts: 127.0.0.1 gather_facts: false connection: local
このmy-playbook.ymlを事前にS3バケットにアップロードしておきます。
componentの中身
Image Builderで実行するビルドコンポーネント(component.yml)ですが以下の流れになっています。
- Ansible をインストール
- S3 バケットからplaybookをダウンロード
- playbook実行
- playbook削除(クリーンアップ)
- Apache が正しいコンテンツを返していることを検証
ここでは解体して説明していますので全文は先ほどのGitHubよりご確認ください。
まずはドキュメントの説明とbuildフェーズの指定をします。
name: 'Ansible Playbook Execution on Amazon Linux 2' description: 'This is a sample component that demonstrates how to download and execute an Ansible playbook against Amazon Linux 2.' schemaVersion: 1.0 phases: - name: build steps:
Amazon Linux 2ではAmazon Linux Extrasを使ってAnsibleをインストールできるので、ExecuteBashアクションを使ってインストールします。
- name: InstallAnsible action: ExecuteBash inputs: commands: - sudo amazon-linux-extras install -y ansible2
S3Download アクションを使用してplaybookをダウンロードし、tmpフォルダに保存します。
S3バケットを指定している箇所は先ほどmy-playbook.ymlをアップロードしたバケットのパスに書き換えてください。
- name: DownloadPlaybook action: S3Download inputs: - source: 's3://mybucket/my-playbook.yml' destination: '/tmp/my-playbook.yml'
ExecuteBinary アクションを使用して Ansible を起動し、playbookに記載されている作業を実行します。
ここでは前段のステップから入力値や出力値を参照できる機能 chaining を使用しています。詳しくは下記をご参照ください。
{{build.DownloadPlaybook.inputs[0].destination}}}は、'/tmp/my-playbook.yml'を指定していることになります。
値の入力ミスによるビルドの失敗を避けるために、このように参照でS3Download先のパスを取得しています。
- name: InvokeAnsible action: ExecuteBinary inputs: path: ansible-playbook arguments: - '{{build.DownloadPlaybook.inputs[0].destination}}'
Ansibleを実行したのでダウンロードしたplaybookを削除しています。
ここでも同様に参照によって取得したパスでExecuteBashアクションを実行しています。
- name: DeletePlaybook action: ExecuteBash inputs: commands: - rm '{{build.DownloadPlaybook.inputs[0].destination}}'
ここまででbuildフェーズが終わったのでvalidateフェーズに移ります。
curlを使ってApacheが正しいコンテンツで応答することを確認しています。
- name: validate steps: - name: ValidateResponse action: ExecuteBash inputs: commands: - curl -s http://127.0.0.1 | grep "Hello world from EC2 Image Builder and Ansible"
validateフェーズが実行されると、EC2が停止しAMIが作成されます。
Image Builderは、このAMIを使用して新しいEC2インスタンスを起動するtestフェーズに移行します。
そのためtestフェーズでもvalidate フェーズと同じ curl コマンドを使用して同様に正しいコンテンツが返ってくるかを確認しています。
※注意:S3バケットへのアクセス権限が必要です。
Image BuilderではAMIをビルドおよびテストする一時的なEC2にIAMロールを設定するのですがそこにplaybookを配置したS3へのアクセス権限が必要です。
ポリシーは下記の様なイメージです。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::mybucket/*" } ] }
完成したAMIを起動してみる
出来上がったAMIからEC2を起動してみました。
トップページが表示されました!やったね!
おわり
apacheのインストールなどもちろんビルドコンポーネントで記述はできるのですがAnsibleを既に使っていた場合はその資産を使いたいですよね。
上記の手順で実行できますのでお試しください。
参考
合わせて読みたい
Ansible
Image Builder