Mercurialの名前付きブランチを試してみた

連投ですが、hbstudy #33のMercurialハンズオンで課題として挙がっていた、名前付きブランチを簡単にですが試してみました。
※defaultブランチは、ハンズオンの中で使っていたものをそのまま使っています。

名前付きブランチを作る

$ hg branch test_named_branch

適当にファイルを更新してコミット

$ vi glossary.rst
$ hg commit -m "modified glossary.rst"

リポジトリサーバにpush ※新しく作ったブランチをpushするときは --new-branch が必要

$ hg push http://localhost:8000 --new-branch

再び適当に編集してコミット

$ vi glossary.rst
$ hg commit -m "add contents to glossary.rst"

defaultブランチとコンフリクトするように編集してコミット

$ vi remote.rst
$ hg commit -m "modified remote.rst"

変更内容をpush

$ hg push http://localhost:8000/ 

defaultブランチに切り替え

$ hg update default

変更内容をpull ※updateをしても特にファイルに変更は生じない

$ hg pull http://localhost:8000
$ hg update

ブランチの内容をマージ

$ hg merge test_named_branch

コンフリクト内容を解決

$ hg resolve --list
$ vi remote.rst
$ hg resolme --mark remote.rst

マージした内容でリポジトリサーバにpush

$ hg commit -m "merged test_named_btanch to default branch."
$ hg push http://localhost:8000/

こんな感じで簡単にブランチ作成やブランチでの変更作業、切り替え、マージなどができました。
うん、簡単。

hbstudy#33のMercurialハンズオンに参加してきました

はい、とてつもなく久しぶりのブログです。最近ブログネタになるようなことをほとんどしていませんです。

4/28(土)に開催された hbstudy #33 に参加してきたので、レポート的なものを書いておこうかと思います。

バージョン管理の必要性

  • ファイルの変更の5w1h(いつ、どこで、だれが、何を、なぜ、どうやって)がわかる

バージョン管理が必要なファイル

  • サーバの設定ファイル
  • デプロイスクリプト
  • 環境構築のためのプロビジョニングスクリプト
  • ドキュメント

など編集するものすべて

バージョン管理すると

  • 変更の経緯がわかる
    • セットアップが職人技じゃなくなる
  • どのファイルが変更されたかすぐにわかる
  • .bakとかできなくなる
    • 心の平穏w

インフラ向きのバージョンな管理システムは

  • git
    • [o] 手軽にバージョン管理
    • [o] 他のサーバと履歴を共有
    • [o] チェンジセット
    • [o] ブランチ
    • [x] コマンド体型が他と違う(モヒカン向け)
    • [x] Windowsで使うにはmsysが必要
  • Mercurial
    • [o] 手軽にバージョン管理
    • [o] 他のサーバと履歴を共有
    • [o] チェンジセット
    • [o] ブランチ
    • [o] Windowsサポート
    • [x] githubをサポートしていない

どこででも使えるMercurialいいよ!!
癖も少ないし!

Mercurial

  • Mercurial = 水銀
    • なのでコマンドは hg (元素記号)

分散バージョン管理システム

  • 手軽にバージョン管理
    • あとからサーバを準備して、他サーバとの共有も可
  • ローカルコミット
  • 手軽なブランチングと安全なマージ
    • コミット済みの変更をマージするので安心

特徴

  • gitに比べてシンプル
    • リビジョングラフがすべて
    • 分岐はブランチ
  • エクステンション
    • pythonで拡張可能
    • 便利な機能はエクステンションなので、有効にしないとダメ(同梱されているものもすべて無効化されている)
    • 履歴改変系もエクステンション
  • 安全な履歴管理
    • 履歴は神聖
    • 改変可能かどうかを示す phase という安全弁
    • 危険な履歴改変はエクステンションを有効にする必要あり
      • rebase, transplant, mq

履歴改変

