トンネリングとダイレクトルーティングの ARP 問題

トンネリングとダイレクトルーティングのクラスタリングシステムでは、バーチャルIPアドレスがロードバランサーとリアルサーバーの両方で割り当てられている。 なぜならそれらは1つのインターフェースにバーチャルIPアドレスをすべて設定しているからだ。ロードバランサーが接続要求を受ける同じネットワーク内のリアルサーバーの設定は、もしリアルサーバーがヴァーチャルIPアドレスの ARP リクエストに答えたら、それは競合条件になり、答えが返ってこなくなる。ヴァーチャルIPアドレスのパケットは1度ロードバランサーに送られるかもしれない。すると次にリアルサーバーに送られ、また次にリアルサーバーに送られ、と無限ループする。だから接続が切れるとすべてが混乱してLVSクラスター全体が機能しなくなる。それゆえ、トンネリングとダイレクトルーティングのクラスタリングシステムでは、バーチャルサービスを受けるためにやってくるパケットを受けるためのバーチャルIPアドレスの ARP 要求を答えるのがロードバランサーだけであることとリアルサーバー(ロードバランサーのネットワークと同じ)がヴァーチャルIPアドレスの ARP リクエストには答えないで、バーチャルIPアドレスに向かったパケットをローカルに処理することを保証しなければならない。

Linux kernel 2.0.xx ではループバックエイリアスとトンネリングインターフェースの ARP 応答をすることができなかった。これはLVSクラスターにとっては都合が良い。しかしながら、Linux kernel 2.2.xx では、ループバックアドレス(IPアドレス 127.0.0.0/255.0.0.0)とマルチキャストアドレス以外すべてのIPアドレスに ARP 応答をする。 だからあなたは他のページで説明したとおり kernel 2.2.xx で動作するリアルサーバーのトンネリングとダイレクトルーティングのクラスタリングシステムで問題を持つだろう。だが kernel 2.2.14 から、ARP のブロードキャストから隠すことができる "hidden" フラグがある。 Julian Anastasovに感謝! 標準カーネルにこの素晴らしいARPポリシーを追加してくれた Alexey Kuznetsovにも感謝!

1. 隠したインターフェースのアプローチ

LVSのARPからインターフェースを隠す実装の設定は次のようになります。

# 機能上インターフェースを隠し始めます
echo 1 > /proc/sys/net/ipv4/conf/all/hidden
# Hide all addresses for this interface
echo 1 > /proc/sys/net/ipv4/conf/<interface_name>/hidden

一度インターフェースを隠すとインターフェースのすべてのアドレスは ARP のブロードキャストから隠され、他のアドレスの ARP 応答に含まれる。もし使わないイーサネットのインターフェースがなければ、実際のイーサネットのエイリアスにバーチャルIPアドレスを設定したりそれを隠したりしても意味がない。

LVS のダイレクトルーティングクラスターにとって、ダミーやループバックデバイスのエイリアスのバーチャルIPアドレスを設定したり、対応したデバイスを隠すことは良い。そうすれば好きなだけたくさんのバーチャルIPアドレスを設定することができる。 設定するのは簡単でここで説明する必要はない。

LVS のトンネリングクラスターにおいて、最初にあなたは tunl0 デバイスを設定する必要があり、トンネル、ダミー、ループバックデバイスのエイリアスバーチャルIPアドレスを設定し、それらのデバイスを隠す。設定例は次のようになります。

# ipip モジュールを追加する
insmod ipip
# tunl0 デバイスを設定する
ifconfig tunl0 up
# 機能上インターフェースを隠す
echo 1 > /proc/sys/net/ipv4/conf/all/hidden
# このトンネルデバイスのためにすべてのアドレスを隠す
echo 1 > /proc/sys/net/ipv4/conf/tunl0/hidden
# トンネルデバイスのエイリアスバーチャルIPアドレスを設定する
ifconfig tunl0:0 <VIP> up

tunl0 デバイスを設定すれば、カーネルは受信した ipip パケットを正確にカプセルから戻すことができるようになる。LVS トンネリングのために好きなだけたくさんのバーチャルIPアドレスを設定することができる。Julianに感謝!

