環境
以下のような VXLAN ネットワークを構築します.
2 台の物理マシンそれぞれに Linux Network Namespace (netns) を作成し,それらを EVPN / VXLAN で接続します.
Underlay: 192.168.40.0/24
Overlay: 10.0.1.0/24
_____________________ _____________________
| host1 | | host2 |
| ___________ | | ___________ |
| | netns5 | | | | netns6 | |
| | | | | | | |
| | _____ | | | | _____ | |
| |__|VXLAN|__| | | |__|VXLAN|__| |
| |_____| | | |_____| |
| 10.0.1.5: ____ | | 10.0.1.6: ____ |
|__________:__|p1p1|__| |__________:__|p1p1|__|
: |____|192.168.40.5 : |____|192.168.40.6
____________:_____|_____________________:_____|_______________
:...........................:
Go
GoBGP や GoPlane を使うために Golang や Glide をインストールしておきます.
Golang
Getting Started - The Go Programming Language
公式サイトからダウンロードしてインストールします.
apt install 等を使うと古いバージョンの go がインストールされてしまうそうです.
$ wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.11.linux-amd64.tar.gz
$ echo 'export GOPATH=$HOME/.golang' >> $HOME/.profile
$ echo 'export PATH=$PATH:$GOPATH/bin:/usr/local/go/bin' >> $HOME/.profile
$ source $HOME/.profile
Glide
GoPlane の依存関係を解決するのに必要です.
$ sudo apt install git gcc
$ go get github.com/Masterminds/glide
GoPlane, GoBGP
- osrg/goplane: an agent for configuring linux network stack via GoBGP
- osrg/gobgp: BGP implemented in the Go Programming Language
順番にインストールしていきます.最後に $GOPATH/bin
を確認しましょう.
goplane は GoBGP のデーモンである gobgpd を含んでいますが,今回は gobgp
コマンドを使用するために gobgp も別途インストールします.
# goplane
$ go get github.com/osrg/goplane # 警告が出力される
$ cd $GOPATH/src/github.com/osrg/goplane; glide install
$ go get github.com/osrg/goplane # 再度入力する
# gobgp
$ go get github.com/spf13/cobra
$ go get github.com/kr/pretty
$ cd vendor/github.com/osrg/gobgp/gobgp
$ go install .
$ ls $GOPATH/bin
glide gobgp goplane
設定ファイル
2 台の物理マシンそれぞれに対して,netns を作成するシェルスクリプトと goplane 用の TOML ファイルを用意します.goplane ではオプションによって YAML や JSON を使用することもできます.
netns
veth0
が netns 内の仮想インタフェース,veth1
が netns 外の仮想インタフェースとなっています.
veth (virtual Ethernet) で L2 的に接続されているイメージです.
ip netns add netns5
ip link add veth0 type veth peer name veth1
ip link set veth0 mtu 1450
ip link set veth1 mtu 1450
ip link set veth0 netns netns5
ip netns exec netns5 ifconfig lo up
ip netns exec netns5 ifconfig veth0 10.0.10.5 netmask 255.255.255.0 broadcast 10.0.10.255 up
ip netns add netns6
ip link add veth0 type veth peer name veth1
ip link set veth0 mtu 1450
ip link set veth1 mtu 1450
ip link set veth0 netns netns6
ip netns exec netns6 ifconfig lo up
ip netns exec netns6 ifconfig veth0 10.0.10.6 netmask 255.255.255.0 broadcast 10.0.10.255 up
goplane
BGP Peer を確立するための IP アドレス (Underlay) や,VXLAN の TEP (Tunnel End point) となる VTEP インタフェース名を指定します.
以下のように VNI (VXLAN Network Identifier) として 10
を指定すると,ホスト上に br10
が自動生成されます.
[bgp.global.config]
as = 65000
router-id = "192.168.40.5"
[[bgp.neighbors]]
[bgp.neighbors.config]
neighbor-address = "192.168.40.6"
peer-as = 65000
[bgp.neighbors.ebgp-multihop.config]
enabled = true
multihop-ttl = 100
[[bgp.neighbors.afi-safis]]
[bgp.neighbors.afi-safis.config]
afi-safi-name = "l2vpn-evpn"
[dataplane]
type = "netlink"
[[dataplane.virtual-network-list]]
member-interfaces = [ "veth1", ]
vni = 10
vxlan-port = 8472
rd = "65000:10"
vtep-interface = "vtep10"
etag = 10
sniff-interfaces = [ "veth1", ]
[bgp.global.config]
as = 65000
router-id = "192.168.40.6"
[[bgp.neighbors]]
[bgp.neighbors.config]
neighbor-address = "192.168.40.5"
peer-as = 65000
[bgp.neighbors.ebgp-multihop.config]
enabled = true
multihop-ttl = 100
[[bgp.neighbors.afi-safis]]
[bgp.neighbors.afi-safis.config]
afi-safi-name = "l2vpn-evpn"
[dataplane]
type = "netlink"
[[dataplane.virtual-network-list]]
member-interfaces = [ "veth1", ]
vni = 10
vxlan-port = 8472
rd = "65000:10"
vtep-interface = "vtep10"
etag = 10
sniff-interfaces = [ "veth1", ]
実行
では,これらの設定ファイルを用いて実行していきます.
準備
もし /etc/sysctl.conf
において net.ipv4.ip_forward=1
がコメントアウトされていたら外してください.
- #net.ipv4.ip_forward=1
+ net.ipv4.ip_forward=1
以下のように表示されれば OK です.これを忘れると思ったようにパケットが転送されません.
$ sudo sysctl -p
net.ipv4.ip_forward = 1
設定を変更したらシステムの再起動をしましょう.
ちなみに sysctl
はカーネル内のパラメータを変更してくれるコマンドです.
ユーザ空間の話では無いので,問題が生じた時に原因を突き止めるのが難しいですね.
何度これに気づけず時間を溶かしたかわかりません.
netns の作成 (host1)
$ sudo ./netns5.sh
host2 では netns6.sh
を実行します.
goplane の起動 (host1)
$ sudo $HOME/.golang/bin/goplane -f ./goplane5.toml
{"level":"info","msg":"Peer 192.168.40.6 is added","time":"2018-09-29T16:04:15+09:00"}
{"Topic":"Peer","level":"info","msg":"Add a peer configuration for:192.168.40.6","time":"2018-09-29T16:04:15+09:00"}
{"level":"info","msg":"VirtualNetwork 65000:10 is added","time":"2018-09-29T16:04:15+09:00"}
{"Key":"192.168.40.6","State":"BGP_FSM_OPENCONFIRM","Topic":"Peer","level":"info","msg":"Peer Up","time":"2018-09-29T16:04:28+09:00"}
こちらも同様に,host2 では goplane6.toml
を使用してください.
正常に設定ができていれば,最後の行で "msg":"Peer Up"
が表示されるはずです.
検証
正しく環境を構築できているかどうか確認していきます.
Peer
確かに State
が Establ
になっていますね.
$ gobgp neigh
Peer AS Up/Down State |#Received Accepted
192.168.40.6 65000 00:02:58 Establ | 2 2
疎通確認
netns 内から ping
を打つと,Overlay で疎通していることが確認できます.
$ sudo ip netns exec netns5 ping 10.0.10.6 -c 3
PING 10.0.10.6 (10.0.10.6) 56(84) bytes of data.
64 bytes from 10.0.10.6: icmp_seq=1 ttl=64 time=0.588 ms
64 bytes from 10.0.10.6: icmp_seq=2 ttl=64 time=0.690 ms
64 bytes from 10.0.10.6: icmp_seq=3 ttl=64 time=0.574 ms
--- 10.0.10.6 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2039ms
rtt min/avg/max/mdev = 0.574/0.617/0.690/0.055 ms
このとき,以下のようなコマンドを実行すると,MAC アドレス情報を学習できていることがわかります.
$ gobgp global rib -a evpn
Network Next Hop AS_PATH Age Attrs
*> [type:macadv][rd:0:0][esi:single-homed][etag:10][mac:2a:1f:8f:52:1f:60][ip:<nil>][labels:[10]]192.168.40.6 00:08:16 [{Origin: i} {LocalPref: 100} {Extcomms: [VXLAN]}]
*> [type:macadv][rd:0:0][esi:single-homed][etag:10][mac:3e:96:f0:e6:db:e9][ip:<nil>][labels:[10]]0.0.0.0 00:08:29 [{Origin: i} {Extcomms: [VXLAN]}]
*> [type:multicast][rd:65000:10][etag:10][ip:192.168.40.5]0.0.0.0 00:08:29 [{Origin: i} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 192.168.40.5} {Extcomms: [65000:10]}]
*> [type:multicast][rd:65000:10][etag:10][ip:192.168.40.6]192.168.40.6 00:08:16 [{Origin: i} {LocalPref: 100} {Extcomms: [65000:10]} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 192.168.40.6}]
Bridge
最後に brctl
でブリッジの様子を見てみましょう.
goplane の実行によって生成された br10
というブリッジグループに,veth1
と vtep10
が含まれています.
vtep10
においてカプセル化を解除されたフレームが br10
に転送され,veth を介して netns の内部に届きます.
$ brctl show br10
bridge name bridge id STP enabled interfaces
br10 8000.caaf73c60baf no veth1
vtep10