Ansible ネットワークモジュールの Persistent Connections 利用方法と注意点


# ■ 1. はじめに
Ansible 2.3 でネットワーク機器に対するSSHコネクションを使いまわすpersistent connections という機能が追加されました。これによりパフォーマンス向上が期待できます。

参考:

- [インフラ自動化ツール「Ansible 2.3」リリース。SSHのコネクションを使い続けるPersistent Connectionでタスク処理が高速に](http://www.publickey1.jp/blog/17/ansible_23sshpersisten_connection.html)
- [NETWORKING FEATURES COMING SOON IN ANSIBLE 2.3](https://www.ansible.com/blog/networking-features-in-ansible-2-3)

本記事では使い方や注意点を記述します。

# ■ 2. 動作イメージ
Playbook実行により一度確立したSSHコネクションを使い続けます。そのコネクションはPlaybook終了後も30秒間残ります。
SSHコネクションはPlaybookをまたいでも再利用されます。


**※ (2018/02/18 追記)　Ansible 2.5 で、コネクションはPlaybook実行後に終了する仕様に変更されました。詳細は[公式ブログ](https://www.ansible.com/blog/coming-soon-networking-features-in-ansible-2.5)の「Persistent SSH Connection Improvements」を参照。**

![image.png](https://qiita-image-store.s3.amazonaws.com/0/124069/af67f7bb-a2be-4c3e-98b1-9abc59fea26c.png)


# ■ 3. 使い方
従来通り、Playbook に `connection: local` と記述しておくことで persistent connections 機能を利用できます。以下は `ios_command` モジュールを利用する例です。

```
- hosts: cisco
  gather_facts: no
  connection: local   # Ansible 2.1 や 2.2 と同じ

  tasks:
    - name: config
      ios_command:
        commands:
         - "show ip route"
        provider: "{{ cli }}"
      register: result

    - name: debug
      debug:
        var: result

  vars:
    cli:
      host:     "{{ inventory_hostname }}"
      username: "{{ ansible_user }}"
      password: "{{ ansible_password }}"
```

# ■ 4. 対象モジュール

すべてのネットワークモジュールがpersistent connections 機能を利用できるわけではありません。私が試した範囲では、ios系モジュールはpersistent connections 機能を利用できました。panos系モジュールは利用できませんでした。

現在のところ、公式ドキュメント上の各モジュールの説明ページではこのことは記載されていません。おそらくなのですが、 例えば `lib/ansible/plugins/action/` 配下のコードで以下のような記述があるモジュールはpersistent connections 機能に対応しているということなのだと思います。

例：ios系モジュール

```py:ios.py
connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)
```
　引用元: [lib/ansible/plugins/action/ios.py](https://github.com/ansible/ansible/blob/stable-2.3/lib/ansible/plugins/action/ios.py#L66)


また、[Network Debug and Troubleshooting Guide](https://docs.ansible.com/ansible/network_debug_troubleshooting.html) というページにも記載されていませんが、このページ対する [[WIP] Network debug docs #22652] (https://github.com/ansible/ansible/pull/22652) というプルリクエスト内では以下のように記述されています。

```text
Persistent Connection had been enable for the following groups of modules:
- dellos6
- dellos9
- dellos10
- eos
- ios
- iosxr
- junos
- nxos (some)
- vyos
- sros
```
　引用元: https://github.com/gundalow/ansible/blob/network-debug-docs/docs/docsite/rst/intro_networking.rst

# ■ 5. 注意点
## (1) コネクション再利用時はPlaybook内の認証情報が反映されない
動作イメージで説明した通り、PlaybookをまたいでSSHコネクションを再利用します。
そのためPlaybook実行完了後、コネクションが残っているうちに、意図的にPlaybook内の認証情報を正しくないものに書き換えて再実行した場合でも、正しく実行できてしまいます。

## (2) known_hosts にない対象機器だとエラーになる
詳細と対処方法は以下の記事にまとめました。
[Ansible で known_hosts にないネットワーク機器への接続時のエラー対処方法（persistent connections 利用時）](http://qiita.com/akira6592/items/558993f5040d1af15c82#_reference-5dc0ea3976f5ea977e4b)

# ■ 6. タイムアウトを待たずに新規コネクションを利用する方法
タイムアウトを待たずに新規コネクションを利用するようにするには、` ~/.ansible/pc` ディレクトリ配下にできたソケットファイルを手動で削除します。（SSH上の操作が30秒間なにもないと自動的に削除されます。）
ただし、SSH切断操作が実行されるわけではないので、ネットワーク機器上にはログインセッションが残ったままになります。（IOSであれば `show users` で確認可能）
そもそも persistent connections 機能を利用しないという方法は不明です。

- 参考: [Clearing Out Persistent Connections](https://docs.ansible.com/ansible/network_debug_troubleshooting.html#clearing-out-persistent-connections)

# ■ 7. まとめ
- Ansible 2.3 の一部のネットワークモジュールでSSHコネクションを再利用する機能が追加された。
- パフォーマンス向上が期待できる。
- Playbook をまたいでも再利用される点、known_hostsにない相手だとエラーになる点に注意。