kernel 2.3.41 またはそれ以降で動作しているリアルサーバーには、Julianの hidden patch をあててカーネルを再構築しなければならない。

2. リダイレクトアプローチ

LVS ダイレクトルーティングクラスターにとって、Horms は ARP 問題をうまく避けるリダイレクトアプローチを提案してくれました。

リアルサーバーのインターフェースのエイリアスを削除し、リダイレクトをセットアップして、ipchains を使ってこの問題を回避することができる。

ipchains -A input -j REDIRECT <port> -d <virtual-ip-address> <port> -p <protocol>

これはマイナス面としてリアルサーバーが基本的にはこの機能をサポートする Linux である必要があり、プラス面では、LANとは違ったネットワークインターフェースをもつ必要がないので、ロードバランサーは簡単にLAN上のどのマシンにも移動させることができる。これはサーバーが落ちた時、ロードバランサーをフェールオーバーすることができる重要な関係がある。

1つのバーチャルIPアドレスで動いている複数のバーチャルサービスにとって、異なるポートに複数のリダイレクトコマンドを指定することがでる。また、次のようにプロトコルにつきすべてのポートをカバーすることができるので、ポート番号を供給しない。
ipchains -A  input -j REDIRECT -d <VIP> -p tcp
ipchains -A  input -j REDIRECT -d <VIP> -p udp

LVS のトンネリングクラスターにとって、システムが適切に ipip パケットをカプセルから戻すことができるように tunl0 を簡単に設定することができ、バーチャルIPアドレスのリダイレクトコマンドを追加する。

3. ルーティングアプローチのポリシー

Julian はリアルサーバーの ARP 問題を回避する進化したルーティングアプローチポリシーを使うよう提案した。 例えば、バーチャルIPアドレスが 172.26.20.118 だとするとコマンドは以下のようになる。
#LAN からリアルサーバーのバーチャルIPアドレスへのアクセスをブロックする。この方
#法でルーターの ARP 検査を無視する。欠点としてはクライアントの検査も無視してしま#うことだ。LAN 上のクライアントがすべてのリアルサーバーから応答を受信することが
#出きるので私たちはこれをしなければならない。

ip rule add prio 99 from 172.26.20/24 table 99
ip route add table 99 blackhole 172.26.20.118

# ローカルに他の通信、例えば 172.26.20.20/24 からでない通信をアクセプトした時 

ip rule add prio 100 table 100
ip route add table 100 local 172.26.20.118 dev lo
ポリシールーティングは透過的なプロキシよりも速いが同一LAN上のクライアントは、バーチャルIPアドレスのバーチャルサービスにアクセスすることができない。リアルサーバーはバーチャルIPアドレスの ARP リクエストも破棄するために LAN からバーチャルIPアドレスへの通信を無視する。

4. kernel 2.2.13 か それ以前の ARP へ向かわないインターフェースを作る古いパッチ

この2つのパッチは kernel 2.2 で、ループバックエイリアスとトンネリングインターフェースに ARP 応答させないようにするパッチです。 Stephen D. Williamsが作った sdw_fullarpfix.patchJulian Anastasovが作った arp_invisible-2213-2.diff があります。

kernel 2.2.13 の Julian が作った ARP パッチは ARP クエリーとリプライに対して見えないダミー(ローカルやトンネルも)インターフェースを設定する機能を追加した。インターフェースが見えるか見えないかの設定を /proc/sys/net/ipv4/conf/*/arp_invisible の値で設定する。/proc/sys/net/ipv4/conf/*/arp_invisible のデフォルトの値は0である。もしこの値が1に設定されたら、ARP クエリーとリプライは無視される。 設定例は次のとおりだ。

# グローバルで使う場合は、1回だけやりなさい
echo 1 > /proc/sys/net/ipv4/conf/all/arp_invisible
# インターフェースを隠し応答しなくさせる
echo 1 > /proc/sys/net/ipv4/conf/<interface_name>/arp_invisible

リアルサーバーのカーネルコードに ARP パッチを当てる必要があり、リアルサーバーに ipvs パッチを当てなくても良い。これらのパッチについては LVS メーリングリスト にコメントをください。


$Id: arp.html,v 1.11 2000/06/26 12:15:43 wensong Exp $
Created on: 1999/11/14