AWS SSM の Run Command で Ansible の Playbook を実行する手順について解説します。
AWS で Ansible を使って OS やミドルウェア周りの管理をコード化して実施したい場合があります。
コード化のメリットとしてはドキュメントが不要になるという点が挙げられます。
昔はExcelファイルやWordを使って基本設計書や詳細設計書(パラメータシート)を書いていたと思います。
そして上長にレビューを依頼して何度も繰り返して数か月、ようやくレビューが通ったと思ったら、運用をしていく中でどんどん仕様が変わっていき、数か月かけて作成したドキュメントは使い物にならずに結局リモートログインをしてコマンドを叩いてみるか、他の人に確認するなりしてドキュメントを全く見ない(もしくはそもそもドキュメントを信用してはいけない)ようになります。
しかしコード化ならコードを見れば一発で把握できます。
(仮にTerraformとGUIでの手動という2つの方法で管理をしていたらコードは全く信用できなくなりますが)
他にもコード化することにより繰り返しインスタンスを構築・設定する必要がある場合はミスなく正確に短時間で構築・設定ができるようになります。
また、人の手が入らないのでヒューマンエラー(開発環境だと思ってたら実は本番環境だった等)が発生しないというメリットもあります。
このようにコード化にはメリットがあります。
設計
まずは簡単に設計します。
- Ansible を利用する。
- AWS SSM を利用する。
- Ansible Playbook の実行は SSM Run Command を利用する。
- Ansible Playbook は S3 バケットに保存する。(Playbook のコードは GitHub で管理するが Planbook の zip ファイルは S3 バケットに保存する)
- Ansible 管理対象は EC2 インスタンスで試す。
- Linux サーバ は Amazon Linux2 にする。(別途 SSM エージェントをインストールする必要なし)
- Linux サーバはパブリックサブネットに構築する。
作業概要
以下、作業概要です。
- Terraform で管理対象の Linux サーバを構築する。
- SSM へのアクセスを許可するため、IAM ロールを作成する。
- AWS 管理コンソールより(GUI より)Run Command で実施する。
※Run Command の他にもステートマネージャからも実行できます。イメージとしては Run Command は単発の処理で利用し、ステートマネージャは運用に乗せて定期的に処理を回す場合に利用するので、今回は Run Command を利用します。
事前準備
Ansible コード管理用に GitHub にリポジトリを作成します。
環境構築用の Terraform の tf ファイル
Ansible 検証用の環境(EC2 インスタンス、S3 バケット)は Terraform で作成します。
■Ec2.tfファイル
$ cat Ec2.tf |
■Iam.tfファイル
$ cat Iam.tf |
■S3.tfファイル
$ cat S3.tf |
■terraform.tfファイル
※tfstate ファイルは S3 バケットに配置します。(複数人での Terraform 管理を想定しています)
$ cat terraform.tf |
Terraformで環境を構築する
tfファイルを作成したら terraform plan、terraform apply コマンドを実行して Ansible のテスト環境を構築します。
■terraform plan コマンド
$ terraform plan |
■terraform apply コマンド
$ terraform apply |
Ansible テスト用の EC2 インスタンスが作成されていることを確認します。
ssm コマンドをログイン確認
Amazon Linux2 で構築した場合は、セキュリティグループの設定不要で ssm コマンドで EC2 インスタンスにログインが可能です。
ポートを全部閉じていても aws cli でログインが可能です。
■ssm コマンドで EC2 インスタンスにアクセスをする
$ aws ssm start-session –target i-0xxxxxxxxxxx sh-4.2$ whoami sh-4.2$ sudo su - ← ssm-user は sudo 権限を持っている。 |
権限さえあれば、ssm-user でログインができます。
しかも ssm-user は EC2 インスタンスに対して sudo 権限を持っているので sudo su – で root にスイッチできます。
Ansible Playboot を作成する
環境ができたら Ansible Playbook を作成します。
■ディレクトリ&ファイル構成
$ tree |
トップディレクトリを「test_yum_update」にしました。
Playbook の内容は単純に yum update を実行するだけです。
テスト段階なのでシンプルな構成にしました。
■server.ymlファイル
$ cat server.yml |
■main.ymlファイル
$ cat main.yml |
「when: ansible_os_family == “RedHat”」で RedHat の場合 yum update コマンドを実行します。
ちなみに今回の管理対象の OS は Amazon Linux2 ですが、ansible_os_family は「RedHat」になります。
Playbook を ZIP で圧縮して S3 バケットに保存する
Playbook ファイルを作成したら zip コマンドで圧縮して S3 バケットに保存します。
まずは再帰的にディレクトリ配下のファイルを全部圧縮します。
ただし .git ディレクトリ配下は Ansible と関係がないので zip コマンドで除外します。
■zip コマンドで圧縮する(.git ディレクトリ配下は除外する)
$ zip -r test_yum_update.zip test_yum_update -x ‘*.git*’ |
-x オプションで指定のディレクトリやファイルを除外できます。
■zipファイルを確認する
$ ls -l test_yum_update.zip |
S3バケットにアップロードします。
■S3バケットにアップロードする
$ aws s3 cp test_yum_update.zip s3://ansible-dev-zip-bucket-xxxxxxxxxxx/ |
■S3バケットにアップロードしたオブジェクトを確認する
$ aws s3 ls s3://ansible-dev-zip-bucket-xxxxxxxx/ |
SSM ダッシュボードより Run Command を実行する
Playbook を S3 にアップロードしたら SSM ダッシュボードより Run Command を実行します。
以下のように Run Command を設定します。
- 名前 ← AWS-ApplyAnsiblePlaybooks
- ドキュメントのバージョン ← 1(デフォルト)
以下のように Run Command を設定します。
- Source Type ← S3
- Source Info ← S3 バケットに配置した ZIP ファイルを URL で指定します。【例:https://[S3バケット名.s3.ap-northeast-1.amazonaws.com/test_yum_update.zip】
- Playbook File ← xxxx.zip ファイルを展開した場合のパスを入力します。
Ansible で管理する対象の EC2 インスタンスを指定します。
タグでもリソースグループでも指定できます。これは非常に便利ですね。
出力オプションで以下のように設定します。
- S3 バケットへの書き込みを有効化する ← チェック
Run Command の設定が問題なければ「実行」ボタンをクリックします。
Run Command が成功すると下図のように「成功」と表示されます。
動作確認
次に本当に EC2 インスタンス上で yum update が実施されたのか確認します。
ssm コマンドで管理対象の EC2 インスタンスにアクセスをします。
■実際に EC2 インスタンスにログインして yum 履歴を確認
$ aws ssm start-session –target i-0xxxxxxxxxxxx |
yum update が実行されたことが確認できました。
ちなみに、ansible のインストールも確認できます。
エラーになった場合
今回は一発で全てうまく行ったわけではなく何度か失敗してエラーになりました。
Run Command を実行してエラーになった場合の原因と対応方法について記載します。
S3 バケットにアップロードした ZIP ファイルのパスが間違っている場合
S3 バケットにアップロードした ZIP ファイルのパスが間違っている場合は以下のエラーが出力されます。
Error内容は
「Installing and or updating required tools: Ansible, wget unzip ….
Error: Nothing to do
The specified Playbook file doesn’t exist in the downloaded bundle. Please review the relative path and file name.
failed to run commands: exit status 2」
と出力されます。
原因はファイルのパスが間違っているためです。
再度ファイルのパスを確認します。
下図のように ZIP ファイルを解凍した時の Playbook のパスを入力します。
S3 バケットへのアクセス権がない場合
S3 バケットへのアクセス権がない場合は以下のエラーになります。
「http request failed. status:403 Forbidden statuscode:403」
原因は S3 バケットへのアクセス権限がないからとなります。
Ansible での管理対象の EC2 インスタンスのロールから S3 バケットへアクセスをして ZIP ファイルをダウンロードする必要がありますが、対象の S3 バケットにアクセスして ZIP ファイルを取得する権限がない場合に上記のエラーになります。
正しい権限(ポリシー)を割り当てればエラーはなくなります。
ポリシーは上記でも記載してありますが、AWS管理ポリシーの「AmazonEC2RoleforSSM」を割り当てればエラーはなくなります。
コメント