AWS を始め、ほとんどのパブリッククラウドは multicast が出来なくて不便。と言われてきましたが、だったら unicast でやってしまえば良い!という考え方が 2013年頃すでにありました。なぜ multicast をやりたいの?と言うと そうだね!、LVS + keepalived
だね! (あとはゴシッププロトコル) これまた2年前に EC2 + LVM (DSR) を実践してみたという素敵な解説があり、パッチを当てればいける
ということは知ってたけど、月日がながれて 今日 keepalived の総本山を見てみたら
http://www.keepalived.org/changelog.html
Release 1.2.8 ぐらいからunicast対応してますね。というか、今更開発が活発になってきたのか?これは。というわけで、最新版の 1.2.19を使ってみます。
予備知識
EC2 で multicast でググると日本語を含めて結構な情報が得られます。混乱しないよう先に言うと、keepalived の VRRPだけ
に限ると、パケットキャプチャ
やら tc
やらで自前実装して、事前準備するということは不要です。keepalived が VRRPを unicastで実現してくれます
上記でもちらっと匂わせていた話ですが、
は、汎用的な話
です。つまり素直に multicast/broadcast をエミュレーションしようということです。
は、keepalived 固有の話
です。ていうか手順。keepalived 側ですでに VRRP via unicast を実現しているので、パケットを覗いてMACアドレス分コピーして再送とかを自前で実装する必要はないです。
構成
LVS * 2 で VRRP 冗長
Web * 2
動作確認用 Client
というこれまたパクリ構成です。
- LVS の2つはお互いに VRRP で生きていることを広告します(正確には VRRP で投げるのは Master のみ、死亡を確認すると Backup が昇格)。重要な要素は VIP (フローティング IP )の存在です。この VIP を2台のうちどちらが持つかを決定します。
- さらにこの VIP は EIP/ENI とは違います。この方法は EIP/ENI のインスタンスへの付替えは発生しません。大事なことなので2度言います EIP/ENI の付替えは行いません。 しかし、ルートテーブルのみ書換は行います。詳細は後述。
- VIP という(VPC から見ると)異物で一旦リクエストを受けるので、 Src/Dest のチェック無効化 が VS 側にも必要です。
- Webサーバの死活監視も LVS(keepalived) で行います。
Web サーバ側は、DSR に備えて Src/Dest のチェック無効化と VIP 宛のパケットを、自分宛てとみなして受け取る設定が必要です。これも後述。
keepalived の実装
上記より、インストールさえ済めば、keepalived.conf の設定のみで、VRRP の部分は終わりです。そのた DSR を実現する部分やらは Sugawara 氏のスライド丸パクリです。
インストール
RPM を作りました、AmazonLinux 用のみです。気が向いたら CentOS 用も作ります。
http://bit.ly/1OZfBtE
でも SRPM があれば簡単なので、自力でなんとかなると思います。keepalived ぐらいでしたら、素直にソースビルドでもよいかと。
keepalived.conf
Sugawara 氏のスライドと違うところは
vrrp_unicast_bind => unicast_src_ip vrrp_unicast_peer => unicast_peer { xxx } 配列になった!
ぐらいです。
- LVS-1 172.31.18.164 MASTER
- LVS-2 172.31.18.163 BACKUP
- VIP 192.168.20.11 必ずVPC外のIPアドレス
!Configuration File for keepalived global_defs { router_id LVS_DEVEL } vrrp_instance VI_1 { state BACKUP # or MASTER interface eth0 virtual_router_id 51 priority 100 # MASTERは 101 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.20.11 } unicast_src_ip 172.31.18.163 unicast_peer { 172.31.18.164 } notify_master "/etc/keepalived/notify_master.sh" } virtual_server_group VSG_1 { 192.168.20.11 80 } virtual_server group VSG_1 { delay_loop 6 lb_algo rr lb_kind DR protocol TCP real_server 172.31.8.1 80 { weight 1 HTTP_GET { url { path / } } } ... }
切替時に走る スクリプト notify_master.sh EC2-Role でやったので、credential のベタ書きはやめました。ここはおこのみで。
#!/bin/bash VIP=192.168.20.11 ROUTE_TABLE_ID=rtb-[your routetable's id] INSTANCE_ID=`curl -s 169.254.169.254/latest/meta-data/instance-id` #export AWS_ACCESS_KEY_ID=... #export AWS_SECRET_ACCESS_KEY=... #export AWS_DEFAULT_REGION=ap-northeast-1 aws --region ap-northeast-1 ec2 delete-route --destination-cidr-block $VIP/32 --route-table-id $ROUTE_TABLE_ID aws --region ap-northeast-1 ec2 create-route --destination-cidr-block $VIP/32 --route-table-id $ROUTE_TABLE_ID --instance-id $INSTANCE_ID
VRRP動作確認
tcpdum -n vrrp
を叩いて、multicast 用 IP アドレスが出ず、上記で指定したローカル IP アドレスが出ていれば OK。他にもip a
を叩いて VIP を eth0 が持っていないことを確認します。2台とも VIP を持っていたら、スプリットブレイン状態です。多分設定ファイルか SG 設定が間違っています
VIP の切り替わりと RouteTable
結構複雑な話が混ざっているので、1つずつひも解きます。
- VIP のこだわり
VIP は必ず VPC の CIDR から外れたもの
を指定します。後で意味が分かります。 具体的にはクラスAを割り当てていれば 172.16.xxx.xxx とか 192.168.xxx.xxx クラスの違うローカル IP を当てるのが良いです。 - RouteTable が必要な理由
VIP の面倒は VRRP が見てくれるなら、RouteTable なんか要らないんじゃないか?それに VIP も PC(Subnet) 内の空いてる IP させば良いんじゃね?と思いますが、それは出来ないです。
VPC 内はそもそもブロードキャストが通りません、よって、MAC アドレスの割り出しのために ARP を打っているわけではないのです。これにより、この VIP がわかっていてもそこに至る経路が分かりません。それを RouteTable で何とかします。 - RouteTable のルール
RouteTable で宛先を指定できるならば、VPC の CIDR 内の IP でも良いんじゃね?と思いますが、これはやりたくても出来ません。実際にやればわかりますが、エラーが出ます。よって、VPC の CIDR 外の適当な IP アドレスを VIP として、これを RouteTable の経路とします。 - notify_master.sh スクリプトがやること
VIP の割当は keepalived が勝手にやりますので、経路の変更のみです。ルートテーブルで、VIP へ向き先を Master となった自分(インスタンスID > ENI)に向けます。
バックエンドの Web サーバ側の設定
DSR で動かすことを意識した設定が必要です。
– Src/Dest のチェックを無効にする
– iptables で VIP 宛のパケットを自分宛てにする
点を注意
iptables
iptables -t nat -A PREROUTEING -d 192.168.20.11 -j REDIRECT
動作と解説
上手く動いていると、Client マシンから curl 192.168.20.11
が正常に動作するはずです。この構成でできることを後述します。
どこでAZをまたいでも問題ない
- Client – LVS (Master) 間の AZ 跨ぎ
VIP へのアクセス経路は RouteTable に制御されています。よって、NAT インスタンスと同じような感覚で使えます。 - LVS 間の AZ 跨ぎ
結局ただの unicast で VRRP を投げるので、AZ を跨いでも全く問題ありません。keepalived の VRRP については万事 OK。
バックエンドサーバ – LVS の AZ 跨ぎ - 問題ないのはわかると思いますが、Client(A) – LVS(C) – Server(A) と最悪の場合でも、DSR でいけるので、コネクション確立後は Client – Server の AZ-A 内で通信ができるはずです。
まとめ
- keepalived の開発がなんか活性化してて、VRRP via unicast に対応。これにより keepalived = multicast 必須でなくなった
- VIP の付替えは keepalived がやってくれるけど、RouteTable の書き換えは AWS CLI でやる必要あり。EIP/ENI 付替えよりはスマートだと思う。
- AZ 跨ぎも問題ない。
multicast について
結局 multicast 関係無くなってしまいましたが、色々ためしてみました。
まだ途中ではありますが、パケットをキャプチャし、MAC アドレス分コピー送信という方法はあまり上手くいっていないです。(私のテストが間違っているだけかもしれませんが)
別解として、GREトンネルを張る方法も下記にドキュメントがあります。いずれ試してみようと思っています。
Overlay Multicast in Amazon Virtual Private Cloud : Articles & Tutorials : Amazon Web Services