Cumulus VXをVagrantで試してみた

# はじめに
今回は、ホワイトボックスSW用のネットワークOSである、Cumulus VXをさわってみたので、備忘録もかねて、記事にしたいと思います。
自分自身は仕事でNW機器を触り始めたのは最近なので、あくまでこの記事は初学者向きです。

# ホワイトボックスSW/ネットワークOSとは
ホワイトボックスSWとはOSやミドルウェアがインストールされておらず、オープンソースのOSをインストールすることで、NW機器として動作させることができるものです。
すでに数年前に一度盛り上がりを見せた？（自分調べ）ホワイトボックスSWなのですが、メリット以下の通りです。

- OSを自由に選択可能⇒ベンダーロックインの解消
- そのうえで動作する機能を自前で開発することで、コストカットが可能
　

一方で、その自由さ故、以下のようなデメリットもあります。

- ネットワークOSの保守がしっかりしていない
- 機能開発のための工数の増加

このような特徴のあるホワイトボックスSWですが、使ってみないとわからないということで、今回は、ネットワークOSの一つであるCumulus OSを試してみました。
Cumulus OSには無償の仮想アプライアンスである、Cumulus VXと呼ばれるものがあります。
Cumulus VXはVM WareやVirtual boxなどハイパーバイザ上で動作するうえ、Cumulus OSのほとんどのNW機能を試すことができます。
この記事では、Cumulus VXをMac OS上のVirtual box+Vagrantで起動し、動作確認した際のやり方を書いていきます。
　
# 実行環境
| HW / OS / ソフトウェア  | バージョン、スペック |
| ---- | ---- |
| macOS | 11.2 Big Sur |
| CPU | Intel Core i5 |
| Virtual Box | 6.1 |
| Vagrant | 2.2.7 |
| Cumulus OS | 4.4.0 |

# やってみたこと
今回は、以下のようなSW4台の構成で、Multi-Link Aggregationを動作させてみました。
複数の物理線を束ねて一つの仮想回線を作成することで、冗長構成を組みながら帯域幅を増やすことができるLink Aggregationという技術があります。
Multi-Link Aggregationとは、LAGを複数SWで組む技術のことを指します。

<img width="800" alt="NW構成図.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498103/4bd90df3-5e53-e1e9-e2f7-c5590017f62c.png">

# 環境構築（インストール、VMの立ち上げ方）
まず、Virtual boxとVagrantをmacにインストールします。
下記サイトからインストールできます。

- VirtualBox：https://www.virtualbox.org/wiki/Downloads
- Vagrant：https://www.vagrantup.com/downloads

適当なフォルダを作成し、以下のコマンドでVMを立ち上げます。

```
mkdir vagrant
vim Vagrantfile
vagrant up
```

Vagrantfileの中身は以下の通り
細かい内容は、vagrantの使い方を紹介しているブログなどを参照ください。
簡単に説明すると、2行目から後ろから2行目までが、一つのVMの設定になります。
複数VMを立ち上げたい場合は、これを複数書いてあげれば良いです。
以下、各パラメータの説明です。

- `host01.vm.box`：インストールするOS
- `host01.vm.hostname`：ホスト名
- `host01.vm.network`：NICの設定
    - 今回は`private_network`を指定しているので、VM間のイントラセグメントです。
    - `virtualbox__intnet`がユニークなセグメント名？になります。これが同じNIC同士が同じセグメントに所属することになります。
- `vbox.customize ['modifyvm', :id, "--nicpromisc#{i+1}", "allow-all"]`：VirtualBoxでは、デフォルトで未知のMACアドレスを遮断する設定になっているため、新たに作成した2番目以降のNIC全てその設定（promisc）を`allow-all`にしてあげることで、未知のMACアドレスとも疎通できるようになります。

```
Vagrant.configure("2") do |config|
config.vm.define "host01" do |host01|
    host01.vm.box = "CumulusCommunity/cumulus-vx"
    host01.vm.hostname = "host01"
    host01.vm.network "private_network", virtualbox__intnet: "intnet-1", auto_config: false
    host01.vm.network "private_network", virtualbox__intnet: "intnet-2", auto_config: false
    host01.vm.provider "virtualbox" do |vbox|
        vbox.customize ['modifyvm', :id, "--nicpromisc#{i+1}", "allow-all"]
    end
end
end
```

