Ansible で作成したばかりのインスタンスをプロビジョンしようとして「UNREACHABLE」と言われるとき

Ansible で「EC2 インスタンスを起動」して「起動したばかりのインスタンスをプロビジョン」するとしよう。素朴に書くと次のようなプレイブックになる。

- hosts: localhost
  connection: local
  tasks:
    # ami-0c11b26d: Amazon Linux AMI 2016.09.0 (HVM), SSD Volume Type
    - ec2:
        key_name: dev
        instance_type: t2.micro
        image: ami-0c11b26d
        wait: yes
        vpc_subnet_id: subnet-xxx
        assign_public_ip: yes
      register: ec2

    - name: Add my host
      add_host:
        groups=my_host
        name={{ ec2.instances[0].public_ip }}

- hosts: my_host
  serial: 1
  user: ec2-user
  tasks:
    - debug: msg="Hello."

単に、ec2 モジュールで作成したインスタンスをadd_host モジュールで動的に my_host インベントリに追加し、そこに接続してデバッグメッセージを出力するだけのものだ。

しかし、このままでは SSH Unreachable メッセージが出てうまく動作しない。具体的には次のようなメッセージだ。

TASK [setup] *******************************************************************
Using module file /usr/local/lib/python2.7/site-packages/ansible/modules/core/system/setup.py
 ESTABLISH SSH CONNECTION FOR USER: ec2-user
 SSH: EXEC ssh -vvv -o ControlMaster=auto -o ControlPersist=30m -o StrictHostKeyChecking=no -o 'IdentityFile="/Users/mahata/.ssh/id_rsa"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-wit
h-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=ec2-user -o ConnectTimeout=10 -o 'ControlPath=~/%h-%r' 54.199.xxx.xxx '/bin/sh -c '"'"'/usr/bin/python && sleep 0'"'"''
fatal: [54.199.xxx.xxx]: UNREACHABLE! => {
    "changed": false,
    "msg": "SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh",
    "unreachable": true
}

このメッセージを確認した後で、あらためて「54.199.xxx.xxx」に SSH で接続しようとすると、もしかしたらうまく接続できてしまうかもしれない。「あれ? Ansible ってバグってる…??」と混乱するかもしれない。そうではない。

ec2 モジュールはインスタンスの起動までは「wait: yes」オプションで待ってくれるものの、OpenSSH が起動する所までは待ってくれない。Ansible が my_host に対してプロビジョンするタイミングで OpenSSH の起動が完了していないと、全体のプレイブックの実行は失敗する。

これを避けるためには wait_for モジュールを使えばいい。次の通りだ。

- hosts: localhost
  connection: local
  tasks:
    # ami-0c11b26d: Amazon Linux AMI 2016.09.0 (HVM), SSD Volume Type
    - ec2:
        key_name: dev
        instance_type: t2.micro
        image: ami-0c11b26d
        wait: yes
        vpc_subnet_id: subnet-xxx
        assign_public_ip: yes
      register: ec2

    - name: Add my host
      add_host:
        groups=my_host
        name={{ ec2.instances[0].public_ip }}

    - name: Wait for host to be available
      local_action: wait_for port=22 host="{{ ec2.instances[0].public_ip }}" search_regex=OpenSSH delay=5

- hosts: my_host
  serial: 1
  user: ec2-user
  tasks:
    - debug: msg="Hello."

これで無事にプロビジョンできるはずだ。

コメントを残す

コメントを投稿するには、以下のいずれかでログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中