ハラミTech

技術系ブログです

AnsibleをAWS Systems Managerセッションマネージャー経由で使えるか試してみた

ちょっと前に、AWS System ManagerのセッションマネージャーがSSH経由で使えるという記事が話題になりました。

docs.aws.amazon.com

dev.classmethod.jp

これが出来るんならAnsibleもセッションマネージャー経由で出来るよな?と思ったので確認のために試してみます。

セッションマネージャーをEC2で使えるようにする

EC2をセッションマネージャーでログインするためには以下の状態になっていなければなりません

  • SSMエージェントをEC2にインストールする
  • EC2のIAM Roleのポリシーに「AmazonSSMManagedInstanceCore」がアタッチされている
  • EC2がインターネットに接続できるか、SSMのVPC Endpointに接続できる

Linuxの場合のSSMエージェントインストール方法は以下に記載してあります。

Amazon EC2 Linux インスタンスに SSM エージェント を手動でインストールする - AWS Systems Manager

AWSのAMIの中には、SSMエージェントがプリインストールされているのもありますので、
新規で作成する場合はこれらを選択してもいいと思います。

2016 年 11 月以降に公開された Windows Server 2003-2012 R2 AMI
Windows Server 2016 および 2019
Amazon Linux
Amazon Linux 2
Ubuntu Server 16.04
Ubuntu Server 18.04

SSM エージェント の使用 - AWS Systems Manager

今回はせっかくなのでプリインストールされているAMIを使用してEC2を作成します。
このときアタッチするセキュリティグループにはSSH(22)のポートは空けないでおきます。
上記の状態を満たしている場合、EC2起動時に、セッションマネージャーのコンソールで起動したインスタンスが表示されます。(表示されるまでちょっと時間かかる)

f:id:mori_morix:20191108165441p:plain

まずはこの画面で、セッションマネージャによるサーバーログインを試してみましょう。
ログインできたら準備完了です。

ローカルPCにSession Managerプラグインをインストールする

aws-cliを使用してセッションマネージャーログインを行うため、ローカルPCにSession Managerプラグインをインストールする必要があります。
インストール方法は下記に記載してあります。

(オプション) AWS CLI 用の Session Manager Plugin をインストールする - AWS Systems Manager

自分のPCはUbuntuなので、以下のコマンドでインストールしました。

$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb" -o "session-manager-plugin.deb"
$ sudo dpkg -i session-manager-plugin.deb
$ session-manager-plugin --version
1.1.35.0

sshでEC2にログインできるようにする

この辺は冒頭の記事のままですが、~/.ssh/configに以下の設定を追記します。

~$ cat ~/.ssh/config
host i-*
  ProxyCommand bash -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

これでインスタンスIDをsshのホスト名に指定すればsshログインできます。
EC2を作成したときに指定したキーペアの秘密鍵の指定も忘れずに。(次の例ではid_rsaを使ってるので省略してます)

# AWSのprofileを指定したい場合は事前に以下の環境変数を指定しましょう
$ export AWS_PROFILE=xxxx

$ ssh ubuntu@i-xxxxxxxx

これでログインできます。セキュリティグループでssh(22)を設定していないにも関わらずです。
便利ですね〜。

プライベートサブネットに属するEC2にもローカルPCから接続してみる

本題とはずれますが、このsshはプライベートサブネットに属するEC2に対しても、別のネットワークのPCからsshできます。

注意としては、上記のセッションマネージャー使う上での条件の

EC2がインターネット経由でSSMエンドポイントに接続できるか、SSMのVPC Endpointに接続できる

ここが、プライベートサブネットだとVPC Endpointに接続する設定をしないといけないです。
やり方は以下に記載されています。

Systems Manager を使用したインターネットアクセスなしでのプライベート EC2 インスタンスの管理

僕も試したので、簡単に手順を記載しておきます。

  1. プライベートネットワークからのインバウンドのhttps(443)ポートの接続を許可する(443 10.0.0.0/16 みたいな感じ)セキュリティグループを作る
  2. VPC > Endpoints > Create Endpointsの画面に行く
  3. サービス名で「com.amazonaws.ap-northeast-1.ssm」を選択
  4. VPCはEC2が属するものを選択
  5. サブネットも必要なものを選択
  6. Enable Private DNS Nameはチェックしておく
  7. セキュリティグループは1で作ったものを指定して保存
  8. 以下のサービス名分、4〜7を繰り返す
    • com.amazonaws.ap-northeast-1.ssmmessages
    • com.amazonaws.ap-northeast-1.ec2messages

