負け組アーキテクトの憂鬱

メモしておきたいことや読書の記録を淡々と書く。

2006年06月

freevrrpdでサーバ冗長化

freevrrpdはFreeBSD、NetBSD、OpenBSDのvrrpd実装。FreeBSDなら/usr/ports/net/freevrrpdにある。

vrrpはルータの多重化を行うためのプロトコルと説明されているけど、特にルータに限定しなくても、普通のホストでも使うことができる。

やっていることは、あるホストが落ちたらそのホストが持っていたIPアドレスを別のホストが引き継ぐ、というイメージ。これを、仮想IPアドレスを定義し複数のホストで共有してやることで実現する。複数のホストのグループはvrrpでグループIDで管理され、この中でプライオリティの最も高いホストがmaster(仮想IPアドレスが割り振られる)、それ以外がbackupとなり、masterが落ちるとbackupの中でプライオリティが高いホストが新しくmasterとなる。freevrrpdでは仮想IPアドレスはmasterとなるホストのIPアドレスエイリアスとして設定される。理屈としてはとてもシンプル。

↓こんなかんじ(192.168.1.253が仮想IPアドレス)

rl0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        options=8<VLAN_MTU>
        inet6 fe80::20d:bff:fe4e:8e42%rl0 prefixlen 64 scopeid 0x2
        inet 192.168.1.3 netmask 0xffffff00 broadcast 192.168.1.255
        inet 192.168.1.253 netmask 0xffffffff broadcast 192.168.1.253
        ether 00:0d:0b:4e:8e:42
        media: Ethernet autoselect (100baseTX <full-duplex>)
        status: active

設定はFreeBSDのportsで入れたら/usr/local/etc/freevrrpd.confで。同じディレクトリにfreevrrpd.conf.sampleがあり、丁寧にいろいろなコメントを記載してくれてある。

masterにしたいホストでの設定例

[VRID]
serverid = 1
interface = rl0
priority = 255
addr = 192.168.1.253/32
password = hogehoge
useVMAC = no
sendgratuitousarp = yes

backupにしたいホストでの設定例

[VRID]
serverid = 1
interface = rl0
priority = 250
addr = 192.168.1.253/32
password = hogehoge
useVMAC = no
sendgratuitousarp = yes

設定すべき項目はざっとこんなところ。

  • serveridはvrrpのグループID。紐付けたいホストで同じIDを使う。
  • interfaceはvrrpをしゃべらせたいNICを指定。
  • priorityは優先度。255が最大値で指定されているとmasterになる。
  • addrは仮想IPアドレス。
  • passwordはvrrp通信時のパスワード。グループ内で同じものを指定。
  • useVMACはMACアドレスも仮想のものを使うかどうかの指定。

仮想MACアドレスを使うと、切り替り後も同じMACアドレスで通信できるため、arpの変更が起こらない(ただし、L2SWでは変更に追従する必要がある。まあ、普通は意識しなくてよい)。仮想MACアドレスを使う場合は、切り替り時にホストのMACアドレスが書き換えられるため、もともとIPアドレスが割り振られているばあいにはそれらに影響が出る(可能性がある)。

仮想MACアドレスを使わない場合は、切り替り後に仮想IPアドレスに対応するMACアドレスが(新しいmasterホストのものに)変更される。このため他のホストにMACアドレスの変更を通知してやる必要がある。これを指示するのが、sendgratuitousarp。切り替り後に自分自身のMACアドレスが含まれたarpリクエストをブロードキャストし、結果的にMACアドレスの変更がローカルリンク内に伝播される。

これでfreevrrpdを立ち上げれば最低限のIPアドレスの切り替えは出来るようになる。仮想IPアドレスを使ったサービスの上げ下ろし(DBやhttpdのstart/stopとか)にはmasterscript、backupscriptで指定したスクリプトで行えばいいだろう。

masterscript = /usr/local/bin/master_script.sh
backupscript = /usr/local/bin/backup_script.sh

データの同期や共有ディスクの利用をきちんと考慮してあげれば、なんちゃってHAクラスタ的な使い方が出来る(んじゃないかなあ)。

Debian GNU/Linuxのアップデートをproxy経由で行いたい

