LoginSignup
1
0

AWS Systems ManagerでAnsible実行を行う前提でのPlaybook構成検討

Posted at

はじめに

今担当しているシステムでは、AWS Identity Centerを使い、キーペアを持たない運用を行っておりますが、AnsibleをEC2インスタンスに実行する場合、Ansibleの仕組み上、SSHを行う必要があることから、Ansibleを使うためにはキーペアを持たなくてはならないと思っていました。

しかし、AWS Systems Manager Run Commandを使用すれば、キーペアを使わずに対象のEC2インスタンスにAnsibleを実行できるため、今回はAWS Systems Manager Run Commandを使ってキーペアなしでAnsibleを実行する際の最適なディレクトリレイアウトについて検討してみようと思います。

AWS Systems Manager Run CommandでのAnsible実行

以前の記事AWS Systems ManagerからのAnsible実行を試しましたが、Systems Manager Run CommandAnsibleを実行する場合、Run Commandで指定するターゲットで対象を指定することから、インベントリファイルによる制御は行えず、ターゲット全てlocalhostで実行されます。

そのため、ベストプラクティス構成のPlaybookを実行しようとしても、ホストはlocalhost一択となるため、group_varshosts_varsによる変数切り替えができず、単純に実行するPlaybookを切り替えるだけではサーバ種別ごとに変数を分けることが難しいです。

そのような特徴を持つRun CommandによるAnsibleを実行する上で、なるべくベストプラクティスの構成を変えずに、あまり修正すること無くRun CommandによるPlaybook実行も、通常のインベントリファイル指定でのPlaybook実行もできるようにしてみたいと思います。

以下、以前紹介した記事。

Ansibleのベストプラクティス構成

Ansibleの公式でベストプラクティスのディレクトリレイアウトとして紹介されている構成は以下となります。

Ansibleベストプラクティスディレクトリレイアウト
.
├── production # inventory file for production servers staging # inventory file for staging environment
├── group_vars/
│   └── group1.yml # here we assign variables to particular groups group2.yml
├── host_vars/
│   └── hostname1.yml # here we assign variables to particular systems hostname2.yml
├── library/ # if any custom modules, put them here (optional) module_utils/ # if any custom module_utils to support modules, put them here (optional) filter_plugins/ # if any custom filter plugins, put them here (optional)
├── site.yml # master playbook webservers.yml # playbook for webserver tier dbservers.yml # playbook for dbserver tier
└── roles/
    ├── common/ # this hierarchy represents a “role”
    │   ├── tasks/ #
    │   │   └── main.yml # <– tasks file can include smaller files if warranted
    │   ├── handlers/ #
    │   │   └── main.yml # <– handlers file
    │   ├── templates/ # <– files for use with the template resource
    │   │   └── ntp.conf.j2 # <——- templates end in .j2
    │   ├── files/ #
    │   │   └── bar.txt # <– files for use with the copy resource foo.sh # <– script files for use with the script resource
    │   ├── vars/ #
    │   │   └── main.yml # <– variables associated with this role
    │   ├── defaults/ #
    │   │   └── main.yml # <– default lower priority variables for this role
    │   ├── meta/ #
    │   │   └── main.yml # <– role dependencies
    │   └── library/ # roles can also include custom modules module_utils/ # roles can also include custom module_utils lookup_plugins/ # or other types of plugins, like lookup in this case
    └── webtier/ # same kind of structure as “common” was above, done for the webtier role monitoring/ # “” fooapp/ # “”

上記例で言うと、普通にPlaybookを実行する場合には、productionというインベントリファイルを指定してsite.ymlを実行することで、インベントリファイルに記載されているグループ名(group1)とホスト名(hostname1)に該当する変数がgroup_varshost_varsから呼び出されsite.ymlに記載されている実行ロール名(commonwebtier)が実行される流れとなります。

また、site.ymlは各サーバごとの処理を記載したPlaybookimport_playbookで読み込む程度の処理しか行わないというのがベストプラクティスとなるため、実際に実行するロールを指定するPlaybookは以下でいうとwebservers.ymldbservers.ymlとなります。

