Browse Month: February 2010

OSC 2010 Tokyo/Spring に行ってきた

OSC 2010 Tokyo/Spring に、次の講演だけを目当てに行ってきました。参加目的は、「そろそろインフラを BSD に切替えてもいいかもと考えていて、そのための情報収集のためと、そろそろ Linux に疲れてきたかもとふと思ってしまったからです」。

オープンソースカンファレンス2010 Tokyo/Spring – イベント案内 | 2010-02-27 (土): LinuxからBSDへ – reallyenglishのインフラとネットワーク

以下、講演内容のメモです。

  • reallyenglish のサービス紹介、おもに BtoB 向けの英語学習サービスを提供
  • データセンターは、日本と香港に二つ借りている
  • サーバ台数 50 台、30 台の L2/L3 スイッチ、10 の IPsec-VPN くらいの規模、L2/L3 レベルですべて冗長化されている
  • OS は、ルータにはすべて OpenBSD、サーバには FreeBSD 7.x を使っている
  • nagios の監視レベルで、100 個のホスト死活監視、400 のサービス監視
  • サーバは、PXE 経由でインストールしている、VLAN を設定してあって、管理コンソールは HP の iLO2 を使っている(つまり HP 製のサーバだということ)
  • 香港のデータセンターは、有料で OS のセットアップまで行ってくれるが、自分たちでなるべくやっている
  • smokeping を使って、ネットワークのレイテンシーをみている
  • ローカルネットワークにパッケージのビルドサーバ、パッケージリポジトリをもっていて、port ツリーを一部カスタマイズしたりしている
  • freebsd-update もローカルのサーバ経由で行っている
  • Marcuscom Tinderbox を使って、パッケージのビルドなどを管理している(かなり便利とのこと)
  • Jail を多用している、雑用系のサーバには 10 くらいの Jail が起動していた、他の仮想化技術と違って仮想化によるオーバーヘッドがほとんどないとのこと、Jail から ZFS も扱えるとのこと
  • Jail の設定はかなりめんどうだったが、ezjail – Jail administration framework というツールでかなり簡単に設定できるようになった
  • LDAP を使っている
  • ZFS を本番環境で使っている
  • Version 13 が RELENG_8 に入っている
  • ほぼ本番環境でも使えるクオリティに仕上っている
  • ZFS の運用では、パーティションやスライスを切らないのが普通とのこと
  • ルートパーティションは、UFS2 にして USB メモリに入れてブートしている
  • ハードディスクは、すべて ZFS に割り当てている
  • SSD 上で ZFS L2ARC : Brendan Gregg にある L2ARC(read), ZIL(write) という仕組みを使うと SSD をキャッシュとして使うことができる
  • Dedup という実装が進んでいる(詳細は調べてみたが分からず)
  • HAST – FreeBSD Wiki という Linux でいうところの DRBD のようなものが開発が進められている
  • HAST + ZFS + iSCSI という夢の組合せができるかもしれないとのこと
  • nagios version 3.0.6 を使って監視しているが、Template Engine を使ってテンプレートで生成している(mixi と同じ方式だと理解しました)
  • reallyenglish では、現在開発エンジニアとインフラエンジニアを絶賛募集中とのこと

その他、貴重な本番の nagios の監視画面や smokeping の画面やネットワーク構成図も見ることができました。

BSD 系のインフラの話は、あまり話を聞く機会がなかったのでかなり参考になりました。

まずは、自分個人の FreeBSD サーバで ZFS や Jail を使ってみたいと思います。

hbstudy #8 に行ってきた

会社のインフラをおもに担当している同僚を誘って、hbstudy #8 http://atnd.org/events/3092 に行ってきました。今回は、kazuho さん、mizzy さん、という豪華な講演だったので参加人数も 120 名くらいと、とても大人数で驚きました。

今回の講演のスライドは、おそらく公開されるのではないかと思いますが、今回の hbstudy #8 ではツール以前にインフラエンジニアとしてどんなところを目指すか、どのような姿勢でインフラを管理するかといった精神論的な考えというか思想が、とても勉強になりました。

まず、インフラにかかわらず、何言にも共通する思想は、

楽をすること