これからお仕事でDebian GNU/Linuxをたくさん使うことになりそう。まずはアップデートの方法くらい知らないとね、ってことでちょっと調べてみた。

自分自身がインターネットに到達できるなら問題ないけど、直接外に出れないセグメントに繋がってる場合、とりあえず安直にproxyで何とかできないかと模索。apt-getコマンドでアップデートする場合のproxyの指定方法はだいたい以下の2種類のようだ。

  • 環境変数http_proxy(必要によってftp_proxyも)を指定
  • /etc/apt/apt.confで設定
  Acquire {
     http {
        Proxy "http://proxy:8080";;
     };
     ftp {
        Proxy "http://proxy:8080";;
     };
  }

いろいろ例外サイトとか指定できるみたい。

あとはsquidなりapacheなりでproxyのキャッシュサーバでも作ってあげれば大丈夫。

今日も眠いのでこんだけ。無念。

ひとつのDNSサーバでWAN向けとLAN向けを住み分けたい

ここではWANはグローバルアドレスが割り振られてるネットワーク、LANはプライベートアドレスのネットワーク、というざっくりとした括りで。

たとえばLANとWANで別のサブドメインで名前解決する場合は問題ないんだけど、同じゾーンでグローバルアドレスを返すレコードとプライベートアドレスを返すレコードを混在させたい場合、そのままひとつのゾーンファイルにすべてのエントリを書き出してしまうと、WANから名前解決したときにプライベートアドレスを返してしまう可能性がある。まあ、名前解決だけなので実害ないっちゃーないんだけど、ちょっとかっこ悪い。

また、同じ名前だけどWANから見た時とLANから見た時で別のアドレスを返したい場合もあるだろう。

WAN向け、LAN向けそれぞれにbindを立ててもいいけれども、こんなときにはbind9のview機能を使うととても便利。WAN向け、LAN向けそれぞれのインターフェイスがあるホストでnamedを動かす場合を想定。

named.confで、まずLANとして認識させるアドレス帯域をaclで区切ってやる。

acl localnet {
        127.0.0.1;
        ::1;
        192.168.0.0/16;
};

viewを区切ってLAN向けとWAN向けのゾーンをそれぞれ記載。以下の例では、クライアントのIPアドレスが、上で指定したlocalnetで定義されているaclに含まれる場合にはlocalというviewが、それ以外ではworldというviewが適用される。

view "local" {
        match-clients { localnet; };
        zone "example.jp" {
                type master;
                file "example.jp.local"; LAN向けゾーンを指定
        };
}
view "world" {
        match-clients { any; };
        zone "example.jp" {
                type master;
                file "example.jp.world";
        };
}
# もちろんこれだけではnamed.confとしての設定は不十分なので、その他の設定も忘れずに。

この指定だと、example.jp.localとexample.jp.worldがそれぞれLAN向け、WAN向けのゾーンファイルになる。それぞれにすべてのホストエントリを記載してもいいけど、数が多くて、しかもそのほとんどがLAN向けでもWAN向けでも共通の内容だったりすると管理がめんどくさい。そんなときには$INCLUDEを使ってやると(場合によっては)楽だ。

LAN向けゾーン example.jp.local

$INCLUDE example.jp.common

;LAN向けのアドレスを記載
ns0            IN      A       192.168.1.53
ns1            IN      A       192.168.1.54
www            IN      A       192.168.1.80
pc0            IN      A       192.168.1.128
pc1            IN      A       192.168.1.129

WAN向けゾーン example.jp.world

$INCLUDE example.jp.common

;WAN向けのアドレスを記載
ns0            IN      A       123.45.67.89
ns1            IN      A       123.45.67.90
www            IN      A       123.45.67.91

共通のエントリ example.jp.common

$TTL 86400
@       IN      SOA     example.jp. root.example.jp.  (
                                2006060301 ; Serial
                                3600    ; Refresh
                                900     ; Retry
                                604800  ; Expire
                                3600 )  ; Minimum

               IN      NS  ns0
               IN      NS  ns1
               IN      MX  mail
mail           IN      A       123.45.67.25
host0          IN      A       123.45.67.1
host1          IN      A       123.45.67.2
host2          IN      A       123.45.67.3

