続 カッコの付け方

AWSを始めとしたクラウドコンピューティング全般と、唯一神emacsにおける()の付け方についてだらだら書きます

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

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のチェック無効化LVS側にも必要です。
  • 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 } 配列になった!

ぐらいです。

!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もVPC(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を跨いでも全く問題ありません。keepalivedVRRPについては万事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