Ansible で AWS セッションマネージャーを使う
AWS では Systems manager の セッションマネージャ を使用することで EC2 インスタンスにログインできます。
ログインする際は通常は ssh を使うことが多いですが、セッションマネージャでは keypair を設定したりセキュリティグループで ssh 用のポートを準備する必要がないので、セキュリティ的に制限のあるような場合に便利です。
一方、Ansible でも実行ノードから対象ノードへの通信には通常 ssh が使用されますが、対象ノードが aws インスタンスの場合は上記のセッションマネージャを使用することができます。
検索するとマネコンを使って playbook をアップロードして実行する手順が出てきますが、Ansible community collections の ssm connection プラグインを使うと CLI 操作だけで完結できます。
今回は ssm connection plugin を試してみます。
セッションマネージャの確認
セッションマネージャのログイン設定が正しく設定されているか確認するため、適当なインスタンスを作成しておきます。
インスタンスを作成したら aws cli の ssm start-session
で正常にログイン出来ることを確認しておきます。
$ aws ssm start-session --target i-0a9a9a1746d5d7f29
ここでエラー等でログインできない場合は aws cli の profile 設定が間違っている、IAM policy の設定が間違っている、インスタンスプロファイルが設定されていない等の可能性があります。
ssm connection のインストール
ssm connection プラグインは aws collection に含まれているので、ansible playbook の実行ノード上で ansible-galaxy でインストールします。
$ ansible-galaxy collection install community.aws
aws collection の依存関係で python の AWS SDK である boto3 も必要となるので、pip 等でインストールします。
$ pip install boto3 botocore
接続確認
以下の 2 種のインスタンスに対して接続確認します。
- Amazon linux 2
- Amazon linux 2023
ssm connection の変数
ssm connection では ansible_connection: aws_ssm
を定義することで playbook 実行ノードから対象ノードへの通信にセッションマネージャーが使用されるようになります。
これ自体はただの ansible 変数なので、インベントリ内で定義したり、play レベル等の場所で定義できます。
また、セッションマネージャーを使うための認証方法として以下の変数を設定する必要があります。
変数名 | 説明 |
---|---|
ansible_aws_ssm_instance_id | 接続対象のインスタンス ID |
ansible_aws_ssm_bucket_name | S3 bucket 名 |
ansible_aws_ssm_access_key_id | 接続に使用する IAM user の access key |
ansible_aws_ssm_secret_access_key | 接続に使用する IAM user の secret key |
ansible_aws_ssm_region | インスタンスのある region |
これらは aws_ssm と同様に Ansible の変数として設定するか、もしくは環境変数としてセットすることも可能です。
変数名に対応する環境変数名は ssm connection の Parameters に書いてあるのでこちらを参照。
Amazon linux 2
動作検証として、Amazon linux 2 (ami-0f89bdd365c3d966d) のインスタンスに docker をインストールする playbook を作成します。
---
- hosts: localhost
gather_facts: false
vars:
ansible_connection: aws_ssm
ansible_aws_ssm_instance_id: i-0a9a9a1746d5d7f29
ansible_aws_ssm_bucket_name: mybucket
ansible_aws_ssm_access_key_id: xxx
ansible_aws_ssm_secret_access_key: yyy
ansible_aws_ssm_region: ap-northeast-1
ansible_python_interpreter: /usr/bin/python
tasks:
- name: Install docker
ansible.builtin.yum:
name: docker
state: present
use_backend: yum
become: true
作成したら playbook を実行。
ansible-playbook ssm.yml
セッションマネージャーでインスタンスにログインし、docker がインストールされたか確認します。
$ aws ssm start-session --target i-0a9a9a1746d5d7f29
sh-4.2$ bash
[ssm-user@ip-172-31-34-141 bin]$ sudo systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: https://docs.docker.com
[ssm-user@ip-172-31-34-141 bin]$ docker -v
Docker version 20.10.23, build 7155243
無事に docker-engine や docker-cli がインストールされていることが確認できました。
Amazon linux 2023
Amazon linux 2023 でも Amazon linux 2 (ami-0a2e10c1b874595a1) と同様の playbook が使用できますが、package manager を dnf に変更します。
---
- hosts: localhost
gather_facts: false
vars:
ansible_connection: aws_ssm
ansible_aws_ssm_instance_id: i-079ba89f2f4ff2e39
ansible_aws_ssm_bucket_name: mybucket
ansible_aws_ssm_access_key_id: xxx
ansible_aws_ssm_secret_access_key: yyy
tasks:
- name: install
ansible.builtin.dnf:
name: docker
state: present
become: true
これで amazon linux 2023 に対しても dnf で docker をインストール出来るはずなのですが、実際に実行するとエラーとなりました。
エラーメッセージで調べてみると以下の issuse に該当しているようです。
Amazon linux 2023 では Bash/readline の仕様変更により Ansible の出力メッセージを正しく処理できず失敗するとのこと。
ワークアラウンドは issue のコメントにあるように、対象インスタンスの /etc/inputrc に enable-bracketed-paste off
を追加すれば良いようです。
#1839 fixes it, but it's taking ages to be merged for unknown reasons. In the meantime I've set set enable-bracketed-paste off into /etc/inputrc which is, needless to say, not a fix at all since you need to configure all servers this way, which is exactly what ansible is meant to do. In my case was just one so for now it's sorted, thanks to @dennisjlee !
対象インスタンス上の etc/inputrc
を編集した後、再度 playbook を実行すると正常にインストールできます。
先程と同様にインスタンスにログインして確認すると docker が正常にインストールされています。
$ aws ssm start-session --target i-079ba89f2f4ff2e39
sh-5.2$ cat /etc/os-release
NAME="Amazon Linux"
VERSION="2023"
ID="amzn"
ID_LIKE="fedora"
VERSION_ID="2023"
PLATFORM_ID="platform:al2023"
PRETTY_NAME="Amazon Linux 2023"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2023"
HOME_URL="https://aws.amazon.com/linux/"
BUG_REPORT_URL="https://github.com/amazonlinux/amazon-linux-2023"
SUPPORT_END="2028-03-01"
sh-5.2$ docker -v
Docker version 20.10.25, build b82b9f3
sh-5.2$ sudo systemctl status docker
○ docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; preset: disabled)
Active: inactive (dead)
TriggeredBy: ○ docker.socket
Docs: https://docs.docker.com
上記の不具合については https://github.com/ansible-collections/community.aws/pull/1839 でつい先週 PR が作成されています。
なので今後の aws collections の最新バージョンでは修正され、わざわざワークアラウンドで対応する必要はなくなりそうです。
Discussion