AWSとSoftLayerをvxlanで繋いでみる

Japan SoftLayer Summit 2015があり、ちょっとSoftLayerに興味を持ったので、
触って見ました。
いつもならOracle RAC構築に走るのですが、
SoftLayerでのOracle RAC構築は以下のURLで紹介されていますので、今回は個人的にアツイvxlanを使って
AWSとSoftLayerをvxlanで繋いでみます。


Oracle RAC+Softlayerの記事はこちら
http://dba-ha.blogspot.jp/2014/07/softlayer-oracle-rac.html


なお、EC2 with vxlanについては、こちらのエントリで紹介していますので、vxlanについて解説はしません。
http://d.hatena.ne.jp/KNOPP/20141210/1418224473


今回の構成は以下の通りです。

AWS/SoftLayer ホスト名 OS(カーネル PublicIP 実インターフェース vxlan用IP vxlan用インターフェース
AWS A Amazon linux 2014.09.2.x86_64(3.14.27-25.47.amzn1.x86_64) 54.200.xx.xx eth0 192.168.1.1 vxlan0
SoftLayer B CentOS7(3.10.0-123.20.1.el7.x86_64) 158.85.xx.xx eth1 192.168.1.2 vxlan0

・事前準備
EC2側、SoftLayer側双方でUDP通信ができるようにしておく。
(ポート番号の指定方法が今のところ不明なので、UDP ALLということで、、、)



・EC2側

###Amazon Linuxにインストールされているiproute2はvxlan(unicast)に対応していないので、
###最新版をソースから入手しインストール
sudo su -
yum -y install git bison flex libdb-devel db4-devel gcc
git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
cd iproute2
./configure
make
make DESTDIR=/usr/share install

###vxlanの構成
#仮装デバイス vxlan0 vlanid 10 使用する物理デバイスはeth0
/usr/share/sbin/ip link add vxlan0 type vxlan id 10 dev eth0
#vxlan0にipアドレスを振る
/usr/share/sbin/ip addr add 192.168.1.1/24 broadcast 192.168.1.255 dev vxlan0
#vxlanインターフェースをアップさせる。
/usr/share/sbin/ip link set vxlan0 up
#ホストBを登録
/usr/share/sbin/bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 158.85.xx.xx

SoftLayer側

###CentOS7ではiproute2がvxlan(unicast)に対応しているので、iproute2のインストールの必要はありません。
###ただし、kernel 3.10.0-123.20.1.el7未満だとvxlanをunicastで使おうとするとKernelパニックが起きるので注意(kernel updateが必要)
###softlayerのCentOS7は2/14現在kernelは3.10.0-123.20.1.el7なので、問題無し。

###vxlanの構成
#仮装デバイス vxlan0 vlanid 10 使用する物理デバイスはeth1(public)
ip link add vxlan0 type vxlan id 10 dev eth1
#vxlan0にipアドレスを振る
ip addr add 192.168.1.2/24 broadcast 192.168.1.255 dev vxlan0
#vxlanインターフェースをアップさせる。
ip link set vxlan0 up
#ホストAを登録
bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 54.200.xx.xx

動作確認 ping ホストB→A

[root@centos ~]# ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=44.1 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=21.7 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=21.6 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=21.7 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=21.8 ms


動作確認 ping ホストA→B

[root@ip-172-31-39-175 iproute2]# ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=22.0 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=21.8 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=21.9 ms
64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=21.9 ms
64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=21.9 ms

動作確認 ホストBへ追加でIP(192.168.1.3/24)付与

[root@centos ~]#ip addr add 192.168.1.3/24 broadcast 192.168.1.255 dev vxlan0

動作確認 ping ホストA→B (追加したIP)

[root@ip-172-31-39-175 iproute2]# ping 192.168.1.3
PING 192.168.1.3 (192.168.1.3) 56(84) bytes of data.
64 bytes from 192.168.1.3: icmp_seq=1 ttl=64 time=45.3 ms
64 bytes from 192.168.1.3: icmp_seq=2 ttl=64 time=22.6 ms
64 bytes from 192.168.1.3: icmp_seq=3 ttl=64 time=22.7 ms
64 bytes from 192.168.1.3: icmp_seq=4 ttl=64 time=22.6 ms
64 bytes from 192.168.1.3: icmp_seq=5 ttl=64 time=22.7 ms


こんな感じでSoftLayer、AWS間で仮想L2ができました。


なお、SoftLayer、AWS間の通信は暗号化されていませんので、ご利用は計画的に。

RHEL7/CentOS7/OEL7でvxlanを使うときの注意点

ここらへんの記事でvxlanを紹介していますが、
RHEL7/CentOS7/OEL7で使用する場合は注意点があります。

kernel 3.10.0-123.20.1.el7未満ですと、以下の不具合に該当し、ユニキャストモードでvxlanを使おうとするとカーネルパニックが発生するようです。


If the vxlan interface is created without explicit group definition,there are corner cases which may cause kernel panic.
https://lkml.org/lkml/2014/4/18/172 *



RHEL7/CentOS7/OEL7でvxlanを使いたい場合は最新のカーネルまでアップデートして使うのが無難です。

*kernel 3.12となっていますが、RHEL7/CentOS7/OEL7ではkernel 3.10にバックポートされており該当します。


また自分でハマりそうなので、ここに記録しておきます。

なお、Amazon Linux AMI 2014.09.2 (kernel 3.14.x)は該当しないようです。

EC2 with vxlan (Oracle RAC on EC2)

JPOUG Advent Calender 2014(http://jpoug.doorkeeper.jp/events/17313) の11日目
AWS Advent Calendar 2014 (http://qiita.com/advent-calendar/2014/aws) の11日目
のクロスエントリです。



AWSはとても便利ですごく好きなのですが、一つだけ不満な点があります。
それが、VPC上でmulticast/broadcastがサポートされていない点です。
multicast/broadcastをなんとか実現する為に、GREOpenVPN、tinc等のトンネリング技術が使われたり
するのですが、ここで紹介するvxlanもまた、そのトンネリング技術のひとつです。

vxlanについて、詳細は以下の@ITの記事を参照ください。


VXLANが登場した理由、他の実装との違い、特徴を整理しよう (1/3)
http://www.atmarkit.co.jp/ait/articles/1412/03/news009.html


Linuxでvxlanが実装された当初はマルチキャストが必要だったのですが、
kernel 3.10ではユニキャストでノード間の接続ができます(Allow setting destination to unicast address)。(それ以前はマルチキャストが必要)
なんと、 このユニキャストで接続できるモードは、kernel 2.6.32-431(RHEL/CentOS/OEL 6.5)以降バックポートされているのです!!このvxlan、個人で確認するかぎりでは、物理インターフェースよりも若干スループットが落ちる程度で非常にパフォーマンスが良いです。(OpenVPNやtincよりもスループットがでます!)
これはEC2で使わない手はありませんね。

というわけで、RHEL/CentOS/OEL 6.5でのEC2 with vxlanの使い方をさらっとここで説明します。
(たぶん、kernel 3.10以降でも手順は同じハズ、、、、、)


○準備
RHEL/CentOS/OEL 6.5のkernel(2.6.32-431 否uek)はvxlanに対応していますが、ipコマンド(iproute2)が対応していませんので、
最新版を取得し、インストールします。
なお、従来のバージョンはそのまま残しておいて、最新バージョンを別ディレクトリ(/usr/share)にインストールします。

yum -y install git bison flex db4-devel
git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
cd iproute2
./configure
make
make DESTDIR=/usr/share install


○使い方
以下の構成とします

ホスト名 実IP vxlan0
ホストA 172.31.10.100 172.16.1.1
ホストB 172.31.10.101 172.16.1.2
ホストC 172.31.10.102 172.16.1.3

仮装ネットワークは 172.16.0.0/20 vxlan0はvxlanid 10


以下のコマンドを実行します。
ホストA

#仮装デバイス vxlan0 vlanid 10 使用する物理デバイスはeth0
/usr/share/sbin/ip link add vxlan0 type vxlan id 10 dev eth0
#vxlan0にipアドレスを振る( 172.16.1.1/20 broadcast 172.16.15.255)
/usr/share/sbin/ip addr add 172.16.1.1/20 broadcast 172.16.15.255 dev vxlan0
#vxlanインターフェースをアップさせる。
/usr/share/sbin/ip link set vxlan0 up
#ホストB、Cを登録
bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 172.31.10.101
bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 172.31.10.101


ホストB

#仮装デバイス vxlan0 vlanid 10 使用する物理デバイスはeth0
/usr/share/sbin/ip link add vxlan0 type vxlan id 10 dev eth0
#vxlan0にipアドレスを振る( 172.16.1.2/20 broadcast 172.16.15.255)
/usr/share/sbin/ip addr add 172.16.1.2/20 broadcast 172.16.15.255 dev vxlan0
#vxlanインターフェースをアップさせる。
/usr/share/sbin/ip link set vxlan0 up
#ホストA、Cを登録
bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 172.31.10.100
bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 172.31.10.102

ホストC

#仮装デバイス vxlan0 vlanid 10 使用する物理デバイスはeth0
/usr/share/sbin/ip link add vxlan0 type vxlan id 10 dev eth0
#vxlan0にipアドレスを振る( 172.16.1.3/20 broadcast 172.16.15.255)
/usr/share/sbin/ip addr add 172.16.1.3/20 broadcast 172.16.15.255 dev vxlan0
#vxlanインターフェースをアップさせる。
/usr/share/sbin/ip link set vxlan0 up
#ホストA、Bを登録
bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 172.31.10.100
bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 172.31.10.101


スループットの確認
(検証の都合上、実IPは上記IPとは異なりますので雰囲気だけ。 SR-IOVを有効にしています。)

m3.medium

実IP
[root@db002 ~]# iperf -c 172.31.14.159
------------------------------------------------------------
Client connecting to 172.31.14.159, TCP port 5001
TCP window size: 92.6 KByte (default)
------------------------------------------------------------
[  3] local 172.31.6.190 port 60109 connected with 172.31.14.159 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   463 MBytes   388 Mbits/sec

vxlan
[root@db002 ~]# iperf -c 172.16.1.1
------------------------------------------------------------
Client connecting to 172.16.1.1, TCP port 5001
TCP window size: 92.1 KByte (default)
------------------------------------------------------------
[  3] local 172.16.1.2 port 48250 connected with 172.16.1.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   460 MBytes   386 Mbits/sec

m3.large
実IP
[root@db002 ~]# iperf -c 172.31.11.88
------------------------------------------------------------
Client connecting to 172.31.11.88, TCP port 5001
TCP window size: 92.6 KByte (default)
------------------------------------------------------------
[  3] local 172.31.15.237 port 20624 connected with 172.31.11.88 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   853 MBytes   715 Mbits/sec

vxlan
[root@db002 ~]# iperf -c 172.16.1.1
------------------------------------------------------------
Client connecting to 172.16.1.1, TCP port 5001
TCP window size: 92.1 KByte (default)
------------------------------------------------------------
[  3] local 172.16.1.2 port 62692 connected with 172.16.1.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   848 MBytes   711 Mbits/sec

→物理インターフェースよりも若干スループットが落ちる程度です。



最後にvxlanを使うとこんなことができる一例です
Oracle Linux 6.5(HVM SRIOV有効化済み) Oracle Database oracle 12.1.0.1 での64ノードクラスタ



参考文献
http://diary.atzm.org/20140416.html
http://www.atmarkit.co.jp/ait/articles/1412/03/news009.html



追記:
vxlanを使う場合に、OS起動と同時にvxlanインターフェース有効化する方法ないですかね?
( ifcfg-xxxx を使うイメージで )
みつからないんで、今回はinit script書いちゃいましたけど。

openvswitch on EC2 その2

まずは、宣伝から

まだ席に余裕がありますので、興味ある方は是非
JPOUG> SET EVNETS 20140907


詳細は、こちら
JPOUG> SET EVNETS 20140907


前回公開したエントリでは、以下の問題がありました
・通信が不安定になることがある
→ブリッジインターフェースを二つに分ける必要がある
・EC2メタデータ(169.254.169.254)にアクセスできない
→br0から169.254.169.254にアクセスするrouteを低メトリックで登録
・インターネットにアクセスできない
デフォルトゲートウェイの指定が必要



前回分も含めて設定をやってくれるスクリプトを作成しましたので、公開します。
https://gist.github.com/s4ragent/c73655fbf6b75096c250


CentOS/RHEL限定です。(Oracle LinuxはUEKだと動かないと思います)
使い方

OVSのダウンロード/インストール
sh ec2openvswitch ovsinstall


ブリッジインターフェイスの作成/初期化
sh ec2openvswitch ovsinit


トンネルの作成
sh ec2openvswitch ovssetgre リモートIP1 リモートIP2 ・・・・


内部インターフェースの作成
sh ec2openvswitch ovscreateint 作成するデバイス名 IPアドレス NETMASK
*デバイス名は 英字+数字(0以外) 数字は vlan-idになります
例 sh ec2openvswitch ovscreateint vlan10 192.168.0.11 255.255.255.0

openvswitch on EC2

タイトルと話がズレますが、まずは、宣伝から


JPOUG> SET EVNETS 20140907


IIJさんの新しいオフィスが会場となります。みなさま奮ってご参加ください。

詳細は、こちら
JPOUG> SET EVNETS 20140907



さて、本題に入ります。


openvswtich をEC2で使う方法がどこ探しても見つからなかったので、真面目に調べてみました。
一応使えるところ(パフォーマンスは別として)までいったので軽くメモします。

ポイントは
・ブリッジのMACをeh0と同じにする
・ブリッジを固定IPにする。
です。


なお、Amazon Linuxでは動きません。
また、eth0にブリッジしているので、手順を誤ると接続不能になりますので、試す際には十分注意してください


環境
AMI ami-4c85ee7c(CentOS 6.5 HVM SRIOV) ・・・・ @understeer さんの公開しているCent OS 6.5(HVM) oregonリージョン(東京だったら ami-7fa6fe7e)
openvswtich 1.10(RDOから入るもの)
openvswtich間はgreで接続
tap0/tap1はvlanで分離

構成

ホスト名 実IP tap0 tap1
ホストA 172.31.10.220 192.168.0.11 192.168.1.11
ホストB 172.31.10.221 192.168.0.12 192.168.1.12
ホストC 172.31.10.222 192.168.0.13 192.168.1.13


インストール(各ホスト共通)

yum -y install https://repos.fedorapeople.org/repos/openstack/openstack-icehouse/rdo-release-icehouse-4.noarch.rpm
yum -y install openvswitch
service openvswitch start
chkconfig openvswitch on

ブリッジの設定(各ホスト共通)

LANG=C
#NETMASKの取得
MyMASK=`ifconfig eth0 | grep 'inet addr' | awk -F '[: ]' '{print $19}'`
#eth0 IPの取得
MyIP=`ifconfig eth0 | grep 'inet addr' | awk -F '[: ]' '{print $13}'`
#eth0のMACアドレスの取得
MyHWADDR=`ifconfig eth0 | grep 'Link encap' | awk '{print $5}'`
ovs-vsctl add-br br0

cat > /etc/sysconfig/network-scripts/ifcfg-br0 <<EOF
DEVICE=br0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
IPADDR=$MyIP
NETMASK=$MyMASK
EOF

sed -i 's/BOOTPROTO/#BOOTPROTO/'  /etc/sysconfig/network-scripts/ifcfg-eth0
echo "MTU=1546" >> /etc/sysconfig/network-scripts/ifcfg-eth0

ovs-vsctl set bridge br0 other-config:hwaddr=$MyHWADDR
ovs-vsctl add-port br0 eth0 && service network restart

最後のnetwork restartで一瞬接続が切れます。

openvswtich間接続(ホストA)

ovs-vsctl add-port br0 gre0 -- set interface gre0 type=gre options:remote_ip=172.31.10.221
ovs-vsctl add-port br0 gre1 -- set interface gre1 type=gre options:remote_ip=172.31.10.222
ovs-vsctl set bridge br0 stp_enable=true

最後のovs-vsctl set bridge br0 stp_enable=trueで応答が10秒ほど途絶えます。

openvswtich間接続(ホストB)

ovs-vsctl add-port br0 gre0 -- set interface gre0 type=gre options:remote_ip=172.31.10.220
ovs-vsctl add-port br0 gre1 -- set interface gre1 type=gre options:remote_ip=172.31.10.222
ovs-vsctl set bridge br0 stp_enable=true

最後のovs-vsctl set bridge br0 stp_enable=trueで応答が10秒ほど途絶えます。

openvswtich間接続(ホストC)

ovs-vsctl add-port br0 gre0 -- set interface gre0 type=gre options:remote_ip=172.31.10.220
ovs-vsctl add-port br0 gre1 -- set interface gre1 type=gre options:remote_ip=172.31.10.221
ovs-vsctl set bridge br0 stp_enable=true

最後のovs-vsctl set bridge br0 stp_enable=trueで応答が10秒ほど途絶えます。

tap設定(ホストA)

cat > /etc/sysconfig/network-scripts/ifcfg-tap0 <<EOF
DEVICE=tap0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
IPADDR=192.168.0.11
NETMASK=255.255.255.0
EOF

cat > /etc/sysconfig/network-scripts/ifcfg-tap1 <<EOF
DEVICE=tap1
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
IPADDR=192.168.1.11
NETMASK=255.255.255.0
EOF

ovs-vsctl add-port br0 tap0 tag=1 -- set Interface tap0 type=internal
ovs-vsctl add-port br0 tap1 tag=2 -- set Interface tap1 type=internal
ifconfig tap0 192.168.0.11
ifconfig tap1 192.168.1.11

tap設定(ホストB)

cat > /etc/sysconfig/network-scripts/ifcfg-tap0 <<EOF
DEVICE=tap0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
IPADDR=192.168.0.12
NETMASK=255.255.255.0
EOF

cat > /etc/sysconfig/network-scripts/ifcfg-tap1 <<EOF
DEVICE=tap1
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
IPADDR=192.168.1.12
NETMASK=255.255.255.0
EOF

ovs-vsctl add-port br0 tap0 tag=1 -- set Interface tap0 type=internal
ovs-vsctl add-port br0 tap1 tag=2 -- set Interface tap1 type=internal
ifconfig tap0 192.168.0.12
ifconfig tap1 192.168.1.12

tap設定(ホストC)

cat > /etc/sysconfig/network-scripts/ifcfg-tap0 <<EOF
DEVICE=tap0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
IPADDR=192.168.0.13
NETMASK=255.255.255.0
EOF

cat > /etc/sysconfig/network-scripts/ifcfg-tap1 <<EOF
DEVICE=tap1
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
IPADDR=192.168.1.13
NETMASK=255.255.255.0
EOF

ovs-vsctl add-port br0 tap0 tag=1 -- set Interface tap0 type=internal
ovs-vsctl add-port br0 tap1 tag=2 -- set Interface tap1 type=internal
ifconfig tap0 192.168.0.13
ifconfig tap1 192.168.1.13


参考サイト
http://trickycloud.wordpress.com/2014/05/02/multiple-private-networks-with-open-vswitch-gre-tunnels-and-libvirt/

EC2で仮想IPにチャレンジ(現時点では諦め)

http://d.hatena.ne.jp/KNOPP/20140728/1406562348

の続き。

プログラムが異常終了するのは、ARPに対応していなかったようです。
(ARPパケットだとframe.ip_headerがNILになるので、異常終了してた)

そこで、ARPパケットでも対応したのが以下スクリプトになります。

#!/usr/bin/ruby
require 'rubygems'
require 'packetfu'
 
dev = ARGV[0]
mac=`ip link show #{dev} | awk '/ether/ {print $2}'`.chomp
ARGV.shift
dests = ARGV
 
cap = PacketFu::Capture.new(
          :timeout => 4000,
          :iface => dev, :start => true,
          :filter => "ether src #{mac} and ether[0] & 1 = 1")
loop do
  cap.stream.each do |pkt|
    frame = PacketFu::IPPacket.parse(pkt)
    i = 0   

    dests.each do |dest|
        frame.eth_daddr = dest
        if frame.proto[1].to_s == "IP" then     
                frame.ip_header.ip_id = frame.ip_header.ip_id + i
                frame.ip_header.ip_sum = frame.ip_header.ip_calc_sum()
                i = i + 1       
        end     
        frame.to_w(dev)
    end
  end
end


これで大丈夫。。。。。

と思いきや。残念なことにVPC側ではブロードキャストだけでなく、ARPパケットもいじっているようで、
multi-unicastしたARPパケットは、VPC側でmanageしているIPアドレスの解決要求以外は届きません。
tcpdumpで確認した結果)

なので、現時点では、multi-unicastを使ってもVIPを使うのは難しいということになります。


諦めてtincで頑張るしかないか。。。。

EC2で仮想IPにチャレンジ(未完)

twitterでは、度々呟いていますが、tincで30ノードRACを越えるべく頑張りつつ、
限界を感じる今日この頃です。
(30ノードを越えると、仮想L2ネットワークが不安定になり、config.shやroot.shが失敗したり、
node evictionが頻発する。。。。。)

そんな中、非常に面白いエントリがあったので、
RAC on EC2に応用できないかと少し検証してみました。

EC2-VPCでIPマルチキャスト/ブロードキャストを実現する(後編)
http://moomindani.wordpress.com/2014/07/22/ec2-vpc_multicast_broadcast_2/

→これで仮想IP扱うことができれば、tincに比べてオーバーヘッドが少ない(はず)なので、
なんとか、ノード数を増やせるかも。。。


環境
ホストA IP 172.31.1.159 (MAC 0a:30:35:58:2e:4d)
ホストB IP 172.31.1.160 (MAC 0a:96:80:90:16:ee)

※ともにAmazon Linux(amzn-ami-hvm-2014.03.2.x86_64-ebs) t2.micro使用


○セットアップ
ほぼそのまま以下のURLの手順で実行しています。
http://moomindani.wordpress.com/2014/07/22/ec2-vpc_multicast_broadcast_2/


○検証内容
・ホストB に仮想IPを割り当てて、使用できるか確認
具体的には、ホストBで  ifconfig eth0:0 172.31.1.161 を実行し、
ホストAから ping 172.31.1.161 を実行するだけです。

ホストB
#ruby mcast.rb eth0 0a:30:35:58:2e:4d 0a:96:80:90:16:ee &
#ifconfig eth0:0 172.31.1.161

ホストA
#ruby mcast.rb eth0 0a:30:35:58:2e:4d 0a:96:80:90:16:ee &
#ping 172.31.1.161

○結果

PING 172.31.1.161 (172.31.1.161) 56(84) bytes of data.
/usr/local/rvm/gems/ruby-1.9.3-p484/gems/packetfu-1.1.10/lib/packetfu/packet.rb:508:in `method_missing': undefined method `ip_header' for nil:NilClass (NoMethodError)
        from mcast.rb:21:in `block (3 levels) in <main>'
        from mcast.rb:19:in `each'
        from mcast.rb:19:in `block (2 levels) in <main>'
        from mcast.rb:15:in `each'
        from mcast.rb:15:in `block in <main>'
        from mcast.rb:14:in `loop'
        from mcast.rb:14:in `<main>'
From 172.31.1.160 icmp_seq=1 Destination Host Unreachable
From 172.31.1.160 icmp_seq=2 Destination Host Unreachable

プログラムが異常終了してしまいました。
なんとなくarpっぽい気がするので、
ホストBからホストAのarpエントリを削除後、ホストBへのpingで再現しました。

ホストB
#arp -a

ip-172-31-1-161.us-west-2.compute.internal (172.31.1.161) at <incomplete> on eth0
ip-172-31-0-2.us-west-2.compute.internal (172.31.0.2) at 0a:99:3b:60:39:13 [ether] on eth0
ip-172-31-0-1.us-west-2.compute.internal (172.31.0.1) at 0a:99:3b:60:39:13 [ether] on eth0
ip-172-31-1-159.us-west-2.compute.internal (172.31.1.159) at 0a:30:35:58:2e:4d [ether] on eth0
ip-172-31-1-255.us-west-2.compute.internal (172.31.1.255) at <incomplete> on eth0
instance-data.us-west-2.compute.internal (169.254.169.254) at 0a:99:3b:60:39:13 [ether] on eth0
ip-172-31-0-255.us-west-2.compute.internal (172.31.0.255) at <incomplete> on eth0

#arp -d ip-172-31-1-159.us-west-2.compute.internal

#ruby mcast.rb eth0 0a:30:35:58:2e:4d 0a:96:80:90:16:ee &

# ping 172.31.1.159

PING 172.31.1.159 (172.31.1.159) 56(84) bytes of data.
64 bytes from 172.31.1.159: icmp_seq=1 ttl=64 time=0.615 ms
/usr/local/rvm/gems/ruby-1.9.3-p484/gems/packetfu-1.1.10/lib/packetfu/packet.rb:508:in `method_missing': undefined method `ip_header' for nil:NilClass (NoMethodError)
        from mcast.rb:21:in `block (3 levels) in <main>'
        from mcast.rb:19:in `each'
        from mcast.rb:19:in `block (2 levels) in <main>'
        from mcast.rb:15:in `each'
        from mcast.rb:15:in `block in <main>'
        from mcast.rb:14:in `loop'
        from mcast.rb:14:in `<main>'
64 bytes from 172.31.1.159: icmp_seq=2 ttl=64 time=0.599 ms
64 bytes from 172.31.1.159: icmp_seq=3 ttl=64 time=0.523 ms

arpエントリがある状態で再度プログラムを実行しても異常終了しません。
#ruby mcast.rb eth0 0a:30:35:58:2e:4d 0a:96:80:90:16:ee &
#ping 172.31.1.159

PING 172.31.1.159 (172.31.1.159) 56(84) bytes of data.
64 bytes from 172.31.1.159: icmp_seq=1 ttl=64 time=0.632 ms
64 bytes from 172.31.1.159: icmp_seq=2 ttl=64 time=0.589 ms
64 bytes from 172.31.1.159: icmp_seq=3 ttl=64 time=0.631 ms
64 bytes from 172.31.1.159: icmp_seq=4 ttl=64 time=0.597 ms
64 bytes from 172.31.1.159: icmp_seq=5 ttl=64 time=0.476 ms
64 bytes from 172.31.1.159: icmp_seq=6 ttl=64 time=0.621 ms
64 bytes from 172.31.1.159: icmp_seq=7 ttl=64 time=0.522 ms
64 bytes from 172.31.1.159: icmp_seq=8 ttl=64 time=0.544 ms
64 bytes from 172.31.1.159: icmp_seq=9 ttl=64 time=0.584 ms

なんとなく発生条件は分かりましたが、どうしたものか。。。。
ネットワークの知識は薄く、packetfuも初めて使ったくらいなので、
これ以上頑張るのはしんどいかも。


P.S.
今回、初めてt2.micro使ってみましたが、パフォーマンスの良さに感激です。
rvm/ruby-1.9.3のコンパイルがt1.microに比べ、体感で3倍以上早く感じました。