読者です 読者をやめる 読者になる 読者になる

$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

vagrantでVMを一度に複数台立てる

以前、#kyotopm 04 Hackathonを開催して、Cinnamonの並列化に取り組んでいました - $shibayu36->blog; でも少しだけ触れましたが、vagrantでVMを一度に複数台立てるのをちょっとだけ試したのでメモ。

vagrantはMulti VMに対応していて、設定を少し書けばvagrant upするだけで複数のVMを立てることが出来る。Vagrant Documentation あたりが参考になる。

precise32でまっさらなサーバを立てる

例えばpreciese32を使って、まっさらのサーバを2台立ててみる。以下の設定を書いてvagrant upするだけで良い。

Vagrant.configure("2") do |config|
  config.vm.box = "precise32"
  config.vm.box_url = "http://files.vagrantup.com/precise32.box"

  config.vm.define :web1 do |web|
  end

  config.vm.define :web2 do |web|
  end
end

vagrant upすると二つ作成される。

$ vagrant up
Bringing machine 'web1' up with 'virtualbox' provider...
[web1] Importing base box 'precise32'...
[web1] Matching MAC address for NAT networking...
...
Bringing machine 'web2' up with 'virtualbox' provider...
[web2] Importing base box 'precise32'...
[web2] Matching MAC address for NAT networking...
...

ネットワークを設定する

もちろんVMごとにネットワーク設定をすることも出来る。以下のように設定するとprivate_networkとしてネットワーク構築し、さらにローカルのポートフォワーディング設定をするようになっている。

Vagrant.configure("2") do |config|
  config.vm.box = "precise32"
  config.vm.box_url = "http://files.vagrantup.com/precise32.box"

  config.vm.define :web1 do |web|
    web.vm.network :private_network, ip: "192.168.1.11" # このへんが増えた
    web.vm.network :forwarded_port, host: 8001, guest: 8000
  end

  config.vm.define :web2 do |web|
    web.vm.network :private_network, ip: "192.168.1.12"
    web.vm.network :forwarded_port, host: 8002, guest: 8000
  end
end

VMごとに自動セットアップを走らせる

以下の設定をして、script/setup.shを作っておけば、VM作成後セットアップを走らせることも出来る。VMごとに設定できるので違う設定をすることも出来る。

Vagrant.configure("2") do |config|
  config.vm.box = "precise32"
  config.vm.box_url = "http://files.vagrantup.com/precise32.box"

  config.vm.define :web1 do |web|
    web.vm.network :private_network, ip: "192.168.1.11"
    web.vm.network :forwarded_port, host: 8001, guest: 8000
    web.vm.provision :shell, :path => "script/setup.sh" # このへんが増えた
  end

  config.vm.define :web2 do |web|
    web.vm.network :private_network, ip: "192.168.1.12"
    web.vm.network :forwarded_port, host: 8002, guest: 8000
    web.vm.provision :shell, :path => "script/setup.sh"
  end
end

script/setup.shの例

#!/bin/bash

sudo aptitude update
sudo aptitude install -y build-essential
sudo aptitude install -y curl
sudo aptitude install -y git-core git-doc
sudo aptitude install -y svtools daemontools daemontools-run
sudo /sbin/initctl start svscan
curl -L http://cpanmin.us | perl - --sudo App::cpanminus
cpanm Carton

各VMにsshで入れるようにする

vagrant ssh-configで各VMごとに、.ssh/configに設定しておけばssh出来るようになる。VMの名前とhost名を指定して設定を出す。

$ vagrant ssh-config web1 --host multi-vagrant-web1
Host multi-vagrant-web1
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile "/Users/shibayu36/.vagrant.d/insecure_private_key"
  IdentitiesOnly yes
  LogLevel FATAL

$ vagrant ssh-config web2 --host multi-vagrant-web1
Host multi-vagrant-web1
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile "/Users/shibayu36/.vagrant.d/insecure_private_key"
  IdentitiesOnly yes
  LogLevel FATAL

適当に以下のようなスクリプトを作っておくとスクリプトを実行するだけで設定できるかもしれない。

print-ssh-config.sh

#!/bin/bash
echo "### multi-vagrant config begin ###"
vagrant ssh-config web1 --host multi-vagrant-web1
vagrant ssh-config web2 --host multi-vagrant-web2
echo "### multi-vagrant config end ###"

setup-ssh-config.pl

#!/usr/bin/env perl
use strict;
use warnings;
use utf8;

use Path::Class;
use IO::Prompt::Simple;

my $ssh_config_file = file("$ENV{HOME}/.ssh/config");
my $ssh_config = $ssh_config_file->slurp;

$ssh_config =~ s{### multi-vagrant config begin ###.*### multi-vagrant config end ###\n}{
    my $config = `./print-ssh-config.sh`;
}mse;

print $ssh_config;

my $confirm = prompt("overwrite ssh config?", { anyone => [qw/y n/]});
exit if $confirm ne 'y';

my $fh = $ssh_config_file->openw;
print $fh $ssh_config;
$ perl script/setup-ssh-config.pl

### multi-vagrant config begin ###
Host multi-vagrant-web1
  HostName 127.0.0.1
  User vagrant
  Port 2201
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile "/Users/shibayu36/.vagrant.d/insecure_private_key"
  IdentitiesOnly yes
  LogLevel FATAL
Host multi-vagrant-web2
  HostName 127.0.0.1
  User vagrant
  Port 2203
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile "/Users/shibayu36/.vagrant.d/insecure_private_key"
  IdentitiesOnly yes
  LogLevel FATAL
### multi-vagrant config end ###
overwrite ssh config? (y/n) : y

すごい適当に作ったので動作は保証しません。

まとめ

今回はvagrantで複数VMを立てるのについて、雑多なメモを書きました。会社とかでバイト用のVMを作ってあげたり、いろいろと出来るかもしれないですね。