Ansible で known_hosts にないネットワーク機器への接続時のエラー対処方法（persistent connections 利用時）

# ■ 1. persistent connections について
Ansible 2.3 でネットーワーク機器に対するSSHコネクションを使いまわすpersistent connections という機能が追加されました。従来通り、Playbook に `connection: local` としておくことで persistent connections 機能を利用できます。

- 参考:
  -  [インフラ自動化ツール「Ansible 2.3」リリース。SSHのコネクションを使い続けるPersistent Connectionでタスク処理が高速に](http://www.publickey1.jp/blog/17/ansible_23sshpersisten_connection.html)
  - [Ansible ネットワークモジュールの Persistent Connections 利用方法と注意点](http://qiita.com/akira6592/items/1cff739ee22e97baad61)

ただし、ios系モジュールなど、一部のモジュール限られます。
これらの persistent connections 対応モジュールを利用した場合、SSHログイン対象のfingerprint が known_hosts にないとエラーになってしまいます。本記事では、その対処方法について説明します。

# ■ 2. 現象：発生するエラー

## -vなし実行時「unable to open shell」
```
[root@localhost ~]# ansible-playbook cat.yml

PLAY [cisco] *******************************************************************************************

TASK [config] ******************************************************************************************
fatal: [192.168.1.254]: FAILED! => {"changed": false, "failed": true, "msg": "unable to open shell. Please see: https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell", "rc": 255}
```
`unable to open shell` にはいくつか原因があり、この出力だけでは詳細な理由がわかりませんので、デバッグを有効にして再度試行します。

## デバッグログ有効時「 (14, 'Bad address')」
```
[root@localhost ~]# export ANSIBLE_LOG_PATH=~/ansible.log   # ログ有効
[root@localhost ~]# export ANSIBLE_DEBUG=True  # デバッグ有効
[root@localhost ~]# ansible-playbook -vvvv cat.yml    # -vvvv も指定して実行（失敗）
　（～省略～）ログたたくさん流れるので注意
PLAY RECAP *********************************************************************************************
192.168.1.254               : ok=0    changed=0    unreachable=0    failed=1

 15047 1493490307.83398: RUNNING CLEANUP
[root@localhost ~]#
```

こうすると `~/ansible.log` に詳細なログが出力されます。
その中で **` (14, 'Bad address')`** というログが出力されます。 

```text:~/ansible.log
2017-04-30 03:26:26,071 paramiko.transport Compression agreed: none
2017-04-30 03:26:26,606 paramiko.transport kex engine KexGroup1 specified hash_algo <built-in function openssl_sha1>
2017-04-30 03:26:26,607 paramiko.transport Switch to new keys ...
2017-04-30 03:26:26,630 p=15119 u=root |  connecting to host 192.168.1.13 returned an error
2017-04-30 03:26:26,630 p=15119 u=root |  (14, 'Bad address')
2017-04-30 03:26:26,708 paramiko.transport EOF in transport thread
　（～省略～）
2017-04-30 03:26:55,985 p=15111 u=root |  fatal: [192.168.1.13]: FAILED! => {
    "changed": false,
    "failed": true,
    "msg": "unable to open shell. Please see: https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell",
    "rc": 255
}
```

# ■ 3. 対処方法
大きく分けて2つの対処方法があります。

- 参考: [Error: “connecting to host <hostname> returned an error” or “Bad address”](https://docs.ansible.com/ansible/network_debug_troubleshooting.html#error-connecting-to-host-hostname-returned-an-error-or-bad-address)

## 【対処方法1】 あらかじめ known_hosts に登録しておく
ansible経由ではなく、普段お使いのターミナルやsshコマンドなでで対象機器にあらかじめログインするなどしてみて、 known_hosts に登録しておけばエラーが出力されなくなり、正常にPlyabookを実行できます。

## 【対処方法2】 knwon_hosts に自動で登録する設定にする
asnbile側の設定として、自動でknown_hosts に登録するように設定する方法あります。

環境変数で指定する場合は以下のようにしてから Playbookを実行します。

```text:環境変数で指定する場合
export ANSIBLE_PARAMIKO_HOST_KEY_AUTO_ADD=True
```

ansible.cfg で設定しておく場合は、以下のように設定してから Playbookを実行します。

```ini:/etc/ansible/ansible.cfg
[paramiko_connection]
host_key_auto_add = True
```


　※2017/04/30 現在、公式ドキュメント上の ansible.cfgでの対処方法が記載されていないように見えますが、単に.rstフォーマットのtypoの影響で見えなくなっているようです。.rstファイルそのものを確認すると上記対処方法が記載されています。


# ■ 4. まとめ
- Ansible 2.3 から persistent connections 機能を利用するネットワークモジュールは、接続対象のfingerprintがknown_hostsにないとエラーになる。
- あらかじめ登録しておくか、自動登録の設定をしておくことで正常に実行できるようになる。