Windows + VagrantでAnsible環境を構築するなら、ansible_localが便利

# ansible_localって何？
ansible_localはVagrantのプロビジョナと呼ばれるものです。
プロビジョナはvagrant upの際にソフトウェアのインストールや設定変更を実施出来るように手助けしてくれる機能を持つものですが、ansible_localはゲストOSにAnsibleをインストールしてくれます。[^1]

参考：[【Vagrantドキュメント意訳】09.プロビジョニング - Qiita](http://qiita.com/ringo0321/items/38743442a9abfc3be5b2)

[^1]: ホストOSにansibleをインストールしてくれる[ansible](https://www.vagrantup.com/docs/provisioning/ansible.html)というプロビジョナもありますが、Windowsにはansibleのインストールが出来ないので今回の検証環境では使用不可です。

# どう便利なの？
事前に必要なファイルを準備しておけば、Vagrant upしただけで、Ansibleがインストールされた仮想マシンが出来上がります。
必要なファイルは最低1つ。お手軽です。[^2]


[^2]: 複数のファイルに多数の設定を記述することも可能です。これにより、複雑なサーバ構成であっても自動で作成出来るようになります。

# 検証環境
- Windows 7 professional (64bit)
- Vagrant 1.9.4 インストール済
- VirtualBox 5.1.22 インストール済
- ゲストOSはCentOS 6.7を使用する為、box「bento/centos-6.7」を追加済
- 対象フォルダは D:\Vagrant\ansible_test

# ゲストOSにansibleを普通にインストールしようと思ったら……
まずは、普通にインストールする手順を見てみましょう。
最初にVagrantfileを作成して……

```
PS D:\Vagrant\ansible_test> vagrant init
```

Vagrantfileをこんな感じに修正して

```ruby:Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  #全ての仮想マシンで公開鍵を共通にする
  config.ssh.insert_key = false

  #box指定
  config.vm.box = "bento/centos-6.7"

  config.vm.define "ansible1" do |server|
    server.vm.hostname = "ansible1"
    server.vm.network :private_network, ip: "192.168.33.35"

    # VirtualBoxのGUI上の名前を設定
    server.vm.provider "virtualbox" do |vb|
      vb.name = config.vm.box.gsub(/\//, "_") + "_" + server.vm.hostname
    end
  end
end
```

Powershellから下記のコマンドを実行して仮想マシンを起動します。（コマンドプロンプトでも可）

```
PS D:\Vagrant\ansible_local> vagrant up
```
起動した仮想マシンにsshで接続して、yum updateコマンドを実行して

```
$ sudo yum update
```

ansibleをインストールする為にEPELをインストールして

```
$ sudo yum install epel-release
```

リポジトリにEPELを指定して、ansibleをインストール

```
$ sudo yum install ansible --enablerepo=epel
```

これで、追加された仮想マシンにansibleがインストールされました。

結構色々コマンドを打って大変ですね。
ansible_localを使えば、このコマンドを打つ手間が、まるっとなくなります。


# ansible_localを使ってみよう

一つだけVagrantの環境を変更します。一度やれば大丈夫です。
共有フォルダが必要なので、Vagrantにvbguestというプラグインを追加しますね。

```
PS D:\Vagrant\ansible_local> vagrant plugin install vagrant-vbguest
```

ansible_localが動作するために、最低限必要なのはansibleのplaybookだけ！

yum updateをかけておきたいので、下記のように記述します。
hosts: allと設定しました。今回は仮想マシンを1つしか作らないので問題ありません。

playbookは、Vagrantfileと同じフォルダに置いて下さい。

```yaml:playbook.yml
---
- hosts: all
  become: true
  tasks:
    - name: yum update
      yum:
        name: '*'
        state: latest
        update_cache: yes
```

Vagrantfileに共有フォルダと、ansible_localの設定を追記します。

```ruby:Vagrantfile
Vagrant.configure("2") do |config|

  config.ssh.insert_key = false

  if Vagrant.has_plugin?("vagrant-vbguest") then
    # Guest Additions自動更新の無効化設定
    config.vbguest.auto_update = false
  end

  config.vm.box = "bento/centos-6.7"

  # 共有フォルダの設定
  config.vm.synced_folder ".", "/vagrant",  create: true, owner: "vagrant", group: "vagrant"

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://atlas.hashicorp.com/search.
  config.vm.define "ansible1" do |server|
    server.vm.hostname = "ansible1"
    server.vm.network :private_network, ip: "192.168.33.35"

    # VirtualBoxのGUI上の名前を設定する
    server.vm.provider "virtualbox" do |vb|
      vb.name = config.vm.box.gsub(/\//, "_") + "_" + server.vm.hostname
    end

    server.vm.provision "ansible_local" do |ansible|
      ansible.playbook = "playbook.yml"
    end

  end
end
```

お待たせしました。後は、vagrant upコマンドを実行するだけです。

```
PS D:\Vagrant\ansible_test> vagrant up
Bringing machine 'ansible1' up with 'virtualbox' provider...
==> ansible1: Importing base box 'bento/centos-6.7'...

（中略）

==> ansible1: Mounting shared folders...
    ansible1: /vagrant => D:/Vagrant/ansible_test
==> ansible1: Running provisioner: ansible_local...
    ansible1: Installing Ansible...
    ansible1: Running ansible-playbook...

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

TASK [Gathering Facts] *********************************************************
ok: [ansible1]

TASK [yum update] **************************************************************
changed: [ansible1]

PLAY RECAP *********************************************************************
ansible1                   : ok=2    changed=1    unreachable=0    failed=0
```

Ansibleがインストールされ、yum updateが完了したと表示されています。
作成した仮想マシンにSSHで接続して、Ansibleのバージョン確認コマンドを打ってみましょう。

```
[vagrant@ansible1 ~]$ ansible --version
ansible 2.3.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]

```

Ansible 2.3.0.0がインストールされています。完了です。


# 雑感あれこれ
上記はCentOSで実行しましたが、UbuntuでもDebianでもAnsibleに対応したOSであれば同様に実行可能です。
但し、インストールされるAnsibleのバージョンはその時点での最新版に固定されます。
特定のバージョンをインストールしたい場合は、ansible_localではなくShellプロビジョナなどを使用する必要があります。

それにしても便利です。もっと早く知りたかった……。


# 参考
[Ansible Local - Provisioning - Vagrant by HashiCorp](https://www.vagrantup.com/docs/provisioning/ansible_local.html)
[Windows上でansible_localプロビジョナーを使ってみた (Vagrant + Ansibleで環境構築の自動化) - Qiita](http://qiita.com/ozawan/items/a4853eb62afef45f5de7)
[ansible_localでvagrantの開発環境構築をしてみた - 地方でリモートワーク in Iwate](http://www.tom08.net/entry/2016/08/30/224839)