LoginSignup
20
20

More than 5 years have passed since last update.

VagrantのProvisionerとしてAnsibleを使う(Windows with CygwinをControl Machineとして)

Last updated at Posted at 2015-04-08

現時点(1.8.4)では、AnsibleはControl MachineとしてWindowsをサポートしていないが、ブログRunning Vagrant with Ansible Provisioning on Windows等を参考にセットアップしてみたので手順をまとめておく。

前半は純粋にWindows(Cygwin)でAnsibleを使う設定になっていてVagrantとは無関係に使用できる。

なお、末尾の回避策に記載しているが未解決の問題(秘密鍵のパーミションが緩過ぎると言われて蹴られてしまう)があり、一部強引にAnsibleのソースコードを書き換えて回避している。

環境

  • Windows 8.1 Pro
  • Cygwin
  • Vagrant 1.7.2
  • Ansible 1.8.4

Cygwinの環境を整える

Cygwinの下記のパッケージを追加する(通常のCygwin Setupを使用)。

  • python
  • python-paramiko
  • python-crypto
  • python-setuptools
  • gcc-core
  • gcc-g++
  • make
  • wget
  • openssh
  • libyaml-devel

pipをインストールする

Ansibleをインストールするためにpip(Pythonのパッケージ管理システム)をインストールする(本作業時点では、CygwinのPythonは、2.7.8であったためpipはデフォルトでは付属していないため)。

$ python /usr/lib/python2.7/site-packages/easy_install.py pip
...
...
Installed /usr/lib/python2.7/site-packages/pip-6.0.8-py2.7.egg
Processing dependencies for pip
Finished processing dependencies for pip

Ansibleをインストールする

$ pip install ansible
Collecting ansible
  Downloading ansible-1.9.0.1.tar.gz (916kB)
...
...
Successfully installed PyYAML-3.11 ansible-1.9.0.1 ecdsa-0.13 jinja2-2.7.3 markupsafe-0.23

なお、
Command "python setup.py egg_info" failed with error code 1
が出てインストールできないときはsetuptoolsをupgradeします。
$ pip install --upgrade setuptools

Ansible単体の動作確認の準備

ここで、VagrantのProvisionerとしてのAnsibleを動作させる前にAnsible単体の動作確認をする。

Managed Nodeを用意する

Managed Node(Ansibleで操作される側のサーバ)として、適当な仮想マシンをvagrant upしておく等して、IP Addressを控えておく(以下では仮に192.168.30.11と192.168.30.12の2ノードとする)。

inventoryファイルを用意する

mkdir /etc/ansible
chmod 755 /etc/ansible
/etc/ansible/hosts
192.168.30.11
192.168.30.12

sshのセットアップ

鍵ペアを作成する。

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/XXXX/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/XXXX/.ssh/id_rsa.
Your public key has been saved in /home/XXXX/.ssh/id_rsa.pub.
The key fingerprint is:

Managed Nodeにsshで使用するホスト名を付ける(オプション)

~/.ssh/config
Host node01
  HostName 192.168.30.11
Host node02
  HostName 192.168.30.12

この設定をした場合は inventoryファイルは下記でも良い。

/etc/ansible/hosts
node01
node02

公開鍵をManaged Nodeに配布する