につきると思います。楽をするための苦労は惜しまずに、楽をするためのツールを自作したり、オープンソースのツールを使ったり、楽をするにはいろいろな方法があります。まず考えることは、楽をするために何をすることなのかなぁと思います。楽をするというと、なんだか怠け者のような印象をもたれることもあると思いますが、楽をするために新しい手法を取り入れていることは大事だと思います。

その次は、インフラエンジニアとしての大切だったと思った思想は、次のとおりです。

  • インフラに導入するツールは、なるべくシンプルなものにする
  • 自作ツールの場合、なるべく同じ技術を使ったツールで統一する
  • ある程度、基本知識がある人なら、自分が管理しているインフラを管理することができるようにする

まず、前提となる知識を習得するのが困難だったり、使い方は複雑なツールは使わないということです。やはり、とても便利なツールでも複雑なツールを導入してしまうと、自分はいいのですが他の人に引き継ぐことになったときなどに説明する手間がかなりかかると思います。また、決してオープンソースのツールだけに選択肢をおかずに機会損失や管理コストなどを総合的に比較して商用ツールも検討するといったこともあるかと必要な場面があると思います。

その次ですが、kazuho さんが基本的にとてもシンプルな自作ツールでインフラを管理しているという話の中で登場してきたツールはほとんど perl で書かれていました。自作ツールでも、シェルスクリプトだったり、C++ だったり、ruby だったり、と実装している技術はバラバラだと、すべての知識が必要になってきます。こうした自作ツールは、perl など1つの実装にまとめることで perl さえ分かれば自作ツールのメンテナンスや改良もできます。最近の Linux の場合、Linux Standard Base (LSB) | The Linux Foundation という規格があるこの規格によると perl や python は最初からインストールされています。残念ながら、ruby や PHP は入っていないので、ruby や PHP で作るときにはパッケージのインストールが必要になります。最近のサーバは、とても早いのでわざわざ C++ などで作成するよりも LL で十分なことも多くなってきていると思います。個人的には、ruby を愛用していますが、python にしたほうが標準インストールされているという観点でみるとありかなと思っています。

最後に、自作ツールでもあまりオレオレ仕様的なツールは作らずに、他のツールの思想や考えたにのとった自作ツール、定番といえるオープンソース、だけをできるだけ組み合わせて、かつシンプルに形でインフラを管理しておくということです。シンプルにしておけば、日常業務の中でも毎日やることが単純になったり、業務レベルで他の担当者と共有することも比較的容易なのでないかと思います。

今回の hbstudy では、このような考え方というか思想が大事なのではないかと感じました。僕が管理しているインフラも、この思想に基づいていけるように日々改善を重ねいたいと思いました。

monit 5.1

愛用している monit の最新版バージョン 5.1 がリリースされました。

このバージョンでは、CHANGELOG をみて分かるようにバグフィックスの他にいくか機能拡張がされています。

その中で、個人的に大きいのは httpd のサービスチェックのときに HOST ヘッダーを指定できるようになったことです。例えば、次のようなに HOST ヘッダーを指定して httpd サービスの監視をすることができます。

if failed host localhost port 80 protocol http and request ‘/ testing’ hostheader ‘example.com’ with timeout 20 seconds for 2 cycles then restart

hostheader という識別子で手軽に指定することができます。

さっそく試そうと RPM を作ってみることにしました。monit には、RPM を作成するための SPEC ファイルが同梱されているので、次のコマンドでさくっと RPM を作成することができます。

$ rpmbuild -ta monit-5.1.tar.gz

しかし、いくつか不用なファイルの設定が原因で RPM をビルドできないので SPEC ファイルを、次のように修正しました。この修正は、本家に連絡してすでにコミットしてもらってあります。

— monit.spec-org      2010-02-18 10:48:56.000000000 +0900
+++ monit.spec  2010-02-18 10:49:09.000000000 +0900
@@ -51,7 +51,7 @@

%files
%defattr(-,root,root)
-%doc CHANGES.txt CONTRIBUTORS COPYING FAQ.txt LICENSE README README.SSL
+%doc CHANGES.txt COPYING LICENSE README README.SSL
%config /etc/monitrc
%config /etc/init.d/%{name}
%{_bindir}/%{name}

RPM を作成して、さっそく monit をアップグレードして、次のような設定で試してみます。

check process httpd with pidfile /var/run/httpd/httpd.pid
start program = “/etc/init.d/httpd start”
stop program = “/etc/init.d/httpd stop”
if failed port 80 protocol http
and request “/” hostheader “example.com”
with timeout 2 seconds for 2 cycles
then restart

