GoBGPでEVPN/VXLANを試す
SFC-RG Advent Calendar 2017 - Qiita の9日目の記事です。EVPNと呼ばれるL2VPNを実現するプロトコルの紹介と、仮想環境上でGoBGPを使って、EVPN/VXLANを試したときの記録になります。
EVPNについて
EVPN (Ethernet VPN) は RFC 7432 で標準化されたL2VPNを実現するプロトコルです。既存のVPNの制約を解決できることからISPやDC事業者を中心に注目を浴びている技術の一つです。用途としては広域イーサーネットサービスの提供におけるL2VPNの実現やDC間の接続が挙げられます。この数年でベンダーの実装が整ってきたため、ここから数年で広くデプロイメントされていく技術ではないかと個人的には考えています。
EVPNの特徴としてコントロールプレーンとデータプレーンが分離されていることを挙げることができます。具体的にはコントロールプレーンにBGP(MP-BGP)を用いてMACアドレスの学習を行うため、BUMトラフィックを抑制することができると同時に、今回紹介するVXLANやMPLS、PBBなど、用途に応じたデータプレーンを選択することができるというメリットがあります。例えばVPLSでは対向のMACアドレスを学習する上でL2の情報をフラッディングしたり、シグナリングにLDPを用いるものとBGPを用いるもので相互接続性がないといった問題がありましたが、EVPNを用いる事でこうした課題を解決することができ、スケールアウトが容易なVPNを実現することが可能であることが期待されています。そのほか、マルチホーム環境下において Active-Active の構成を取ることができることもEVPNのメリットの1つと言うことができるでしょう。
EVPNに関連した日本語の情報は少ないのですが、詳細については EVPN: Intro to next gen L2VPN - Packet Pushers や RFC 7432 - BGP MPLS-Based Ethernet VPN が参考になると思います。
VXLANについて
今回の検証ではデータプレーンにVXLANを用います。VXLANではイーサネットフレームをVXLANヘッダでカプセリングすることで、レイヤ3のIPネットワーク上に仮想的なレイヤ2のネットワークを構築することを可能にします。また、ネットワークの識別に24bit長のVNI (VXLAN Network ID) と呼ばれる識別子を用いることで、最大224個までネットワークを分割することができるため、212個までしかネットワークを分割することのできないVLANよりも多くのネットワークを識別をすることができます。
VXLANではVTEPを検出するためにマルチキャストを使っていますが、EVPNを用いる事でマルチキャストを透過的に扱うことができます。そのため、マルチキャストが使えない環境下においてもVXLANによるL2延伸を行うことができるというメリットがあります。
VXLANの詳細については JANOG37 :: VXLANチュートリアル の資料が参考になるので、興味がありましたらご一読ください。
GoBGPを用いた検証
こうした特徴を持つEVPNですが、GoBGPとGoPlaneを使うことで手元でも動作させることができます。今回はVagrantを使って仮想マシン (Ubuntu 16.04) を3台立ち上げ、GoBGPを用いたEVPN/VXLANの動作検証を行いました。
検証に用いたトポロジーは下記の通りになります。仮想マシン3台をPCルータ(PE)として動作させ、それぞれのゲストOS内でNamespaceを分割し、CEとして動作させています。また、ゲストOSではそれぞれGoBGPでBGPデーモンを動かし、それぞれのVMごとにBGP neighborを確立させています。CEとして動作している Network Namespace に属する仮想インターフェースは同じレイヤ2ネットワーク(192.168.1.0/24)に所属しています。
また、検証では本トポロジーにおける gobgp1からgobgp2 および gobgp1からgobgp3 のスループットを iperf を使って計測しました。
環境のセットアップ
下記のリポジトリに今回の検証で用いたVagrantfileとセットアップの手順を置いてあります。環境のセットアップに関しては README.md を参照してください。
github.com
BGPのステータス確認
EVPNではBGP経由でL2の情報を学習するため、各VMでBGPが Establish しているかどうかを確認します。
root@gobgp1:~# gobgp neigh Peer AS Up/Down State |#Received Accepted 10.0.12.20 65000 00:00:32 Establ | 2 2 10.0.23.20 65000 00:00:09 Establ | 2 2
ピア同士で BGP status が Establish されていれば OK です。
VTEPの状態の確認
root@gobgp1:~# gobgp global rib -a evpn Network Next Hop AS_PATH Age Attrs *> [type:multicast][rd:65000:10][etag:10][ip:1.1.1.1]0.0.0.0 00:01:20 [{Origin: i} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 1.1.1.1} {Extcomms: [65000:10]}] *> [type:multicast][rd:65000:10][etag:10][ip:2.2.2.2]10.0.12.20 00:01:01 [{Origin: i} {LocalPref: 100} {Extcomms: [65000:10]} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 2.2.2.2}] *> [type:multicast][rd:65000:10][etag:10][ip:3.3.3.3]10.0.23.20 00:00:38 [{Origin: i} {LocalPref: 100} {Extcomms: [65000:10]} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 3.3.3.3}]
このときはまだL2の情報は学習されていません。
gobgp1から gobgp2, gobgp3 にICMPパケットを送信する
gobgp1 の network namespace 内の仮想インターフェース(192.168.1.1) から
- gobgp2 の network namespace 内の仮想インターフェース(192.168.1.4)
- gobgp3 の network namespace 内の仮想インターフェース(192.168.1.6)
へICMPパケットを送信してみます。
gobgp1 から gobgp2
root@gobgp1:~# ip netns exec vxlan ping -c 5 192.168.1.4 PING 192.168.1.4 (192.168.1.4) 56(84) bytes of data. 64 bytes from 192.168.1.4: icmp_seq=1 ttl=64 time=1003 ms 64 bytes from 192.168.1.4: icmp_seq=2 ttl=64 time=0.637 ms 64 bytes from 192.168.1.4: icmp_seq=3 ttl=64 time=0.735 ms 64 bytes from 192.168.1.4: icmp_seq=4 ttl=64 time=0.621 ms 64 bytes from 192.168.1.4: icmp_seq=5 ttl=64 time=0.988 ms --- 192.168.1.4 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4010ms rtt min/avg/max/mdev = 0.621/201.353/1003.788/401.217 ms
gobgp1 から gobgp3
root@gobgp1:~# ip netns exec vxlan ping -c 5 192.168.1.6 PING 192.168.1.6 (192.168.1.6) 56(84) bytes of data. 64 bytes from 192.168.1.6: icmp_seq=2 ttl=64 time=4.86 ms 64 bytes from 192.168.1.6: icmp_seq=3 ttl=64 time=1.20 ms 64 bytes from 192.168.1.6: icmp_seq=4 ttl=64 time=0.857 ms 64 bytes from 192.168.1.6: icmp_seq=5 ttl=64 time=0.647 ms --- 192.168.1.6 ping statistics --- 5 packets transmitted, 4 received, 20% packet loss, time 4006ms rtt min/avg/max/mdev = 0.647/1.894/4.869/1.729 ms
最初のパケットを送信するときに時間がかかりますが、その後で疎通性が取れていることがわかります。
再度VTEPの状態の確認してみる
root@gobgp1:~# gobgp global rib -a evpn Network Next Hop AS_PATH Age Attrs *> [type:macadv][rd:0:0][esi:single-homed][etag:10][mac:a2:42:36:45:55:07][ip:<nil>][labels:[10]]0.0.0.0 00:00:31 [{Origin: i} {Extcomms: [VXLAN]}] *> [type:macadv][rd:0:0][esi:single-homed][etag:10][mac:be:5e:f1:3a:50:a8][ip:<nil>][labels:[10]]10.0.12.20 00:00:31 [{Origin: i} {LocalPref: 100} {Extcomms: [VXLAN]}] *> [type:macadv][rd:0:0][esi:single-homed][etag:10][mac:c6:2a:b1:40:ed:07][ip:<nil>][labels:[10]]10.0.23.20 00:00:22 [{Origin: i} {LocalPref: 100} {Extcomms: [VXLAN]}] *> [type:multicast][rd:65000:10][etag:10][ip:1.1.1.1]0.0.0.0 00:03:35 [{Origin: i} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 1.1.1.1} {Extcomms: [65000:10]}] *> [type:multicast][rd:65000:10][etag:10][ip:2.2.2.2]10.0.12.20 00:03:16 [{Origin: i} {LocalPref: 100} {Extcomms: [65000:10]} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 2.2.2.2}] *> [type:multicast][rd:65000:10][etag:10][ip:3.3.3.3]10.0.23.20 00:02:53 [{Origin: i} {LocalPref: 100} {Extcomms: [65000:10]} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 3.3.3.3}]
正しくL2の情報が広報され、学習できたことが確認できました。
スループットの評価
参考までにiperfを用いてスループットを計測した際の検証結果を下図に示します。オーバーレイのMTUが1450、アンダーレイのMTUを1500に設定しているため、パケットサイズを 64, 100, 200, …, 1500 に変動させて計測しました。
ショートパケットではほぼ同等の性能、MTUサイズが大きくなっても9割ほどの性能が出ていることが確認できました。実環境での検証はできていませんが、実運用でも耐えられるのではないでしょうか。
終わりに
本記事ではGoBGPを利用して仮想環境上でのEVPN/VXLANの動作検証を行い、実際にBGP経由でL2の情報を交換し、トラフィックの送受信をするところまで確認しました。
ただ、シングルホームの構成でのみの検証しかできていないので、今度はマルチホームにしたときの Active-Standby の挙動、Active-Active の挙動を確認してみたいと思います。