以上のコマンドで、VMが立ち上がるはずなのですが、自分の環境では、以下のようなエラーが出てしまいました。
（どうやらbox.ovfというファイルがないらしい、、）

```
$ vagrant up
Bringing machine "host01' up with 'virtualbox' provider...
=› host01: Importing base box "CumulusCommunity/cumulus-vx'
There was an error while executing'VBoxManage', a CLI used by Vagrant for controlling Virtualbox. The comand and stderr is shonn below.

Cormand: ["import", "/Users/mizu/.vagrant.d/boxes/CumulusCommunity-VAGRANTSLASH-cumulus-vx/4.4.0/virtualbox/box.ovf"]

Stderr: 0%...
Progress state: VBOX_E_OBJECT_NOT_FOUND
VBoxManage: error: Appliance read failed
VBoxManage: error: Failed to open OVF file '/Users/mizw/.vagrant.d/boxes/CumulusCormunity-VAGRANTSLASH-cumulus-vx/4.4.0/virtualbox/box.Ovf' (VERR_FILE_NOT_FOUND)
VBoxManage: error: Details: code BOX_E_OBJECT_NOT_FOUND (®x80bb0001), component Appliancetrap, interface IAppliance
VBoxManage: error: Context: "RTEXITCODE handleIrportAppliance(HandlerArg*)" at line 417 of file VBoxManageAppliance.cpp
```

一度vagrant upを実行し、エラーが出た後に、vagrantのディレクトリにcumulus vxのovfファイルができるので、コピーしてbox.ovfを作成します。

```
cd ~/.vagrant.d/boxes/CumulusCommunity-VAGRANTSLASH-cumulus-vx/4.4.0/virtualbox/
cp cumulus-linux-vm-amd64-4.4.0.1040-vbox.ovf box.ovf
```

この後に再度、vagrant upを実行すると、今度はエラーなくvmが立ち上がると思います。
以上の工程で、CumulusVXがインストールされたVMを立ち上げることができます。

# 初期設定
次は、各SW（VM）にログインし、初期設定をおこないます。
vagrantで立ち上げたVMには、`vagrant ssh <ホスト名>`でログインすることができます。
ホスト名は、先ほどVagrantfileで指定した、`config.vm.define "<ホスト名>"`になります。
Cumulus VXでは、netコマンドというCLIが用意されております。(netコマンドを使用する際は、rootユーザになる必要があります。)
以下が`ip a`と`net show interface`を実行した結果になりますが、`net show interface`では`swp1`と`swp2`が認識されていないため、認識させます。

```
vagrant@sw01:mgmt:~$ ip a
1: lo: <LOOPBACK, UP, LONER UP> mtu 65536 qdisc noqueue state UNKNOWN group default alen 1000
    link/loopback00:00:00:00:00:00 brd00: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,LONER_UP> mtu 1500 qdisc pfifo_fast master mgmt state UP group default qlen 1000
    link/ether 08:00:27:50:05ef brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 br 10.0.2.255 scope global dynamic eth0
        valid_lft 86273sec preferred_lft 86273sec
    inet6 fe80::000:27ff:fe50:5ef/64 scope link
        valid_lft forever preferred_lft forever
3: swp1: «BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 08:00:27: c9:61:2a brdff:ff:ff:ff:ff:ff
4: swp2: «BROADCAST,MULTICAST> mtu 1500 adisc noop state DOWN group default qlen 1000
    link/ether 08:00:27:77:46:7e br ff:ff:ff:ff:ff:ff
```

```
vagrant@sw01 :mgmt:~S sudo su

ZTP in progress. To disable, do 'ztp -d'

root@sw01:mgmt:~# net show interface
State  Name  Spd  MTU    Mode      LLDP   Summary
-----  ----  ---  -----  --------  ----   ----------------------
UP     lo    N/A  65536  Loopback         IP: 127.0.0.1/8
       lo                                 IP: ::1/128
UP     eth0  1G   1500   Mgmt             Master: mgmt (UP)
       eth0                               IP: 10.0.2.15/24(DHCP)
UP     mgmt  N/A  65536  VRF              IP: 127.0.0.1/8
       mgmt                               IP: ::1/128
```

