Vagrant では一つの Vagrantfile を使って複数の仮想マシンを管理することもできる。 そういったとき、それぞれの仮想マシンでお互いのホスト名が解決できると扱いやすくなる。 それを実現するには、自前でプロビジョニングを設定する以外にも vagrant-hosts というプラグインを使うと楽ができる。 今回は、これまでやっていた自前のプロビジョニングと、それを自動化してくれる vagrant-hosts プラグインについて紹介する。
使った環境は次の通り。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.13.4 BuildVersion: 17E202 $ vagrant --version Vagrant 2.0.4 $ vboxmanage | head -n 1 Oracle VM VirtualBox Command Line Management Interface Version 5.2.10
一つの Vagrantfile で複数の仮想マシンを扱う上での問題点
複数のマシンで構成されるシステムの検証で Vagrant を使うときは、次のように一つの Vagrantfile で複数の仮想マシンを取り扱う。 この Vagrantfile を使えば vm1 と vm2 という名前の二つの仮想マシンが Vagrant で管理できる。 ポイントとしては Private Network の設定を入れるところで、こうするとお互いにその IP アドレスを使って通信できるようになる。
$ cat << 'EOF' > Vagrantfile # -*- mode: ruby -*- # vi: set ft=ruby : # All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what # you're doing. Vagrant.configure("2") do |config| config.vm.define :vm1 do |vm1| vm1.vm.box = "bento/ubuntu-16.04" vm1.vm.network "private_network", ip: "192.168.33.10" end config.vm.define :vm2 do |vm2| vm2.vm.box = "bento/ubuntu-16.04" vm2.vm.network "private_network", ip: "192.168.33.11" end end EOF
それでは上記の Vagrantfile を使って実際に仮想マシンを起動してみよう。
$ vagrant up
起動し終わったら、試しに vm1 から vm2 に向けて ping を打ってみる。 宛先は Private Network で vm2 に割り振られた IP アドレスの 192.168.33.11 を使う。
$ vagrant ssh vm1 -c "ping -c 3 192.168.33.11" PING 192.168.33.11 (192.168.33.11) 56(84) bytes of data. 64 bytes from 192.168.33.11: icmp_seq=1 ttl=64 time=0.678 ms 64 bytes from 192.168.33.11: icmp_seq=2 ttl=64 time=0.664 ms 64 bytes from 192.168.33.11: icmp_seq=3 ttl=64 time=0.566 ms --- 192.168.33.11 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 0.566/0.636/0.678/0.049 ms Connection to 127.0.0.1 closed.
ちゃんと届いた。
ただし、この状態では vm1 から vm2 に対してホスト名を使った通信はできない。 これは vm1 の DNS リゾルバに vm2 に関する情報が登録されていないため。
$ vagrant ssh vm1 -c "ping -c 3 vm2" ping: unknown host vm2 Connection to 127.0.0.1 closed.
まあ、これでも問題はないんだけどやっぱりホスト名を使って通信をしたいよねと思う。
従来の解決方法 (自前でのプロビジョニング)
続いては、これまでにやっていた自前でのプロビジョニングについて。 先ほどからの変更点は Shell を使ったプロビジョニングを登録しているところ。
$ cat << 'EOF' > Vagrantfile # -*- mode: ruby -*- # vi: set ft=ruby : # All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what # you're doing. Vagrant.configure("2") do |config| config.vm.define :vm1 do |vm1| vm1.vm.box = "bento/ubuntu-16.04" vm1.vm.network "private_network", ip: "192.168.33.10" vm1.vm.provision "shell" do |s| s.path = "setup.sh" end end config.vm.define :vm2 do |vm2| vm2.vm.box = "bento/ubuntu-16.04" vm2.vm.network "private_network", ip: "192.168.33.11" vm2.vm.provision "shell" do |s| s.path = "setup.sh" end end end EOF
続いて上記で参照している setup.sh
を用意する。
内容としては /etc/hosts
に vm1 と vm2 の情報を書き込むものになっている。
$ cat << 'EOF_' > setup.sh #!/bin/sh set -x : "Add hostname to /etc/hosts" && { grep vm1 /etc/hosts >/dev/null if [ $? -ne 0 ]; then cat << 'EOF' | sudo tee -a /etc/hosts 192.168.33.10 vm1 192.168.33.11 vm2 EOF fi } EOF_
/etc/hosts
に IP アドレスとホスト名を登録することで DNS リゾルバが名前を解決できるようになる。
実際にプロビジョニングを実行してみよう。
$ vagrant provision
プロビジョニングが終わったら vm1 から vm2 に対して ping を打ってみる。
$ vagrant ssh vm1 -c "ping -c 3 vm2" PING vm2 (192.168.33.11) 56(84) bytes of data. 64 bytes from vm2 (192.168.33.11): icmp_seq=1 ttl=64 time=0.772 ms 64 bytes from vm2 (192.168.33.11): icmp_seq=2 ttl=64 time=0.618 ms 64 bytes from vm2 (192.168.33.11): icmp_seq=3 ttl=64 time=0.587 ms --- vm2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2004ms rtt min/avg/max/mdev = 0.587/0.659/0.772/0.080 ms Connection to 127.0.0.1 closed.
ちゃんと名前解決できて疎通がとれている。
ただ、これだと環境に合わせて setup.sh
を作らないといけないしめんどくさい。
vagrant-hosts プラグインを使った場合
vagrant-hosts プラグインを使うと前述した問題点を解消できる。
まずはプラグインをインストールしよう。
$ vagrant plugin install vagrant-hosts
vagrant-hosts プラグインに対応させた Vagrantfile を次に示す。 ポイントは vagrant-hosts を使ったプロビジョニングが登録されているところ。
$ cat << 'EOF' > Vagrantfile # -*- mode: ruby -*- # vi: set ft=ruby : # All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what # you're doing. Vagrant.configure("2") do |config| config.vm.define :vm1 do |vm1| vm1.vm.box = "bento/ubuntu-16.04" vm1.vm.network "private_network", ip: "192.168.33.10" vm1.vm.provision :hosts, :sync_hosts => true end config.vm.define :vm2 do |vm2| vm2.vm.box = "bento/ubuntu-16.04" vm2.vm.network "private_network", ip: "192.168.33.11" vm2.vm.provision :hosts, :sync_hosts => true end end EOF
先ほど作った仮想マシンには既に /etc/hosts
にホスト名が登録されてしまっているので、一旦作り直そう。
$ vagrant destroy -f && vagrant up
名前解決はキャッシュが効くので、上手く動いていたと思ったらキャッシュでした、というオチが起こりやすい。 ちなみに解決に失敗した情報もキャッシュされることがある。(ネガティブキャッシュという)
仮想マシンを作り直したら、先ほどと同じように vm1 から vm2 に ping を打ってみよう。
$ vagrant ssh vm1 -c "ping -c 3 vm2" PING vm2 (192.168.33.11) 56(84) bytes of data. 64 bytes from vm2 (192.168.33.11): icmp_seq=1 ttl=64 time=0.655 ms 64 bytes from vm2 (192.168.33.11): icmp_seq=2 ttl=64 time=0.781 ms 64 bytes from vm2 (192.168.33.11): icmp_seq=3 ttl=64 time=0.658 ms --- vm2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2005ms rtt min/avg/max/mdev = 0.655/0.698/0.781/0.058 ms Connection to 127.0.0.1 closed.
ちゃんと名前解決できた。
自前の仮想マシン以外の名前を登録する
先ほどの例では Vagrantfile に含まれる仮想マシンだけに限った名前解決をした。 とはいえ、それ以外にも IP アドレスに名前をつけたいといった場面はあるはず。 続いてはそれを vagrant-hosts プラグインで扱ってみることにしよう。
早速、サンプルとなる Vagrantfile を以下に示す。
この中では Google Public DNS (Primary) の IP アドレスである 8.8.8.8 を google-dns
という名前で解決できるようにしている。
$ cat << 'EOF' > Vagrantfile # -*- mode: ruby -*- # vi: set ft=ruby : # All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what # you're doing. Vagrant.configure("2") do |config| config.vm.define :vm1 do |vm1| vm1.vm.box = "bento/ubuntu-16.04" vm1.vm.network "private_network", ip: "192.168.33.10" vm1.vm.provision :hosts do |provisioner| provisioner.autoconfigure = true provisioner.sync_hosts = true provisioner.add_host '8.8.8.8', ['google-dns'] end end config.vm.define :vm2 do |vm2| vm2.vm.box = "bento/ubuntu-16.04" vm2.vm.network "private_network", ip: "192.168.33.11" vm2.vm.provision :hosts, :sync_hosts => true vm2.vm.provision :hosts do |provisioner| provisioner.autoconfigure = true provisioner.sync_hosts = true provisioner.add_host '8.8.8.8', ['google-dns'] end end end EOF
追加したのは新しく解決するホスト名なので仮想マシンは使いまわすことにしよう。 vagrant-hosts プラグインを使ったプロビジョニングを実行する。
$ vagrant provision
まずは Google Public DNS (Primary) サーバに ping を打ってみよう。
$ vagrant ssh vm1 -c "ping -c 3 google-dns" PING google-dns (8.8.8.8) 56(84) bytes of data. 64 bytes from google-dns (8.8.8.8): icmp_seq=1 ttl=63 time=4.83 ms 64 bytes from google-dns (8.8.8.8): icmp_seq=2 ttl=63 time=5.52 ms 64 bytes from google-dns (8.8.8.8): icmp_seq=3 ttl=63 time=8.03 ms --- google-dns ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2004ms rtt min/avg/max/mdev = 4.836/6.132/8.034/1.376 ms Connection to 127.0.0.1 closed.
ちゃんと解決できた。
仮想マシンについても再度確認しておく。
$ vagrant ssh vm1 -c "ping -c 3 vm2" PING vm2 (192.168.33.11) 56(84) bytes of data. 64 bytes from vm2 (192.168.33.11): icmp_seq=1 ttl=64 time=0.322 ms 64 bytes from vm2 (192.168.33.11): icmp_seq=2 ttl=64 time=0.750 ms 64 bytes from vm2 (192.168.33.11): icmp_seq=3 ttl=64 time=0.710 ms --- vm2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2001ms rtt min/avg/max/mdev = 0.322/0.594/0.750/0.193 ms Connection to 127.0.0.1 closed.
ちゃんと解決できているね。ばっちり。
めでたしめでたし。
スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログ (1件) を見る