2006.04.08 carp(4)マンセー carp(4)はいい。面白い。というわけで carp(4) ネタ。 carp(4)は Common Adress Redundancy Protocol (CARP)の制御と実装 を担当する疑似インターフェース(pseudo interface)です。 (以下伝聞) CARP は Virtual Router Redundancy Protocol (VRRP)か ら特許に触れる技術を置き換えたプロトコルとのこと。VRRP よりは多 少効率が落ちるそうですが, 特許フリーなプロトコルとして将来が期 待されてるそうです。 さて。要は冗長構成・負荷分散のための機構ということで, 運用が簡単 で, 構成が容易という, この手の仕組みとしては信じられないくらいナ イスな仕組みです。 構成の簡単さは下記のようにふつーにネットワーク組んでから追加がで きる。というものです(192.168.1.1/24 を空けたのがミソ:-)。 | +---+----+ | ROUTER | +---+----+ | 192.168.1.254/24 | ------+----------+----------+------ | | | 192.168.1.2/24 | 192.168.1.3/24 +-----+-----+ +-----+-----+ |FreeBSD A | |FreeBSD B | +-----------+ +-----------+ 1. カーネルコンフィギュレーション carp(4) はカーネルモジュールとして提供されていませんので カーネルコンフィギュレーションに下記の行を追加して再構築 する必要があります。 ※FreeBSD A・FreeBSD B 共通 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - device carp # Common Address Redundancy Protocol - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2. /etc/rc.conf cloned_interfaces に carp0 を指定する必要があります。 ※FreeBSD A - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cloned_interfaces="carp0" ifconfig_carp0="vhid 1 pass mekmitasdigoat 192.168.1.1/24" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ※FreeBSD B - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cloned_interfaces="carp0" ifconfig_carp0="vhid 1 advskew 100 pass mekmitasdigoat 192.168.1.1/24" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - そして再起動。と。ネットワーク的には 192.168.1.1/24 という サーバーが追加されたように見えますが, 192.168.1.1/24 への アクセスは 2 台のうち, どちらかに行くということになります。 各サーバーではもちろん 192.168.1.1/24 でサービスを提供する ことになります。 | +---+----+ | ROUTER | +---+----+ | 192.168.1.254/24 | ------+----------+----------+------ |192.168.1.1/24(carp0)| | | | 192.168.1.2/24 | 192.168.1.3/24 +-----+-----+ +-----+-----+ |FreeBSD A | |FreeBSD B | +-----------+ +-----------+ ■ifconfig(8) の設定の意味 1. vhid バーチャルホスト ID です。1〜255 の間で指定します。この vhid が一致するもの同士で分散します。 2. advskew 通知メッセージに対しての遅延応答する時間(1/256 秒単位)です。 1〜254 の間で指定します(advskew を指定しない場合は 0)。 一番最初に, 通知に対して応答したサーバーが通信する権利を得 ます。 3. pass vhid に参加するためのパスワードです。 4. advbase 通知メッセージを出す間隔(秒単位)です。1〜255の間で指定します。 advbase 秒間に 1 回通知メッセージを出します(死活監視)。 ■ポイント 1. 切り替えの原理(?) 上記設定の場合, FreeBSD A サーバーが MASTER となって常時通信 する(他は BACKUP)ことになります。ここで, FreeBSD A サーバー のケーブルを引き抜くと通知メッセージに応答しなくなるので, FreeBSD B サーバーが通信を引き継ぐことになります。 2. 切り替えに 5 秒? 検証した限りでは, 切り替えに 5 秒かかるように見えます。このあ たりの数字が何を見てるかは今のところ不明です。 3. セッション維持してるものには無効 当然, セッションを維持している類の通信で切り替えは発生しませ ん(いやするんだけど)。HTTP 通信のようにセッション維持時間が 短いものに対しては, 障害時のリカバリという意味で有効ですが, SSH 等でつなげてるものに対して, 切り替えが発生しても, もう一 方では SSH 受け付けてませんから, セッションを維持できません (もっともそのレベルでケアできるものなんてないですが)。 という理由でルータで使うのがいいみたい:-)。あるいはホットス タンバイ。 4. ちょい謎の現象 ルータになってるマシン(192.168.1.254)から 192.168.1.2, 192.168.1.3 にはつなげるのですが, ルータの向こうから(ルータ 越しに)つなげません。色々と構成を検証していたために発生した 問題かもしれないということで, 今回は追求せず。 5. 中途半端に生きてたら… FreeBSD では mbuf cluster に不足が生じると通信できなくなり ますが(通常, その時, 極めて高負荷状態なのでコンソールでのオ ペレーションもできなくなるくらい極めて重くなります), ping には, それなりに応答するという嫌らしい障害が発生します。 この時 carp(4) も正常に機能している可能性があるため(in-kernel なので), 現時点ではハードウェア障害でしか使えないと思われます。 ちなみに, panic して kernel が停止しても, ping に応答してい る時(おそらくは network 割り込みが生きていて, network subsystem が応答しているのでしょう)もあったので, carp(4) もそこまで粘 りそうな予感がします。 よって, ユーザーランドで監視するプログラムを必要と思われます。 まぁ ifconfig carp0 advskew 254 するようなプログラムでいいの でしょうが。もっとも超高負荷状態で切り替えられるとは思いませ んが(^^;。 このあたりの運用は advskew を高めに設定しておいて, 切り替えた いものが advskew を下げる。というあたりを考えた方がいいかもし れません。 6. 遅延時間制御の妙 advskew で指定する時間がネットワーク遅延速度と有意な差が無い とパタパタ切り替わる可能性があります。ルータとして使用するな らパタパタ切り替わって負荷分散を楽しむのもありですが, リーフ ノードとして使うなら, パケット単位で分散されて通信が成立しな い可能性があります(3 項参照)。 7. というわけでやっぱルータとしてか, ホットスタンバイで使うのが 正解かな。と。 ■追加は簡単 というわけで下記のようなマシンを用意しましょう。ということで。 ------+------ | | | 192.168.1.3/24 +-----+-----+ |FreeBSD C | +-----------+ ※FreeBSD C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cloned_interfaces="carp0" ifconfig_carp0="vhid 1 advskew 200 pass mekmitasdigoat 192.168.1.1/24" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - まぁ削除も簡単なのは予想できるでしょう。 ■というわけでルータとして使うなら… 致命的かと(爆)。 今回 WAN 側(例ではプライベートIPですが)の設定を行いましたが 用は DMZ 側に対しても carp1 を設定することが可能です。 | ------+----------+----------+------ |192.168.1.1/24(carp0)| | | | 192.168.1.2/24 | 192.168.1.3/24 +-----+-----+ +-----+-----+ |FreeBSD A | |FreeBSD B | +-----------+ +-----------+ ×| 172.16.1.2/24 | 172.16.1.3/24 | | | 172.16.1.1/24(carp1)| ------+----------+----------+------ | この時, 片側のどちらかで障害が発生した場合(例えば A 系の DMZ 側 / ×のインターフェース), 切り替えが行われて B 系で通信する ようになりますが, 上流の切り替えとは連動しないため, A 系に返 って(?)来たパケットがそのまま消えてなくなる可能性が高いです。 これに対応できるかどうかはわかっていません。おそらくは可能だと 思いますが(net.inet.carp.preempt=1 に設定), 残念ながらここま で検証している時間がありませんでした:-(。 Written by 重村法克