Vagrant と Chef で仮想マシンの環境をいろいろいじれるようにしたい!

この記事は書かれてから1年以上が経過しており、最新の情報とは異なる可能性があります

前々回前回までで、ようやく気軽に作って壊せる仮想環境が用意できたので、 ここからは実際に仮想環境に作っていくところをやりたいと思います。

※まだあやふやな部分が多いので、明らかに違っていた箇所はあとで修正する可能性があります。

もちろんゴールは、実際に少し作れるところまでです。(ファイルを自動で配置するとか、アプリケーションインストール済みの状態にするとか)

ただ、そこまで大規模なものは想定していないので(数百台を一元管理とかは絶対やらない)、ローカル環境だけで気軽に試せる方法をとっていきます。

以下、こんな感じで最小構成で進めていきます。

  1. Vagrant を最低限使えるようにする(終わってます)
  2. Chef を最低限使えるようにする
  3. 簡単な Cookbook を用意する
  4. Vagrant, Chef を連携させて、仮想環境が変化するか見てみる

Chef とは?

最近かなり頻繁に聞くワードです。

サーバ構築、システム管理の自動化を助けてくれるツールです。アプリケーションのインストールや、OS・ミドルウェアの設定などを、Cookbook と呼ばれる設定ファイルに落とし込んでおくと、各プラットフォームの差異を吸収したうえで、その設定ファイルの状態に保ってくれます。

詳しくはまだまだこれからです。ただ気軽に試せる環境を用意したので、ここからどんどんと試してみようと思います。

また、自動化というメリットの他にも、こういう気軽に試して壊してが出来るってところは大きなメリットだなーと思います。 では早速。

Chef をインストール

まず Chef に関連したパッケージを gem でインストールしてみます。gem ならば比較的すぐです。

$ gem install chef
Fetching: chef-11.4.4.gem (100%)
Successfully installed chef-11.4.4
1 gem installed
$ chef-solo -v
Chef: 11.4.4

chefというパッケージを入れると、chef-solo, chef-client, knife などのコマンドが一式用意されるようです。試しに chef-solo -v と打ってみたら、「Chef のバージョンは11.4.4ですよー」と表示されました。

ちなみに、数百、数千台とか管理するわけでもないので、Chef Server を用意してうんぬん・・・というのは今回やらずに、 サーバの役割を内包しつつ単独で動く、Chef Solo を使っていきます。

さてさて、何か Cookbook を作ってみることにします。

Cookbook を作る!

※以下、2012年10月に発売された『Software Design / Chef 入門』を参考に進めます。

Cookbook 自体は、ただのディレクトリとテキストファイル群にすぎないので、 実際 Chef のコマンド一式なくても作れます。 (knife というひな形を作ってくれるコマンドがあるものの、後回しにしようと思います。)

また、設定ファイルも最近よくある、設定ファイルっぽく書いていたら実はそれが Ruby のスクリプトだった(DSL)という類のものなので、 これもエディタさえあれば用意できてしまいます。

実際に Chef が担当するのは、その Cookbook に書かれた設定項目に沿って、アプリケーションなり設定値なりを反映するところになるので、 そのあたりを理解するためにも、最初は手書きで用意してみようと思います。

Vagrantfile を若干見直し

Cookbook を用意する前に、1つだけ Vagrantfile の見直しをしたいと思います。 というのも、今後こちらに Cookbook の置き場所の指定などをするためです。

Vagrant.configure("2") do |config|
  config.vm.box = "CentOS_6.4_x86_64_Minimal"

  config.vm.define :vmclient1 do |vmclient|
    vmclient.vm.hostname = "vmclient1"
    vmclient.vm.network :private_network, ip: "192.168.100.11"
  end

  config.vm.define :vmclient2 do |vmclient|
    vmclient.vm.hostname = "vmclient2"
    vmclient.vm.network :private_network, ip: "192.168.100.12"
  end
end

こんな感じで、config.vm.define で仮想マシンを複数立ち上げることが可能です。 先にも書いたようにこれ実際は Ruby のコードなので、ループとかで回すこともできますね。 (とはいえ、ゲストOS立ち上げまくったらホストOSが重くなるのは必然ですし、それぞれの起動時間もそれなりにかかります。)

ゆくゆくは仮想マシン間のネットワークの検証なども行っていきたいので、最小構成は2台としておきたいなーと思います。

それぞれを、vmclient1, vmclient2 として管理していき、 vmclient1 の方は簡単なテキストファイルの設置 (/tmp/test.txt) を、 vmclient2 の方は簡単なアプリケーションの設置 (Webサーバ, Apache) を行ってみようと思います。

レシピを用意する

前回までで、Vagrant 用のディレクトリを作っていたので、その中で Cookbook 用のディレクトリを用意します。

$ cd ~/Vagrant
$ mkdir cookbooks

vmclient1, vmclient2 用のレシピを用意します。まず vmclient1 から。

cat cookbooks/vmclient1/recipes/default.rb
# Cookbook ファイル設置テスト

file "/tmp/test.txt" do
  content "vmclient1 にダミーテキストファイルを作りました!"