以下が、インターフェースを認識させるコマンドになります。
内部的には、configファイルに二つのインターフェースを書き込んでいます。
Cumulus VXでは、コマンドを実行し、configを書き換えるときには、一旦実ファイルには保存されていないため、設定は変わりません。
pending状態になっている設定を確認したい場合には、`net pending`を実行します。
その設定を実ファイルに書き込むためには、`net commit`を実行します。

```
root@sw01 :mgmt:~# net add interface swp1-2
root@sw01:mgmt :~# net pending
---/etc/network/interfaces    2021-07-04 09:04:59.000000000 +0000
# /run/nclu/ifupdownz/interfaces.tmp  2021-12-09 04:13:53.170778000 +0000
@ -5,15 +5,21 @@

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp
    vrf mgmt

auto swp1
iface swp1

auto swp2
iface swp2

auto mgmt
iface mgmt
    address 127.0.0.1/8
    address : :1/128
    vrf-table auto
net add/del commands since the last "net commit"
================================================

User  Timestamp                   Command
----  --------------------------  ------------------------
root  2021-12-09 04:13:49.160402  net add interface swp1-2
```

以上で、インターフェースを認識させることができました。

# MLAGの設定
ここからは、今回実際に動作を確認したMLAGの設定内容を説明します。

### SW03とSW04の設定
SW03とSW04には、単純なLAGの設定を入れます。以下が、そのコマンドです。
注意すべきは、作成したbondインターフェースをさらにbridgeインターフェースに追加し、そこにIPアドレスを設定することです。 
Cumulus VXでは、bondインターフェースに直接IPアドレスを設定してもL3で通信できません。

```
# net add bond bond0 bond slaves swp1-2
# net add bridge bridge ports bond0
# net add interface bridge ip address 10.0.0.1/24（SW04は10.0.0.2/24）
# net pending
# net commit
```

### SW01とSW02（Peerlink）の設定
今度は、SW01とSW02にPeerlinkの設定を入れていきます。
Cumulus VXでは、Peerlinkの設定を1行で行えます。
実際に設定される内容は下記の通りです。

- 渡りのインターフェースを子インターフェースに持つ、bondインターフェースの作成
- backup ipアドレス
- mlagのプライオリティ値
- mlagで使用するシステムMACアドレス

```
# net add clag peer sys-mac 44:38:39:BE:EF:AA interface swp2-3 primary backup-ip 10.10.10.2（SW04では10.10.10.1）
# net pending
# net commit
```

```text:config(peerlink)
interface peerlink
  bond-slaves swp2 swp3
interface peerlink.4094
  address 10.10.10.1/24
  clagd-backup-ip10.10.10.2
  clagd-peer-ip linklocal
  clagd-priority 1000
  clagd-sys-mac 44:38:39:BE:EF:AA
```

### SW01とSW02（SW03、SW04との接続部分）の設定
最後にSW01とSW02にSW03とSW04との接続部分の設定を入れています。
基本的には、普通のLAGの設定と同じです。
異なる点としては、mlag idを各ポートで設定する必要があるという点です。
このmlag idは対抗のスイッチと揃える必要があります。

```
# net add bond bond1 bond slaves swp1
# net add bond bond1 alias bond1 on swp1 # net add bond bond4 bond slaves swp4
# net add bond bond4 alias bond2 on swp4 # net add bond bond1 clag id 1
# net add bond bond4 clag id 4
# net add bridge bridge ports bond1,bond4 # net pending
# net commit
```

以上で、mlagを動作させるためのconfigは一通り設定できたことになります。

# 感想
今回、Cumulus VXというネットワークOSの一つを触ってみましたが、NWの知識もままらないため、結構苦戦しました。。
次回は、NW機器の設定自動化を試してみようと思います。