Systems Managerでベストプラクティス構成のPlaybook運用する場合に注意すること

# はじめに
以前から気になっていた`Systems Manager`からの`Ansible Playbook`実行ですが、今回実際に自分で試してみた結論として、注意しないといけないことを書こうと思います。

- [AWS Systems Manager で複雑な Ansible のプレイブックを実行可能に](https://aws.amazon.com/jp/about-aws/whats-new/2019/09/now-use-aws-systems-manager-to-execute-complex-ansible-playbooks/)

今回の記事を読むにあたり、以下の記事の内容が前提となるため、一読して頂けると幸いです。

- 【参考1】[Amazon S3からのスクリプトの実行をやってみた。](https://qiita.com/sakai00kou/items/326a36fbdea10a6b2da8)
- 【参考2】[SSM Agentの実行スクリプトを削除する方法](https://qiita.com/sakai00kou/items/f6e04760783b805d55d5)

:::note info
今回の記事は2022年9月現在の仕様となります。
今後のアップデートで変わる可能性があることご了承ください。
:::

# Systems ManagerでAnsibleを実行する場合の構成
仕組みとしては「[Amazon S3からのスクリプトの実行をやってみた。](https://qiita.com/sakai00kou/items/326a36fbdea10a6b2da8)」で紹介した`Run Command`機能で`Ansible`を実行する仕組みとなるので、以下の通り構成も同様となります。

```plantuml
@startuml
!include <awslib/AWSCommon>
!include <awslib/ManagementGovernance/SystemsManagerRunCommand.puml>
!include <awslib/Storage/SimpleStorageServiceBucket.puml>
!include <awslib/Compute/EC2.puml>
!include <awslib/SecurityIdentityCompliance/IdentityAccessManagementRole.puml>
!include <awslib/General/Client.puml>
'!include <awslib/AWSSimplified>

'left to right direction
top to bottom direction
title Amazon S3 からのスクリプトの実行

Client(cl,"操作PC","操作PC")
SimpleStorageServiceBucket(s3,"スクリプト格納バケット","S3")
SystemsManagerRunCommand(ssm,"スクリプト実行","SSM")
EC2(ec2,"実行対象インスタンス","EC2")
IdentityAccessManagementRole(role,"S3アクセス用IAMロール","IAM_Role")

cl --> s3 :①スクリプトアップロード
cl --> ssm :②RunCommand実行
ssm --> ec2 :③RunCommandの処理をEC2上で実行
ec2 --> s3 :④スクリプト取得&実行
role ..0 ec2 :S3アクセス用ロールのアタッチ
@enduml
```

`Run Command`機能で`Ansible`を実行する場合、**インベントリファイル**は使用せず、`Systems Manager`で実行ノードを指定する必要があります。

内部的には`localhost`で実行するため、対象のEC2インスタンスに`Ansible`をインストールする必要があることから、`Ansible`の特徴となる、対象ノードにエージェントレスで実行できるというメリットは消えてしまいますが、１ファイル構成の`Playbook`だけではなく、ベストプラクティスのディレクトリ構成の`Playbook`を`Systems Manager`で実行できること、出力ログ等の制御を`Systems Manager`で行えること、`CodePipeline`等のサービスと連携しやすいということは有用かと思います。

尚、`Ansible`が対象ノードにインストールされていない場合は、自動で`Ansible`をインストールしてから実行されるため、先に手動で`Ansible`をインストールしたり、インストール処理を予め含めておく必要はありません。

が、今回色々と調べてみた結果として、**`Systems Manager`でベストプラクティス構成の`Playbook`を実行＆継続的に運用する場合、以下の点について理解した上で使用する必要があります。**

## Systems Managerでベストプラクティス構成のPlaybook運用する場合に注意すること
私の所感として今回試した結果以下の点に注意する必要があります。

- **対象ノード全てにAnsibleインストールが行われる**
- **RunCommand実行時、ベストプラクティス構成のディレクトリを毎回ダウンロードする**
- **実行対象ホスト指定はSystems Managerで行うため、Ansibleのインベントリファイルによる制御ができない**

先程も説明しましたが`Run Command`機能で`Playbook`を実行する場合、対象ノードで`Playbook`を実行する必要があるので、エージェントレスで実行できるメリットは消えてしまいます。

実行`Playbook`についても、対象ノードで毎回実行スクリプトをダウンロードする動作となり、かつ、ダウンロードディレクトリは毎回異なる仕様となることから、差分だけダウンロードしたりすることができません。（多分回避策なし）

実行対象ホスト指定についても、インベントリファイルを使ったホスト指定ではなく、`Systems Manager`で指定する仕様となり、各ノードで`Ansible`実行する際には`localhost`で実行されるため、元々各ノードごとに`host_vars`等で変数を切り替えていた場合は移行が難しいかと思います。

また、`SSM Agent`のデフォルト設定では、ダウンロード先となる`orchestration`ディレクトリは自動で削除されないため、実行した回数分、ファイル・ディレクトリがベストプラクティス構成のまま残り続けることになります。（こちらについては設定で回避可能）

```bash:実行時の/var/lib/amazon/ssm/[インスタンスID]/document/orchestration配下状態例
[1回目のPlaybook実行用ディレクトリ]
 │ └―[ベストプラクティス構成のファイル・ディレクトリ群]
[2回目のPlaybook実行用ディレクトリ]
 │ └―[ベストプラクティス構成のファイル・ディレクトリ群]
・・・
[n回目のPlaybook実行用ディレクトリ]
   └―[ベストプラクティス構成のファイル・ディレクトリ群]
```

そのため、`Ansible`で使用するファイル・ディレクトリサイズが大きければ大きいほど、毎回のダウンロードに時間がかかり、実行するごとに対象ノードの容量を圧迫することから`Playbook`全体のサイズが大きい場合は`Run Command`による`Ansible`実行はおすすめできません。

`Run Command`実行時の動作や`orchestration`ディレクトリのクリーンアップ方法は以下で紹介しているので、詳細はそちらでご確認ください。

- [SSM Agentの実行スクリプトを削除する方法](https://qiita.com/sakai00kou/items/f6e04760783b805d55d5)

### インベントリファイルによる制御ができないことに対するアプローチ
`Systems Manager`で`Playbook`を実行した場合、`host_vars`が使い物にならないことから、`Playbook`内で条件式を書き、読み込み変数を変えたり、`site.yml`を実行するのではなく、ホストごとに実行`Playbook`を分けたりするようなアプローチを行う必要があるかと思います。

# おわりに
本来は`Systems Manager`でベストプラクティス構成の`Playboook`を実行する機能を試して、将来どこかのシステムで提案できればと思い、試してみましたが、注意点もいくつかあり、既存の`Ansible`構成をそのまま置き換えられるとは言いづらい結果となりました。

今後のアップデートでAWS側で`Ansible`を管理できる機能が追加されればベストですが、それまではこの記事を参考に各自のシステムでベターな構成は何かを検討して貰えればと思います。