end

こちらは、content に書かれた内容のファイルを、仮想マシンの /tmp/test.txt へと作成するレシピです。

続けて vmclient2 の方です。

cat cookbooks/vmclient2/recipes/default.rb
# Cookbook アプリケーション設置テスト

package "httpd" do
  action :install
end

こちらは、httpd(つまりApache)をインストールするというレシピになります。

※まだこのあたりが完全に分かってないのですが、CentOS では httpd で良さげでも、他ディストリビューションなどでは apache2 というパッケージ名にしたりする必要があるらしく、この辺のパッケージ名は吸収してくれないのかなーとか、ちょっと疑問でした。

Vagrant, Chef の連携

Vagrantfile の中には、chef-solo の設定項目も存在します。

http://docs.vagrantup.com/v2/provisioning/chef_solo.html

これを使って、Vagrant 経由で起動した仮想マシンに対して、レシピを適用してみます。

再度 Vagrantfile を見直し

Vagrant.configure("2") do |config|
  config.vm.box = "CentOS_6.4_x86_64_Minimal"

  config.vm.define :vmclient1 do |vmclient|
    vmclient.vm.hostname = "vmclient1"
    vmclient.vm.network :private_network, ip: "192.168.100.11"

    vmclient.vm.provision :chef_solo do |chef|
      chef.cookbooks_path = "cookbooks"
      chef.run_list = "recipe[vmclient1]"
    end
  end

  config.vm.define :vmclient2 do |vmclient|
    vmclient.vm.hostname = "vmclient2"
    vmclient.vm.network :private_network, ip: "192.168.100.12"

    vmclient.vm.provision :chef_solo do |chef|
      chef.cookbooks_path = "cookbooks"
      chef.run_list = "recipe[vmclient2]"
    end
  end
end

やってることは簡単で、今回用意した2つの仮想マシンそれぞれに対して、chef-solo の設定項目を設け、 Cookbook のパスとレシピ名を指定しているだけです。

とりあえずここまでやったら、一旦仮想マシンを壊して初期状態に戻しておきます。

$ vagrant destroy
Are you sure you want to destroy the 'vmclient2' VM? [y/N] y
[vmclient2] Forcing shutdown of VM...
[vmclient2] Destroying VM and associated drives...
Are you sure you want to destroy the 'vmclient1' VM? [y/N] y
[vmclient1] Forcing shutdown of VM...
[vmclient1] Destroying VM and associated drives...

レシピの適用!

さて、いよいよレシピを適用してみます。vagrant up!! vagrant up!!

$ vagrant up

すると、ずらずらーっとログが出力されます。

Bringing machine 'vmclient1' up with 'virtualbox' provider...
Bringing machine 'vmclient2' up with 'virtualbox' provider...
[vmclient1] Importing base box 'CentOS_6.4_x86_64_Minimal'...

[vmclient1] Matching MAC address for NAT networking...
[vmclient1] Setting the name of the VM...
[vmclient1] Clearing any previously set forwarded ports...
[vmclient1] Fixed port collision for 22 => 2222. Now on port 2202.
[vmclient1] Creating shared folders metadata...
[vmclient1] Clearing any previously set network interfaces...
[vmclient1] Preparing network interfaces based on configuration...
[vmclient1] Forwarding ports...
[vmclient1] -- 22 => 2202 (adapter 1)
[vmclient1] Booting VM...
[vmclient1] Waiting for VM to boot. This can take a few minutes.
[vmclient1] VM booted and ready for use!
[vmclient1] Setting hostname...
[vmclient1] Configuring and enabling network interfaces...
[vmclient1] Mounting shared folders...
[vmclient1] -- /vagrant

2つの仮想マシンを立ち上げているので、それぞれログにも名前がついてます。 ただ基本的に1台のときとやっていることは同じで、 ネットワークの設定やら共有ディレクトリの設定やらをやってくれてます。

ここまでは同じですね! さらに出力は続きます。

[vmclient1] -- /tmp/vagrant-chef-1/chef-solo-1/cookbooks
[vmclient1] Running provisioner: chef_solo...
Generating chef JSON and uploading...
Running chef-solo...

おっと、ここから chef-solo が起動してることが確認できました。

[2013-05-09T22:14:33+00:00] INFO: *** Chef 11.4.0 ***
[2013-05-09T22:14:33+00:00] INFO: Setting the run_list to "recipe[vmclient1]" from JSON
[2013-05-09T22:14:33+00:00] INFO: Run List is [recipe[vmclient1]]
[2013-05-09T22:14:33+00:00] INFO: Run List expands to [vmclient1]
[2013-05-09T22:14:33+00:00] INFO: Starting Chef Run for vmclient1
[2013-05-09T22:14:33+00:00] INFO: Running start handlers
[2013-05-09T22:14:33+00:00] INFO: Start handlers complete.
[2013-05-09T22:14:33+00:00] INFO: Processing file[/tmp/test.txt] action create (vmclient1::default line 3)
[2013-05-09T22:14:33+00:00] INFO: entered create
[2013-05-09T22:14:33+00:00] INFO: file[/tmp/test.txt] created file /tmp/test.txt
[2013-05-09T22:14:33+00:00] INFO: Chef Run complete in 0.060882068 seconds
[2013-05-09T22:14:33+00:00] INFO: Running report handlers
[2013-05-09T22:14:33+00:00] INFO: Report handlers complete

