Vagrantで複数のVMを立ち上げる

Vagrantで1台のVMを上げるのは特に問題ないけど、2台以上のVMを立ち上げたいときはどうすれば…:thinking:
となったので、調べて試してみた。

## 検証環境

- macOS Mojave
- Vagrant 2.2.2
- VirtualBox 5.2.22

## 参考

公式のドキュメントに例が載っていたので、これを見ながらサクッと真似してみた。
[Multi-Machine - Vagrant by HashiCorp](https://www.vagrantup.com/docs/multi-machine/)

## Vagrantfile作成

boxはubuntu/bionic64を使用。

```sh
$ vagrant init ubuntu/bionic64
$ vi Vagrantfile
```

ドキュメントではprovisioningとか書いたりVMごとにboxを変えたりしてるようだったけど、単純に同じboxで2台起動するだけならこんな感じでOKだった。

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

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"
  config.vm.define "machine_a"
  config.vm.define "machine_b"

  config.vm.provider "virtualbox" do |vb|
    # Display the VirtualBox GUI when booting the machine
    vb.gui = false
  
    # Customize the amount of memory on the VM:
    vb.memory = "2048"
    vb.cpus = "1"
  end
end
```

メモリとかCPUの設定はお好みで。`config.vm.define`でVMを複数定義できる。

## 起動

起動はいつもどおり`vagrant up`で。

```
$ vagrant up
Bringing machine 'machine_a' up with 'virtualbox' provider...
Bringing machine 'machine_b' up with 'virtualbox' provider...
==> machine_a: Importing base box 'ubuntu/bionic64'...
==> machine_a: Matching MAC address for NAT networking...

(略)

==> machine_b: Importing base box 'ubuntu/bionic64'...
==> machine_b: Matching MAC address for NAT networking...

(略)

    machine_b: Inserting generated public key within guest...
    machine_b: Removing insecure key from the guest if it's present...
    machine_b: Key inserted! Disconnecting and reconnecting using new SSH key...
==> machine_b: Machine booted and ready!

(略)
```

定義した`machine_a`の後から`machine_b`が起動している様子。`vagrant status`で確認。

```
$ vagrant status
Current machine states:

machine_a                 running (virtualbox)
machine_b                 running (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.
```

上がってるっぽい。VMに入るときは単純に`vagrant ssh`だけすると「複数あるから名前指定しろ！」って怒られるので、`vagrant ssh <VM名>`で。

```
$ vagrant ssh
This command requires a specific VM name to target in a multi-VM environment.
$ vagrant ssh machine_a
Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-39-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon May  6 07:42:41 UTC 2019

(略)
```

## ネットワーク設定

このままだと起動したVM同士で疎通がとれないので、ネットワークの設定を変更してお互い同じセグメントで起動するようにする。`config.vm.define`のブロックで各VMのIPを設定する。
ちなみにネットワークの設定についてはこちらを参照。
[Networking - Vagrant by HashiCorp](https://www.vagrantup.com/docs/networking/)

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

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"
  # config.vm.network "private_network", type: "dhcp"

  config.vm.define "machine_a" do |machine|
    machine.vm.network "private_network", ip: "192.168.1.101"
  end

  config.vm.define "machine_b" do |machine|
    machine.vm.network "private_network", ip: "192.168.1.102"
  end

  config.vm.provider "virtualbox" do |vb|
    # Display the VirtualBox GUI when booting the machine
    vb.gui = false
  
    # Customize the amount of memory on the VM:
    vb.memory = "2048"
    vb.cpus = "1"
  end
end
```

各VM内でIPを確認してみる。

```:machine_a
vagrant@ubuntu-bionic:~$ ip a | grep inet
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
    inet6 fe80::c2:ccff:fedd:c7b8/64 scope link
    inet 192.168.1.101/24 brd 192.168.1.255 scope global enp0s8
    inet6 fe80::a00:27ff:fe41:d68b/64 scope link
```

```:machine_b
vagrant@ubuntu-bionic:~$ ip a | grep inet
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
    inet6 fe80::c2:ccff:fedd:c7b8/64 scope link
    inet 192.168.1.102/24 brd 192.168.1.255 scope global enp0s8
    inet6 fe80::a00:27ff:fe06:6400/64 scope link
```

pingも通るか確認。

```:machine_a
vagrant@ubuntu-bionic:~$ ping 192.168.1.102
PING 192.168.1.102 (192.168.1.102) 56(84) bytes of data.
64 bytes from 192.168.1.102: icmp_seq=1 ttl=64 time=0.616 ms
64 bytes from 192.168.1.102: icmp_seq=2 ttl=64 time=0.578 ms
64 bytes from 192.168.1.102: icmp_seq=3 ttl=64 time=0.617 ms
64 bytes from 192.168.1.102: icmp_seq=4 ttl=64 time=0.850 ms
^C
--- 192.168.1.102 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 0.578/0.665/0.850/0.109 ms
```

```:machine_b
vagrant@ubuntu-bionic:~$ ping 192.168.1.101
PING 192.168.1.101 (192.168.1.101) 56(84) bytes of data.
64 bytes from 192.168.1.101: icmp_seq=1 ttl=64 time=0.225 ms
64 bytes from 192.168.1.101: icmp_seq=2 ttl=64 time=0.610 ms
64 bytes from 192.168.1.101: icmp_seq=3 ttl=64 time=0.385 ms
64 bytes from 192.168.1.101: icmp_seq=4 ttl=64 time=0.833 ms
^C
--- 192.168.1.101 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3047ms
rtt min/avg/max/mdev = 0.225/0.513/0.833/0.230 ms
```

いい感じ。

## まとめ

これで2台以上のVMを立ち上げる場合もVagrantでサクッと環境構築できそう。provisioningについても共通処理と個別の処理で分けて記述できそうな感じだけど、今ならだいたいDockerで事足りるのかなぁ、と。