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で実現してくれます 上記でもちらっと匂わせていた話ですが、

www.slideshare.net

は、汎用的な話 です。つまり素直に multicast/broadcast をエミュレーションしようということです。

www.slideshare.net

は、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

元記事はこちら

unicast対応でよみがえる keepalived on VPC-EC2