Edited at

Vagrant and Chef on Windows

More than 5 years have passed since last update.

===========================

VagrantChefで環境構築を自動化してくれるツールです。仮想マシンにはVirtualBoxなどが利用できます。

Windowsはsshrsyncなどを追加するとKnife Soloが使えます。

Chef Soloの入門としてRuby(rbenv)の環境を自動構築する方法を紹介します。

(WindowsにUNIX互換の環境を追加するだけなのでChefの使い方はMacやLinuxでも同じです。)


Download & Install

こちらをWindowsのインストーラーでインストールします。


VirtualBox

VirtualBox for Windowsをインストールします。

VirtualBoxの登場はここだけです。あとはVagrantで仮想マシンをコントロールします。


Vagrant

Vagrant for Windowsをインストールします。

(この手順のインストールディレクトリはC:¥opt¥vagrant¥です。)

VagrantにはRubyが必要なのでRuby for Windowsがインストールされます。

これでMinGWもインストールされるのでUNIX互換の環境が利用できます。

(RubyGems1.0.x系なので注意しましょう。)


Minimalist GNU for Windows

VagrantのMinGWにパッケージ管理ツールはないのでMinGWをインストールします。

(この手順のインストールディレクトリはC:¥opt¥MinGW¥です。)


msysGit

MinGWのパッケージにGitはないのでGit for Windowsをインストールします。

(この手順のインストールディレクトリはC:¥opt¥git¥です。)


Terminal

VagrantのインストールでMinttyもインストールされています。

まずC:\opt\vagrant\embedded\bin\mintty.exeのショートカットを作ります。

そのショートカットのリンク先(T)/bin/bash --loginを追加します。

.minttyrcファイルを設定していますが、通常はGUIで設定します。

(Minttyは背景を透過にできます。Macでも作業をするので透過はポイントです。)

$ cat << __EOS__ > ~/.minttyrc

Transparency=high
FontHeight=12
__EOS__


Package

VagrantのMinGWにmingw-getコマンドを追加してsshrsyncなどをインストールします。

$ cp -r /c/opt/MinGW/. /c/opt/vagrant/embedded/

$ cd /c/opt/vagrant/embedded/var/lib/mingw-get/data/
$ cat defaults.xml|(rm defaults.xml;sed 's/%R\/msys\/1.0/\/opt\/vagrant\/embedded/g' > defaults.xml)
$ cat profile.xml|(rm profile.xml;sed 's/%R\/msys\/1.0/\/opt\/vagrant\/embedded/g' > profile.xml)
$ mingw-get update
$ mingw-get upgrade
$ mingw-get install msys-openssl msys-openssh
$ mingw-get install msys-rsync msys-tar
$ mingw-get install msys-vim

パッケージの一覧はこちらで確認できます。

$ mingw-get list | grep Package


Editor

Vimをインストールしていますが好きなエディターを使いましょう。

WindowsのExplorerからの操作でVagrantfileやChefのRecipeを編集できます。

Sublime TextはTerminalとExplorerから操作できるので使用しています。

.bash_profileファイルにエイリアスを設定すると便利です。

$ cat << __EOS__ >> ~/.bash_profile

alias ll='ls -al'
alias ee='/c/opt/sublimetext2/sublime_text'
__EOS__
$ . ~/.bash_profile


Virtual Machine

仮想マシンはGetting Startedと同じUbuntu 12.01を利用します。

ログインはvagrant sshコマンドではなく/.ssh/configファイルとsshコマンドを使います。

$ vagrant box add precise32 http://files.vagrantup.com/precise32.box

$ mkdir -p ~/vagrant/precise
$ cd ~/vagrant/precise
$ vagrant init precise32
$ vagrant up
$ mkdir ~/.ssh
$ vagrant ssh-config --host precise >> ~/.ssh/config
$ ssh precise
...
Welcome to your Vagrant-built virtual machine.

これでゲストOSにログインできました。次はVagrantfileを設定して環境を自動構築しましょう。


Chef

VagrantはChef Soloが利用されます。リモートマシンにリポジトリ(構築手順)を

rsyncで同期させてsshでコマンドを実行するシンプルな仕組みです。

