てくなべ (tekunabe)

ansible / network / automation

【Ansible】ホストに到達不能だった状態を無視する ignore_unreachable について(Ansible 2.7 新機能)

■ はじめに

Ansible 2.7 で、ターゲットホストに到達不能の状態を無視する ignore_unreachable キーワードが追加されました。

changelog

New keyword ignore_unreachable for plays and blocks. Allows ignoring tasks that fail due to unreachable hosts, and check results with is unreachable test.

言葉では少し説明しにくいので、試した結果を紹介します。


■ 構成

以下のように、 Ansibleから到達できるホストとできないホストを想定して試します。

ホスト OS Ansible からの到達性
testsv1 linux ○:可
testsv99 linux ×:不可


■ 基本 Playbook

2つのタスクがあり、1つめの yum モジュールでは、あえて存在しないパッケージ名を指定して エラーが発生するようにしてます。

- hosts: linux
  gather_facts: no

  tasks:
    - name: yum error
      yum:
        name: invalid_package_xxx # エラー

    - name: debug
      debug:
        msg: "Hello debug."

この Playook を基本として、ignore_unreachable を指定を変えて試してみます。


ignore_unreachable: no(デフォルト)の場合

  • Playbook
- hosts: linux
  gather_facts: no

  tasks:
    - name: yum error
      yum:
        name: invalid_package_xxx # エラー
      ignore_unreachable: no   # デフォルト

    - name: debug
      debug:
        msg: "Hello debug."
  • 実行結果
$ ansible-playbook -i inventory iu_linux.yml

PLAY [linux] ********************************************************************

TASK [yum error] ****************************************************************
fatal: [testsv1]: FAILED! => {"ansible_facts": {"pkg_mgr": "yum"}, "changed": false, "msg": "No package matching 'invalid_package_xxx' found available, installedor updated", "rc": 126, "results": ["No package matching 'invalid_package_xxx' found available, installed or updated"]}
fatal: [testsv99]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 172.16.0.11 port 22: No route to host\r\n", "unreachable": true}
        to retry, use: --limit @/vagrant/a27/iu_linux.retry

PLAY RECAP **********************************************************************
testsv1                    : ok=0    changed=0    unreachable=0    failed=1
testsv99                   : ok=0    changed=0    unreachable=1    failed=0

testsv1 では、1つめの yum モジュールのタスクでエラーが発生したためしたが、処理が中断されます。 一方、testsv99 では、1つめのタスクの時点で unreachable なので、処理が中断されます。 これがデフォルトの動作です。 このように、2つめのタスクが実行されなかった点では testsv1 も teest99 も同じですが、理由が異なります。


ignore_unreachable: yes の場合

次に、ignore_unreachable: yes に変更した Playbook を用意します、 - Playbook

- hosts: linux
  gather_facts: no

  tasks:
    - name: yum error
      yum:
        name: invalid_package_xxx # エラー
      ignore_unreachable: yes   # point

    - name: debug
      debug:
        msg: "Hello debug."
  • 実行結果
$ ansible-playbook -i inventory iu_linux.yml

PLAY [linux] ********************************************************************

TASK [yum error] ****************************************************************
fatal: [testsv99]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 172.16.0.11 port 22: No route to host\r\n", "skip_reason": "Host testsv99 is unreachable", "unreachable": true}
fatal: [testsv1]: FAILED! => {"ansible_facts": {"pkg_mgr": "yum"}, "changed": false, "msg": "No package matching 'invalid_package_xxx' found available, installedor updated", "rc": 126, "results": ["No package matching 'invalid_package_xxx' found available, installed or updated"]}

TASK [debug] ********************************************************************
ok: [testsv99] => {
    "msg": "Hello debug."
}
        to retry, use: --limit @/vagrant/a27/iu_linux.retry

PLAY RECAP **********************************************************************
testsv1                    : ok=0    changed=0    unreachable=0    failed=1
testsv99                   : ok=1    changed=0    unreachable=1    failed=0

先ほどと異なる点は、2つめの dubug モジュールのタスクが実行されるかどうかです。

testsv1 では、1つめの yum モジュールのタスクでエラーが発生したためしたが、処理が中断されます。 一方、testsv99 では、1つめのタスクの時点で unreachable です。ただし、ignore_unreachable: yes が指定されているので、2つめの debug モジュールのタスクが実行されました。


■ おまけ ignore_errors: yes の場合

比較をするため、Ansible 2.6 までにもあった、似たようなオプション ignore_errors: yes でも試します。

  • Playbook
- hosts: linux
  gather_facts: no

  tasks:
    - name: yum error
      yum:
        name: invalid_package_xxx # エラー
      ignore_errors: yes          # point

    - name: debug
      debug:
        msg: "Hello debug."
  • 実行結果
$ ansible-playbook -i inventory iu_linux.yml

PLAY [linux] ********************************************************************

TASK [yum error] ****************************************************************
fatal: [testsv1]: FAILED! => {"ansible_facts": {"pkg_mgr": "yum"}, "changed": false, "msg": "No package matching 'invalid_package_xxx' found available, installedor updated", "rc": 126, "results": ["No package matching 'invalid_package_xxx' found available, installed or updated"]}
...ignoring
fatal: [testsv99]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 172.16.0.11 port 22: No route to host\r\n", "unreachable": true}

TASK [debug] ********************************************************************
ok: [testsv1] => {
    "msg": "Hello debug."
}
        to retry, use: --limit @/vagrant/a27/iu_linux.retry

PLAY RECAP **********************************************************************
testsv1                    : ok=2    changed=0    unreachable=0    failed=0
testsv99                   : ok=0    changed=0    unreachable=1    failed=0

testsv1 では、1つめの yum モジュールのタスクでエラーが発生しましたが、 ignore_error: yes のため、無視して2つめの debug モジュールのタスクが実行されました。 一方、testsv99 では、1つめのタスクの時点で unreachable なので、その時点で処理が終わっています。


■ 補足

ignore_unreachable を指定できる箇所

公式ドキュメントの Playbook Keywords によると、Play、Role、Block、Task のいずれにも指定できるようです。

例えば、Play に指定する場合はこのようになります。

- hosts: linux
  gather_facts: no
  ignore_unreachable: yes

  tasks:
  ...(略)...

利用できるコネクションプラグイン

試した限り、network_clinetconf といったネットワークモジュール向けのコネクションプラグインでは、ignore_unreachable の指定が効かなかっです。


■ さいごに

ignore_unreachableignore_errors についてまとめると以下のようになります。

ignore_unreachable ignore_errors 到達不能の場合 到達可能だが、モジュール実行エラーの場合
no (デフォルト) no (デフォルト) 中断 中断
yes no (デフォルト) 無視して継続 中断
yes yes 無視して継続 無視して継続
no (デフォルト) yes 中断 無視して継続

ignore_unreachable: yes を指定する必要がるケースは限定的かもしれませんが、何かのときに思い出していただければ幸いです。