Continuous Ops

Exploring the world of 'Infrastructure as Code'

BerkshelfとVagrantの連携(2)

Berkshelf+Vagrantで簡単にGraphiteをインストール

昨日はBerkshelfの導入をやりました。とりあえず簡単なレシピがインストールできることは分かったので、今回は実用的なところで、インストールしてみたかったけど一見面倒そうで敬遠していた、Graphiteをchefのcookbookを使ってインストールしてみます。

  • Graphite

http://graphite.wikidot.com

http://graphite.readthedocs.org/en/0.9.10/

Graphiteはデータのリアルタイム集積・グラフ可視化ツールです。フロントのGUIはDjangoで、そこでデータを集計加工してみたりグラフを描画したりができます。バックエンドはcarbonというデーモンで、ここに向かってネットワーク経由でデータを送信します。・・・というところまでがドキュメントを読んだ限りの概要で、まだ使ったことはありません。とりあえずインストールします。

GitHub上のcookbookをFork

ウェブ上にGraphiteをインストールするレシピが無いかと探してみました。Ubuntu向けのものは公式であるのですが、CentOS/Amazon Linuxで使えるものではなかったので、GitHubを探したところ、ありました。

https://github.com/taos/graphite-chef-centos

しかし、このcookbookのままだとepelのrpmが404になってしまって動作しませんでした。 そこで自分のところにforkして、修正して使います。

https://github.com/chokkoyamada/graphite-chef-centos

修正したのはepelのRPMのURLだけで動きました。

metadataのバージョン番号がポイント

Berksfileを次のように書きます。

1
cookbook 'graphite-chef-centos', git: 'git://github.com/chokkoyamada/graphite-chef-centos.git'

ここではまりどころだったのは、その前にオリジナルの作者であるtaos氏のレポジトリのURLを指定していたのを自分のレポジトリのURLに書き換えたのですが、その後vagrant up/reloadしてもキャッシュが効いていたのか、cookbookがうまく更新できなくて悩みました。

metadataがポイントなんですね。バージョン番号を更新 したら新しいものが入りました。gemと同じ要領ですね。

今回のVagrantfileはこちらです。ローカル(Mac)からウェブを見るためにポートフォワーディングを設定している以外は前回と同じです。

1
2
3
4
5
6
7
8
9
10
11
12
13
Vagrant.configure("2") do |config|
  config.berkshelf.enabled = true
  config.berkshelf.berksfile_path = "Berksfile"
  config.vm.box = "centos63chef"

  config.vm.network :forwarded_port, guest: 80, host: 8080

  config.vm.synced_folder "data", "/vagrant_data"

  config.vm.provision :chef_solo do |chef|
    chef.add_recipe "graphite-chef-centos"
  end
end

あとはvagrantを走らせるだけ。

1
vagrant up
1
2
vagrant ssh
sudo service iptables stop

でiptablesを止めてから、[http://localhost:8080/] にアクセスします。

Graphiteがこんなに簡単にインストールできました! コマンド1個1個打っていくよりはるかに楽です。

Pull Requestもしておきました。

次はGraphiteを使い倒していきます。

BerkshelfとVagrantの連携(1)

他所にあるchefのcookbookを気軽にインポートしたい

chefのcookbookを依存管理してくれるBerkshelfと、Mac上のVM実行補助のライブラリであるVagrantとの連携を試してみます。

私はAWSでchef-soloを使ったインフラの管理をしているのですが、開発の全てをEC2上でやろうとするとどうしてもインスタンスの起動・削除にお金がかさんでしまうので、開発はローカル環境で進めたいと思っています。

AWS上にproduction環境を置く場合、どうしてもAWS上でのテスト環境やステージング環境のようなものは必要になってきますが、その前段階の開発作業はローカルのLinux VM上でできないかと試行錯誤してきました。

その解決策として使ってきたのがVagrantです。VagrantはVirtual Boxをコマンドライン+設定ファイルで扱えるようにしたツールで、chefやpuppetとの連携機能も備えているため、chefのcookbookのテストを気軽に試すことができます。Vagrantは起動も速いので、開発とテストにもってこいです。

さらに最近やりたいと感じていたこととして、「GitHub上にある他ユーザーのcookbookをインポートして気軽に使いたい」というのがありました。

例えばGraphiteやZabbixやHadoopなどといったような、セットアップが多少面倒くさいツールをセットアップしたいときに、他のユーザーのcookbookを使ってさくっとprovisionできたら非常に楽だと思ったのです。cookbookにはセットアップ手順が整理されて書いてあるので、必要なものを素早く把握することもでき一石二鳥です。

そのニーズを満たしてくれるライブラリとして、Berkshelfというのが便利、と同僚の神から教えてもらったので試してみました。今回は必要最低限の設定を行います。

VagrantとBerkshelfのセットアップ

BerkshelfとVagrantの連携機能を使うためには公式サイトにある最新版を使う必要がありました。現時点で私が設定した環境のバージョンは次の通りです。

1
2
3
4
5
6
7
8
ᐅ ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.4.0]

ᐅ vagrant --version
Vagrant version 1.2.2

ᐅ berks --version
Berkshelf (1.4.4)

RubyはRVMを使っています。 Vagrantはgemだと古いバージョンだったので、公式サイトのdmgファイルからインストールしました。Berkshelfはgem install berkshelfでインストールしました。

VagrantのboxはCentOS 6.3 x86_64 + Chef 10.14.2 + VirtualBox 4.1.22 (with guest additions)を使いました。

