Vagrant and Chef on Windows

  • 165
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

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

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を使いましょう。