履歴改変はpushしていないもののみ可能
→ push 後は誰が触っているかわからない
  • コミットログをあとから変更
  • コミット忘れの追加など
  • コミットを移動する

用語など

資料を参照

ハンズオン

各自で進めましょう!

  1. 課題のダウンロード
  2. おすすめ.hgrcをベースに.hgrc設定
  3. 基本操作
  4. リポジトリサーバを使う

基本操作

  • Blockdigのリポジトリをcloneして、ログやリビジョングラフを見てみる
    • 深夜2時過ぎにcommitしてる!
  • 課題用ディレクトリでリポジトリを作成
    • hg init
  • 今あるファイルをリポジトリに追加
    • status -> add -> status -> commit -> status
  • 少しずつファイルを変更しながら、コマンドの使い方を覚える
    • 編集 -> diff -> status -> commit
  • (直前の)コミットの取り消し
    • commit -> rollback -> revert
      • 直前以前のコミットを取り消すにはbackuoutを使う
  • マルチプルヘッドを作る
    • prarentsで現在のリビジョンを確認(Nとする)
    • 編集 -> commit -> update N -> 編集 -> commit -> update N -> 編集 -> commit -> glog でリビジョングラフを確認
  • マルチプルヘッドをマージ
    • merge
      • ヘッドが3つ以上ある場合は merge REV のようにリビジョン番号を指定する
    • マージしたらコミット
    • マージツールが起動してしまう場合は update --clean で元に戻して、 merge --tool=internal:merge をする
  • マージの取り消し
    • update --clean

リポジトリサーバを使う

  • 簡易的にサーバを起動
    • リポジトリのあるディレクトリで hg serve
      • 8000ポートでサーバが起動
    • pull, push, cloneを試す

hgrcの内容はこんな感じで

[web]
    allow_push = *
    push_ssl = False
  • コンフリクトさせたり解決したり

このへんで時間切れと相成りました。


講師の troter さんとサポートで来て下さっていた方々、heartbeatsの皆様、お疲れ様でした!
懇親会も含めて、楽しめました。

※相変わらず、まとまりもなく、資料を見れば書いてあることばかりですが、大目に見てください。

第1回 アマゾン ウェブ サービス(AWS)オープンセミナー@VOYAGE GROUP に参加してきました (2012/03/21)

