Apache mod_rewrite RewriteMap の internal function を追加するためのテンプレ
Apache モジュール界のスイスアーミーナイフこと mod_rewrite の中でも、最も何でもありな rewrite ができるのが、RewriteMap での prg タイプによる外部プログラム実行ですが、こいつは外部プログラムがひとつだけ常駐し、httpd と標準入出力を介してやりとりする、という形なので、並列処理させることができません。これは rewrite 処理するときにデータベースへ問い合わせるなど、I/O ブロッキングが発生するような処理をさせたいときには致命的なパフォーマンス劣化を引き起こすことになります。
これを解決するためには、Apache モジュールの中で望みの rewrite 処理をさせるようにすればいいのでは、と思い、RewriteMap にある int タイプに好きな internal function を追加できればいけるんじゃないないか、と考えたものの、mod_rewrite のリファレンス では、「you cannot create your own」とか書かれていて、追加できないっぽい。かと言って mod_rewrite.c に手を入れるのもやだなー、と思っていたところ、mod_icpquery のドキュメント を見つけた。これを見ると、好きな internal function を独立したモジュールの形で追加できそう、ってことでやってみたらできた。
以下が internal function を追加するためのモジュールテンプレ。rewrite_mapfunc_custom の中で、望みの処理を記述してあげるだけで OK。
#include "httpd.h"
#include "http_config.h"
#include "apr_optional.h"
typedef char *(rewrite_mapfunc_t)(request_rec *r, char *key);
APR_DECLARE_OPTIONAL_FN(void, ap_register_rewrite_mapfunc,
(char *name, rewrite_mapfunc_t *func));
static char *rewrite_mapfunc_custom(request_rec *req, char *key)
{
return value;
}
static int pre_config(apr_pool_t *pconf,
apr_pool_t *plog,
apr_pool_t *ptemp)
{
APR_OPTIONAL_FN_TYPE(ap_register_rewrite_mapfunc) *map_pfn_register;
map_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_rewrite_mapfunc);
if (map_pfn_register) {
map_pfn_register("custom", rewrite_mapfunc_custom);
}
return OK;
}
static void register_hooks(apr_pool_t *p)
{
ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA rewrite_mapfunc_custom_module = {
STANDARD20_MODULE_STUFF,
NULL,
NULL,
NULL,
NULL,
NULL,
register_hooks
};
追加した internal function を呼び出すための httpd.conf は以下のような感じ。
LoadModule rewrite_mapfunc_custom_module modules/mod_rewrite_mapfunc_custom.so
RewriteEngine On
ProxyPreserveHost On
RewriteMap custom int:custom
RewriteRule ^/(.*)$ http://${custom:%{HTTP_HOST}}/$1 [P,QSA]
この例では、Host ヘッダの内容を custom function に渡して、ホスト名を変換して proxy するけど、Host ヘッダはオリジナルのままで変換しない、といった処理を想定してます。
例の件はこんな感じで実現できそうだよ。>id:hiboma
2009/05/10 13:57:00 追記
github に Makefile 等も含めてコードアップしました。
http://github.com/mizzy/mod_rewrite_mapfunc_custom/tree/master
Updated on 2009/05/10 13:58
30days Album キャンペーンと Software Design 2009年4月号への寄稿
宣伝エントリです。
30days Album では 2009/3/10 から 2009/3/31 まで 卒業おめでとうキャンペーン やってます。フジフィルムモールでのプリント料金が 20% OFF になるクーポンをプレゼントしてます。クーポンは期間中何回でも利用できます。
また、通常はアルバム作成後30日経過しないとダウンロードできない、オリジナルサイズ画像のアーカイブダウンロードが、期間中はいつでもダウンロード可能です。このために MogileFS のストレージノードを2台ほど追加しました。
それから、Software Design 2009年4月号 の第2特集『~サーバエンジニアがプログラムを知る意味~ システム運用/管理に役立つ「開発力」 ~楽天,mixi,paperboy&co.の事例紹介!~』に寄稿しました。
第1章、第4章、第5章の一部、を担当してます。原稿料が入ったらダイソンの掃除機を買います。
Updated on 2009/03/21 07:15
CPAN モジュールの rpm 化ノウハウ
Wassr で ZIGOROu さん や hidek さん とやりとりした内容をまとめてみます。
CPAN モジュールの rpm パッケージ作成なんですが、自分はRPM::Specfile に付属している、cpanflute2 を基本的に使ってます。
cpan2rpm の方がメジャーだとは思うんですが、オリジナルのダウンロード用FTPサイトが接続できないのと、吐き出す SPEC ファイルが微妙な感じがするので、なんとなくイヤで使ってないんですが、それ以外はそんなに明確な理由もなく、cpanflute2 の方を使ってます。
ただ、cpanflute2 には以下の問題点があります。
- 依存関係を自動的に解決してくれない(これは cpan2rpm も同じ)
- モジュールの tar ball を自分で取得しないといけない(cpan2rpm はsearch.cpan.org から取得してくれる)
なので、cpanflute2_wrapper.pl といったラッパースクリプトを書いて使ってます。これを使うと、
$ cpanflute2_wrapper.pl --buildall Catalyst::Runtime
みたいに実行すると、Catalyt::Runtime とそれに依存するモジュールの srpm と rpm を「半自動」で全部作ってくれます。--buildall とかのオプションは、中で呼び出される cpanflute2 にそのまま渡されます。
「半自動」と言ってるのは、スクリプトがいろいろとイケてなくて、場合によっては途中でこけてるのを目視で確認して、依存関係を自分で解決しないといけない時があったりするからです。あと、エラー処理やエラーメッセージもイケてなくてわかりにくかったり、ということもあって、今まで公開してなかったんですが、Wassr の流れで gist にスクリプト貼り付けちゃったので、ここでまとめてみることにしました。
他にも注意点があって、まずは rpmbuild の問題。rpmbuild でパッケージを作る際に、use/require してるモジュールがすべて勝手に SPEC ファイルのRequires に含まれてしまう、という問題があります。eval しているモジュールは依存関係の対象とはならないが、以下のように複数行にまたがっていると、依存関係の対象になってしまう。
eval {
require 'Hoge';
}
そのせいで、Linux 上でビルドしてるのに、Requires に Win32::*** が含まれる、ということがあったりします。で、Requires に含まれないようにするためには、/usr/lib/rpm/perl.req を以下のように修正します。(cpanflute2 が Makefile.PL を見て Requires に加えてくれるので、rpmbuild で Requires の処理してる部分はコメントアウトしちゃう。)
-
/usr/lib/rpm/perl.req
| old |
new |
|
| 221 | 221 | |
|---|
| 222 | 222 | ($module =~ m/\.ph$/) && next; |
|---|
| 223 | 223 | |
|---|
| 224 | | $require{$module}=$version; |
|---|
| 225 | | $line{$module}=$_; |
|---|
| | 224 | #$require{$module}=$version; |
|---|
| | 225 | #$line{$module}=$_; |
|---|
| 226 | 226 | } |
|---|
| 227 | 227 | |
|---|
| 228 | 228 | } |
それから、cpanflute2自体に問題があって、以下のパッチをあてておく必要がある。
-
cpanflute2
| old |
new |
|
| 159 | 159 | my $yaml = Load($contents); |
|---|
| 160 | 160 | |
|---|
| 161 | 161 | while (my ($mod, $ver) = each %{$yaml->{build_requires}}) { |
|---|
| 162 | | push @build_requires, [ "perl($mod)", $ver ]; |
|---|
| | 162 | $mod = "perl($mod)" if $mod ne 'perl'; |
|---|
| | 163 | push @build_requires, [ "$mod", $ver ]; |
|---|
| 163 | 164 | } |
|---|
| 164 | 165 | while (my ($mod, $ver) = each %{$yaml->{requires}}) { |
|---|
| 165 | | push @requires, [ "perl($mod)", $ver ]; |
|---|
| | 166 | $mod = "perl($mod)" if $mod ne 'perl'; |
|---|
| | 167 | push @requires, [ "$mod", $ver ]; |
|---|
| 166 | 168 | } |
|---|
| 167 | 169 | } |
|---|
| 168 | 170 | |
| … | … | |
| 289 | 291 | my $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" %{__perl} Makefile.PL < /dev/null}; |
|---|
| 290 | 292 | my $make_install = qq{make pure_install PERL_INSTALL_ROOT=\$RPM_BUILD_ROOT}; |
|---|
| 291 | 293 | |
|---|
| 292 | | if ($use_module_build) { |
|---|
| 293 | | $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" %{__perl} Makefile.PL destdir=\$RPM_BUILD_ROOT $installdirs < /dev/null}; |
|---|
| 294 | | } |
|---|
| 295 | | else { |
|---|
| 296 | | $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" %{__perl} Makefile.PL $installdirs}; |
|---|
| 297 | | } |
|---|
| | 294 | $makefile_pl = qq{CFLAGS="\$RPM_OPT_FLAGS" %{__perl} Makefile.PL $installdirs}; |
|---|
| 298 | 295 | |
|---|
| 299 | 296 | $spec->build(<<EOB); |
|---|
| 300 | 297 | $makefile_pl |
前半の修正は、Makefile.PL の PREREQ_PM とか requires とかに perl が含まれていると、SPEC ファイルの Requires に perl(perl) とか入っちゃっておかしなことになるので、そうならないように修正。
後半の修正は、なんで修正したかあまり覚えてないんだけど、時々 RPM_BUILD_ROOT がおかしくなることがあって、それに対する修正だったと思う。
そういえば、まっさらなサーバを30分で本番投入できるようにする で stanaka さんが「CPANの依存関係を解析してrpm化する手製スクリプトで、CPANモジュールのrpm化が、ほぼ自動化されています」と書いてるんだけど、これって公開してくれないのかなー。
Puppet の競合 Chef のファーストインプレッション
Puppet 作者 Luke Kanies 氏のブログエントリ にて、Puppet の競合となる Chef というソフトウェアについて触れられていた。
ソフトウェアのポジション的にも、使われている用語的にも、かなり Puppet を意識している模様。開発言語が Ruby という点も Puppet と同じ。
Luke 氏としては、Puppet を散々使っていながらあまりコードに貢献することなしに、新しいプロジェクトを立ち上げるってどうなのよ、とか、競合が存在するのはいいことなんだけど、 そんなたくさん競合がある分野じゃないんだから、もっと色々話してくれてもいいのに、といった不満があるみたい。
また、名前が SEO 的にまずいよね、自分もそれで苦労した、といったことや、Puppet が外部 DSL なのに対し、Chef は内部 DSL なんだけどそれってどうなのよ、的なことも書いてますね。自分も外部 DSL の方が、制限があるけどわかりやすくていいんじゃないかとは思ってます。
で、"I’m not afraid of competition." と言っていて、Puppet の競合なんて笑わせるぜ、的なことを言ってる(実際にこういうニュアンスかはよくわからないけど)わけですが、やはり気にはなるので試してみました。
最初は CentOS 5.2 で環境作ろうとしてたんですが、あまりにも面倒で挫折したので、インストールガイド で対象としてる Ubuntu で試してみました。
インストール手順
今回はひとつの Ubuntu 8.10 VM 上で、サーバ/クライアント両方を兼ねる形でセットアップしました。基本的には インストールガイド にある通りなんですが、いくつか説明通りではうまくいかなかった点があるので、その点をここで補足しておきます。
「Install Ruby and Rubygems」では、libhttp-access2-ruby も合わせてインストールしておく必要があります。
$ sudo apt-get install ruby ruby1.8-dev rubygems build-essential libhttp-access2-ruby
また、「Bring up the Chef Server」にある、
$ sudo chef-solo -r http://wiki.opscode.com/download/attachments/1179839/chef-server-install-solo.tar.gz
ですが、これをそのまま実行しても、エラーが出て途中で止まってしまいました。この手順では、chef-solo というスタンドアローンな chef クライアントを使って、chef に必要となるパッケージをインストールし、初期化等を行っているのですが、runit パッケージと couchdb パッケージのインストール部分でこけてました。なので、まずは一度上記コマンドを実行してエラーが出た後に、この2つのパッケージを手動でインストールしておきます。
$ sudo apt-get install runit couchdb
それから、http://wiki.opscode.com/download/attachments/1179839/chef-server-install-solo.tar.gz の展開先にある二つのファイルを修正し、runit と couchdb をインストールしている部分をコメントアウトします。
/tmp/chef-solo/cookbooks/runit/recipes/default.rb
# package "runit" do
# action :install
# notifies :run, resources(:execute => "start-runsvdir")
# end
/tmp/chef-solo/cookbooks/chef/recipes/server.rb
#package "couchdb"
修正後、ファイルを tar.gz で固めます。
$ cd /tmp
$ tar cvf chef-solo.tar chef-solo
$ gzip chef-solo.tar
その後この tar.gz ファイルを指定して、chef-solo を走らせます。
$ sudo chef-solo -r /tmp/chef-solo.tar.gz
これでインストールは完了し、ウェブブラウザで 4000 番ポートにアクセスすることができるようになります。
Chef Repository の作成
インストールの次に行うのは、Chef Repository の作成 です。Chef Repository とは、Chef でサーバ管理をするために必要な Cookbooks(Puppet でいうマニフェス)や設定ファイル等を管理するためのリポジトリです。
ここも基本的には Wiki の手順書 の通りなので、その通りに実行すればいいだけなんですが、いくつか補足を。
リポジトリの雛形を作成するところは、git clone してますので、当然 git が必要となります。なので、あらかじめインストールしておきます。
$ sudo apt-get install git git-core
rake new_cookbook してる手順ですが、これは cookbook の雛形となるファイルを生成してくれます。
$ rake new_cookbook COOKBOOK=apache
(in /home/mizzy/chef-repo)
** Creating cookbook apache
を実行すると、以下のようなディレクトリ/ファイルが生成されます。
$ ls -FR cookbooks/apache/
cookbooks/apache/:
attributes/ definitions/ files/ libraries/ recipes/ templates/
cookbooks/apache/attributes:
cookbooks/apache/definitions:
cookbooks/apache/files:
default/
cookbooks/apache/files/default:
cookbooks/apache/libraries:
cookbooks/apache/recipes:
default.rb
cookbooks/apache/templates:
default/
cookbooks/apache/templates/default:
例えば、cookbooks/apache/recipes/default.rb の内容は以下のようになってます。
#
# Cookbook Name:: apache
# Recipe:: default
#
# Copyright 2009, Example Com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
rake install を実行すると、作成/編集した cookbooks を /var/chef/cookbooks の下に配置してくれたり、cofig/server.rb, client.rb, solo.rb を /etc/chef の下に配置してくれたりします。なので、雛形を git clone したままだと、勝手に設定が書き換えられるので注意が必要です。
実行時には、rake update (upstream リポジトリからの pull) と rake test も合わせて実行してくれ、sudo も自動的に実行してくれます。実行した結果は以下のようになります。
$ rake install
(in /home/mizzy/chef-repo)
** Updating your repository
Already up-to-date.
** Testing your cookbooks for syntax errors
Testing recipe /home/mizzy/chef-repo/cookbooks/apache/recipes/default.rb: Syntax OK
** Installing your cookbooks
* Creating Directories
* Installing new Cookbooks
sending incremental file list
README
54 100% 0.00kB/s 0:00:00 (xfer#1, to-check=10/12)
apache/
apache/attributes/
apache/definitions/
apache/files/
apache/files/default/
apache/libraries/
apache/recipes/
apache/recipes/default.rb
628 100% 18.04kB/s 0:00:00 (xfer#2, to-check=1/12)
apache/templates/
apache/templates/default/
sent 1063 bytes received 86 bytes 2298.00 bytes/sec
total size is 682 speedup is 0.59
* Installing new Site Cookbooks
sending incremental file list
README
96 100% 0.00kB/s 0:00:00 (xfer#1, to-check=0/2)
sent 178 bytes received 31 bytes 418.00 bytes/sec
total size is 96 speedup is 0.46
* Installing new Chef Server Config
* Installing new Chef Client Config
Chef クライアント のサーバへの登録
Chef クライアントを動作させるためには、まずは Chef サーバへのノード登録が必要となります。手順は http://wiki.opscode.com/display/chef/Nodes#Nodes-RegistrationviatheWebUI の通りで、サーバの 4000 番ポートにブラウザでアクセスし、
- 右上の「Login」をクリックして、OpenID でログインする
- 上部の「Registration」をクリックする
- 対象となるノードの「Validation」をクリックする
で完了です。
ここで気になるのは、OpenID でログインするので、有効な OpenID アカウントさえ持っていれば、とりあえずログインできちゃうんですよね。なので、デフォルトで誰でもログインできちゃうような状態なんで、これはまずいだろ、と。
それから、Nodes have OpenIDs のところを読むと、内部的に Chef サーバがノードを認証するための仕組みとしても OpenID を使っているみたいなんだけど、そのメリットとか意図がさっぱりわからない。
cookbook を 作成して Chef クライアントに適用する
サンプル cookbook の作成の仕方は、Quick Start を参照すれば OK です。ここでは特に補足しません。
わかりにくいのが、作成した cookbook を特定のノードに適用する方法。Puppet だと以下のようなやつ。
node 'client.example.org' {
include apache
}
これには ウェブ UI を利用する方法 と chef-client コマンドを利用する方法 があります。
ウェブ UI の方では、上部メニューの「Nodes」をクリックし、該当するノードを選択。するとノードに関する詳細情報が表示されるので、適当なところをクリック。すると、テキストエリアに以下のように JSON 形式で内容が表示されて編集可能に。
{
"name": "ubuntu",
"_rev": "4279229607",
"attributes": {
"kernel": {
"machine": "i686",
"name": "Linux",
"os": "GNU\/Linux",
"version": "#1 SMP Thu Nov 20 21:57:00 UTC 2008",
"release": "2.6.27-9-generic"
},
... 中略 ...
"uptime": "4 hours 56 minutes 03 seconds",
"platform": "ubuntu",
"block_device": {
"ram13": {
"size": "131072",
"removable": "0"
},
... 中略 ...
"ram9": {
"size": "131072",
"removable": "0"
}
},
"uptime_seconds": 17763
},
"json_class": "Chef::Node",
"recipes": [
],
"chef_type": "node"
}
この下のほうにある「recipes」ところに、適用したい cookbook を追加して、save すれば OK らしいのですが、うちの環境ではうまく save ができませんでした。
chef-client コマンドを使う方法では、
$ sudo chef-client -j node.json
といった形で、JSON ファイルをロードできるようなのですが、この方法でもうまくいかず、結局試すことができませんでした。また後ほど環境作り直して再チャレンジの予定。
まとめ
ここまでざっと使ってみた感想をまとめてみます。
- セットアップがめんどくさい。Puppet は Ruby と Facter があれば OK なのに対し、Chef はいろいろなものが必要。特に CouchDB は、CentOS 5 用のパッケージがなく、パッケージ作るのも大変そうだったので、今回は諦めた。(誰かパッケージの在り処を知っていったら教えてください。)
- OpenID をつかってる意味がよくわからない。誰か教えて。
- ウェブ UI は必要ない。すべてコマンドラインで完結してくれるほうがうれしい。
- Chef Repository の考え方ははよさげ。
- Rakefile を覗いてみると、git と subversion に対応してるみたい。
- rake コマンド で特定のタスクを実行できるのもいい。
- git に対応してるのは、外部の人たちと cookbooks を共有するのに良さげ。ただ、システム管理者に git 使わせるのは厳しいかも。
- 内部 DSL よりも外部 DSL の方が、制限がある分逆に誰が書いても同じような記述になるし、分かりやすいと思うので、特にメンテナンスや他メンバーとの共有を考えると、外部 DSL である Puppet の方が個人的には好き。
今のところ、まだ Puppet からの乗換えを検討しようとは思わないけど、今後ウォッチしていこうと思います。
Updated on 2009/05/05 14:45
本当に15分で Remedie を始めるための資料
overlast さんのこれから15分で Remedie を始めるための資料 に触発されて書いてみました。こっちは CPAN モジュールをインストールする時間も入れて15分。ただし限定された環境のみ。
Remedie 用に CPAN モジュールの RPM パッケージ作ったので、これプラス Puppet を利用します。ただし、RPM パッケージを CentOS 5 x86_64 でビルドしてるので、この環境限定。SRPM はあるので、他の環境の方はこいつをビルドして使ってください。
まずは Puppet をインストールするための yum リポジトリ設定。以下の内容で /etc/yum.repos.d/dlutter.repo を作成。
[dlutter]
name=lutter
baseurl=http://people.redhat.com/dlutter/yum/rhel/$releasever/$basearch/
enabled=1
gpgcheck=0
Puppet のインストール。
# yum -y install puppet-server
Puppet で署名するのはだるいので、以下の内容で /etc/puppet/autosign.conf を作成。
*
/etc/puppet/manifests ディレクトリを作成。
# mkdir /etc/puppet/manifests
以下の内容の /etc/puppet/manifests/site.pp を作成。
node default {
yumrepo {
'mizzy':
baseurl => 'http://svn.mizzy.org/public/yum/RPMS/centos/$releasever/$basearch/',
enabled => 1,
gpgcheck => 0;
'dag':
baseurl => 'http://ftp.riken.jp/Linux/dag/redhat/el$releasever/en/$basearch/dag/',
enabled => 1,
gpgcheck => 0;
'updates':
exclude => 'perl';
'extras':
exclude => 'perl';
}
Package {
require => [ Yumrepo['mizzy'], Yumrepo['dag'], Yumrepo['updates'], Yumrepo[extras] ],
}
package {
'git':
ensure => present;
'perl':
ensure => '5.8.8-15.1';
'perl-Moose':
ensure => present;
'perl-Class-C3':
ensure => present;
'perl-Sub-Name':
ensure => present;
'perl-Devel-GlobalDestruction':
ensure => present;
'perl-Rose-DB':
ensure => present;
'perl-Rose-DB-Object':
ensure => present;
'perl-DateTime-TimeZone':
ensure => '0.8301-8';
'perl-MooseX-Types-Path-Class':
ensure => present;
'perl-DBD-SQLite':
ensure => present;
'perl-FindBin-libs':
ensure => present;
'perl-HTTP-Engine':
ensure => present;
'perl-MIME-Types':
ensure => present;
'perl-Path-Class-URI':
ensure => present;
'perl-String-CamelCase':
ensure => present;
'perl-Log-Dispatch':
ensure => present;
'perl-JSON-XS':
ensure => present;
'perl-MooseX-Getopt':
ensure => present;
'perl-MooseX-ConfigFromFile':
ensure => present;
'perl-File-Find-Rule':
ensure => present;
'perl-UNIVERSAL-require':
ensure => present;
'perl-Class-Accessor':
ensure => present;
'perl-DateTime-Format-Strptime':
ensure => present;
'perl-Feed-Find':
ensure => present;
'perl-Class-ErrorHandler':
ensure => present;
'perl-XML-Atom':
ensure => present;
'perl-XML-XPath':
ensure => present;
'perl-XML-Feed':
ensure => present;
'perl-Template-Toolkit':
ensure => present;
'perl-DateTime-Format-ISO8601':
ensure => present;
'perl-MooseX-ClassAttribute':
ensure => present;
'perl-XML-OPML-LibXML':
ensure => present;
'perl-File-Find-Rule-Filesys-Virtual':
ensure => present;
'perl-HTTP-Response-Encoding':
ensure => present;
'perl-HTML-ResolveLink':
ensure => present;
'perl-HTML-Selector-XPath':
ensure => present;
'perl-HTML-TreeBuilder-XPath':
ensure => present;
'perl-YAML':
ensure => present;
'perl-YAML-Syck':
ensure => present;
'perl-HTML-Scrubber':
ensure => present;
'perl-Image-Info':
ensure => present;
'perl-Text-Tags':
ensure => present;
'perl-XML-RSS-LibXML':
ensure => present;
'perl-Web-Scraper':
ensure => present;
}
}
puppetmasterd を起動。
# puppetmasterd --verbose --no-daemonize
puppetd を起動して、マニフェストを適用。注意点としては、localhost とかではなく、きちんと FQDN で指定すること。(puppetmasterd 初回起動時に自動作成される証明書中の CN と --server で指定するサーバ名が一致してないと怒られる。)
# puppetd --server host.example.org --verbose --no-daemonize
このままログを見ながらしばらく待つ。完了したら Remedie を github.com から取得して起動。
# git clone git://github.com/miyagawa/remedie.git
# cd remedie
# perl -Ilib -MRemedie::DB::Schema -e 'Remedie::DB::Schema->install'
# ./bin/remedie-server.pl
自分でやったら10分ぐらいで終わった。
Updated on 2009/01/13 14:05
OSS だけでスケーラブルなストレージを安価に構築する方法 #5
ずいぶん間があいちゃいましたが、OSS だけでスケーラブルなストレージを安価に構築する方法 #4 のつづき。今回は DM-MP により束ねられた仮想的なブロックデバイス(/dev/mapper/mpath0 と /dev/mapper/mpath1)を、更に CLVM でひとつの論理ボリュームにし、GFS2 でフォーマットした後、実際にマウントしてみます。今回が最終回です。
CLVM のインストールと設定
client0, client1 双方でインストールと設定。
$ sudo yum -y install lvm2-cluster
/etc/lvm/lvm.conf を編集し、locking_type を 3 に設定。
locking_type = 3
clvmd を起動。
$ sudo /etc/init.d/clvmd start
物理ボリューム/ボリュームグループ/論理ボリュームの作成
通常の LVM と同様に、物理ボリューム/ボリュームグループ/論理ボリュームを作成。これは client0 上だけで行う。通常の LVM と異なるのは、vgcreate で --clustered y を指定すること。
$ sudo /usr/sbin/pvcreate /dev/mapper/mpath0
$ sudo /usr/sbin/pvcreate /dev/mapper/mpath1
$ sudo /usr/sbin/vgcreate --clustered y VG0 /dev/mapper/mpath0 /dev/mapper/mpath1
$ sudo /usr/sbin/lvcreate --extent=510 --name=LV0 VG0
pvdisplay, vgdisplay, lvdisplay で確認。
# pvdisplay
--- Physical volume ---
PV Name /dev/dm-0
VG Name VG0
PV Size 1023.90 MB / not usable 3.90 MB
Allocatable yes (but full)
PE Size (KByte) 4096
Total PE 255
Free PE 0
Allocated PE 255
PV UUID 8Whtgb-7jrP-4M24-AMmB-aqA3-VQ8G-iSvijF
--- Physical volume ---
PV Name /dev/dm-1
VG Name VG0
PV Size 1023.90 MB / not usable 3.90 MB
Allocatable yes (but full)
PE Size (KByte) 4096
Total PE 255
Free PE 0
Allocated PE 255
PV UUID RC8J4S-hCRI-IlmJ-DqKB-Lk06-6Pza-nke5f8
# vgdisplay
--- Volume group ---
VG Name VG0
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 2
VG Access read/write
VG Status resizable
Clustered yes
Shared no
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 2
Act PV 2
VG Size 1.99 GB
PE Size 4.00 MB
Total PE 510
Alloc PE / Size 510 / 1.99 GB
Free PE / Size 0 / 0
VG UUID XPwKeu-5lDP-9eCv-gUoC-HIB0-ItMV-4bxRHN
sudo /usr/sbin/lvdisplay
--- Logical volume ---
LV Name /dev/VG0/LV0
VG Name VG0
LV UUID PYScA4-OeAf-Dndj-5hMW-4a0x-Yfaj-6zIYpE
LV Write Access read/write
LV Status available
# open 0
LV Size 1.99 GB
Current LE 510
Segments 2
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 253:2
client1 でも lvdisplay で論理ボリュームが見えるかを確認。
sudo /usr/sbin/lvdisplay
--- Logical volume ---
LV Name /dev/VG0/LV0
VG Name VG0
LV UUID PYScA4-OeAf-Dndj-5hMW-4a0x-Yfaj-6zIYpE
LV Write Access read/write
LV Status available
# open 0
LV Size 1.99 GB
Current LE 510
Segments 2
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 253:2
GFS2でフォーマットしてマウント
client0, client1 両方に gfs2-utils パッケージをインストール。
$ sudo yum -y install gfs2-utils
client0 上だけで、mkfs2.gfs2 を実行してフォーマットする。
$ sudo /sbin/mkfs.gfs2 -p lock_dlm -t client:gfs2 -j 4 /dev/VG0/LV0
This will destroy any data on /dev/VG0/LV0.
Are you sure you want to proceed? [y/n] y
Device: /dev/VG0/LV0
Blocksize: 4096
Device Size 1.99 GB (522240 blocks)
Filesystem Size: 1.99 GB (522240 blocks)
Journals: 4
Resource Groups: 8
Locking Protocol: "lock_dlm"
Lock Table: "client:gfs2"
client0, client1 両方でマウント。
$ sudo mount /dev/VG0/LV0 /mnt
client0 上でファイルをつくると、client1 でも見えることを確認。
client0$ sudo touch /mnt/ieiri
client1$ ls /mnt
ieiri
これで完了。現在の状態を図にすると、以下のような感じで、4台のサーバに分散されたブロックデバイスがひとつの論理ボリュームとして見え、更に複数のマシンから同時にマウントできている。
最後に
本当はここから更に、ダイナミックにストレージサーバを追加して容量を拡張する手順なんかも書きたいところなんですが、#0 でも書いたような、以下の懸念点があるため、今のところ実用で使おうとは考えていません。
- 協調動作するコンポーネントが多くて、トラブルが起こりやすそう。
- 実際に各コンポーネントを起動/停止する順を間違えると、ハングアップしたりする。
- 低レイヤーなだけに、トラブルが起きたときの対応がとても難しそう。
- 安定性。
- パフォーマンス。
- ストレージとなるサーバを追加して容量を増やした場合のオーバーヘッドの増加具合。
というわけで、これ以上踏む込むことは今のところやめておきます。まずはこんな技術があるんだ、ということを知って、動くところまで試しただけでも、自分にとっては十分収穫があったな、と。
関連エントリ
インフラエンジニア討論会2008で登壇しました
パソナテック10周年記念 PTカンファレンスVol.6 インフラエンジニア討論会2008 ~インフラエンジニア進化論~ でパネリストとして登壇してきました。
ドクターペッパーは出ませんでした。(と lopnor さん から指摘されて、そういえば、と思った。)
思ったこととかは後で書く。(と言っておいて書かないと思う、たぶん。)
ドクターペッパーランキング更新
lopnor さん からランキング漏れを指摘されたので、naoya さんの分も合わせて更新。
| 1 | naoya さん | 240本
|
| 2 | ひろせさん | 25本
|
| 3 | 弊社代表取締役社長 | 10本
|
| 4 | Xen Summit 2008 Tokyo | 3本(フリードリンクとして提供されたものからいただいた数)
|
| 5 | lopnor さん | 2本(CodeReposCon #1 で、株式会社ソフリットの経費から)
|
| 6 | overlastさん | 1本(たしか SoozyCon かな?いまはなきアジトでいただいた)
|
| 7 | id:hiboma | 0.5本(YAPC::Asia Tokyo 2008 でプレゼン時のドリンクとして)
|
| 7 | みるくぜりーさん | 0.5本(同じく YAPC::Asia Tokyo 2008 で、id:hiboma とともに持ってきてくれた)
|
| 9 | 弊社サーバエンジニアのまーくん | 2本(ただしドクターペッパーではなくルートビア。あれ、ドクペももらったことあったっけ?)
|
| 10 | Yappo さん | 1本(ただしドクターペッパーではなくピンクペッパー)
|
まだ漏れがあるような気がするので、お気づきの方はご連絡ください。
naoya さんからもお祝いを頂きました
はてな CTO の naoya さん からもお祝いをいただきました。しかも10箱(240缶)も。naoya さん、ありがとうございます!
240缶のドクペを前に満足げな様子。
なんとなくポーズをとってみる。
今回も pplog さん が撮影だけじゃなく、ネタ画像つくってくれました。いつもありがとうございます!
Updated on 2008/11/26 01:22
ひろせさんからお祝いを頂きました&ドクターペッパーランキング
ペパボの上場承認のお祝い、ということで、ひろせさん よりドクターペッパーを頂きました。
朝会社に来てみると、やけにでかい Amazon の段ボール箱が机の前にあり、空けてみたところこんな物体が入ってました。
大きさを比較するために自分で持ってみたところ。
ラッピングを外してみると。
箱の中身。
というわけで、僕へのドクターペッパープレゼント数ランキングでは、今までトップであった弊社代表取締役社長家入(10本)を軽々と突破し、ひろせさんが25本でダントツの一位となりました。(今回の24本+KLab勉強会での1本。)
ちなみに、現在のドクターペッパープレゼントランキングは下記のとおり。
| 1 | ひろせさん | 25本
|
| 2 | 弊社代表取締役社長 | 10本
|
| 3 | Xen Summit 2008 Tokyo | 3本(フリードリンクとして提供されたものからいただいた数)
|
| 4 | overlastさん | 1本(たしか SoozyCon かな?いまはなきアジトでいただいた)
|
| 5 | id:hiboma | 0.5本(YAPC::Asia Tokyo 2008 でプレゼン時のドリンクとして)
|
| 5 | みるくぜりーさん | 0.5本(同じく YAPC::Asia Tokyo 2008 で、id:hiboma とともに持ってきてくれた)
|
| 7 | 弊社サーバエンジニアのまーくん | 2本(ただしドクターペッパーではなくルートビア。あれ、ドクペももらったことあったっけ?)
|
| 8 | Yappo さん | 1本(ただしドクターペッパーではなくピンクペッパー)
|
「あれ、俺プレゼントしたのにランキングに載ってないよ?」という方がいらっしゃいましたら、ご連絡ください。
また、写真撮影してくれた pplog さんが、今回のひろせさんからのプレゼントを記念して、素敵な画像を作成してくれました。
ちなみに、中段の「飲みきれないドクペのために 今、何ができるか」は Yappo さんのアイデア。
Updated on 2008/11/22 14:43