WindowsでもVagrant+Ansibleで開発環境を構築する



## Overview

Windows上で開発をする際は仮想環境で開発することがほとんどだがWindowsホストをAnsibleのコントロールマシンとして動かそうとすると途端に苦行っぽくなったのでその時のメモ。


## Requirements

- [Vagrant](https://www.vagrantup.com/) (Tested on 1.7.4)
- [Virtualbox](https://www.virtualbox.org/wiki/Downloads) (Tested on 5.0)
- [Cygwin](http://cygwin.com/install.html) (Tested on 2.1.0)


## Installation

### [Vagrant](https://www.vagrantup.com/), [VirtualBox](https://www.virtualbox.org/wiki/Downloads)のインストール

それぞれ公式からDLしてインストール。
再起動を要求されるので一度再起動する。

### Cygwinのインストール

以下のパッケージをインストール時に指定する。お好みで`vim`や`zsh`を追加しておくと開発するとき楽。

  - Devel

    - gcc-core
    - git
  
  - Network

    - openssh

  - Python

    - python
    - python-setuptools



### Cygwinを起動

右クリックで「管理者として実行」から起動する
以下Cygwinのターミナルでの操作とする。

### pipのインストール

```
easy_install pip
```

### Ansibleのインストール

```
pip install ansible
```

### Ansible provisionerでprovisioning

サンプルとして[拙作](https://github.com/shufo/ansible-haproxy-keepalived)のVagrant+AnsibleでHAProxy+keepalived環境を構築するplaybookを実行してみる。

```
git clone https://github.com/shufo/ansible-haproxy-keepalived.git
cd ansible-haproxy-keepalived
```

```bash
➜  vagrant up
Bringing machine 'haproxy1' up with 'virtualbox' provider...
Bringing machine 'haproxy2' up with 'virtualbox' provider...
==> haproxy1: Importing base box 'ubuntu/trusty64'...
〜中略〜
==> haproxy1: Running provisioner: ansible...
PYTHONUNBUFFERED=1 ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_NOCOLOR=true ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --user=vagrant --connection=ssh --timeout=30 --limit='haproxy1' --inventory-file=C:/cygwin/home/admin/work/ansible-haproxy-keepalived/.vagrant/provisioners/ansible/inventory --extra-vars={"keepalived_priority":100} --sudo -v site.yml

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [haproxy1]

TASK: [Ensure dependencies are installed] *************************************
skipping: [haproxy1]

TASK: [Ensure dependencies are installed] *************************************
changed: [haproxy1] => (item=build-essential,zlib1g-dev,libpcre3-dev,libssl-dev,socat) => {"changed": true, "item": "build-essential,zlib1g-dev,libpcre3-dev,libssl-dev,socat", "stderr": "", "stdout": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nThe following extra packages will be installed:\n  dpkg-dev g++ g++-4.8 libalgorithm-diff-perl libalgorithm-diff-xs-perl\n  libalgorithm-merge-perl libdpkg-perl libfile-fcntllock-perl libpcrecpp0\n  libssl-doc libstdc++-4.8-dev\nSuggested packages:\n  debian-keyring g++-multilib g++-4.8-multilib gcc-4.8-doc libstdc++6-4.8-dbg\n  libstdc++-4.8-doc\nThe following NEW packages will be installed:\n  build-essential dpkg-dev g++ g++-4.8 libalgorithm-diff-perl\n  libalgorithm-diff-xs-perl libalgorithm-merge-perl libdpkg-perl\n  libfile-fcntllock-perl libpcre3-dev libpcrecpp0 libssl-dev libssl-doc\n  libstdc++-4.8-dev socat zlib1g-dev\n0 upgraded, 16 newly installed, 0 to remove and 0 not upgraded.\nNeed to get 11.9 MB of archives.\nAfter this operation, 43.4 MB of additional disk space will be used.\nGet:1 http://archive.ubuntu.com/ubuntu/ trusty/main libpcrecpp0 amd64 1:8.31-2ubuntu2 [14.5 kB]\nGet:2 http://archive.ubuntu.com/ubuntu/ trusty/main libstdc++-4.8-dev amd64 4.8.2-19ubuntu1 [1050 kB]\nGet:3 http://archive.ubuntu.com/ubuntu/ trusty/main g++-4.8 amd64 4.8.2-19ubuntu1 [7038 kB]\nGet:4 http://archive.ubuntu.com/ubuntu/ trusty/main g++ amd64 4:4.8.2-1ubuntu6 [1490 B]\nGet:5 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libdpkg-perl all 1.17.5ubuntu5.4 [179 kB]\nGet:6 http://archive.ubuntu.com/ubuntu/ trusty-updates/main dpkg-dev all 1.17.5ubuntu5.4 [726 kB]\nGet:7 http://archive.ubuntu.com/ubuntu/ trusty/main build-essential amd64 11.6ubuntu6 [4838 B]\nGet:8 http://archive.ubuntu.com/ubuntu/ trusty/main libalgorithm-diff-perl all 1.19.02-3 [50.0 kB]\nGet:9 http://archive.ubuntu.com/ubuntu/ trusty/main libalgorithm-diff-xs-perl amd64 0.04-2build4 [12.6 kB]\nGet:10 http://archive.ubuntu.com/ubuntu/ trusty/main libalgorithm-merge-perl all 0.08-2 [12.7 kB]\nGet:11 http://archive.ubuntu.com/ubuntu/ trusty/main libfile-fcntllock-perl amd64 0.14-2build1 [15.9 kB]\nGet:12 http://archive.ubuntu.com/ubuntu/ trusty/main libpcre3-dev amd64 1:8.31-2ubuntu2 [237 kB]\nGet:13 http://archive.ubuntu.com/ubuntu/ trusty/main zlib1g-dev amd64 1:1.2.8.dfsg-1ubuntu1 [183 kB]\nGet:14 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libssl-dev amd64 1.0.1f-1ubuntu2.15 [1073 kB]\nGet:15 http://archive.ubuntu.com/ubuntu/ trusty-updates/main libssl-doc all 1.0.1f-1ubuntu2.15 [966 kB]\nGet:16 http://archive.ubuntu.com/ubuntu/ trusty/universe socat amd64 1.7.2.3-1 [302 kB]\nFetched 11.9 MB in 28s (422 kB/s)\nSelecting previously unselected package libpcrecpp0:amd64.\n(Reading database ... 86712 files and directories currently installed.)\nPreparing to unpack .../libpcrecpp0_1%3a8.31-2ubuntu2_amd64.deb ...\nUnpacking libpcrecpp0:amd64 (1:8.31-2ubuntu2) ...\nSelecting previously unselected package libstdc++-4.8-dev:amd64.\nPreparing to unpack .../libstdc++-4.8-dev_4.8.2-19ubuntu1_amd64.deb ...\nUnpacking libstdc++-4.8-dev:amd64 (4.8.2-19ubuntu1) ...\nSelecting previously unselected package g++-4.8.\nPreparing to unpack .../g++-4.8_4.8.2-19ubuntu1_amd64.deb ...\nUnpacking g++-4.8 (4.8.2-19ubuntu1) ...\nSelecting previously unselected package g++.\nPreparing to unpack .../g++_4%3a4.8.2-1ubuntu6_amd64.deb ...\nUnpacking g++ (4:4.8.2-1ubuntu6) ...\nSelecting previously unselected package libdpkg-perl.\nPreparing to unpack .../libdpkg-perl_1.17.5ubuntu5.4_all.deb ...\nUnpacking libdpkg-perl (1.17.5ubuntu5.4) ...\nSelecting previously unselected package dpkg-dev.\nPreparing to unpack .../dpkg-dev_1.17.5ubuntu5.4_all.deb ...\nUnpacking dpkg-dev (1.17.5ubuntu5.4) ...\nSelecting previously unselected package build-essential.\nPreparing to unpack .../build-essential_11.6ubuntu6_amd64.deb ...\nUnpacking build-essential (11.6ubuntu6) ...\nSelecting previously unselected package libalgorithm-diff-perl.\nPreparing to unpack .../libalgorithm-diff-perl_1.19.02-3_all.deb ...\nUnpacking libalgorithm-diff-perl (1.19.02-3) ...\nSelecting previously unselected package libalgorithm-diff-xs-perl.\nPreparing to unpack .../libalgorithm-diff-xs-perl_0.04-2build4_amd64.deb ...\nUnpacking libalgorithm-diff-xs-perl (0.04-2build4) ...\nSelecting previously unselected package libalgorithm-merge-perl.\nPreparing to unpack .../libalgorithm-merge-perl_0.08-2_all.deb ...\nUnpacking libalgorithm-merge-perl (0.08-2) ...\nSelecting previously unselected package libfile-fcntllock-perl.\nPreparing to unpack .../libfile-fcntllock-perl_0.14-2build1_amd64.deb ...\nUnpacking libfile-fcntllock-perl (0.14-2build1) ...\nSelecting previously unselected package libpcre3-dev:amd64.\nPreparing to unpack .../libpcre3-dev_1%3a8.31-2ubuntu2_amd64.deb ...\nUnpacking libpcre3-dev:amd64 (1:8.31-2ubuntu2) ...\nSelecting previously unselected package zlib1g-dev:amd64.\nPreparing to unpack .../zlib1g-dev_1%3a1.2.8.dfsg-1ubuntu1_amd64.deb ...\nUnpacking zlib1g-dev:amd64 (1:1.2.8.dfsg-1ubuntu1) ...\nSelecting previously unselected package libssl-dev:amd64.\nPreparing to unpack .../libssl-dev_1.0.1f-1ubuntu2.15_amd64.deb ...\nUnpacking libssl-dev:amd64 (1.0.1f-1ubuntu2.15) ...\nSelecting previously unselected package libssl-doc.\nPreparing to unpack .../libssl-doc_1.0.1f-1ubuntu2.15_all.deb ...\nUnpacking libssl-doc (1.0.1f-1ubuntu2.15) ...\nSelecting previously unselected package socat.\nPreparing to unpack .../socat_1.7.2.3-1_amd64.deb ...\nUnpacking socat (1.7.2.3-1) ...\nProcessing triggers for man-db (2.6.7.1-1ubuntu1) ...\nSetting up libpcrecpp0:amd64 (1:8.31-2ubuntu2) ...\nSetting up libstdc++-4.8-dev:amd64 (4.8.2-19ubuntu1) ...\nSetting up g++-4.8 (4.8.2-19ubuntu1) ...\nSetting up g++ (4:4.8.2-1ubuntu6) ...\nupdate-alternatives: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto mode\nSetting up libdpkg-perl (1.17.5ubuntu5.4) ...\nSetting up dpkg-dev (1.17.5ubuntu5.4) ...\nSetting up build-essential (11.6ubuntu6) ...\nSetting up libalgorithm-diff-perl (1.19.02-3) ...\nSetting up libalgorithm-diff-xs-perl (0.04-2build4) ...\nSetting up libalgorithm-merge-perl (0.08-2) ...\nSetting up libfile-fcntllock-perl (0.14-2build1) ...\nSetting up libpcre3-dev:amd64 (1:8.31-2ubuntu2) ...\nSetting up zlib1g-dev:amd64 (1:1.2.8.dfsg-1ubuntu1) ...\nSetting up libssl-dev:amd64 (1.0.1f-1ubuntu2.15) ...\nSetting up libssl-doc (1.0.1f-1ubuntu2.15) ...\nSetting up socat (1.7.2.3-1) ...\nProcessing triggers for libc-bin (2.19-0ubuntu6.6) ...\n"}

TASK: [Ensure haproxy src is downloaded] **************************************
changed: [haproxy1] => {"changed": true, "checksum": "6774c9d0517cd74cff799ef19a559424145f2ea0", "dest": "/tmp/haproxy-1.5.11.tar.gz", "gid": 0, "group": "root", "md5sum": "5500a79d0d2b238d4a1e9749bd0c2cb2", "mode": "0644", "msg": "OK (1340429 bytes)", "owner": "root", "sha256sum": "", "size": 1340429, "src": "/tmp/tmp4rkQ7F", "state": "file", "uid": 0, "url": "http://www.haproxy.org/download/1.5/src/haproxy-1.5.11.tar.gz"}

〜中略〜
```

実行できた。

## ハマったところ

以下試していたときにハマったところ

### ansible-playbookコマンドが見つからないと出る

PATH上には存在するのにVagrant provisionerからansibleを起動すると`no such file or command`となる
workaroundとして以下のような方法があった。

[Running Vagrant with Ansible Provisioning on Windows | Azavea Labs](http://www.azavea.com/blogs/labs/2014/10/running-vagrant-with-ansible-provisioning-on-windows/)

下記のような内容のファイルを` ansible-playbook.bat`というファイル名でWindowsのPATH上(どこでもいい)に置く。

```
@echo off

REM If you used the stand Cygwin installer this will be C:\cygwin
set CYGWIN=C:\cygwin

REM You can switch this to work with bash with %CYGWIN%\bin\bash.exe
set SH=%CYGWIN%\bin\bash.exe

"%SH%" -c "/usr/bin/ansible-playbook %*"
```

ansible-playbook本体のパス等は各環境に合わせて書き換えてください。
また実行ファイルとして使うためbatファイルを実行可能なpermissionにsetしておきましょう。


### keyがgroup-readable or world-readable and thus insecureと怒られる

ansible 1.8から追加されたSSHキーに関するチェックらしくCygwinではこのチェックによりprovisioning出来ないためansibleのソースに少し手を加える

```
vi /usr/lib/python2.7/site-packages/ansible/runner/connection.py
```

以下の4行をコメントアウト

```python
if st is not None and st.st_mode & (stat.S_IRGRP | stat.S_IROTH):
  raise AnsibleError("private_key_file (%s) is group-readable or world-readable and thus insecure - "
                                   "you will probably get an SSH failure"
                                   % (private_key_file,))

```

参考: [don't chk this so it works on cygwin · majidaldo/ansible@cbe17bf](https://github.com/majidaldo/ansible/commit/cbe17bf90118fa72ae495e4c8e1f7a69d0518b49)

## Conclusion

WindowsでVagrant+Ansibleで仮想環境を構築した。
公式的にサポートされている方法ではないのでいずれこの方法が使えなくなるかもしれないが、現状でWindowsをAnsibleのコントロールマシンとして使うにはこういった方法しかないっぽいので無理せずOS Xを使いましょう。

参考: [Windows(Cygwin)でAnsible動かしてみる | blog.s-uni.net](http://blog.s-uni.net/2013/08/27/ansible-running-on-cygwin/)