最近めっきりブログを書かなくなってきていますが、とりあえず生きています。
ただ、ちょっと業務に追われてブログに書けるネタが無かったくらいです(´;ω;`)

先日、2012年3月21日に開催された、「第1回 アマゾン ウェブ サービス(AWS)オープンセミナー@VOYAGE GROUP」に参加してきたので、そのレポート的なものを。
ustされてたんだから、書いても大丈夫だよね?

開始時刻を間違えていて遅刻したので途中からです。
間違いなどありましたら、ご指摘ください。

事例とデモで学ぶはじめてのAWS -アマゾンクラウドの最新動向-

AWSの大谷 ( @shot6 ) さんによる発表。(多分)初めて大谷さんの実物を大谷さんとして認識して見たのが、この時。

事例: Amazon ECサイト

  • 負荷に応じて1台単位で増減。
  • OracleのテープバックアップをやめてS3へ
    • リストア時間が大幅に減少!

事例: netflix

  • ビジネスアジリティを優先事項と考えてAWSを採用
    • DCを利用していると、サービスの成長にDCの成長が追いつかない
  • 映像のマスターテープのデータはS3に
    • そこから各種デバイス向けのencodingはEC2で

AWSの意義

改善 + 革新

質疑応答

  • EMRのデータをS3に上げるときは50MBからいのチャンクにしたほうが早い(アップロードは)。
  • 解析は大きなデータのほうがいい。

実例で学ぶAWS -オーディエンスデータプラットフォームcosmiを例に-

主催のadingoの中の人、岩川さんによる発表

  • AMI + AutoScale + EMRをメインに利用
  • ApacheのログをEMRで解析
  • AutoScaleはcpu使用率で
    • 懇親会で @shot6 さんが言っていたが、AutoScaleは増やすときは2項目のORで、減らすときは2項目のANDでと言っていた(酒により記憶が濁されていなければ)
  • EMRの解析結果はMongoに格納
  • 計算方法の変更があった場合は台数増やして遡って再計算させる
  • Mongoのデータは専用のEC2インスタンスからELBを介して参照

クックパッドはAWSで動いてます

クックパッドの成田 ( @mirakui ) さんのよる発表。
画像配信、サイト高速化を担当しているとのこと。

AWSへの移行

  • バレンタイン対策(一番少ない時の倍くらいのアクセス)
  • 当時インフラエンジニアが二人
    • 今は五人
  • 3倍ルール(3倍は耐えられる様にしておく)
  • 物理ハードの面倒だけで、他にやりたいことができない。
  • 今は物理サーバはない!
  • リソースあたりのコストは増
  • 箇条投資がなくなったので、結果あまり変わらず
  • 物理作業からの開放
  • ビジネススピードアップ

構成

利用方法

  • Base AMI + puppetで構築
  • tofu(自作)でサムネイル作成
    • 画像はすべてS3に
      • 何がすごいって、S3がスゲー!
  • R53(・∀・)イイ!!

質疑

  • Q: RDSじゃないのは?
    • A: 以前はTritonを使っていたから自前ビルドのMySQLが必要だった。
  • Q: Cloud FrontではなくAkamaiなのはなぜ?
    • A: その時はAKAMAIのが早かったし、ずっと使っていてノウハウがあったから。価格としても、性能の割には安い。
  • Q: R53がなぜいい?
  • MySQLスナップはどれくらいの頻度?取る時にはサービスはどうしてる?
    • A: 一日均等に4回。スナップを取る専用のスレーブがあって、スナップ取得時にはデーモンを止めて、レプリケーションも止める。
  • Q: ネットワークまわりのトラブルはある?
    • A: これまでは特にない。インスタンスがいきなり死ぬほうが多い。結構頻繁に。DBマスタに起きたこともあるけど、マルチマスタ構成にしたりしているから、長時間の停止はない。

 

HerokuはAWSで動いてます

Herokuエバンジェリストの相澤さんによる発表。
話したいことがたくさんあったらしいが、ustされていたため口を閉ざしてしまわれた。残念。

Herokuの構成

  • Routing Mesh (erlangで作ってある)
  • psmgr (プロセス単位で増減させる)
    • ダイノスという単位でプロセスを管理している
  • Add-on
    • アドオン対応すれば、tofuをHerokuで使えるようになるし、お金も入って来るようになるYO!

サポート

Herokuは基本英語での対応だが、ayuminさんに連絡すれば、日本語で対応してくださるとのこと。

質疑

  • Q: 東京リージョンは?
    • A: テクニカルには動かせるが、様々な政治的理由がある。あとはどれだけ使ってもらえるか。お金を払ってくれるユーザさんの声が鍵。

感想

コンサル的にSWXさんに協力いただいたりもしたけど、自分のとこでやっているNameタグとホスト名のひもづけ+内部DNSによる管理をクックパッドさんでもやっていることを知って、なんだか嬉しくなったw Base AMI+puppetってところも、うちはChefだけど近いし。あとは、監視周りをどうやって柔軟にしていくかがポイントかな。
※わけあって自分の所属企業は伏せています

VPC周りの近々来るであろうお話も大谷さんに聞けたのはすごく良い収穫。

やっぱり、AWSはどうやってサービスを組み合わせるかと、自分たちで自動化した柔軟な運用をできるかが大事なんだよな。

odstudy 2012.02 「エンジニアのための提案力向上セミナー」 in qpcon のメモ

2012.02.25のqpstudy系の勉強会が一同に介したカンファレンスに参加してきました。その中で聴講した odstudy の「エンジニアのための提案力向上セミナー」のメモです。ほとんど書き写しになっちゃいましたが、そこはまとめ力のない私を笑って済ましていただければとw

話者

  • teian-lab 式町久美子さん (APMP)

teian-lab

  • 提案力を高めたいヒトタチによる提案力を高めるための勉強会
  • いろんな業界/業種でノウハウ、経験を共有
  • 内容
    • 提案書の書き方
    • 提案計画の仕方
    • プレゼンテーション
  • 大事にしたいこと
    • 頑張り過ぎない
    • 自分もみんなも楽しむ

どのような提案?

  • 上司への改善提案
  • お客様への提案
  • コンペ
    • どう考えても負け試合になりそうな場合とかにどう対応していくか
  • 将来チェレンジしてみたいこと

どうやって書くの?

  1. 提案戦略
  2. エグゼクティブサマリー
  3. ストーリーボーディング
  4. FAB (Feature, Advantage, Benefit)

提案戦略

  • 説明が通じない
  • 的を外す/話す相手を間違える
    • いつも話している人(現場)のレベルに合わせるのではなく、その上司(決済者)に届くように
  • 承認を得られない
    • 伝え方がよくないのかも
戦略策定
  • 優位性
    • 自分の提案でなければならない理由を見つけて伝える
    • 調整
  • 提案相手を取り巻く環境
    • プロジェクト名、背景、ニーズなど
    • 社内の場合は、どういう経路でニーズが生まれているか(誰の要望が背景にあるか)とか
  • 強み・弱み分析
    • 自社/競合
    • 自社でなければならない理由
      • ディスカウントできないときに、ギャップを埋めるために何ができるか
      • 要求を満たすためにできること
  • 優位性を導き出す
    • プロジェクト管理とか
  • どれだけ相手を理解しているか
    • 伝えるべき相手
      • 立場に寄って関心事が違う
      • 誰に提案をするのか
        • 技術のわからない人に、細かい技術を説明するのはNG.Issueをどれだけ満足させられるか、予算はどれくらいか
      • ホットボタン
        • 顧客にとって最も重要なこと

エグゼクティブサマリー

  • 短時間で提案内容が理解できるもの
  • ココだけ読めば8割のない様が理解できる
  • 全ページの1割以内
  • お客さんと相談しながら作ると良い
ベネフィット
  • お客さん目線のベネフィット
ポイント
  • 相手の要求にダイレクトな答えが出せているか
  • 他社との違いが明確に打ち出せているか
    • 製品の機能や使い方だけの説明になっていないか(自分主体の言葉)
    • 相手主体の言葉を使う

ストーリーボーディング

伝わりやすいストーリーを書き始める前に考える
  • ホットボタンや評価基準への答えをわかる位置に見せる
    • 1章で要求に対する回答をまとめておく
  • ちゃんと内容の整合性があるか
    • 2章以降で話す詳細説明が、1章で伝えたissueへの回答から外れることがないか
    • 資料を作る人の間での連携
      • 1枚は「必ずこれを入れるべき(1章との整合性の担保)」を指定しておく
執筆者向けガイド
  • テンプレートを作って渡す
    • ここにベネフィットを書くなど
    • RFPから外れることが無いように必須要件は記載しておく
読み手を惹きつける
  • ベネフィットから書く

FAB (Feature Advantage Benefit)

  • 特徴
  • 利点
  • 利益
相手にとってのベネフィットを先に述べる
  • 固有の問題解決に対してどう役立つか
  • 仕様から書かない
    • エンジニアは仕様から書きがち
    • 何が得なのかは理解されない

質問

  • 技術的な内容ではなく、金額で決まってしまう場合にどういう提案の仕方がいいのか?
    • 自分たちでなければならないような関係を作るように、そういうアクションを会社全体で作っていく。
    • この技術でないとお客さんの要求が満たせないというような関係を作れるか
      • ここはちょっと質問者が求めてる回答とは違ったような空気だった。
  • 仕事をしてる時に気をつけていること
    • お客さんの状態を事実に基づいて判断したいので、営業さんにそれが本当に事実なのか(営業フィルタがかかっていないか)を聞き出すようにする
    • チーム全体(営業、SEなど話を聞いてきた人+それ以外の人)で要求を共有するようにする

まとまらないまとめ

  • 自分のやったことをアピールする発表と違って、「提案」は相手からの「要求」があってそれに対する「回答」である
  • 自分(たち)がやったこと/できること(仕様)を事細かに説明するのは、要求者側からするとあまり意味のあるものではない
  • 誰に対して(現場の人間だけではなく、決済者全員)響く内容にするかが重要
  • 何よりも、「要求」に対する「回答」を全面に押し出して、わかりやすく伝える
  • 「回答」の中にはFABを含める
  • ヒアリング内容に個人のフィルタがかからないように、要求を聞くときは立場の違う複数人(営業とSEとか)で聞き、帰社後に関係者全員で共有することで認識のズレが起こらないようにする。

といったところでしょうか。
自分は対お客さんに提案をしたことは(ほぼ)ないのですが、対社内(上司)では苦労をしているので聞いた内容を生かしていければいいな思う所存にございます。

ChefでのMySQLパスワードの扱い

opscodeのリポジトリにあるMySQLのcookbookでは、rootユーザやレプリケーション用のユーザのパスワードをランダムに生成して設定している。

opscode の recipe の特徴

このランダムという点をカバーするべく、うまい仕組みが組み込まれている。

パスワードを設定するところは

node.set_unless['mysql']['server_root_password'] = secure_password

といった形で、attributeに設定されていない場合はランダムに生成するという事をして、2度目以降も同じパスワードとなるようになっている。

2回目以降も同じパスワードを保証するために、もうひとつの技が

unless Chef::Config[:solo]
  ruby_block "save node data" do
    block do
      node.save
    end
    action :create
  end
end

ここの node.save というやつ。
普通であれば、recipe(run_list)の実行がすべて完了するまではattributeがサーバに保存されないんだけど、このメソッドを使うことで、即時に保存される。これで、万が一rootのパスワードが設定されたあとのどこかでコケても、同じパスワードで設定を続けることができる(上のコードにあるようにchef-soloのときは実行されないけど)。また、masterは途中でコケたけど、スレーブはそこで設定された(であろう)であろうパスワードを使ってセットアップだけは続けることができる。

これはよく考えられた仕組みですよね。

Encrypted Data Bag

ただ、ランダムであれば推測されづらくていいかもしれないけど、好きなパスワードを設定したいし、アプリからのアクセスを考えるとすべてのサーバでアプリ用ユーザは共通にしておきたいといった要望もある。また、提供されているrecipeのままだったりattributeにそのまま設定してしまうと、平文のパスワードがattributeの一覧から確認できてしまう。

そんな時に便利なのが、Encrypted Data Bagという平文で保存したくないデータをChefに保持しておくための機構。Encrypted Data Bag を使うために必要なのはencrepted_data_bag_secretと呼ばれる共通鍵だけ。
※やってることはOpscodeのサイトに書かれていることと全く同じです。

共通鍵の作成

# openssl rand -base64 512 | tr -d '\r\n' > /etc/chef/encrypted_data_bag_secret

これをEncrypted Data Bags利用する各クライアントと共有する。共有方法は初回セットアップであれば、knifeコマンドのbootstrapで指定してあげれば良い。その方法は後ほど。

knifeコマンドで暗号化されたデータをdata bagsに保存

passwordというdata bagにmysqlという項目を作成します。ここで指定するmysqlというのは、data bagのIDとなり、これは暗号化されません。

# knife data bag create --secret-file /etc/chef/encrypted_data_bag_secret passwords mysql
[editorが開くので以下のように入力して保存]
{
  "id": "mysql",
  "user": "root",
  "pass": "your_password"
}

※EDITOR環境変数を設定していないとErrorになります。

作成したdata bagを確認してみましょう。

# knife data bag show passwords mysql
{
  "id": "mysql",
  "pass": "trywgFA6R70NO28PNhMpGhEvKBZuxouemnbnAUQsUyo=\n",
  "user": "e/p+8WJYVHY9fHcEgAAReg==\n"
}

userとpassが暗号化されて保存されています。
では、復号化して表示してみます。

# knife data bag show --secret-file /etc/chef/encrypted_data_bag_secret passwords mysql
{
  "id": "mysql",
  "user": "root",
  "pass": "your_password"
}

先程入力したものが表示されました。

Recipeから Encrypted Data Bagのデータを呼び出す

実際に recipe からdata bagの値を呼ぶには、以下のような感じにしてあげます。

共通鍵を直接指定する場合

mysql_data = Chef::EncryptedDataBagItem.load("passwords", "mysql", secret)
user = mysql_data["user"]
password =mysql_data["pass"]

共通鍵ファイルがデフォルトの /etc/chef/encrypted_data_bag_secret に配置されている場合はsecretを指定しなくてもOK

mysql_data = Chef::EncryptedDataBagItem.load("passwords", "mysql")
user = mysql_data["user"]
password =mysql_data["pass"]

ここで、ユーザ名やパスワードを node['mysql']['user'] とやってしまうと、せっかく暗号化して保存されているユーザ名とパスワードが平文でattributeに登録されてしまいますので、やめたほうがいいと思います。data bagに保存されているので、次回以降に変わるという事も無いですしね。

recipe内で定義したローカル変数のままだとテンプレートに渡せないので、templateリソースの中で以下のように定義すればテンプレート内で呼び出せる。

template "hoge" do
  source "hoge.erb"
  ...
  variables(
    :user => user,
    :pass => pass
  )
end

これでめでたくattributeに平文のパスワードが登録されることなく、自分の好みのパスワードが設定出来ました。

bootstrap で encrypted_data_bag_secret を渡す

初回セットアップのサーバの場合には、validation.pemやchef_server_urlを新規クライアントに設定するために bootstrap の仕組みを利用する。この中で、encrypted data bagの共通鍵をセットアップするサーバに配置することができる。

以下のようにbootstrapファイルに書く。

(
cat <<'EOP'
<%= encrypted_data_bag_secret %>
EOP
) > /etc/chef/encrypted_data_bag_secret

encrypted_data_bag_secret など、bootstrap で使用される値などは、knifeを実行するノードのknife.rbに設定されているものが利用される。そのため、encrypted_data_bag_secretファイルの場所もknife.rbに指定しておく必要がある。

encrypted_data_bag_secret "/etc/chef/encrypted_data_bag_secret"

これで、knifeコマンドからbootstrapファイルをして初期実行をすれば、recipeを実行するクライアントでも問題なくdata bagを復号化できる。


(追記:2012-02-12 16:25) recipe内のローカル変数をテンプレートで使うための記述を追記。

knife ec2でインスタンスの初期設定(RVM+Ruby1.9.2編)

前回はnodeのchef-clientを動かすためにrbelリポジトリRubyを使っていた。特にこだわりがなかったり、動かすシステムでRubyを使うわけじゃなければ、RPMだと楽でいいですよね。
ただ、セットアップするnodeでRubyを使いたい、RVMで複数バージョンのRubyを使いたいなんてことがある場合もあると思う。
であれば、bootstrapでインストールするRubyもRVMでインストールしちゃえばいいじゃない。

という訳で、基本的には前回と同じで、bootstrapの中身を変えればOK。セットアップ対象はCentOS6で、Ruby1.9.2をインストールしてデフォルトRubyにします。

$CHEF_REPO/.chef/bootstrap/centos6-rvm.erb を以下のように作成。

bash -c '
<%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%>

yum install -y gcc bison autoconf patch git curl readline-devel libxml2-devel libxslt-devel wget man

if [ ! -f /usr/local/rvm/bin/rvm ]; then
  bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
  source /etc/profile.d/rvm.sh
  rvm install 1.9.2
  rvm use 1.9.2 --default
fi

gem install ohai --no-ri --no-rdoc
gem install chef --no-ri --no-rdoc
ln -nfs $(which chef-client) /usr/bin/chef-client

mkdir -p /etc/chef

(
cat <<'EOP'
<%= validation_key %>
EOP
) > /tmp/validation.pem
awk NF /tmp/validation.pem > /etc/chef/validation.pem
rm /tmp/validation.pem

(
cat <<'EOP'
<%= config_content %>
EOP
) > /etc/chef/client.rb

(
cat <<'EOP'
<%= { "run_list" => @run_list }.to_json %>
EOP
) > /etc/chef/first-boot.json

<%= start_chef %>'

上記bootstrapテンプレートが出来上がったら、前回使用したknife ec2コマンドの -d オプションでの指定を今回作ったものに変えてあげる。

$ knife ec2 server create -G security_roup -I ami-12345678 -f t1.micro -S key-pair-name -i ~/.ssh/private-key.pem -x ec2-login-user -d centos6-rvm -r 'rolw[rails_server]' --region ap-northeast-1 -Z ap-northeast-1a


しばらく待てば、はい完成。(microだとちょっと時間がかかります。)

ChefでEC2インスタンスの起動から初期設定までを行う

前回はChefのサーバとクライアントをインストールして、簡単なチュートリアルを試してみました。今回はより実践的な内容をやってみようと思います。

やること

chefとknifeを用いて、EC2インスタンスの起動と(ごく簡単な)設定を行う。

構成

  • chef-server: CentOS6 on EC2 (t1.micro)
  • 設定対象ノード: CentOS6 on EC2 (t1.micro)
    • knife-ec2を用いて起動〜設定までを行う対象 (chef-client)
  • workstation: CentOS6 on EC2 (t1.micro)
    • knifeコマンドを実行する端末(chef-client)

CentOS6はsuz-labさんが提供している ami-46902747 をベースに、カーネル以外のパッケージを最新にして AMI 化しておいたものを用いる。

事前準備

chef-server

手順は簡単。たったこれだけ。epelのリポジトリは最初から使えるようになっているので、無問題。

# yum install couchdb erlang rabbitmq-server libxml2-devel zlib-devel.x86_64 --enablrepo=epel
# rpm -Uvh http://rbel.frameos.org/rbel6
# yum install ruby ruby-devel ruby-ri ruby-rdoc ruby-shadow gcc gcc-c++ automake autoconf make curl dmidecode --enablerepo=rbel6
# yum install rubygem-chef-server --enablerepo=rbel6
# setup-chef-server.sh

workstation (chef-client)

インストール〜初期設定

knifeコマンドを実行したり、cookbookなどの編集を行うためのchef-client。こちらも簡単。
libxml2-develとlibxslt-develはknife-ec2をインストールするために必要となる。

# rpm -Uvh http://rbel.frameos.org/rbel6
# yum install rubygem-chef --enablerepo=epel,rbel6
# yum install ruby-devel libxml2-devel libxslt-devel --enablerepo=epel,rbel6
# gem install knife-ec2
# scp user@chef-server:/etc/chef/validation.pem /etc/chef/validation.pem
# vi /etc/chef/client.rb
chef_server_url 'http://chef-server:4000'
node_name       'matetsu-work'
# chef-client

ここで通常作業する一般ユーザに切り替える。

$ knife configure
$ sudo chmod 644 /etc/chef/client.pem
$ ln -s /etc/chef/client.pem ~/.chef/matetsu-work.pem

ここで、server-webuiにログインして、登録したクライアント(matetsu-work)にadmin権限を与えておく。

Cookbookなどの準備

knife-ec2でEC2インスタンスを操作できるようにACCESS KEYなどを設定する。
~/.chef/knife.rb に以下を設定する。

knife[:aws_access_key_id] = "hoge"
knife[:aws_secret_access_key] =  "fuga"

最終的にはRailsアプリを動かすところまでやりたいので、rails-quick-startを使うことにする。とりあえずはあるものをserverに上げてしまう。ただ、この rails-quick-start のリポジトリにあるのは、Ubuntuで動かすための設定なので、CentOSの場合は変更すべきところが何点かあるが、今は気にしない。

$ git clone git://github.com/opscode/rails-quick-start.git
$ knife cookbook upload -a -o ./cookbooks/
$ rake roles
$ knife data bag from file apps radiant.json

EC2インスタンス起動時に最初に実行するコマンド群を記述したbootstrapをubuntu用から、CentOS用に作り変える。

$ cp .chef/bootstrap/ubuntu10.04-gems-qs.erb .chef/bootstrap/centos6-chef.erb[]

内容は以下のような感じ。

bash -c '
<%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%>

if [ ! -f /usr/bin/chef-client ]; then
  rpm -Uvh http://rbel.frameos.org/rbel6
  yum install -y rubygem-chef ruby-devel libxml2-devel libxslt-devel wget --enablerepo=epel,rbel6
fi

mkdir -p /etc/chef

(
cat <<'EOP'
<%= validation_key %>
EOP
) > /tmp/validation.pem
awk NF /tmp/validation.pem > /etc/chef/validation.pem
rm /tmp/validation.pem

(
cat <<'EOP'
<%= config_content %>
EOP
) > /etc/chef/client.rb

(
cat <<'EOP'
<%= { "run_list" => @run_list }.to_json %>
EOP
) > /etc/chef/first-boot.json

<%= start_chef %>'

roleのbaseを今回必要なものだけに絞るためにコピーをする。

$ roles/base.rb roles/centos_base.rb

内容はこんな感じ。gitはgitパッケージのインストールで、build-essentialはgccなどの開発ツールパッケージのインストール。

name "centos_base"
description "Base role applied to all centos nodes."
run_list(
  "recipe[git]",
  "recipe[build-essential]"
)

ちなみに、レシピ build-essential の centos向けの設定を以下のように変えている。

when "centos","redhat","fedora"
  %w{gcc gcc-c++ make automake}.each do |pkg|
    package pkg do
      action :install
    end
  end
end

変更をserverに反映する。

$ knife cookbook upload -o ./cookbooks/ build-essential
$ rake roles
EC2インスタンスの起動から初期設定まで

準備したcookbookやroleを用いて、実際にEC2インスタンスの起動〜初期設定を行ってみる。これまた簡単。knife ec2コマンドで一発です。

$ knife ec2 server create -G [SECURITY_GROUP] -I [AMI_ID] -f [INSTANCE_KIND] -S [KEY_PAIR_NAME] -i [PRIVATE_KEY_FILE] -x [EC2_LOGIN_USER] -d [BOOTSTRAP_FILE] -r '[COMMA_SEPARATED_ROLES_OR_RECIPES]' --region [REGION_NAME] -Z [AZ_NAME]

これでAMIからEC2インスタンスを作成、bootstrapに記述された内容を実行、roleで指定されたレシピの実行が行われ、初期設定が完了した状態のノードが完成する。起動したインスタンスのIPなどは、server-webuiのnode一覧からも確認できますし、コマンド実行完了後に標準出力にも出力される。

こんな感じでコマンド一発で求める環境ができちゃうなんて、感動ですね。なんでもっと早く使っていなかったんだろう。

次は、railsアプリが動いている状態を作れるようにしたいと思います。