OpenVNetのGREトンネルとMAC2MACを使った仮想ネットワークをVirtualBoxで試す

OpenVNetの[インストールマニュアル](http://openvnet.org/installation/)ではホストマシン1台の上にLXCコンテナ二つを立ち上げてその間に仮想ネットワークを構築する手順が紹介されていますが、OpenVNetは複数のホストマシン間で、同じネットワークならMAC2MAC、異なるネットワークならGREトンネルを使って自由に仮想ネットワークを構築できます。

今回はこのGREトンネルとMAC2MACを使ってOpenVNetで複数ホストマシンに被さった仮想ネットワークを構築します。

#準備

「[VirtualBoxとCentOSでOpenVNetのテスト環境をつくったときのまとめ](VirtualBoxとCentOSでOpenVNetのテスト環境をつくったときのまとめ)」で作った環境をそのまま使います。


#LXC
OpenVNetの設定を始める前にLXCのコンテナを作ってみます。
最後にこのコンテナ間で通信できるようになることが目標です。

まずはVM1にコンテナを作ります。

```
yum -y install lxc lxc-templates

mkdir /cgroup
echo "cgroup /cgroup cgroup defaults 0 0" >> /etc/fstab
mount /cgroup

yum install -y rsync (既に入っていることもあります)

lxc-create -t centos -n inst1
lxc-create -t centos -n inst2
```
inst1、inst2の設定ファイルを編集します。
既にいろいろと書いてありますがすべて消して以下の設定を書きます。

```
vi /var/lib/lxc/inst1/config


lxc.network.type = veth
lxc.network.flags = up
lxc.network.veth.pair = inst1
lxc.network.ipv4 = 10.100.0.10/24
lxc.network.hwaddr = 10:54:FF:00:00:01
lxc.rootfs = /var/lib/lxc/inst1/rootfs
lxc.include = /usr/share/lxc/config/centos.common.conf
lxc.arch = x86_64
lxc.utsname = inst1
lxc.autodev = 0
```
同じようにinst2も

```
vi /var/lib/lxc/inst2/config

lxc.network.type = veth
lxc.network.flags = up
lxc.network.veth.pair = inst2
lxc.network.ipv4 = 10.100.0.11/24
lxc.network.hwaddr = 10:54:FF:00:00:02
lxc.rootfs = /var/lib/lxc/inst2/rootfs
lxc.include = /usr/share/lxc/config/centos.common.conf
lxc.arch = x86_64
lxc.utsname = inst2
lxc.autodev = 0
```

同じ手順でVM2にinst3、VM3にinst4を作ります。
最終的に下の図のような状態になります。

![vm-ovn.png](https://qiita-image-store.s3.amazonaws.com/0/86684/fb1099ac-3018-1ebe-b952-370ea19bb8d7.png)



# OpenVNet

VM1の設定です。すべて書くと長いので各ファイルの変更箇所だけ。
redisを他のマシンからのアクセスを受けるようにして、
vna、vnmgr、webapiが動いているVM1の管理線側のIPアドレスを設定します。
最後にcommonファイルでredisが動くマシンVM1のIPアドレスを教えます。

```
vi /etc/redis.conf
	
bind 0.0.0.0

vi /etc/openvnet/vna.conf

host "192.168.198.10"

vi /etc/openvnet/vnmgr.conf

host "192.168.198.10"

vi /etc/openvnet/webapi.conf

host "192.168.198.10"

vi /etc/openvnet/common.conf

host "192.168.198.10"
```

VM2の設定です。
vnaは各マシンで動いているのでVM2でもvna.confは編集します。
またvnaのidはすべて異なるものが設定されている必要があるので、
今回はidも編集します。
commonファイルはVM1と同じです。

```
vi /etc/openvnet/vna.conf

id "vna2" 
host "192.168.198.11"

vi /etc/openvnet/common.conf

host "192.168.198.10"
```

VM3の設定です。
VM2と同じです。
```
vi /etc/openvnet/vna.conf

id "vna3" 
host "192.168.198.12"

vi /etc/openvnet/common.conf

host "192.168.198.10"
```

VM1、VM2、VM3でopenvswitchをスタートさせbr0も有効化させます。

```
service openvswitch start
ifup br0
```

VM1ではredisもスタートさせます。

```
service redis start
```

VM1でデータベースを設定します。

```
service mysqld start
chkconfig mysqld on
PATH=/opt/axsh/openvnet/ruby/bin:${PATH}
cd /opt/axsh/openvnet/vnet
bundle exec rake db:create
bundle exec rake db:init
```

OpenVNetのvnmgrとwebapiをスタートさせます。

```
initctl start vnet-vnmgr
initctl start vnet-webapi
```

DBへの登録を行います。
下のを実行してください。

```
# datapath マシン1
curl -X POST \
--data-urlencode uuid=dp-test1 \
--data-urlencode display_name="test1" \
--data-urlencode dpid="0x020100000001" \
--data-urlencode node_id="vna" \
http://127.0.0.1:9090/api/datapaths

# datapath マシン2
curl -X POST \
--data-urlencode uuid=dp-test2 \
--data-urlencode display_name="test2" \
--data-urlencode dpid="0x020100000002" \
--data-urlencode node_id="vna2" \
http://127.0.0.1:9090/api/datapaths

# datapath マシン3
curl -X POST \
--data-urlencode uuid=dp-test3 \
--data-urlencode display_name="test3" \
--data-urlencode dpid="0x020100000003" \
--data-urlencode node_id="vna3" \
http://127.0.0.1:9090/api/datapaths

# パブリックネットワーク　マシン1・マシン2
curl -s -X POST \
--data-urlencode uuid=nw-pub1 \
--data-urlencode display_name="nw-pub1" \
--data-urlencode ipv4_network="192.168.56.0" \
--data-urlencode ipv4_prefix="24" \
--data-urlencode network_mode="physical" \
http://127.0.0.1:9090/api/networks

# パブリックネットワーク　マシン3
curl -s -X POST \
--data-urlencode uuid=nw-pub2 \
--data-urlencode display_name="nw-pub2" \
--data-urlencode ipv4_network="192.168.125.0" \
--data-urlencode ipv4_prefix="24" \
--data-urlencode network_mode="physical" \
http://127.0.0.1:9090/api/networks

# 仮想ネットワーク
curl -s -X POST \
--data-urlencode uuid=nw-test1 \
--data-urlencode display_name="testnet1" \
--data-urlencode ipv4_network="10.100.0.0" \
--data-urlencode ipv4_prefix="24" \
--data-urlencode network_mode="virtual" \
http://127.0.0.1:9090/api/networks

# 物理interface マシン1eth1
curl -s -X POST \
--data-urlencode uuid="if-dp1eth1" \
--data-urlencode owner_datapath_uuid="dp-test1" \
--data-urlencode mac_address="02:01:00:00:00:01" \
--data-urlencode network_uuid="nw-pub1" \
--data-urlencode ipv4_address="192.168.56.10" \
--data-urlencode port_name="eth1" \
--data-urlencode mode="host" \
http://127.0.0.1:9090/api/interfaces


# interface マシン1コンテナ
curl -s -X POST \
--data-urlencode uuid="if-inst1" \
--data-urlencode owner_datapath_uuid="dp-test1" \
--data-urlencode mac_address="10:54:ff:00:00:01" \
--data-urlencode network_uuid="nw-test1" \
--data-urlencode ipv4_address="10.100.0.10" \
--data-urlencode port_name="inst1" \
--data-urlencode mode="vif" \
http://127.0.0.1:9090/api/interfaces

curl -s -X POST \
--data-urlencode uuid="if-inst2" \
--data-urlencode owner_datapath_uuid="dp-test1" \
--data-urlencode mac_address="10:54:ff:00:00:02" \
--data-urlencode network_uuid="nw-test1" \
--data-urlencode ipv4_address="10.100.0.11" \
--data-urlencode port_name="inst2" \
--data-urlencode mode="vif" \
http://127.0.0.1:9090/api/interfaces


# 物理interface マシン2eth1
curl -s -X POST \
--data-urlencode uuid="if-dp2eth1" \
--data-urlencode owner_datapath_uuid="dp-test2" \
--data-urlencode mac_address="02:01:00:00:00:02" \
--data-urlencode network_uuid="nw-pub1" \
--data-urlencode ipv4_address="192.168.56.11" \
--data-urlencode port_name="eth1" \
--data-urlencode mode="host" \
http://127.0.0.1:9090/api/interfaces


# interface マシン2コンテナ
curl -s -X POST \
--data-urlencode uuid="if-inst3" \
--data-urlencode owner_datapath_uuid="dp-test2" \
--data-urlencode mac_address="10:54:ff:00:00:03" \
--data-urlencode network_uuid="nw-test1" \
--data-urlencode ipv4_address="10.100.0.12" \
--data-urlencode port_name="inst3" \
--data-urlencode mode="vif" \
http://127.0.0.1:9090/api/interfaces

# 物理interface マシン3eth1
curl -s -X POST \
--data-urlencode uuid="if-dp3eth1" \
--data-urlencode owner_datapath_uuid="dp-test3" \
--data-urlencode mac_address="02:01:00:00:00:03" \
--data-urlencode network_uuid="nw-pub2" \
--data-urlencode ipv4_address="192.168.125.10" \
--data-urlencode port_name="eth1" \
--data-urlencode mode="host" \
http://127.0.0.1:9090/api/interfaces


# interface マシン3コンテナ
curl -s -X POST \
--data-urlencode uuid="if-inst4" \
--data-urlencode owner_datapath_uuid="dp-test3" \
--data-urlencode mac_address="10:54:ff:00:00:04" \
--data-urlencode network_uuid="nw-test1" \
--data-urlencode ipv4_address="10.100.0.13" \
--data-urlencode port_name="inst4" \
--data-urlencode mode="vif" \
http://127.0.0.1:9090/api/interfaces

# MAC2MAC・GRE用 マシン1
curl -s -X POST \
--data-urlencode broadcast_mac_address="00:00:00:00:d1:01" \
--data-urlencode interface_uuid="if-dp1eth1" \
http://127.0.0.1:9090/api/datapaths/dp-test1/networks/nw-test1

curl -s -X POST \
--data-urlencode broadcast_mac_address="00:00:00:00:d1:02" \
--data-urlencode interface_uuid="if-dp1eth1" \
http://127.0.0.1:9090/api/datapaths/dp-test1/networks/nw-pub1

# MAC2MAC・GRE用 マシン2
curl -s -X POST \
--data-urlencode broadcast_mac_address="00:00:00:00:d2:01" \
--data-urlencode interface_uuid="if-dp2eth1" \
http://127.0.0.1:9090/api/datapaths/dp-test2/networks/nw-test1

curl -s -X POST \
--data-urlencode broadcast_mac_address="00:00:00:00:d2:02" \
--data-urlencode interface_uuid="if-dp2eth1" \
http://127.0.0.1:9090/api/datapaths/dp-test2/networks/nw-pub1

# MAC2MAC・GRE用 マシン3
curl -s -X POST \
--data-urlencode broadcast_mac_address="00:00:00:00:d3:01" \
--data-urlencode interface_uuid="if-dp3eth1" \
http://127.0.0.1:9090/api/datapaths/dp-test3/networks/nw-test1

curl -s -X POST \
--data-urlencode broadcast_mac_address="00:00:00:00:d3:02" \
--data-urlencode interface_uuid="if-dp3eth1" \
http://127.0.0.1:9090/api/datapaths/dp-test3/networks/nw-pub2
```

基本的には1台でOVNを動かしたときと同じですが「パブリックネットワーク」、「物理interface」などと書いてあるところと
最後の「MAC2MAC・GRE用」と書いてあるところが追加してあります。

これはOVNで仮想ネットワークを構築するとき、
MAC2MACやGREトンネルを使う場合に必要となります。

最後に各マシンでvnaを起動します。

```
initctl start vnet-vna
```


# LXCを仮想ネットワークに参加させる
ここはホストマシン1台の時と同じです


VM1の操作です。

```
lxc-start -d -n inst1
lxc-start -d -n inst2

ovs-vsctl add-port br0 inst1
ovs-vsctl add-port br0 inst2
```

VM2の操作です。

```
lxc-start -d -n inst3

ovs-vsctl add-port br0 inst3
```

VM3の操作です。

```
lxc-start -d -n inst4

ovs-vsctl add-port br0 inst4
```

#確認

これで各コンテナ間でpingが通るようになっていれば成功です。


例えばVM1で

```
 ovs-vsctl show
```

と打つと下のようなものが表示されます。

```
e3654af9-29a0-42ce-b407-92be72e64284
    Bridge "br0"
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: standalone
        Port "br0"
            Interface "br0"
                type: internal
        Port "inst2"
            Interface "inst2"
        Port "eth1"
            Interface "eth1"
        Port "inst1"
            Interface "inst1"
        Port "t-4i1dldh2"
            Interface "t-4i1dldh2"
                type: gre
                options: {in_key=flow, local_ip="192.168.56.10", out_key=flow, remote_ip="192.168.125.10"}
    ovs_version: "2.3.1"

```

この中で今回だとPort "t-4i1dldh2"がGREトンネルで使っているものでOpenVNetが自動で作ってくれています。

また

```
ovs-ofctl -O OpenFlow13 dump-flows br0
```

と打つと

```
OFPST_FLOW reply (OF1.3) (xid=0x2):
 cookie=0x900000000000000, duration=85802.737s, table=0, n_packets=6, n_bytes=476, priority=0 actions=write_metadata:0x80000000000/0xc0000000000,goto_table:3
 cookie=0x900000000000000, duration=85802.737s, table=0, n_packets=0, n_bytes=0, priority=1,tun_id=0 actions=drop
 cookie=0x900000000000000, duration=85802.737s, table=0, n_packets=0, n_bytes=0, priority=2,in_port=CONTROLLER actions=write_metadata:0x4040000000000/0x40c0000000000,goto_table:7
以下略
```

みたいなのが表示されます。
今回、一回目はうまく動きませんでした。
その時はinst1とinst2間では通信できて、
VM2、VM3でもGREトンネルのPortが作成されているのに
VM2、VM3ではflowが登録されていないという状況で
iptablesが邪魔をしてたのが原因でした。

iptablesを切ってvnaを再起動すると治りました。