OpenFlow controller「Faucet」を触ってみた

# はじめに
もろもろの経緯からOpenFlowやらねばと思い、はじめはtremaを試していましたがどうもtremaがメンテナンスされてなくてサンプルコードを動かすのにいちいちイライラしたので、さらにいろいろさまよった結果Faucetに行きつきました。というか以下の記事です。

[FAUCET コントローラ: OpenFlowが生き残っている理由](https://eng-blog.iij.ad.jp/archives/5022)

軽くググった程度ではFaucetの日本語の記事がこれぐらいしかないのですが、まあ盛り上がっているということを信じて少し遊んでみることにしました。[^1]

## 主な参考文献
0. https://docs.faucet.nz/en/latest/tutorials/first_time.html#configure-prometheus
0. https://eng-blog.iij.ad.jp/archives/5022

この記事は主に1番の内容に沿って書いています。

## 実施環境
Hyper-V上のUbuntuです。あまり真面目に更新していません。

```
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="19.04 (Disco Dingo)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 19.04"
VERSION_ID="19.04"
```

## 筆者のレベル
ネットワークはTCPとか多少わかるけど、インフラとかが本職ではないです。
普段はストレージ系の組み込みファームウェアをCでちんたら書いています。

# 詳細
## [Installing faucet for the first time](https://docs.faucet.nz/en/latest/tutorials/first_time.html)
* dockerとかもあるようですが、Package installationをすればいいかなと思います
* 一つ注意が必要で、こいつらはやたらディスク容量を使います。  
（おかげでhyper-Vのディスクが枯渇していろいろやってチェックポイントまで戻る破目になりました）

## Configure
### [Prometheus](https://docs.faucet.nz/en/latest/tutorials/first_time.html#configure-prometheus)
* FaucetはPrometheus[^2]を経由してGaugeなどのコンポーネントと連携するようなので、Prometheusの設定を行います。
* `/etc/prometheus/prometheus.yml` にすでに基本の設定が書かれています。
    + ドキュメントに書いてありますが、rule_fileとかjobの設定がデフォルトとドキュメントで違うので追記する形になると思います。
    + また`/etc/default/prometheus`の引数を指定することでprometheus.ymlの位置を変えることができます。これは必要なのかどうか不明です。

### [Grafana](https://docs.faucet.nz/en/latest/tutorials/first_time.html#configure-grafana)[^3]
#### data source⇒Prometheusの登録

* localhost:3000で接続できるよと書いてありますが、IPアドレスを指定してlistenしているわけではないので、仮想マシンなどの場合はホストから見える仮想マシンのアドレス:3000で接続できます。
* 開いた画面の真ん中あたりに並んでいる項目から「Add data source」を選び次の画面でPrometheusを選びます。[^4]

#### Dashboard⇒Faucetの登録
* data sourceと同様にDashboardを選択します
* 画面左側に＋ボタンがあるので、それを押してImportを選択します
* Importの画面の右上のUploadからJSONファイルを入れられるので、ドキュメントに書いてある下記のURLのJSONをダウンロードして入れます。
    0. https://docs.faucet.nz/en/latest/_static/grafana-dashboards/faucet_instrumentation.json
        - ここまで手順が間違っていなければ何かしらのグラフが出てきます。何もプロットされていないグラフになったら何か間違ってます。ここまでの手順をドキュメントどおりにやることをオススメします。
    + https://docs.faucet.nz/en/latest/_static/grafana-dashboards/faucet_inventory.json
        - Countroller Countに2って出ると思います
    + https://docs.faucet.nz/en/latest/_static/grafana-dashboards/faucet_port_statistics.json
        - ここはたぶん何も出ません。たぶん……

* 「ただダウンロードしてアップロードしろ」とか書いてある気がしますが、Uploadの画面でPrometheusの登録を選択しないといけないようです。先に登録したPrometheusを選択します。

### [Faucet](https://docs.faucet.nz/en/latest/tutorials/first_time.html#configure-faucet)
* `/etc/faucet/faucet.yaml`にたぶんサンプルがすでに書いてありますがドキュメントに合わせます。
    + switchとかが余分に定義されているので。合わせないとエラーログが出たりします。

### [Gauge](https://docs.faucet.nz/en/latest/tutorials/first_time.html#configure-gauge)[^5]

* `/etc/faucet/gauge.yaml`にたぶんサンプルがすでに書いてあります。
    + とりあえずこのままで良いと思う……のですが、もしかしたら下記のようにしないと、あとでiperfをしたときに結果が何も出ないかもしれません。

```diff:gauge.yaml 
    prometheus:
        type: 'prometheus'
-       prometheus_addr: '0.0.0.0'
+       prometheus_addr: '127.0.0.1'
        prometheus_port: 9303
```

## [Connect your first datapath](https://docs.faucet.nz/en/latest/tutorials/first_time.html#connect-your-first-datapath)[^6]
* ここではいよいよNetwork namespace(netns)を使って仮想ネットワークを作成して動作を見ていきます。
    + Open vSwitchが必要です。Ubuntu19.04とかなら普通にapt install できますが、16とかの場合は主要文献1にしたがってインストールしてくださいma
    + 古い環境だともしかしたらipコマンドのインストールも必要かもしれません。
* まずnetnsの構築を行います:
    + https://docs.faucet.nz/en/latest/tutorials/first_time.html#connect-your-first-datapath の3番目の手順:
    0. まずas_ns と create_ns という2つのbash関数を宣言します。私はシェルスクリプトにしました。
        + create_nsの中ではveth peerの作成と接続なども行います 
    0. create_ns を使って host1とhost2のnetnsを作成します
        + IPアドレスは仮想ネットワークなので何でもいいです。実在のネットワークと被っている場合はもしかしたらダメかもしれません。
* 次にOpen vSwitchの設定をします:
    +  `Configure Open vSwitch` のコマンドをそのまま実行すればいいと思います
* ここまでできるとGrafanaのdashboard「Faucet Inventory」でDatapath countが1になったりPort Countが2になったりしていると思います。
    + なっていない場合はログを見ろ、とのことです。

## Generate traffic between virtual hosts
* ２つの仮想ホスト(netns)間でデータを流してみます
* まずはping:

```bash
> as_ns host1 ping 192.168.0.2
```

* netnsとovsの設定が間違っていなければpingが通ります。`/var/log/faucet/faucet.log`に`L2 learned`とか書かれたログが出てきます
* つぎにiperf。iperfがない場合はインストールします:

```bash
> as_ns host1 iperf3 --server --pidfile /run/iperf3-host1.pid --daemon
> as_ns host2 iperf3 --client 192.168.0.1
```

* pingが通っていればiperfも動くと思いますが、grafanaの設定が正しければ、dashboard「Faucet Port Statistics」にiperfが大量のデータを流したことを示すグラフが出てくると思います

# おわりに/感想
* とりあえずfaucetが動いたらしいです
* 個人的にはnetnsとかOpen vSwitchの使い方がちょっとだけわかったことの方が収穫でした
* Further stepsがあるようなので理解できたら続編を投稿します

## 追加の参考文献/netnsに関して

https://qiita.com/hana_shin/items/ab078b5552f5df029030
http://blog.serverworks.co.jp/tech/2019/08/05/post-70460/

[^1]: faucetというとそれよりもBitcoin関連がいろいろ出てきますが、たぶん関係ないです
[^2]: PrometheusとはZabbixとかと同じ監視管理ツールのようです
[^3]: (https://qiita.com/Chanmoro/items/a23f0408f0e64658a775 より) Grafana は Grafana Labs が公開しているログ・データ可視化のためのツールです
[^4]: ドキュメントではPrometheusの登録に誘導されると書いてある気がしますが、どうもこの開いている画面の項目の並びがそのガイダンスみたいです。いまいちですねー。
[^5]: (https://docs.faucet.nz/en/latest/intro.html#what-is-gaugeより) `Faucet has two main OpenFlow controller components, Faucet itself, and Gauge. ` とのことです。主要文献2を見た感じだとfaucet→Gauge→Prometheus/InfluxDBなのかもしれません。
[^6]: datapathとはスイッチとかデバイスまでのパスを指しているんじゃないかと思います。用語の説明がないのでわからんのですが。