・・・vmclient1 のログはここまでのようですね。

Vagrantfile に指定されたレシピが、 chef-solo を介して実行され、実際にファイルの設置が行われていたようです。

確認は後回しにして、さらに vmclient2 のログも見てみます。

[vmclient2] Importing base box 'CentOS_6.4_x86_64_Minimal'...

[vmclient2] Matching MAC address for NAT networking...
[vmclient2] Setting the name of the VM...
[vmclient2] Clearing any previously set forwarded ports...
[vmclient2] Fixed port collision for 22 => 2202. Now on port 2203.
[vmclient2] Creating shared folders metadata...
[vmclient2] Clearing any previously set network interfaces...
[vmclient2] Preparing network interfaces based on configuration...
[vmclient2] Forwarding ports...
[vmclient2] -- 22 => 2203 (adapter 1)
[vmclient2] Booting VM...
[vmclient2] Waiting for VM to boot. This can take a few minutes.
[vmclient2] VM booted and ready for use!
[vmclient2] Setting hostname...
[vmclient2] Configuring and enabling network interfaces...
[vmclient2] Mounting shared folders...
[vmclient2] -- /vagrant

vmclient2 も、ここまでは今までと同様です。

[vmclient2] -- /tmp/vagrant-chef-1/chef-solo-1/cookbooks
[vmclient2] Running provisioner: chef_solo...
Generating chef JSON and uploading...
Running chef-solo...
[2013-05-09T22:15:42+00:00] INFO: *** Chef 11.4.0 ***
[2013-05-09T22:15:42+00:00] INFO: Setting the run_list to "recipe[vmclient2]" from JSON
[2013-05-09T22:15:42+00:00] INFO: Run List is [recipe[vmclient2]]
[2013-05-09T22:15:42+00:00] INFO: Run List expands to [vmclient2]
[2013-05-09T22:15:42+00:00] INFO: Starting Chef Run for vmclient2
[2013-05-09T22:15:42+00:00] INFO: Running start handlers
[2013-05-09T22:15:42+00:00] INFO: Start handlers complete.
[2013-05-09T22:15:42+00:00] INFO: Processing package[httpd] action install (vmclient2::default line 3)
[2013-05-09T22:15:59+00:00] INFO: package[httpd] installing httpd-2.2.15-26.el6.centos from base repository
[2013-05-09T22:16:06+00:00] INFO: Chef Run complete in 23.898427112 seconds
[2013-05-09T22:16:06+00:00] INFO: Running report handlers
[2013-05-09T22:16:06+00:00] INFO: Report handlers complete

こちらのログは、httpd 関連のログになってますね。ログを見る限りではインストールは正しく行われたようです。

正しくレシピが反映されたか確認してみる

まず vmclient1 の方へログインしてみます。

$ vagrant ssh vmclient1
Welcome to your Vagrant-built virtual machine.

さて、ファイルは存在しているでしょうか?

[vagrant@vmclient1 ~]$ cat /tmp/test.txt
vmclient1 にダミーテキストファイルを作りました![vagrant@vmclient1 ~]$

あ・・・最後に改行が入ってなかったのでちょっとアレですが、 でもファイルはちゃんと出来てました!

ついでに、こちらに httpd がインストールされていないことを確認しておきます。

$ which httpd
/usr/bin/which: no httpd in (/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/vagrant/bin)

入ってませんでした。

続けて、vmclient2 の方へログインしてみます。

$ vagrant ssh vmclient2
Welcome to your Vagrant-built virtual machine.

[vagrant@vmclient2 ~]$ which httpd
/usr/sbin/httpd

おおー、入ってますね。

こちらもついでに、上記パスにテキストファイルが置かれていないことを確認しておきます。

[vagrant@vmclient2 ~]$ cat /tmp/test.txt
cat: /tmp/test.txt: そのようなファイルやディレクトリはありません

無かったですね。レシピがきちんと環境ごとに分かれて適用されてました。すげー。

まとめ

Cookbook をローカルで気軽に試してレシピが書ける環境があれば、 物理マシンや VPS 上などでの作業が格段に減り、かなりの効率化が図れるなーという印象です。

個人的には、何よりも作って試して、時には壊して、という気持ち的な敷居が低いところがとてもいいなーと思います。 かなり楽しんでやれちゃいそうです。

ここから先は、Cookbook の書き方を種類ごとに覚えつつも、 自分で作った Cookbook を実践配備するところも併せてやっていけたらなーと思います!

参考URL

この記事は書かれてから1年以上が経過しており、最新の情報とは異なる可能性があります

もし記事内に誤りなどございましたら、 @girigiribauer @girigiribauer.com までご一報いただけると助かります。

Related articles