この設定をしておくと、プライベートサブネットに属するEC2へsshログインできるようになります。

Ansibleで実行してみる

じゃあやってみましょう。
Ansibleの構成は以下にコミットしてます。

GitHub - morix1500/ansible-ssm-test

.
├── ansible.cfg
├── group_vars
│   └── all
│       └── vars.yml
├── hosts.yml
├── roles
│   ├── copy-files
│   │   ├── files
│   │   │   └── test.txt
│   │   └── tasks
│   │       └── main.yml
│   └── copy-files2
│       ├── files
│       │   └── test2.txt
│       └── tasks
│           └── main.yml
└── site.yml

hosts.ymlはこんな感じで、インスタンスIDが指定されてます。

all:
  children:
    test:
      hosts:
        i-0290aa0692d91b322

site.ymlはこんな感じ。内容はテキストファイルをコピーするだけのロールを2つ用意してます。

- hosts: test
  become: yes
  roles:
    - { tags: "test", role: "copy-files" }
    - { tags: "test", role: "copy-files2" }

では実行してみます。

$ ansible-playbook -l test site.yml

PLAY [test] ************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [i-0290aa0692d91b322]

TASK [copy-files : copy file] ******************************************************************************************************************************************************************************
changed: [i-0290aa0692d91b322]

TASK [copy-files2 : copy file] *****************************************************************************************************************************************************************************
changed: [i-0290aa0692d91b322]

PLAY RECAP *************************************************************************************************************************************************************************************************
i-0290aa0692d91b322        : ok=3    changed=2    unreachable=0    failed=0

はい、行きました。
ということで、セッションマネージャー経由でもansibleが動きます。(そりゃそうだろと思うけど)

通常のsshと速度差はあるのか?

なんか微妙に遅い気がしたので、通常のsshとセッションマネージャー経由のsshで速度差があるか比較してみました。
といっても雑です。↑のやつをsshでやってみるだけです。

################
# 通常のssh
################

$ time ansible-playbook -l test site.yml

PLAY [test] ************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [54.199.142.244]

TASK [copy-files : copy file] ******************************************************************************************************************************************************************************
changed: [54.199.142.244]

TASK [copy-files2 : copy file] *****************************************************************************************************************************************************************************
changed: [54.199.142.244]

PLAY RECAP *************************************************************************************************************************************************************************************************
54.199.142.244             : ok=3    changed=2    unreachable=0    failed=0


real    0m8.032s
user    0m2.109s
sys     0m0.768s

################
# セッションマネージャー経由のssh
################
$ time ansible-playbook -l test site.yml

PLAY [test] ************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [i-0cf6d9186cfd7ed34]

TASK [copy-files : copy file] ******************************************************************************************************************************************************************************
changed: [i-0cf6d9186cfd7ed34]

TASK [copy-files2 : copy file] *****************************************************************************************************************************************************************************
changed: [i-0cf6d9186cfd7ed34]

PLAY RECAP *************************************************************************************************************************************************************************************************
i-0cf6d9186cfd7ed34        : ok=3    changed=2    unreachable=0    failed=0


real    0m9.463s
user    0m1.994s
sys     0m0.655s

通常のsshが約2秒、セッションマネージャー経由が約3秒でした。
後者は最初だけ時間がかかりますが、その後は体感だと変わらなかったです。

これはsshのProxyコマンドをコネクション確立時に実行しているためです。
一度確立させるとそのコネクションを使いまわすようになっています。
Ansbileのデフォルトの動作でControlMasterが有効になっている影響かと思います。

感想

sshポート空けずに済むので、安全性を高められるし、踏み台も不要なるかもと思いました。
あとは実際に業務で使ってみて使い勝手を試したいですね。

ただたまにうまく接続できないことがあるのがちょっと気になりました。
接続に時間がかかることによるタイムアウトかな?