ポイントはSOAを共通ファイルに、ns0とns1は個別のゾーンで指定してやることだろうか。ns0は自分自身のアドレス、ns1はそれぞれのネットワークでのセカンダリサーバを指定すれば問題ないだろう。

SOAは共通ファイルに含まれるので、たとえばLAN向けのゾーンを修正した場合でも、共通ファイルのSerialを増加させてあげる必要があるので注意。SOAをWAN向けとLAN向けで別々に管理したい場合はもちろんそれぞれに記載しても構わないが、今度は共通ファイルを更新した場合にそれぞれのSerialを増加させるのを忘れないように。TTLはどちらで管理しても問題ないだろう。

ns0とns1をWAN向けとLAN向けで分ける必要があるのは、LANからの問い合わせ時にはLAN向けのDNSサーバアドレスを、WANからの問い合わせにはWAN向けのアドレスを返してあげるため。LANからでもWANのDNSに問い合わせてしまうと、(NATとかが働いていればだけど)view worldとして処理された結果が返ってきてしまう。

IPv6の場合はプライベートアドレスという概念がないので(サイトローカルアドレスは廃止されちゃったしね)、ネットワークを区切って、単純に見せたいもの、見せたくないもので考えられる。

どうしても使い続けなければならない場合の選択肢

どこにでもOSのイニシャルコスト(ライセンス費用だね)を節約したい、という案件はある。ちゃんとランニングコストの増分を折り込んでるなら問題ないんだけど、目先のお金がケチれたら満足できちゃうケースって少なくない(よね)。

そんなわけで、比較的短いライフサイクルのLinuxディストリビューション等々、製造元が面倒みてくれなくなった時に大きなしっぺ返しが来るわけです。

http://www.fedoralegacy.org/
使うかどうかは別問題として、こんなありがたいプロジェクトがあった。今のところRedHat7.3、RedHat9、FedoraCore1〜3がサポートされてるようだ。

今ではLinuxもそれなりのシェアがあるから、既知の脆弱性を放置することはとても危険だ。有償のサポート代行サービスもやってくれているところはあるけど、こういうOSを導入したきっかけって、ライセンス費用とかサポート費用とかの節約が第一目的の可能性が非常に高いわけで、導入は難しいケースも多いだろうと思う。

なんかMicr○s○ftの広告みたいになったな・・・。

それでもライセンス費用もサポート費用もかけたくないよ!年に数回の大規模アップデートなんてもっての他だよ!という場合には、CentOSのような選択肢もあるらしい。有償のRedHatEnterprizeLinuxのクローンで、GPLを根拠にRHELのソースを入手して再コンパイル、再配布しているものなんだそうだ。セキュリティアップデートもRHELでリリースされたその日か数日のうちには追従してリリースされるらしいし、手堅い運用をしたい場合には有力候補なんじゃないだろうか。もちろん誰もサポートしてくれないけど。

SECURITY ADVISORIESが更新されてた

http://security.freebsd.org/advisories/FreeBSD-SA-06:16.smbfs.asc
http://security.freebsd.org/advisories/FreeBSD-SA-06:15.ypserv.asc

どちらも直接関係なさそげ。

RELENG_4_10は5月末でメンテナンス終了かと思いきや、滑り込みセーフで更新されたみたいだ。これが最後になるのかな。

SIGUSR1を食らったhttpdが上がってこない

月初にしばしば起きる問題。困ったもんだ。


Jun 1 00:00:00 ns newsyslog[92788]: logfile turned over

[Thu Jun 01 00:00:03 2006] [notice] seg fault or similar nasty error detected in the parent process




newsyslogでローテーションする時にSIGUSR1(シグナル30番)を送って、ファイル記述子を手放させてやる必要があるんだけど、そこで上がってこない。



ググってみたらどうもPHP4が原因っぽい雰囲気を醸し出していた。
http://www.freebsd.org/cgi/query-pr.cgi?pr=64904
http://bugs.php.net/bug.php?id=27899
http://bugs.php.net/bug.php?id=27810

何とかしようと思い立ったけど、やっぱりもう眠いから寝る。精査は明日〜(とか言って来月まで放置しそう)。