Vagrant + Chef Solo + Berkshelfで開発環境作成

Vagrant + Chef (Solo)って流行ってるんで、使ってみることにしたよ。

概要

やりたいこと

まずは今回目指すことを書いておく。

とあるWeb系のシステムの開発環境を、数名の開発者で共有したい。具体的には、VirtualBox上のVMにCentOS、JDK、nginx, Play! framework、PostgreSQLとかを自動でインストールして環境を作りたい。

Chef Serverは使わず、ChefのレシピはGitHub上に登録する。コミュニティが作成したcookbookも使えるものは使う。

あと、knife-soloを使用。伊藤直也さんの入門Chef Solo – Infrastructure as Codeで紹介されていて初めて知ったんだけど、Chef Soloを使う場合には、knife soloを使うと色々便利。

本記事で扱わないこと

  • Chefのレシピの書き方。これはサイトなり書籍で色々情報があるので、わざわざ書く必要はないと判断。
  • Vagrantの使い方。理由は上に同じ。

基本情報

知ってると思うけど簡単に説明。

Vagrant → VirtualBoxとかVMware上のVMを簡単に作れるツール。

Chef → 構成管理ツール、みたいなもん。事前に定義した設定ファイルに従って、サーバーの環境を構築してくれる。

上の2つに比べると、Berkshelf は比較的知名度が低いかもしれない。という自分も、今回はじめて知ったんだけど・・・

Berkshelf が何をするものかというと、Chefのcookbookを管理してくれるもの。まぁそれだけだと分かりづらいと思うので、追々実例を見ながら説明、と。

環境情報

MacBook Pro上で作業してます。

  • Vagrant 1.6.2
  • VirtualBox 4.3.12
  • Chef と Berkshelf は Chef DK (Chef Development Kit)を使って入れた。バージョンはChef 11.14.0.alpha.1とBerkshelf 3.0
  • knife-solo 0.4.2
  • VMではCentOSを動かす。

世の中のBerkshelf関連の情報は2.0以前のものが多いみたいだけど、Berkshelf 3.0だといろいろ変わっている事が多いので注意。移行ガイドみたいなのはこちら

環境構築というか事前準備

インスコ

Vagrantはパッケージを使って入れる。RubyGemsを使って入れてたのは過去の話なので要注意。

Chefは、通常だったらこちらのページに従って入れるんだけど、今回はBerkshelfも使うし、Chef DK (Chef Development Kit) というのを入れると両方入るし便利。dmgをダウンロードして、通常のMacのソフトみたいにインストールする。

VirtualBoxのインストールはまぁ説明不要かと。

kinfe-soloは、こちらのページに有るように、gem install knife-solo でいいんだけど、Chef DKでは元から入っているのとは別でrubyの環境をインストールするので、以下のようにそれをPATHに通してから実行した。

PATH=/opt/chefdk/embedded/bin:$PATH
sudo gem install knife-solo

knife configure

knife configure

を実行すると、~/.chef/knife.rb が作成される。

また、以下のように”client key”と”validation key”を所定の場所に置けというメッセージが出る。これらは基本的にはChef Serverを使うときに必要なものらしい。ただ、client keyはOpscodeからのcookbookのダウンロードに必要っぽい。

You must place your client key in:
  /Users/kazu/.chef/kazu.pem
Before running commands with Knife!

You must place your validation key in:
  /etc/chef-server/chef-validator.pem
Before generating instance data with Knife!

client keyを取得

Opscode Communityに登録していない人は、まずSign upする。

ログインしたあと、private keyというのを取得し、それを前述のknife.rbに書かれているパスに保存する。

レポジトリ構成とか

cookbookは当然gitで管理したい。今回は以下の様なディレクトリ構成を考えている。プロジェクトで1つのgitレポジトリがあって、その下にプログラムのソースコード、設定ファイル、そしてサーバーや開発環境のレシピがchef-repo の下にある、という形。

foo-project
    ├-.git
    ├-src
    ├-conf
    └-chef-repo

 knife solo init

プロジェクトディレクトリの直下で以下のコマンドを実施。

knife solo init chef-repo
Creating kitchen...
Creating knife.rb in kitchen...
Creating cupboards...

そうすると、以下の様なディレクトリができる。

kazu% ls chef-repo
cookbooks      data_bags      environments   nodes          roles          site-cookbooks

この下のsite-cookbooksディレクトリに自分が作成したcookbookを、cookbooksディレクトリはサードパーティの(コミュニティの)cookbookを置くようにする。

vagrant init

とりあえず、プロジェクトディレクトリで以下のコマンドを実行すると、Vagrantfileというファイルができる。

vagrant init

具体的にこのファイルをどう修正していくのかは、後ほど。

サードパーティ(コミュニティ)のcookbookを使う方法

さて、こっからはChefを使って環境構築をしていくんだけど、一から全部recipeをゴリゴリ書いていくのは面倒なので、既に存在するコミュニティのcookbookを積極的に使っていく。

knife cookbook site vendor xxxだと勝手にコミットされる

1つ目の方法は、前述の伊藤直也さんの本にも載っている方法。Opscode Communityにあるyumのcookbookを使う場合は、以下のコマンドを使う。

knife cookbook site vendor yum

この方法ではcookbookをダウンロード・解凍して、その後git add + git commitをしてくれる。伊藤直也さんは「若干余計なお世話」って書いてるんだけど、自分にとっては相当余計なお世話という感じ。

自分が作ったcookbookではないし修正予定もないので、自分のgitレポジトリで管理したくはない。ということで、この方法は却下。

knife cookbook site download xxxはコミットされないけど、面倒