動作確認するために、sudo monit -Iv してみると、hostheader の syntax エラーになります。ソースコードをみてみると、不具合っぽいのでさっそく連絡してみると、作者の Martin さんから、次のようなパッチが送られてきました。

Index: p.y
===================================================================
— p.y (revision 128)
+++ p.y (working copy)
@@ -1077,7 +1077,7 @@
;

hostheader      : /* EMPTY */
–                | hostheader STRING {
+                | HOSTHEADER STRING {
portset.request_hostheader = $2;
}
;

monit バージョン 5.1 の不具合のようです。さっそく、上のパッチとあわせて本家に掲載されている FTP のパッチをあわせて RPM を作成しました。パッチをあてて作成した RPM は、ここに置いておきます。

パッチをあてた monit でさっそく動作確認してみると、hostheader 識別子をちゃんと認識して問題なく動作しました。

これからの修正は、CHANGELOG をみてみると、おそらく近いうちに monit バージョン 5.1.1 でリリースされるのでないかと思います。hostheader のバグレポートを報告したので、CHANGELOG になんと僕の名前が掲載されています。こんな小さな報告でも CHANGELOG に追加されるんですね。

Fix the HTTP protocol test’s hostheader option which was added in 5.1.
Thanks to Naoya Nakazawa for report.

httpd のサービスチェックで HOST ヘッダーを指定できると、かなり便利になるので、monit を愛用している人はバージョン 5.1.1 を待つか、パッチをあてたバージョンにアップグレードするといいと思います。

monit は、なんといっても設定ファイルが書きやすい、メーリングリストで質問やバグレポートをすると翌日にはすぐに返信があるのでかなり活発なプロジェクトなので、使っていない人はぜひ使ってみるといいと思います。

# 2010.02.25: 追記

monit バージョン 5.1.1 がリリースされました。バグフィックスのみのリリースです。

Release checksums
=================
md5:    4bbd3845ae1cbab13ec211824e0486dc
sha256: bf789e0660410e8c63f4b3dc2eeab9889347e6494a6dc1c0e764343cae0dc1ba

Release information:
====================
Bug fixes
* Fixed FTP protocol test. Thanks to Axel Reinhold for report.
* Fixed the hostheader option in the HTTP protocol test, which was
added in Monit 5.1. Thanks to Naoya Nakazawa for report.
* Removed an erroneous warning message about missing system service check.
* Improved manual page formatting. Thanks to Stefan Alfredsson for report.

僕の名前があって、ちょっとうれしいです(笑)。

iptstate

iptstate というコマンドがあることを始めて知りました。

iptstate は、netfilter の接続をトラックキングしているテーブルの情報を top のように表示してくれるコマンドです。

CentOS の場合は、すでに iptstate バージョン 1.4.1 が提供されていて、普通にインストールすると iptstate パッケージがインストールされています。

さっそく、試してみます。iptstate は、netfilter つまり iptables の接続トラックキングテーブルの情報を表示してくれるので、iptables が動作している必要があります。

$ sudo /usr/sbin/iptstate

IPTables – State Top
Version: 1.4          Sort: SrcIP           s to change sorting
Source                  Destination             Proto   State        TTL
127.0.0.1:33005         127.0.0.1:8020          tcp     ESTABLISHED  119:59:58
127.0.0.1:52326         127.0.0.1:8021          tcp     ESTABLISHED  119:59:56
192.168.161.1:60730     192.168.161.125:22      tcp     ESTABLISHED  119:59:12
192.168.161.1:54619     192.168.161.125:22      tcp     ESTABLISHED  119:59:55
192.168.161.1:17500     192.168.161.255:17500   udp                    0:00:09

な感じで、接続元の IP アドレス、経路情報、プロトコル、状態、TTL、を表示してくれます。

もちろん、top のように並び替えもできます。iptstate では、次の並び替えのキーが定義されています。

d   カラムのサイズを動的に変更して、古いデフォルトのサイズを使用する

f   loopback でフィルタリングする

l   IPアドレスの中で DNS を探している順にする

m   ホスト名を切り取った形でフィルタリングする

n   DNS に関連した表示にする

q   終了する

r   逆順に並び替える

space   表示をすぐに更新する

昔から存在するコマンドですが、どこから接続があるので、どのポートに接続しているのか、などがすぐに分かるので、とても便利なコマンドです。

Puppet Dashboard を試してみた

Puppet Dashboard  がリリースされたので、さっそく試してみました。

Puppet Dashboard とは、ノード管理とレポートツールを提供してくれる Puppet のウェブアプリケーションです。ノード情報はYAML 形式でエクスポートすることができて、ダッシュボードから外部ノードツールとして使うこともできるようです。

まず、最初にPuppet Dashboard を動作させるために、次のものが必要です。

  • ruby >= 1.8.1
  • rake >= 0.8.4
  • mysql
  • puppet
  • rubygems >= 1.3.2
  • rails >= 2.3.4

さっそくインストールしてみましょう。

$ git clone git://github.com/reductivelabs/puppet-dashboard.git

$ cd puppet-dashboard

$ rake install

rake install すると、dashboard_development というデータベースが作成されてテーブルがいくつか作成されるので、localhost に mysql が起動している必要があります。

Rails アプリケーションなので、さっそく起動します。

$ ./script/server

http://localhost:3000 にアクセスすると、次のような Puppet Dashboard トップ画面が表示されます。

ノードの例として、「sample node」が定義されています。さっそく、ユーザ登録してみます。ユーザ登録は、ユーザ名とパスワードを入力するだけのシンプルな形です。

ユーザ登録できたところで、実際のノードを追加してみます。Nodes タブをクリックして、ノードを追加します。

この他にも、ノードクラス、ノードグループ、レポート、の機能があります。

まず、レポートの機能は、現在の puppet レポートの実行結果が /var/puppet/lib/reports にある場合は、次のコマンドで Puppet Dashbaord へインポートできます。

$ rake reports:import

また、puppet レポートの実行結果が、他の場所にある場合は、次のコマンドで Puppet Dashboard へインポートすることができます。REPORT_DIR という環境変数に Puppet レポートの実行結果を格納してあるディレクトリを指定するだけです。

$ rake reports:import REPORT_DIR /path/to/your/reports

Importing 1 report from /path/to/your/reports
Importing:     100% |##########################################| Time: 00:00:00
1 of 1 report imported

試しに1件レポートデータをインポートした画面は、次のようになっています。

毎回、レポートをインポートするのが面倒なので、Puppet サーバと連携する方法も用意されています。Puppet サーバと連携するには、puppetmasterd に、次のように –reports オプションを指定するだけです。

–reports <puppet_bashboardのサーバ名>

ただし、Puppet Dashboard は、localhost:3000 で動作するようにハードコーディングされています。これを変更するには、lib/puppet/puppet_dashboard.rb を変更する必要があります。

次に Puppet Dashboard には、Puppet 互換の外部ノード情報と連携することができます。Puppet 互換の外部ノード情報は、YAML 形式で出力しますが、Puppet Dashboard に付属している bin/external_node プログラムを使います。このプログラムも、localhost:3000 でハードコーディングされているので、環境に応じて変更するとよいでしょう。

今のところ、僕が Puppet を投入している本番環境ではレポート機能をオフにして、エラーログのみチェックしていますが、比較的少ない台数で運用している場合は、Puppet Dashboard 管理画面からレポートの実行結果をチェックすることができるので、便利なツールと言えそうです。

将来的には、次の機能が実装予定とのことです。

  • LDAP と ActiveDirectory 認証
  • 管理者の権限によるアクセス制御
  • データをよりよく可視化して、情報にアクセスしやすくする
  • さらに多くのノード状態情報(オフライン状態、通信エラー、など)
  • リソースの変更を報告して、トラックキングする
  • Puppet の実行スケジューリング
  • その他のコミュニティからのリクエスト機能

まだ、Puppet Dashboard は登場したばかりなので、これから期待できるツールにもなりますね。

接続元の IP アドレスをラウンドロビン的に変更する方法

とあるサーバから、あるサーバに接続したとき、あるサーバに残るアクセスログの接続元 IP アドレスをラウンドロビン的に変更することが必要になったので調査してみた。そうすると、iptables を使うとできるというまさにぴったりの記事を発見した。

さっそく、CentOS で試してみると、iptables の libipt_statistic モジュールがないというエラーになってしまった。次に RedHat のページを調べていると、Bug 215361 – iptables is missing /lib/iptables/libipt_statistic.so というまさにぴったりな情報が見つかった。その情報では、iptables バージョン 1.3.6 から追加されたとあったので、さっそく netfilter iptables バージョン 1.3.6 のページの変更点を調べてみると、たしかに次のような記載があった。

- Add support for statistic match (needs kernel >= 2.6.18)
  [ Patrick McHardy ]

CentOS 5.3 x86_64 の iptables のバージョンは、iptables-1.3.5-4.el5 なので一つバージョンが古いのが原因のようだ。Linux カーネル 2.6.18 が必須とのことなので、CentOS でもおそらく使えるそうだ。

さっそく、iptables バージョン 1.3.6 を導入するために、RPM を作成にとりかかった。

まず、iptables-1.3.5-4.el5 の SRPM をダウンロードして、このバージョンの iptables.spec ファイルをパッチなどはすべて正しくあてるように、かつ libipt_statistic をビルドして組み込むように RPM を作成した。

libipt_statistic は、iptables バージョン 1.4.0 以降から標準で組み込まれるようになっているが、バージョン 1.3.6 では標準では組み込まれない。ちょうど、該当のコミットログがあったので、コミットログを参照しながら RPM を作成した。

作成した RPM は、ここにアップロードしてある。あわせて、SRPM もアップロードした。他に作った人がいないかも調べてみたが、見つからなかった。

iptables を現時点での最新版であるバージョン 1.4.6 ではなく、バージョン 1.3.6 にしようとした理由は RPM のおそらくメジャーアップグレードになるので RPM の作成が大変であること、安定性の面で経験がまったくないのでなるべる標準にインストールされるバージョンに近いものにしたいと思ったからだ。

作成した RPM で、CentOS にインストールされている既存の iptables をバージョンアップして、さっそく試してみた。

まず、外側のネットワークのデバイスに IP エイリアスを設定する。次の例は、ifconfig eth0 の出力結果だが、不要な情報は省いてある。

eth0      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
inet addr:192.168.161.125  Bcast:192.168.161.255  Mask:255.255.255.0

eth0:0    Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
inet addr:192.168.161.124  Bcast:192.168.161.255  Mask:255.255.255.0

eth0:1    Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
inet addr:192.168.161.123  Bcast:192.168.161.255  Mask:255.255.255.0

eth0:2    Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
inet addr:192.168.161.122  Bcast:192.168.161.255  Mask:255.255.255.0

次の iptables の設定で NAT チェインを、次のように設定する。(スマイルアイコン対策のため、PREGROUTING と POSTROUTING の前のセミコロンは省いてある)

*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o eth0 -p tcp –dport 80 -m statistic –mode nth –every 4 -j SNAT –to-source 192.168.161.125
-A POSTROUTING -o eth0 -p tcp –dport 80 -m statistic –mode nth –every 4 -j SNAT –to-source 192.168.161.124
-A POSTROUTING -o eth0 -p tcp –dport 80 -m statistic –mode nth –every 4 -j SNAT –to-source 192.168.161.123
-A POSTROUTING -o eth0 -p tcp –dport 80 -m statistic –mode nth –every 4 -j SNAT –to-source 192.168.161.122
COMMIT

iptables を再起動して、さっそく接続先のサーバに Apache HTTPD を起動して、アクセスログを確認してみると、次のような結果になった。

192.168.161.125 – – [11/Feb/2010:23:17:07 +0900] “GET / HTTP/1.1” 200 44
192.168.161.124 – – [11/Feb/2010:23:17:08 +0900] “GET / HTTP/1.1” 200 44
192.168.161.123 – – [11/Feb/2010:23:17:09 +0900] “GET / HTTP/1.1” 200 44
192.168.161.122 – – [11/Feb/2010:23:17:09 +0900] “GET / HTTP/1.1” 200 44
192.168.161.125 – – [11/Feb/2010:23:17:10 +0900] “GET / HTTP/1.1” 200 44
192.168.161.125 – – [11/Feb/2010:23:17:11 +0900] “GET / HTTP/1.1” 200 44
192.168.161.124 – – [11/Feb/2010:23:17:12 +0900] “GET / HTTP/1.1” 200 44
192.168.161.125 – – [11/Feb/2010:23:17:13 +0900] “GET / HTTP/1.1” 200 44
192.168.161.125 – – [11/Feb/2010:23:17:14 +0900] “GET / HTTP/1.1” 200 44
192.168.161.123 – – [11/Feb/2010:23:17:14 +0900] “GET / HTTP/1.1” 200 44

完全にはラウンドロビンにはなっていないが、リクエストごとにアクセス元の IP アドレスが毎回変更されている。

最後に libipt_statistic のモジュールとはどんなモジュールかソースコードを読んでみた。libipt_statistic モジュールとは、ある状態になっているかを調べることができるモジュールのようである。

設定内容は、次のような設定が可能。

–mode mode: マッチモード (random あるいは nth)

–probability p: 確立

–everyn: n 番目のパケットに毎回マッチする

–packet p: 初期値のカウント値(p は、0 以上 p – 1 以下)、デフォルトは 0

どうやらこのモジュールは、ある状態ごとに iptables の設定を変更できるモジュールのようだ。

いろいろと試した結果、完全なラウンドロビンにするには、次のような設定でいけるようだ。(スマイルアイコン対策のため、PREGROUTING と POSTROUTING の前のセミコロンは省いてある)

*nat
PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o eth0 -p tcp –dport 80 -m statistic –mode nth –every 4 -j SNAT –to-source 192.168.161.125
-A POSTROUTING -o eth0 -p tcp –dport 80 -m statistic –mode nth –every 3 -j SNAT –to-source 192.168.161.124
-A POSTROUTING -o eth0 -p tcp –dport 80 -m statistic –mode nth –every 2 -j SNAT –to-source 192.168.161.123
-A POSTROUTING -o eth0 -p tcp –dport 80 -m statistic –mode nth –every 1 -j SNAT –to-source 192.168.161.122
COMMIT

上の設定のときの Apache アクセスログは、次のようになった。

192.168.161.122 – – [11/Feb/2010:23:27:29 +0900] “GET / HTTP/1.1” 200 44
192.168.161.125 – – [11/Feb/2010:23:27:30 +0900] “GET / HTTP/1.1” 200 44
192.168.161.124 – – [11/Feb/2010:23:27:31 +0900] “GET / HTTP/1.1” 200 44
192.168.161.123 – – [11/Feb/2010:23:27:32 +0900] “GET / HTTP/1.1” 200 44
192.168.161.122 – – [11/Feb/2010:23:27:32 +0900] “GET / HTTP/1.1” 200 44
192.168.161.125 – – [11/Feb/2010:23:27:33 +0900] “GET / HTTP/1.1” 200 44
192.168.161.124 – – [11/Feb/2010:23:27:34 +0900] “GET / HTTP/1.1” 200 44
192.168.161.123 – – [11/Feb/2010:23:27:34 +0900] “GET / HTTP/1.1” 200 44
192.168.161.122 – – [11/Feb/2010:23:27:35 +0900] “GET / HTTP/1.1” 200 44
192.168.161.125 – – [11/Feb/2010:23:27:36 +0900] “GET / HTTP/1.1” 200 44

どうして、この設定だと、完全にラウンドロビンになるのか、よく分かっていない。。。

iptables には、こんなこともできるのかと感動した。

# 2010.04.01: 追記

iptables の設定ファイルの例は、ここに置いた。

HipHop for PHP

HipHop for PHP の技術的な講演動画が ustream にあったので、チェックしてみました。動画は、全部で 40 分弱くらいですが、講演自体は 20 分くらい、その他は質問でした。

以下、動画からのメモです。

  • CPU の高い使用率が問題になっていた
  • 10,000 台のウェブサーバ
  • それぞれのリクエストに 800 ミリ秒かかっている
  • コードベースが巨大になるにつれて、さらに遅くなる
  • ハードウェアは、フリーではない
  • 言語ごとのベンチマークした結果の CPU の使用率
  • CPU の使用率が低い順 No1: C++, No2: Java, No3: C#, No4: Erlang, No5: Python, No6: Perl,  No7: PHP
  • PHP と Perl は同等、C++ や Java に比べると10 倍くらい遅いという結果
  • 高いメモリ使用率が問題
  • – 150M
    for ($i = 0; $i < 1000000; $i++) {
    $a[] = $i;
    }
  • – 750MB
    for ($i = 0; $i < 5000000; $i++) {
    $a[] = $i
    }
  • HipHop for PHP では、次の問題点を解消するために作った
  • 高い CPU の使用率を解消するため
  • 多くのメモリの使用率を解消するため
  • 他のシステムで既存の PHP のロジックを再利用するため
  • 拡張は、ほとんどの PHP 開発者には書くことが難しい作業
  • HipHop for PHP は、2年間の成果で、ソースコードの最適化された C++ コード(g++ を使う)の変換機
  • 効果は、ウェブサーバは 50% 以下に下がった、API は 2 倍のトラフィックに対して 30% 以下に下がった(APC を使った PHP コードベースと比べた結果)
  • 7つのステップを通して、コードを変換する
  • 本番環境でのデプロイは、通常の PHP コードでのデプロイとは異なっている
  • 複数のスレッドで一つのプロセスを起動している
  • 再起動している間のダウンタイムがない(port takeover… ポートを乗っ取り?)
  • 巨大なバイナリを置く
  • HipHop は、現在とてもシンプルなウェブサーバ上で使っている
  • これからのロードマップ
  • 現在、PHP 5.2 をサポートしているが、5.3 もサポートしたい
  • ウェブサーバのオプションとして Apache をサポートしたい
  • Facebook では、Apache 1.3 Prefrok で使っているとのこと
  • 同時にデータベースのコネクションも減っている
  • PHP の拡張はスレッドセーフでない問題は解決できていないとのこと

まだ、ちゃんと試していないのでよく分かりませんが、PHP なウェブサービスで PHP が CPU ボトルネックになっている場合には、物理サーバを減らすための有効なソリューションの一つになるかもしれないイメージをうけました。ただし、Facebook では、まだとても単純なウェブサーバ上でしか使っていないそうので、実際のサービスに使うにまだまだ時間がかかりそうです。

あと、個人的には Java は C++ と同様のベンチマーク結果だということも注目です。

なお、HipHop for PHP のソースコードは、github でもうすぐ公開予定とのことです。

sudos

本番サーバ上で、sudo コマンド経由でスーパーユーザ権限で実行することはよくあります。

sudo コマンドはなくてはならないコマンドですが、同時に危険なコマンドでもあります。

今まで、ずっとデフォルトの sudo の設定で使っていたのですが、改めて設定を見直してみました。

sudo の公式ページをみてみると、頻繁にバージョンアップされているのがよく分かります。/etc/sudoers の設定方法も詳しいドキュメントがあっていい感じです。

次の2点ほど設定を見直しました。

  • デフォルトのパスワードのキャッシュ時間を 0 にする
  • パスワードプロンプトにホスト名を表示する

まず、最初の設定はデフォルトだと 5 分間、パスワードがキャッシュされます。そうすると、連続で sudo コマンドを実行するとき、パスワードを聞かれないためオペミスを起こしてしまう可能性が高まります。そこで、キャッシュ時間を 0 にすることにより、必ず毎回パスワードを聞くように設定します。この設定は、visudo コマンドを使って、次の行を追加します。

Defaults timestamp_timeout = 0

次にパスワードを聞かれるときのプロンプトにホスト名を表示して、念のためどのホストで sudo を実行しようとしているのか表示します。次の行を追加します。

Defaults passprompt = “%u@%h Password: “

この設定をすると、例えば hoge というユーザ名で、s1 というホスト名の場合、次のようなパスワードプロンプトになります。

hoge@s1 Password:

デフォルトのパスワードプロンプトに比べると、かなり分かりやすい表示になりました。

最新版の sudo バージョン 1.7.1 以降からは、次のような構文で別の設定ファイルも読み込めるようになっています。

これを使えば、ホストごとに異なった設定も管理しやすくなります。ただし、CentOS の場合、バージョン 1.6.8 なので対応していません。すこしはまってしまいました。。。

#includedir /etc/sudoers.d/hoge

最新版の sudo に入れ替えようと思いましたが、今のところそれほど困っていないので最新版は使っていません。

普段何気なく使っている sudo。もちろん、なるべく本番サーバ上では使わないのが賢明ですが、メンテナンスのときなど使う機会があるので、なるべくオペミスのリスクを減らしたいものです。

さらに、僕は sudo をコマンド補完履歴に追加しないようにしています。

# 2/5 追記

ちなみに、sudo のパスワードキャッシュをクリアするときは sudo -k あるいは -K オプションで行います。