Subsystem for Linux上のAnsibleからHyper-V上のLinuxに接続してみる

# はじめに

ローカル環境でテストを行うためにHyper-V上に環境を構築することあると思う。

Ansibleを利用すれば簡単に構築できるのは周知の事実だが、Windowsで利用する場合は何らかの方法で仮想マシンを作成してその上で作業をする必要がある。

今回はWindows 10から追加されたSubSystem for Linux上のUbuntuにAnsibleをインストールして、Hyper-V上のCent OSを構成管理する。

# 仮想マシンの準備

今回は、Hyper-V上に3台のマシンを準備してすべての環境を同時に初期構築する。
Hyper-Vで仮想マシンをコピーしたい場合は、[前回](https://qiita.com/whale_shark/items/02f22d003a2e91912fd3)の記事を参考のこと

# Subsystem for LinuxへAnsibleをインストール

すでにStoreからUbuntuのSubsystem for Linuxがインストールされていることが前提。
[Ansible公式](http://docs.ansible.com/ansible/latest/intro_installation.html#latest-releases-via-apt-ubuntu)の手順に則って作業を行う。

bashを起動して以下のコマンドを実行する。

```bash:ansibleのインストール
$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible
```

```bash:執筆時のバージョン
$ ansible --version
ansible 2.4.2.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.12 (default, Nov 20 2017, 18:23:56) [GCC 5.4.0 20160609]
```

# 仮想マシンへ秘密鍵をインストール

SubSystem for LinuxのBashで秘密鍵の作成する。

```bash:秘密鍵の作成(Windows10)
$ sshkey-gen
<出てきた文言は必要に応じて入力>
```

各仮想マシンに配信する。

```bash:秘密鍵の配信(Windows10)
$ ssh-copy-id root@<仮想マシンのIPアドレス>
```

# Ansbileの動作確認

各仮想マシンにPINGを飛ばしてみる。

```bash:AnsibleからのPing(Windows10)
$ ansible ＜仮想マシンのIPアドレス＞ -m ping
 [WARNING]: Could not match supplied host pattern, ignoring: all

 [WARNING]: provided hosts list is empty, only localhost is available

 [WARNING]: Could not match supplied host pattern, ignoring: ＜仮想マシンのIPアドレス＞

 [WARNING]: No hosts matched, nothing to do
```

エラーが出てPingが出力されない。
[ここ](http://www.corundum.blue/2017/10/ansible-2-4-0-0%E3%81%AEansible-cfg%E3%81%A7hostfile%E3%82%92%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B%E3%81%A8%E6%80%92%E3%82%89%E3%82%8C%E3%82%8B/)の記事を参考に、以下の設定を実施

```bash:作業ディレクトリの作成と設定ファイルの格納(Windows10)
$ mkdir ansible
$ cd ansible
$ cp /etc/ansible/ansible.cfg ./
$ vi ansible.cfg
---
#inventory      = /etc/ansible/hosts
  ↓
#inventory      = ./hosts
---
$ vi hosts
---
[VM]
<仮想マシンのIPアドレス>
---
```

これで再度Ansibleコマンドを実行すると今度は別のエラーが発生した。

```bash:認証できないエラー
$ ansible <仮想マシンのIPアドレス> -m ping
<仮想マシンのIPアドレス> | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n",
    "unreachable": true
}
```

調査用のオプションをつけて実行したところ、ユーザ名が正しく設定されていないことが判明した。

```bash:調査コマンド実行結果
$ ansible ＜仮想マシンのIPアドレス＞ -m ping -vvv
ansible 2.4.2.0
  config file = /ansible/ansible.cfg
  configured module search path = [u'/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.12 (default, Nov 20 2017, 18:23:56) [GCC 5.4.0 20160609]
Using /ansible/ansible.cfg as config file
Parsed /ansible/hosts inventory source with ini plugin
META: ran handlers
Using module file /usr/lib/python2.7/dist-packages/ansible/modules/system/ping.py
<仮想マシンのIPアドレス> ESTABLISH SSH CONNECTION FOR USER: None
<仮想マシンのIPアドレス> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=.ansible/cp/a843a8612c 仮想マシンのIPアドレス '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
<仮想マシンのIPアドレス> (255, '', 'Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n')
<仮想マシンのIPアドレス> | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n",
    "unreachable": true
}
```

hostsファイルを以下の様に変更した。

```text
<仮想マシンのIPアドレス> ansible_user=root
```

これで、結果が帰ってくる。

```
$ ansible <仮想マシンのIPアドレス> -m ping
<仮想マシンのIPアドレス> | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
```

うまくいかない場合は設定ファイルを見直すこと
(筆者はhostsファイルのansible_user=rootの=の前後に空白をいれてしまい正しくパース出来ないエラーが出た)

# 参考

* [Ansible 1.9以降のansible.cfgでhostfileを定義すると怒られる](http://www.corundum.blue/2017/10/ansible-2-4-0-0%E3%81%AEansible-cfg%E3%81%A7hostfile%E3%82%92%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B%E3%81%A8%E6%80%92%E3%82%89%E3%82%8C%E3%82%8B/)

* [Failed to connect to the host via ssh: Permission denied (publickey,password) #19584](https://github.com/ansible/ansible/issues/19584)