まずBerksfileを設定します。Berkshelfの公式サイトの例にあるサンプルを試してみます。

1
2
3
4
site :opscode

cookbook 'mysql'
cookbook 'nginx', '~> 0.101.5'

この場合、MySQLはこれNginxはこれが使われるみたいです。

次にVagrantfileを書きます。こちらはvagrant init centos63chefで自動生成してそこからカスタマイズしていきます。

1
2
3
4
5
6
7
8
9
10
11
12
Vagrant.configure("2") do |config|
  config.vm.box = "centos63chef"
  config.vm.synced_folder "data", "/vagrant_data"

  config.berkshelf.enabled = true
  config.berkshelf.berksfile_path = "Berksfile"

  config.vm.provision :chef_solo do |chef|
     chef.add_recipe "mysql"
     chef.add_recipe "nginx"
  end
end

これで動きました。

あとはvagrnat upでVMの作成とプロビジョンが行われます。今回は、mysqlクライアントとnginxパッケージとデーモンがインストールされたはずです。

serverspecで確認

serverspecを使ってテストしてみます。serverspecは今回の主題ではないので詳細はすっ飛ばしますがmysqlとnginxがvagrantサーバーにきちんと入っているかどうかを調べています。

spec/vagrant/nginx_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require 'spec_helper'

describe package('nginx') do
  it { should be_installed }
end

describe service('nginx') do
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end

describe file('/etc/nginx/nginx.conf') do
  it { should be_file }
  it { should contain "pid" }
end
spec/vagrant/mysql_spec.rb
1
2
3
4
5
require 'spec_helper'

describe package('mysql') do
  it { should be_installed }
end
spec/vagrant/mysql_spec.rb
1
2
3
4
5
6
 rake spec
/Users/xxxx/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/vagrant/mysql_spec.rb spec/vagrant/nginx_spec.rb
......

Finished in 0.18744 seconds
6 examples, 0 failures

serverspecのテストが通りました。

これで外部のcookbookを使う準備ができました。次回は他のもうちょっと複雑なcookbookを試したり、パラメータを渡したりといったことが問題なくできるかどうかをやっていきます。 

Octopressを始めました

Octopressの気に入ったところ

GitHub Pagesを使ってOctopressを始めてみました。ずっとwordpressを使っていたのですが、次の3点が気にいって使ってみようと思い立ちました。

  • 静的HTMLでサイトが生成される
  • Git(Hub)ベースなので履歴が残る
  • Pushしておけば、必ずGitHubにバックアップがある
  • vimとmarkdownで書ける

静的に生成できればS3やCloudFrontに置くことで高速化もできるし、サーバーに負荷がかかりにくいです。

WordpressはMySQLに記事データが入っていましたが、Octopressは生のテキストデータとしてデータが残っています。Markdownのテキストデータとしてデータが残っているというのは気分的に安心感があります。 HTML以外の他のデータフォーマットへのエクスポートもしやすいかと思いました。

最近、仕事でもプライベートでもGitHubをよく使っているので、セットアップも手こずらないだろうという見込みもありました。

vimで書けてそのままアップできるのも気持ちいいです。Markdownはvimとの相性も良いです。vim-markdown を組み合わせて使っています。

日本語を使うところではまる

日本語をタイトルや本文に入れて投稿しようとしたところ、

1
2
3
4
5
6
7
8
9
10
11
➜  octopress git:(source) be rake generate

## Generating Site with Jekyll
identical source/stylesheets/screen.css 
Configuration from /Users/caaios5/Documents/git/octopress/_config.yml
Building site: source -> public


ERROR: YOUR SITE COULD NOT BE BUILT:
------------------------------------
"\xE3" on US-ASCII in /Users/caaios5/Documents/git/octopress/source/_posts/2013-05-19-hello.markdown

という感じでなぜか記事をgenerateできず。文字コードの問題だと分かったので、ググって環境変数を設定したらいけました。

1
2
export LC_CTYPE=en_US.UTF-8 
export LANG=en_US.UTF-8

これを~/.zshrcに記載します(使ってるシェルに合わせて変更してください)

zshだとrake new_post["hoge"]とは書けず、rake new_post\["hoge"\]とエスケープする必要がある

1
2
➜  octopress git:(source) be rake new_post["hoge"]
zsh: no matches found: new_post[hoge]

これはOctopress関係ないのですが、rakeコマンドが通らないので一瞬悩みました。bashならこの問題はありません。 またはrake “new_post[hoge]”でもいけます。

Octopressレポジトリのブランチ構成

Octopressのレポジトリは、”master”と”source”という2つのブランチを使いわけた構成になっています。

  • master

rake generateで生成された静的なHTMLコンテンツが置かれている。通常こちらを直接更新はしない。

  • source

普段の作業ディレクトリ。rake new_post['hoge']などを実行して投稿を作るのもこちら。

「masterが公開する部分」、「sourceが管理側」といったイメージです。

なので、rake deployでは実質的にmasterがpushされます(実際、Rakefileの中はそのようになっています)、git push origin sourceで管理側をpushしておけば、git cloneしてgit checkout sourceで別のマシンから作業の続きができます。

参考:

http://tokkonopapa.github.io/blog/2011/12/30/octopress-on-github-and-bitbucket/

記事を書き始めるのにはここが参考になりました。

http://blog.zerosharp.com/clone-your-octopress-to-blog-from-two-places/

文字コードの問題は環境変数を設定すると解決するのはここを読んで気づきました。