ホストOS(Knife Solo) <-- ssh --> ゲストOS(Chef Solo)

[Chef Repository] <--- rsync ---> [Chef Repository]


Knife Solo

Gemのknife-soloをインストールするとChefが使えるようになりますが

MSYSに対応していない部分があるのでソースからインストールします。

Cygwinと認識されてディレクトリの先頭に/cygdrive/を付けられるのでv0.2.0をForkして修正しました。

(CygwinとMSYSをRbConfigで区別できないものか… pull requestをするならv0.3.x系にします)


Git

GitHubからソースを利用するのでgitコマンドを使えるようにします。

また、Chefのリポジトリ管理はGitを使います。

$ ln -s /c/opt/git/bin/git.exe /c/opt/vagrant/embedded/bin/git.exe

$ ln -s /c/opt/git/libexec/git-core /c/opt/vagrant/embedded/libexec/git-core
$ ln -s /c/opt/git/share/git-core /c/opt/vagrant/embedded/share/git-core


Gem

ドキュメントが不要なら.gemrcファイルに設定します。

$ echo 'gem: --no-ri --no-rdoc' > ~/.gemrc

$ gem install bundler
$ gem install rake
$ gem install ffi

修正したmsysのブランチをインストールします。

$ git clone git://github.com/ogom/knife-solo.git

$ cd ./knife-solo/
$ git checkout msys
$ bundle && rake install
$ cd ..
$ rm -rf ./knife-solo/


Cookbook

まずは簡単なレシピを作りましょう。Hello, Chef!が出力されると成功です。

(個人のクックブックはsite-cookbooksに作ります。)

$ cd ~/vagrant/precise

$ knife configure
$ knife solo init chef-repo
$ cd ./chef-repo/
$ knife cookbook create hello -o ./site-cookbooks
$ echo 'log "Hello, Chef!"' >> ./site-cookbooks/hello/recipes/default.rb
$ echo '{"run_list":["hello"]}' > ./nodes/precise.json
$ knife solo prepare precise
$ knife solo cook precise
...
* log[Hello, Chef!] action write

ここでGitのリポジトリを作ります。

リポジトリはknife cookbookコマンドの前に必要です。

$ git config --global user.email "user@example.com"

$ git config --global user.name "user"
$ git init
$ git add .
$ git commit -m 'first commit'

KnifeでゲストOSで'git'コマンドを使えるようにします。

(サードパーティーのクックブックはcookbooksを使います。)

$ knife cookbook site install git -o ./cookbooks

$ echo '{"run_list":["git"]}' > ./nodes/precise.json
$ knife solo cook precise
Recipe: git::default
* package[git] action install
- install version 1:1.7.9.5-1 of package git
$ ssh precise
vagrant@precise32:~$ git --version
git version 1.7.9.5


Vagrantfile

先ほどのGitのrecipeをVagrantに設定します。

$ cd ~/vagrant/precise/

$ cat << __EOS__ > ./Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "precise32"
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "./chef-repo/cookbooks"
chef.roles_path = "./chef-repo/roles"
chef.data_bags_path = "./chef-repo/data_bags"
chef.add_recipe "git"
end
end
__EOS__

マシンを削除してから、マシンを新しく作ります。

$ vagrant destroy --force

$ vagrant up
$ ssh precise
vagrant@precise32:~$ git --version
git version 1.7.9.5

マシンを再作成してもgitコマンドが使えます。続いてRubyの環境を自動構築します。


rbenv

rbenvはRubyのバージョン管理ツールです。これを簡単にインストールできます。

Cookbookを管理するにはBerkshelfが便利です。

$ gem install berkshelf

先ほどのリポジトリに追加します。(rbenvはGitHubのリポジトリを利用します。)

$ cd ~/vagrant/precise/chef-repo

$ cat << __EOS__ > ./Berksfile
site :opscode
cookbook 'git'
cookbook 'ruby_build'
cookbook 'rbenv', github: "fnichol/chef-rbenv"
__EOS__
$ berks install --path ./cookbooks

まずはknifeで試します。

$ cat << __EOS__ > ./nodes/precise.json