$ ssh-copy-id vagrant@node01`
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
vagrant@192.168.30.11's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'vagrant@node01'"
and check to make sure that only the key(s) you wanted were added.

$ ssh-copy-id vagrant@node02
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
vagrant@192.168.30.11's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'vagrant@node02'"
and check to make sure that only the key(s) you wanted were added.

ここで、@の前の"vagrant"は、node01,node02へログインするユーザー名。

ControlMasterの設定

ansibleでは、sshのcontrol masterとの通信に問題があるらしく下記の修正が必要だった。

/etc/ansible/ansible.cfg
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
control_path = /tmp

ちなみに、この設定をしないと

fatal: [node01] => SSH Error: Failed to connect to new control master
    while connecting to 192.168.30.11:22

となる。

sshの認証エージェントを起動する

パスフレーズの入力を省略するため認証エージェントを使う。

$ eval `ssh-agent`
Agent pid 9148

(ssh-agentは、バッククオートで囲む)

ちなみに、認証エージェントを使わないとパスフレーズを何度も入力しなければならないだけでなく、複数ノードへのssh接続要求を平行して処理するためパスフレーズの入力要求が入り乱れうまく入力できない。その場合は、ansible-playbook起動時に -f 1 を付けて一度に1ノードづつ処理するようにすればパスフレーズの入力が可能となる。

認証エージェントに秘密鍵を記憶させる

$ ssh-add .ssh/id_rsa
Enter passphrase for .ssh/id_rsa:
Identity added: .ssh/id_rsa (.ssh/id_rsa)

Ansible単体の動作確認

Ad-hocコマンド

Ad-hocコマンドを実行してAnsibleが単体で動作することを確認する。
2つのManaged Node両方から /etc/redhat-releaseを取ってくるAd-hocコマンドを実行してみる。

$ ansible all -a "cat /etc/redhat-release" -u vagrant
192.168.30.12 | success | rc=0 >>
CentOS Linux release 7.1.1503 (Core)

192.168.30.11 | success | rc=0 >>
CentOS Linux release 7.1.1503 (Core)

無事成功。

Playbook

簡単なPlaybookの動作も確認しておく。
2つのノード両方に"kuroneko"というユーザーを登録するPlaybookを用意する。

$ cat <<EOF > add_user.yml
> - hosts: all
>   sudo: yes
>   remote_user: vagrant
>   vars:
>     username: kuroneko
>   tasks:
>     - name: add user
>       user: name={{ username }} group=wheel shell=/usr/bin/bash
> EOF

ansible-playbookを実行してみる。

$ ansible-playbook add_user.yml

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

GATHERING FACTS ***************************************************************
ok: [192.168.30.11]
ok: [192.168.30.12]

TASK: [add user] **************************************************************
changed: [192.168.30.11]
changed: [192.168.30.12]

PLAY RECAP ********************************************************************
192.168.30.11              : ok=2    changed=1    unreachable=0    failed=0
192.168.30.12              : ok=2    changed=1    unreachable=0    failed=0

無事成功。念のため、kuronekoが作成されていることを確認。

$ ansible all -a "grep kuroneko /etc/passwd" -u vagrant
192.168.30.12 | success | rc=0 >>
kuroneko:x:1002:10::/home/kuroneko:/usr/bin/bash

192.168.30.11 | success | rc=0 >>
kuroneko:x:1002:10::/home/kuroneko:/usr/bin/bash

ユーザー"kuroneko"が確かに追加されていて、playbookが正常に実行されたことが確認できた。

ansible-playbookをvagrantから呼び出せるように設定

ansible-playbook.batファイルを用意する

Vagrantからansible-playbookをvagrantから呼び出すためには

  • Windows PATHの中に ansible-playerを配置する
  • ansible-playerがCygwinのPaythonを使用できる

ことが必要。
そこで、下記のbatファイルをC:\HashiCorp\Vagrant\binに配置。

ansible-playbook.bat
@echo off

set CYGWIN=C:\cygwin64

set SH=%CYGWIN%\bin\bash.exe

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

ここで、CYGWIN=C:\cygwin64は、Cygwinをインストールしたディレクトリです。実環境に合わせてください。また、batファイルを配置するディレクトリは、C:\HashiCorp\Vagrant\binである必要はありません。WindowsのPATHが通っている場所に配置します。

ansible-playbook.batの動作確認をしておきます。

ansible-playbook.bat動作確認
$ ansible-playbook.bat add_user.yml

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

GATHERING FACTS ***************************************************************
ok: [node01]
ok: [node02]

TASK: [add user] **************************************************************
ok: [node01]
ok: [node02]

PLAY RECAP ********************************************************************
node01                     : ok=2    changed=0    unreachable=0    failed=0
node02                     : ok=2    changed=0    unreachable=0    failed=0

batファイルからansible-playbookが呼び出されて、無事add_user.ymlが実行されています。

VagrantのProvisionerとしてのAnsibleの動作確認

Vasgrantfileの用意

2つのCentOS 7 (1503)の仮想サーバを作成して、ApacheをprovisioningするVagrantfileを用意。

Vagrantfile
Vagrant.configure(2) do |config|

  if Vagrant.has_plugin?("vagrant-cachier")
    config.cache.scope = :box
  end
  if Vagrant.has_plugin?("vagrant-vbguest")
    config.vbguest.auto_update = false
  end
  config.vm.define "web02" do |web|
    web.vm.box = "centos7-1503-01-min"
    web.vm.hostname = "web02"
    web.vm.network "private_network", ip: "192.168.40.12"
    web.vm.provision "shell",
      inline: "nmcli connection reload;systemctl restart network.service"
    web.vm.provision "ansible" do |ansible|
      ansible.playbook = "ensure-apache-latest.yml"
    end
  end
  config.vm.define "web01" do |web|
    web.vm.box = "centos7-1503-01-min"
    web.vm.hostname = "web01"
    web.vm.network "private_network", ip: "192.168.40.11"
    web.vm.provision "shell",
      inline: "nmcli connection reload;systemctl restart network.service"
    web.vm.provision "ansible" do |ansible|
      ansible.playbook = "ensure-apache-latest.yml"
    end
  end

end

呼び出されているPlaybookは以下のとおり。

ensure-apache-latest.yml
- hosts: all
  sudo: yes
  remote_user: vagrant
  tasks:
    - name: ensure apache is at the latest version
      yum: pkg=httpd state=latest
      notify:
      - stop firewalld
      - restart httpd
  handlers:
    - name: stop firewalld
      service: name=firewalld state=stopped enabled=no
    - name: restart httpd
      service: name=httpd state=restarted enabled=yes

動作確認(失敗)

上記のVagrantfileで、vagrant upすると下記のエラーメッセージが表示され、Playbookを起動できない。

ansibleのエラーメッセージ
fatal: [web01] => private_key_file (D:/Vagrant/projects/ansible-windows/.vagrant/machines/web01/virtualbox/private_key) is group-readable or world-readable and thus insecure - you will probably get an SSH failure

秘密鍵ファイルのパーミションが寛容過ぎるということのようだが、chmod 600したり setfaclでaclを厳しくしても解決できなかった。
本記事の上の方で ~/.ssh/id_rsaを使って、Playbookの動作確認をしているので、このファイルと同じパーミションを設定したり getfacl ~/.ssh/id_rsa | setfacl -f - private_key 等を試してみたがなぜか解決できなかった。stat private_key等してみてもおかしなところはないように見える。CygwinとWindowsのパーミション関係で何か見逃していそうだがわからない。そこで、次の回避策を強行した。

回避策

上のエラーメッセージは、/usr/lib/python2.7/site-packages/ansible/runner/connection.pyから出力されている。

connection.py抜粋
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,))

試験的にこの部分を#でコメントアウトして、vagrant destroy;vagrant upしたところ無事、provisioningすることができた。

実行ログの抜粋
$ vagrant up
Bringing machine 'web02' up with 'virtualbox' provider...
Bringing machine 'web01' up with 'virtualbox' provider...
...
...
...
==> web02: Running provisioner: ansible...
...
...
...
PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [web02]

TASK: [ensure apache is at the latest version] ********************************
changed: [web02]

NOTIFIED: [stop firewalld] ****************************************************
changed: [web02]

NOTIFIED: [restart httpd] *****************************************************
changed: [web02]

PLAY RECAP ********************************************************************
web02                      : ok=4    changed=3    unreachable=0    failed=0
==> web02: Configuring cache buckets...
==> web01: Importing base box 'centos7-1503-01-min'...
...
...
...
==> web01: Running provisioner: ansible...
...
...
...
PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [web01]

TASK: [ensure apache is at the latest version] ********************************
changed: [web01]

NOTIFIED: [stop firewalld] ****************************************************
changed: [web01]

NOTIFIED: [restart httpd] *****************************************************
changed: [web01]

PLAY RECAP ********************************************************************
web01                      : ok=4    changed=3    unreachable=0    failed=0
==> web01: Configuring cache buckets...

余談

上のVagrantfileのansible playbookの呼び出し方だと、仮想サーバ作って、プロビジョンして、仮想サーバ作って、プロビジョンしてをただひたすらシーケンシャルに実行するだけでつまらない。VagrantのドキュメントのAnsibleのTIPS AND TRICSに"ANSIBLE PARALLEL EXECUTION"という記載がある。これをまねて下記のVagrantfileで、provisioningの並列実行をやってみた。

Vagrantfile
Vagrant.configure(2) do |config|

  if Vagrant.has_plugin?("vagrant-cachier")
    config.cache.scope = :box
  end
  if Vagrant.has_plugin?("vagrant-vbguest")
    config.vbguest.auto_update = false
  end
  config.ssh.insert_key = false
  config.vm.define "web02" do |web|
    web.vm.box = "centos7-1503-01-min"
    web.vm.hostname = "web02"
    web.vm.network "private_network", ip: "192.168.40.12"
    web.vm.provision "shell",
      inline: "nmcli connection reload;systemctl restart network.service"
  end
  config.vm.define "web01" do |web|
    web.vm.box = "centos7-1503-01-min"
    web.vm.hostname = "web01"
    web.vm.network "private_network", ip: "192.168.40.11"
    web.vm.provision "shell",
      inline: "nmcli connection reload;systemctl restart network.service"
    web.vm.provision "ansible" do |ansible|
      ansible.playbook = "ensure-apache-latest.yml"
      ansible.limit = 'all'
    end
  end

end

すべての仮想サーバへひとつの秘密鍵でsshするためconfig.ssh.insert_key = falseを忘れると1台を除いてprovisioningに失敗するので注意。

後でlegacy insecure keyを入れ替えなければならないが、使えそうだ。

20
20
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
20