Cumulus VX on KVM (on ESXi) を "フツウに" 使う

## What?

とある都合により Cumulus の機能試験みたいな話をすることになったんですね。そうなると、 [Cumulus VX](https://cumulusnetworks.com/products/cumulus-vx/) でサクッと動かしてみようということになるわけです。Cumulus VX 自体は VMware/VirtualBox/KVM それぞれで動くよイメージが公開されているのですが、今回は最終的に Linux をベースにしたシステムで動かす想定だったので KVM ベースで試しておいた方が都合が良かった。

で、KVM ベースに動かすドキュメントを見るわけですが…。 

*  [Getting Started \- Cumulus VX \- Cumulus Networks](https://docs.cumulusnetworks.com/display/VX/Getting+Started)
  *  [Libvirt and KVM \- QEMU \- Cumulus VX \- Cumulus Networks](https://docs.cumulusnetworks.com/display/VX/Libvirt+and+KVM+-+QEMU)
  *  [GNS3 and QEMU \- KVM \- Cumulus VX \- Cumulus Networks](https://docs.cumulusnetworks.com/display/VX/GNS3+and+QEMU+-+KVM)

あたりですね。どっちも KVM を生で使う説明なんですよね。まあフロントエンドに GNS3 使う場合やドキュメントに書いてある構成で組んでみるならこれでもいいんですけどね。自分で環境構成したいのであれば virsh をフロントエンドで使いたいなと。ということでちょっと触ってみたのでメモを残しておきます。

## Nested VM on ESXi

KVM 使う場合はホストで VT-x あるいは AMD-v がサポートされる必要があります。VirtualBox ではいまのところこれがサポートできないのでパス。

とはいえベアメタルサーバが手元にないので、VMware ESXi 上で作業を進めます。なので Cumulus VX on KVM on VMware の nested VM 構成です。Nested VM をする場合 ESXi 側でもちょっと設定が必要になるので注意しましょう。(というのを忘れていて時間を食ったので記録を…)

* ホストの BIOS で VT-x/AMD-v が有効になっていること
* ESXi 上で VHV (Virtual Hardware-Assisted Virtualization) が有効になっていること
  * [ESXi5.1上の仮想マシンでVT-xを有効にしてみた](https://aimless.jp/blog/archives/1589/)
  * [Nested Virtualizationの設定について（ESXi6） \- 雑木林](http://zokibayashi.hatenablog.com/entry/2015/04/17/005106)
* ゲストの設定で VT-x/AMD-v を有効にすること

それと、ESXi の vSwitch で promiscuous mode の設定をしておきましょう。これをやっておかないと nested VM が arp request を ESXi サーバの外部とやりとりできません。(…というのも見落としていて時間を食ったので以下略)

## KVM セットアップ

今回は Ubuntu Server 18.04 LTS 上で Cumulus VX 3.6 を動かします。

ref.

* [KVM/Installation \- Community Help Wiki](https://help.ubuntu.com/community/KVM/Installation)

VT-x/AMD-v サポートの確認。

```
hagiwara@ckvm:~$ sudo cat /proc/cpuinfo | egrep -c  '(vmx|svm)'
2
hagiwara@ckvm:~$
```

Install

```
hagiwara@ckvm:~$ sudo apt install qemu-kvm libvirt-bin virt-manager bridge-utils
```

KVM 使える?

```
hagiwara@ckvm:~$ kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used
hagiwara@ckvm:~$
```

Virsh/libvirt 動作チェック

```
hagiwara@ckvm:~$ virsh list --all
Id    Name                           State
----------------------------------------------------
hagiwara@ckvm:~$ sudo ls -la  /var/run/libvirt/libvirt-sock
srwxrwx--- 1 root libvirtd 0 May 27 14:05  /var/run/libvirt/libvirt-sock
hagiwara@ckvm:~$ ls -l /dev/kvm
crw-rw---- 1 root kvm 10, 232 May 27 14:05 /dev/kvm
hagiwara@ckvm:~$
```

Default bridge の確認

```
hagiwara@ckvm:~$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue  state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500  qdisc fq_codel state UP mode DEFAULT group default qlen  1000
    link/ether 00:0c:29:60:75:31 brd ff:ff:ff:ff:ff:ff
3: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500  qdisc fq_codel state UP mode DEFAULT group default qlen  1000
    link/ether 00:0c:29:60:75:3b brd ff:ff:ff:ff:ff:ff
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500  qdisc noqueue state DOWN mode DEFAULT group default qlen  1000
    link/ether 52:54:00:13:cc:d7 brd ff:ff:ff:ff:ff:ff
5: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc  fq_codel master virbr0 state DOWN mode DEFAULT group  default qlen 1000
    link/ether 52:54:00:13:cc:d7 brd ff:ff:ff:ff:ff:ff
hagiwara@ckvm:~$
```

## Cumulus VX のインポート

Original OS Image をコピーして使うことにします。

```
hagiwara@ckvm:~$ sudo cp cumulus-linux-3.6.0-vx-amd64.qcow2 /var/lib/libvirt/images/cumulus02.qcow2
```

VM image のインポート (ref. [3\.2\. virt\-install を使用したゲストの作成 \- Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/virtualization_deployment_and_administration_guide/sect-guest_virtual_machine_installation_overview-creating_guests_with_virt_install))

```
hagiwara@ckvm:~$ sudo virt-install  --connect=qemu:///system \
--name=cumulus02 --vcpus=1 --ram=1024 \
--import \
--disk  path=/var/lib/libvirt/images/cumulus02.qcow2,format=qcow2
```

このとき

```
WARNING  No operating system detected, VM performance may  suffer. Specify an OS with --os-variant for optimal  results.
```
と出ますが、あえて `--os-variant` はつけていません。

`virt-install` するときはオプション `--os-variant` で何の OS を入れるのか指定しておくことが推奨されています。このオプションで指定できる OS 名は `osinfo-query` で調べられるので見てみますが 'cumulus' というのはないんですよね。Cumulus は debian ベースなので[^base] `--os-variant debian8` とかをつけてみると console の設定が合わないらしく、Cumulus VX は起動するものの console とれなくて何も操作できない、という状態になってしまいます。

[^base]: [Cumulus Linux User Guide \- Cumulus Linux 3\.6 \- Cumulus Networks](https://docs.cumulusnetworks.com/display/DOCS/Cumulus+Linux+User+Guide) では "Debian Jessie based" とあります。

起動してみましょう

```
hagiwara@ckvm:~$ sudo virsh console cumulus02
Connected to domain cumulus02
Escape character is ^]
Debian GNU/Linux 8 cumulus ttyS0
cumulus login: cumulus
Password:
Linux cumulus 4.1.0-cl-7-amd64 #1 SMP Debian  4.1.33-1+cl3u13 (2018-04-25) x86_64
Welcome to Cumulus VX (TM)
...
```

この状態は最低限のオプションでインポートしてとりあえず起動するようにようにしたという状態なので、ここから VM 設定をいじっていきます(`sudo virsh edit cumulus02` して VM 設定ファイル(XML)を編集する)。

## CumulusVX VM設定 (default network編)

KVM の default network (virbr0) で動かす場合。

インポート直後の VM NIC 設定

```
    <interface type='network'>
      <mac address='52:54:00:d9:1a:97'/>
      <source network='default' bridge='virbr0'/>
      <target dev='vnet0'/>
      <model type='rtl8139'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00'  slot='0x03' function='0x0'/>
    </interface>
```

こうします。(model type を e1000 にしないと起動しない)

```
    <interface type='bridge'>
      <mac address='52:54:00:d9:1a:97'/>
      <source bridge='virbr0'/>
      <model type='e1000'/>
      <address type='pci' domain='0x0000' bus='0x00'  slot='0x03' function='0x0'/>
    </interface>
```

あとは必要に応じて linux bridge, Cumulus switchport (swp) を追加してやれば OK ですね。外部接続用のブリッジとして expbr0 を作ってみます。なお、virbr0 周りの設定は省略しますが、デフォルトで dhcp サーバが動いていて eth0 側が dhcp ウケるようになっているので cumulus が起動した時点で KVM host と eth0 経由で通信ができる状態になります。

![Linux bridge config](https://qiita-image-store.s3.amazonaws.com/0/154230/c03caf00-c367-d602-4510-6f9e09368c99.png)

```
hagiwara@ckvm:~$ sudo brctl addbr expbr0
hagiwara@ckvm:~$ sudo brctl show
bridge name     bridge id               STP enabled      interfaces
expbr0          8000.000000000000       no
virbr0          8000.52540013ccd7       yes              virbr0-nic
hagiwara@ckvm:~$
hagiwara@ckvm:~$ sudo brctl addif expbr0 ens33
hagiwara@ckvm:~$ sudo brctl show
bridge name     bridge id               STP enabled      interfaces
expbr0          8000.000c2960753b       no               ens33
virbr0          8000.52540013ccd7       yes              virbr0-nic
hagiwara@ckvm:~$
```

VM config 修正 (NIC追加)

```
    <interface type='bridge'>
      <mac address='52:54:00:d9:1a:97'/>
      <source bridge='virbr0'/>
      <model type='e1000'/>
      <address type='pci' domain='0x0000' bus='0x00'  slot='0x03' function='0x0'/>
    </interface>
    <interface type='bridge'>
      <mac address='52:54:00:d9:1a:98'/>
      <source bridge='expbr0'/>
      <model type='e1000'/>
    </interface>
```

VM 起動してブリッジの状態チェック

```
hagiwara@ckvm:~$ sudo brctl show
bridge name     bridge id               STP enabled      interfaces
expbr0          8000.000c2960753b       no               ens33
                                                         vnet1
virbr0          8000.52540013ccd7       yes              virbr0-nic
                                                         vnet0
```

Cumulus 側で追加した NIC が見えて up していることを確認。見えて入るけど up しない場合 /etc/network/interfaces に追記します。

```
auto swp1
iface swp1
```

```
cumulus@cumulus:/etc/network$ sudo ifup swp1
cumulus@cumulus:/etc/network$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue  state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc  pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:d9:1a:97 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.248/24 brd 192.168.122.255 scope  global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fed9:1a97/64 scope link
       valid_lft forever preferred_lft forever
3: swp1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc  pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:d9:1a:98 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::5054:ff:fed9:1a98/64 scope link
       valid_lft forever preferred_lft forever
cumulus@cumulus:/etc/network$
```

## CumulusVX VM設定 (Open vSwitch 編)

やっぱり、いろいろできる OVS 使いたいですよね。

ref.

* [openvswitchのvxlanで、KVM\(libvirt\)ホストの仮想ネットワークを接続する \- Qiita](https://qiita.com/Kaz_K/items/d9d50ac70c02a09c498f)
* [KVM環境で、OpenvSwitchでゲストVMを外部ネットワークと接続するメモ \- Qiita](https://qiita.com/kure/items/8645c28cba67aae49519)
* [CentOS7 仮想ブリッジvirbr0の無効化と有効化](http://www.orangetakam.com/blog/archives/1034)

Default network とかを止めます。

```
hagiwara@ckvm:~$ sudo brctl show
[sudo] password for hagiwara:
bridge name     bridge id               STP enabled      interfaces
expbr0          8000.000c2960753b       no               ens33
virbr0          8000.52540013ccd7       yes              virbr0-nic
hagiwara@ckvm:~$ virsh net-destroy default
Network default destroyed
hagiwara@ckvm:~$ sudo brctl show
bridge name     bridge id               STP enabled      interfaces
expbr0          8000.000c2960753b       no               ens33
hagiwara@ckvm:~$ virsh net-list --all
Name                 State      Autostart     Persistent
----------------------------------------------------------
default              inactive   yes           yes
hagiwara@ckvm:~$ virsh net-autostart default --disable
Network default unmarked as autostarted
hagiwara@ckvm:~$ virsh net-list --all
Name                 State      Autostart     Persistent
----------------------------------------------------------
default              inactive   no            yes
hagiwara@ckvm:~$
```

ためしにつくった expbr0 も消しておきます。

```
hagiwara@ckvm:~$ sudo brctl delbr expbr0
hagiwara@ckvm:~$ sudo brctl show
bridge name     bridge id               STP enabled      interfaces
hagiwara@ckvm:~$
```

OVSインストール

```
hagiwara@ckvm:~$ sudo apt install openvswitch-switch  openvswitch-common
```
OVS 動作チェック

```
hagiwara@ckvm:~$ sudo ovs-vsctl show
b3781bdb-2b1f-4985-ab54-d2e195a01c8a
    ovs_version: "2.9.0"
hagiwara@ckvm:~$
```

OVS に bridge を追加

```
hagiwara@ckvm:~$ sudo ovs-vsctl add-br intbr
hagiwara@ckvm:~$ sudo ovs-vsctl add-br expbr
hagiwara@ckvm:~$ sudo ovs-vsctl add-port intbr ens32
hagiwara@ckvm:~$ sudo ovs-vsctl add-port expbr ens33
hagiwara@ckvm:~$ sudo ovs-vsctl show
b3781bdb-2b1f-4985-ab54-d2e195a01c8a
    Bridge expbr
        Port "ens33"
            Interface "ens33"
        Port expbr
            Interface expbr
                type: internal
    Bridge intbr
        Port "ens32"
            Interface "ens32"
        Port intbr
            Interface intbr
                type: internal
    ovs_version: "2.9.0"
hagiwara@ckvm:~$
```

こういう構成です (ここではまだ vnet0/1 はいってないですが)。上(default netwrok)でやっていたときは、eth0 につながるネットワークは virbr0 とそこに紐付く dhcp server があり、KVM host (ckvm) からはアクセスできるようになっていました。OVS ではそうした作り込みは特になく、ごく単純な bridge とおして外とつながるだけです。


![ovs bridge config](https://qiita-image-store.s3.amazonaws.com/0/154230/90da9875-a1e5-fe29-ce81-4ff6097fd135.png)

VM NIC 設定変更: 接続する bridge 指定と、OVS 利用時は `virtual port type='openvswitch'` します。

```
    <interface type='bridge'>
      <mac address='52:54:00:d9:1a:97'/>
      <source bridge='intbr'/>
      <virtualport type='openvswitch'/>
      <model type='e1000'/>
      <address type='pci' domain='0x0000' bus='0x00'  slot='0x03' function='0x0'/>
    </interface>
    <interface type='bridge'>
      <mac address='52:54:00:d9:1a:98'/>
      <source bridge='expbr'/>
      <virtualport type='openvswitch'/>
      <model type='e1000'/>
      <address type='pci' domain='0x0000' bus='0x00'  slot='0x08' function='0x0'/>
    </interface>
```

あとは同じように VM 起動、インタフェース・ブリッジ状態確認をします。

## まとめ

Cumulus VX を Linux/KVM の一般的なオペレーションに載せるためメモを書いてみました。ここでは管理ポート(eth0) + スイッチポート1ポート分が使えるようになるところまでしか書いていませんが、これができていれば後は組合せでいろんなトポロジを作ったり、他のネットワークとつないだりというのがやれるようになるはずです。でも、ひとつの VM 内部で Cumulus VX だけを直接つないでトポロジ組めばいいという場合であれば、Cumulus のドキュメントにあるような形にするか GNS3 使ってやるのが楽でしょう。そこは用途に応じて選択するってことで。