トラフィックが急増! ボトルネックを退治しよう〜 【設定編】
DSR構成のレシピ
まずは、設定項目をおさらいしておきましょう。次の6つでした。- LVS の負荷分散の設定をDSRに変更する(ipvs の設定)
- Webサーバが、DSRなリクエストパケットを扱えるようにする(iptables の設定)
- Webサーバを、outer VLAN に参加させる(L2 スイッチの設定)
- Webサーバが、outer VLAN において通信できるように設定する(VLAN 用インタフェースの追加)
- Webサーバにおいて、上位ルータへの通信経路を設定する(ルーティングと iptablesの設定)
- Webサーバが、上位ルータに対して応答パケットを送信できるように設定する(ARP エントリの設定)
LVS の負荷分散の設定をDSRに変更する
ipvs で負荷分散する場合、LVS マシンに到達したクライアントからのパケットを Webサーバへと転送する方法には、3種類あります。1つ目は LVS 上で NATして転送する方法、2つ目は届いた IPパケットをカプセル化して転送する方法、3つ目が DSRです。 ipvs の仮想サービスの設定で DSR を指定するには、は、ipvsadm
コマンドで設定する場合でしたら --masquerading (-m)
(= NAT)や --ipip (-i)
(= カプセル化)の代わりに --gatewaying (-g)
を指定します。 keepalived
を使っているのでしたら、仮想サービスの設定で lb_kind
オプションに DR
を指定します。
Webサーバが、DSRなリクエストパケットを扱えるようにする
DSR 構成を採った場合、LVS から Webサーバに転送されてくるパケットは前回説明したように、送信先IPアドレスが LVSの仮想サービス用のアドレス(図では A.B.C.D)のままになっています。このパケットを、Webサーバの OSが受け取ったときに自分宛のパケットだと認識させるためには、追加の設定が必要になります。方法はいくつかありますが、DSAS for Social では Webサーバ上で NAT する方法を使っています。つまり、送信先IPアドレスが A.B.C.D
であるパケットを受け採った場合、Webサーバ自身がそのパケットの送信先アドレスを自分のアドレス(ss.tt.uu.vv
)に書き換えるのです。そうすれば、そのパケットは Webサーバの OSが自分宛のパケットだと理解して、Apacheなどのアプリケーションに渡してくれるようになります。
設定方法は、OSに依って変わりますが、Linux の場合、次のようにするのが簡単です。
# iptables -t nat -A PREROUTING -p tcp --dport 80 -d A.B.C.D -j REDIRECTこれで、クライアントから LVSを経由して Webサーバに届いた宛先アドレス=
A.B.C.D
なパケットが、Webサーバ自身で処理されるようになります。
Webサーバを、outer VLAN に参加させる
ここからは、Webサーバが直接上位ルータに対して応答パケットを渡すために必要となる設定になります。そのためには、まずは Webサーバが "outer VLAN" に参加しないと始まりません。その際 "inner VLAN" と "outer VLAN" が混ざらないように、どちらかの VLAN には tag VLAN として参加させる必要があります。DSAS for Social では、"outer VLAN" 側を、tag VLAN にして参加させています。
Webサーバを "outer VLAN" に属させるためには、L2 スイッチの設定が必要になります。どのような設定になるのかはスイッチによって変わってきますが、DSAS for Social で主に使っている hp社の Procurve シリーズでは、例えば次のようにします。
# config (config)# vlan 4 (vlan-4)# tagged 10-20これは、"outer VLAN" の VLAN番号が 4、Webサーバ(群)が接続されているポートのポート番号が 10番〜20番ポートの場合の例です。
Webサーバが、outer VLAN において通信できるように設定する
Webサーバが "outer VLAN" に対して通信するには、Webサーバ側でも追加設定が必要になってきます。というのも、先ほどのスイッチの設定において、 Webサーバは tag VLAN で "outer VLAN" に参加するようにしたので、Webサーバがスイッチと "outer VLAN" 向けのパケットをやりとりするときは、VLAN tag をつけてるようにしなければならないのです。Linux において tag VLAN を扱うためには、VLAN ID に対応した仮想的なネットワークインタフェース(NIC)を作成してやります。この仮想的な NIC は物理的な NIC にひもづけられます。仮想 NIC はどの物理 NIC に対してひもづけるかと言うと、当然ながら先ほどスイッチの設定で "outer VLAN" に参加させたポートに接続している NIC に対してになります。
Linux において、tag VLAN 用の仮想 NIC を使うためには、8021q
ドライバモジュールが必要となります。カーネルを手元でコンパイルする際にこのドライバを含めるには
CONFIG_VLAN_8021Q CONFIG_VLAN_8021Q_GVRPの2つのオプションを有効にしてください(モジュールにしても組み込みにしても、どちらでも構いません)。
物理NICに紐づいた tag VLAN 用の仮想 NIC を作成するには、vconfig コマンドを使います。
# vconfig add eth0 4 # ip link set eth0.4 upこれで、Webサーバが "outer VLAN" 上でパケットをやりとりする準備が整いました。tcpdump などで eth0.4 を観察すれば、broadcast パケットなどが流れる様子が観察できるはずです。
Webサーバにおいて、上位ルータへの通信経路を設定する
Web サーバが直接上位ルータとパケットをやりとりするための環境は整いました。しかしこれだけでは OS は Webサーバの応答パケットを上位ルータに渡してはくれません。ルーティングを設定する必要があります。そして、前回の要件であげたように、default gateway を変更すること無く、DSRしたいパケットだけ上位ルータに対してルーティングするように設定する必要があります。
これを実現するためには、Linux のポリシールーティング機能を使います。これは、様々な条件に基づいてルーティング設定を切り替える機能で、Linux の他の機能の例に漏れず非常に柔軟な設定をすることができます。今回は Netfilter の mangle テーブル上で DSRしたいパケットに対してマーキングを行い、そのマーキングしたパケットに対してのみ適用する DSR専用のルーティングテーブルを、通常のルーティングテーブルとは別に作成しすることで、DSRを実現します。
Netfilter の mangle テーブルと、ポリシールーティング機能を使うためには、それぞれカーネルの機能を有効にする必要があります。mangle テーブルを使うには、モジュールがすでにある場合は iptable_mangle
モジュールを読み込みます(iptables コマンドで mangleテーブルを触れば自動的にロードされます)。無ければ CONFIG_IP_NF_MANGLE
を有効にして、カーネルを作り直してください。ポリシールーティング機能はカーネルモジュールにはできず、組込みにしなければなりません。お使いのカーネルの config を見て、CONFIG_IP_MULTIPLE_TABLES
が y
になっているか、確認してください。y
になってなければ、カーネルを作り直す必要があります。
カーネルの機能を有効にしたら設定していきましょう。まずは、DSRしたいパケットに対してマーキングをします。
# iptables -t mangle -A OUTPUT -s A.B.C.D -j MARK --set-mark 4
-s
オプションで DSRしたいパケット=ソースアドレスが A.B.C.D
のものを指定します。そして -j MARK --set-mark 4
でマーキングを施します。最後の 4 は DSRしたいパケットにつける識別ID になります。この後に設定するポリシールーティングにおいて、どのパケットに対して DSR用のルーティングテーブルを適用するのかを、この IDを使って指定します。
ポリシールーティングのための設定は、次の様になります。
# ip route add H.I.J.K/32 dev eth0.4 table 100 # ip route add default via H.I.J.K table 100 # ip rule add prio 100 fwmark 4 table 100 # ip route add H.I.J.K/32 dev eth0.4まず、デフォルトのルーティングテーブルとは別の、DSR用のルーティングテーブルを作成します。このテーブルの名前をここでは "100" にしています。最初の2行はこの "100" というルーティングテーブルに対して、ルーティング情報を追加しています。つまり、上位ルータ(アドレス=H.I.J.K)とは eth0.4 という NICを通じてやりとりできることを示し(1行目)、インターネットに対してパケットを送信するときは、その上位ルータを中継すればよいことを指定(2行目)します。
3行目は、先ほど Netfilter の mangle テーブルにて DSRしたいパケットに対してマーキングした 4
というIDを手がかりにして(fwmark 4 の部分です)、新しく作った "100" というルーティングテーブルを参照するよう、指示しています。つまり、mangle テーブルで 4 という ID を付与されたパケットは、3行目の指示にしたがって、1,2行目で新しく作った特別なルーティングテーブルを参照して、行き先が決定されるようになります。
Webサーバが、上位ルータに対して応答パケットを送信できるように設定する
さて最後に、上位ルータと Webサーバがパケットをやりとりする上で必要な、ちょっとした設定を追加します。先ほどは、IP上での(L3的)上位ルータとのやりとりする経路の設定をしました。通常はこれだけで問題なく上位ルータと Webサーバはやりとりができるのですが、今回の設定例では Webサーバの VLAN インタフェースに IPアドレスを振らなかったため、ちょっとした小細工が必要になります。どういうことかというと、上位ルータの MACアドレス=Ethrnetのアドレスが、このままでは Webサーバには分からないのです。通常は通信相手の MACアドレスは、 ARPプロトコルを使って自動的に取得されるのですが、Webサーバは上位ルータと直接通信するために必要な、同一のサブネットに属したIPアドレスを持っていないので、ARPプロトコルが使えないのです。しかたがないので、上位ルータの MAC アドレスは、人間が手動で与えてやることにします。やり方は、上位ルータの MACアドレスが hh:ii:jj:kk:ll:mm だとすれば
# arp -s -i eth0.4 H.I.J.K hh:ii:jj:kk:ll:mmとなります。
以上で、Webサーバが DSRするための設定が完成しました。これでもう負荷分散機がボトルネックになることはありません。