site.yml
---
# file: site.yml
- import_playbook: webservers.yml
- import_playbook: dbservers.yml

私が考えたAWS Systems Manager Run Commandで実行する場合のベストプラクティス構成

詳細は後述しますが、以下は俗に言う「俺が考えた最強の○○」

私が考えたAWS Systems Manager Run Commandで実行する場合のディレクトリレイアウト
.
├── group_vars/
│   └── group1.yml
├── ssm_webservers.yml
├── ssm_dbservers.yml
└── roles/
    ├── common/
    │   ├── tasks/
    │   │   └── main.yml
    │   ├── handlers/
    │   │   └── main.yml
    │   ├── templates/
    │   │   └── ntp.conf.j2
    │   ├── files/
    │   │   └── bar.txt
    │   ├── vars/
    │   │   └── main.yml
    │   ├── defaults/
    │   │   └── main.yml
    │   ├── meta/
    │   │   └── main.yml
    │   └── library/
    └── webtier/

Run Commandでの実行だけではなく、普通にPlaybookを実行する場合でもあまり構成を変えずに実行したかったため、基本的なディレクトリレイアウトはベストプラクティスの構成とほぼ同じです。

インベントリファイルはRun Commandでは使えないため除外、site.ymlRun Commandで実行する場合はインポートする意味がないので除外、host_varsもホスト単位での変数指定はRun Commandでは難しいため、こちらも除外。

group_varsはそのままでは全てのホストを示すall.ymlしか読み込んでくれないため、host_varsと同じようにあまり意味がないのですが、Playbookにパス指定して読み込ませるようにすることで、既存のgroup_vars変数ファイルを使い回せることが分かったので、そのまま使用します。

Run Commandで実行する場合に用意するファイル

上記のディレクトリレイアウトでRun Commandで実行する場合に準備するファイルについて以下で見ていきます。

site.ymlがない代わりにsite.ymlから読み込まれるサーバ種別ごとのPlaybookRun Command用に準備します。

Playbook内のhostsの指定は、localhostしか指定できないのでlocalhostは固定として、vars_filesgroup_varsに存在するグループ用変数をAnsibleディレクトリからの相対パス指定で読み込みます。

こうすることで、group_varsの変数ファイルは既存のまま使用することができるのでRun Command用に準備するファイルはPlaybookファイルとなるssm_webserver.ymlssm_dbserver.ymlのみで済むことになります。

ssm_webserver.yml
---
- become: true
  hosts: localhost
  vars_files:
    - group_vars/group1.yml
  roles:
    - common

Systems Manager Run CommandによるAnsibleの実行

Systems Manager Run Commandで実行する場合は、ターゲットをRun Commandの画面から指定して、Playbook Filessm_webserver.ymlssm_dbserver.ymlを指定すれば動きます。

ターゲットは複数指定できても、ターゲットに対して実行されるPlaybookファイルをターゲットごとに分けることはできないので、もし実行するPlaybookファイルを分けたい場合は、別々に実行しましょう。

注意点

Run CommandによるAnsible実行は、実行するたびにAnsiblePlaybookなどを毎回ダウンロードする仕組みとなります。

そのため、rolesfilesなどにインストール用パッケージを置いたりするようなことは行わず、S3等からダウンロードするようにした上で、roles実行する場合も条件式等を使い、毎回インストール用パッケージ等がダウンロードされないようにするのが良いかと思います。

  • インストール用パッケージ等のサイズが大きいファイルはAnsibleのディレクトリには置かずに別のストレージに置く
  • Playbookの条件式や実行rolesで制御してサイズの大きいファイルがダウンロードされないようにする

おわりに

Playbookファイルでvars_filesで変数ファイルを指定することで既存のAnsibleにあまり手を入れること無く使い回すことができました。

1台毎に別々のPlaybookファイルを準備すれば、もちろんhost_varsでのホスト用変数の呼び出しもできますし、多分Playbookファイル内で条件式等書いて1台に絞り込むような処理が書ければ、既存のAnsibleはそのままで操作感変わらずに実行することもできるかと思います。

Ansibleを実行するためだけにキーペア運用を行っている方は、今回の記事を見てキーペアを消してみてはいかがでしょうか。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0