ziguzagu.org

Perlbal::Plugin::ServerStarter

Perlbal で Server::Starter(start_server command) によるホットデプロイをサポートするためのプラグイン、Perlbal::Plugin::ServerStarter というのを作った(作っている)。

https://github.com/ziguzagu/Perlbal-Plugin-ServerStarter

Perlbal の素敵な点の一つに、動的に設定変更できる(管理ポートに telnet, nc などでつないでコマンド送り込む)というのがあるけど、たぶんほとんどのプラグインでは設定の削除ができない。たとえば Vhosts プラグイン。

VHOST app.example.com   = app
VHOST admin.example.com = admin     ## これがいらなくなっても動的に削除するコマンドはない
VHOST www.example.com   = web

また、複雑な設定や開発環境などではテスト済みの大きめの設定変更なんかをちまちま動的に変更するのは、作業自体のテストもしづらいし、そもそもが面倒くさい。なので、ときには再起動で設定読み直しがどうしても必要になったりならなかったりする。ただ(一応)ロードバランサーという位置づけのソフトウェアでもあり、サーバーのエッジあたりで運用されることもなくはないので、できれば無停止でいきたい。

ということで Server::Starter 対応。以下使い方。

プラグインを読み込むと LISTEN というコマンドが使えるようになるので、/SET listen = [ip:]port/ の代わりに使う。

LOAD ServerStarter

CREATE SERVICE web
  SET role    = web_server
  SET docroot = /path/to/htdocs
  LISTEN = 5000
ENABLE web

と設定ファイルに書き、start_server 経由で perlbal 起動。

$ start_server --port 5000 -- perlbal -c /etc/perlbal/perlbal.conf

ただ、ポート番号をコマンドラインと設定ファイルで重複して管理することになるのがアレなので、設定ファイルからポート番号抜き出して start_server に食わせてくれる start_perlbal というコマンドも用意した。

$ start_perlbal -c /path/to/perlbal.conf

これでよしなにしてくれる。知らないオプションは start_server にパススルーするので、

$ start_perlbal -c /path/to/perlbal.conf --pid-file perlbal.pid

というのも機能するように。

1つ注意点があるとすればログについてはちょっと見直しが必要。Perlbal(1.80現在) のログ出力は、

  • foreground で実行したら STDOUT
  • –daemon オプションで daemonize したら syslog

という実装になっていて、foreground で実行しつつもログは syslog に、というのができない。Server::Starter は仕様上 foreground で実行する必要がある(daemonize すると pid が変わってしまうので(fork して exit するから)、start_server で起動失敗扱いになる。はず。試した限り。)ので、perlbal –daemon でいままで運用していた場合は、daemontools (multilog) 使ったりするか、

$ sudo start_perlbal 2>&1 | /usr/bin/logger -p local7.warn -t perlbal &

とかして syslog やらファイルにログ出すようにする必要がある。

あと、start_server を経由せずに perlbal で起動しようとすると Server::Starter#server_ports よんだところで死んでそのまま起動できなんだけど、警告だけだして SET listen = [ip:]port の指定に読み替えてとにかく起動できたほうがいいかどうかは迷いどころ。そのフォールバックのせいで気づかずに start_server なしで起動してた、なんてことになるのはそれはそれで事故のもとかなぁとも思うけどはたして…。

実装自体は Perlbal 本体に取り込んだほうが美しいので安定したら考えたいところ。

とはいえ、これで Perlbal 無停止運用が可能になったよ。たぶん。