2つめの方法は、単にcookbookをダウンロード・解凍だけする方法。以下のコマンドで、現在のディレクトリに、圧縮されたcookbookがダウンロードされてくる。

knife cookbook site download yum

自分が考える、この方法の欠点は以下のとおり。

  • ちっちゃな問題だけど、自分で解凍する必要がある
  • あるcookbookが別のcookbookに依存している場合、依存しているものも手動でdownloadしなければいけない
  • そもそも、downloadすべきcookbook一覧をどっかで管理しとかなければいけない

例えば、プロジェクトでnginx, yum-epel, postgresqlのcookbookを使いたい場合、それらをどっかのファイルに記載しておかないとだめ。自分の場合、以下の様なシェルスクリプトとかを作りかけた。

#/bin/bash
cookbooks=(nginx yum-epel postgresql)
cookbooks_dir=/path/to/foo-project/chef-repo/cookbooks
cd /tmp
for c in $cookbooks[@]
do
  knife cookbook site download $c
  tar xf "$c*tar.gz" -C $cookbooks_dir
  rm $c*tar.gz
done

しかし、これはあまりにイケてなさすぎる方法だし、何か別の方法があるはずと思ってググったら、Berkshelfというのを使えば解決しそうな事が判明。

Berkshelfなら出来るよ

Berkshelfだと、上に書いたようなことが簡単にできる。ただ、すんなりは行かなかった面もある。

Berkshelf

Berkshelfって何?

そもそもBerkshelfって何?って人もいるけど、ドキュメントによればManage a Cookbook or an Application’s Cookbook dependenciesとのこと。cookbookや依存性の管理をしてくれる。

ちなみに、世の中のサイトは、Berkshelf 2.0を扱ったページが多いけど、3.0だと変わっている部分も結構あるので要注意。

cookbookの構成

foo-project
    ├-(省略)
    └-chef-repo
        ├-(省略)
        ├-cookbooks
        |   ├-nginx
        |   └-etc.
        └-site-cookbooks
            ├-play
            └-great-web-service

chef-repo以下は、上のような構成を考えている。

cookbooksディレクトリ以下には、Opscode Communityからダウンロードしてきたcookbookを入れ、site-cookbooks以下には自作のcookbookを入れる。

playはPlay! frameworkをインストールするための自作のcookbook。2014/6/6現在、Opscode CommunityにはPlay! frameworkのまともなcookbookは存在しないようなので、自分で作ることにした。

great-web-serviceは、今回のwebサービスの全体を設定するcookbook。このページで言うEnvironment cookbookに近いものと思ってもらえれば良いかと。

berks init お前もか!

BerkshelfのドキュメントのGetting Startedによると、まずはberks initコマンド使ってねーって書いてあるんだけど、こいつもBerkshelfの設定ファイルであるBerksfileなどいくつかのファイルを作ったあとに、勝手にコミットとかしてくれる。

なんで勝手にコミットするようになっているかは、Berkshelfの設計ポリシーによるもので、後のほうで簡単に説明するけど、自分のようなシナリオの場合はうざいだけ。

Berksfileを直接作ろう

上に書いたとおり、berks initだと勝手にgit add + git commitされてしまうので、今回は以下のとおりBerksfileを手動で作成する。

まぁ大体意味はわかると思う。”play”以外はOpscode Communityからダウンロードしてくる。

source "https://api.berkshelf.com"

metadata

cookbook 'yum-epel'
cookbook 'nginx'
cookbook 'postgresql'
cookbook 'play', path: '../play

この状態でgreat-web-serviceディレクトリで以下のコマンドを実行する。

berks vendor ../../cookbooks

そうすると、依存するcookbookが全部cookbooksディレクトリにダウンロードされる。

マジ便利。

VagrantでのVM起動時に、Chefを実行する

ここまでで、自作のcookbookとコミュニティのcookbookが全部手元に揃った状態となっている。

あとは、VagrantでVMを立ち上げて、これらのcookbookを使って、環境を構築していく。

Vagrantfileの該当部分だけ抜き出すと、以下のとおり。

  config.omnibus.chef_version = :latest
  config.vm.provision "chef_solo" do |chef|
    chef.cookbooks_path = ["./chef-repo/cookbooks", "./chef-repo/site-cookbooks"]
    chef.roles_path = "./chef-repo/roles"
    chef.data_bags_path = "./chef-repo/data_bags"

    chef.add_recipe "yum-epel"
    chef.add_recipe "nginx"
    chef.add_recipe "java"
    chef.add_recipe "postgresql"
    chef.add_recipe "play"

    chef.json = {
      "postgresql" => {
        "enable_pgdg_yum" => true,
        "version" => "9.3"
      },
      "java" => {
        "jdk_version" => "7"
      }
    }

    chef.node_name = "server1"
  end

特に変わった内容ではないはず。

あとはvagrant upとか、いつも通り。

Berkshelfの設計ポリシーに関して

なんで勝手にgit commitが実行されるとか、その辺のポリシーに関して。

BerkshelfはChef Serverを使うことを前提として、いろんな機能が設計されているぽい。

英語が読める方は、以下のページを参考に。

まとめ

Vagrant + Chef Soloで簡単に環境構築ができる。コミュニティのcookbookも併用する場合は、Berkshelfも使うと、cookbookの依存関係を簡単に解決してくれる。

VagrantもChefもBerkshelfも機能が豊富なので、仕組みとか設計ポリシーとかを知っておくと良いと思う。とはいえ、それでも最初はどうやって進めていいか分からないことも多いので、本記事がそういう人のお役に立てば幸い。

書いてるうちに長くなったので、後日読み返して、必要に応じて修正をする・・・かも。

参考文献・ページ

Chef Solo, Vagrant

Berkshelf関連

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です