{
"run_list": [
"git",
"ruby_build",
"rbenv::user"
],
"rbenv": {
"user_installs": [
{
"user": "vagrant",
"rubies": ["1.9.3-p429"],
"global": "1.9.3-p429",
"gems": {
"1.9.3-p429": [
{"name": "bundler"}
]
}
}
]
}
}
__EOS__
$ knife solo prepare precise
$ knife solo cook precise
$ ssh precise
vagrant@precise32:~$ which rbenv
/home/vagrant/.rbenv/bin/rbenv
vagrant@precise32:~$ ruby -v
ruby 1.9.3p429

/home/vagrant/パスにrbenvがインストールされています。最後にVagrantで試します。

$ cd ~/vagrant/precise/

$ cat << __EOS__ > ./Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "precise32"
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "./chef-repo/cookbooks"
chef.roles_path = "./chef-repo/roles"
chef.data_bags_path = "./chef-repo/data_bags"
chef.add_recipe "git"
chef.add_recipe "ruby_build"
chef.add_recipe "rbenv::user"
chef.json = {
"rbenv" => {
"user_installs" => [{
"user" => "vagrant",
"rubies" => ["2.0.0-p195"],
"global" => "2.0.0-p195",
"gems" => {
"2.0.0-p195" => [
{"name" => "bundler"}
]
}
}]
}
}
end
end
__EOS__

マシンを再起動します。

$ vagrant reload

$ ssh precise
vagrant@precise32:~$ rbenv versions
system
1.9.3-p429
* 2.0.0-p195 (set by /home/vagrant/.rbenv/version)
vagrant@precise32:~$ ruby -v
ruby 2.0.0p195

Rubyのバージョンが変わりました。 レシピ通りです。 (キリッ


Actor

アクターが多いので今回の関係を図にしました。

chef_solo


Tree

今回の主なファイルです。(Chefの用語は慣れましょう。)

.

└─vagrant [ベイグラントの作業エリア]
└─precise [マシンの作業エリア]
│ Vagrantfile [ベイグラントの設定ファイル]

└─chef-repo [シェフのリポジトリ]
│ Berksfile [バークシャーの設定ファイル]
│ solo.rb

├─cookbooks [各種クックブック]
│ ├─build-essential
│ ├─chef_handler
│ ├─git
│ ├─rbenv [rbenvのクックブック]
│ │ │ Berksfile
│ │ │ Gemfile
│ │ │ Rakefile
│ │ │ Vagrantfile
│ │ │
│ │ ├─attributes
│ │ ├─libraries
│ │ ├─providers
│ │ ├─recipes [各種レシピ]
│ │ │ default.rb
│ │ │ system.rb
│ │ │ system_install.rb
│ │ │ user.rb
│ │ │ user_install.rb [ユーザにrbenvをインストールするレシピ]
│ │ │ vagrant.rb
│ │ │
│ │ ├─resources
│ │ ├─templates
│ │ └─test
│ └─ruby_build
├─data_bags
├─nodes
├─roles
└─site-cookbooks
└─hello
├─attributes
├─definitions
├─files
├─libraries
├─providers
├─recipes
│ default.rb [Hello, Chef!のレシピ]

├─resources
└─templates


Tips


Chef Solo

リモートマシンでChef Soloを実施することができます。

vagrant@precise32:~$ git clone git://github.com/opscode/chef-repo.git

vagrant@precise32:~$ cd ./chef-repo/
vagrant@precise32:~$ knife configure
vagrant@precise32:~$ knife cookbook create hello -o ./cookbooks
vagrant@precise32:~$ echo 'log "Hello, Chef!"' >> ./cookbooks/hello/recipes/default.rb
vagrant@precise32:~$ echo '{"run_list":["hello"]}' > ./localhost.json
vagrant@precise32:~$ echo 'file_cache_path "/tmp/chef-solo"' > ./solo.rb
vagrant@precise32:~$ echo 'cookbook_path ["/home/vagrant/chef-repo/cookbooks"]' >> ./solo.rb
vagrant@precise32:~$ sudo chef-solo -c ./solo.rb -j ./localhost.json
...
INFO: Hello, Chef!

Chef Soloで確認してからKnife Soloを使いましょう。