自己紹介
こんにちは、Othlotechにたまーに参加しているさっとです。
普段はサーバサイドやインフラを主に触っています。
最近はフロントエンドにも興味がでてきてReactなんかも書いています。
概要
研究でTremaと呼ばれるSDNのフレームワークを構築することがありましたが、
Ubuntu18.04LTで構築するとき躓いた部分がいくつかあったので、メモとして残したいと思います。
あとは、Tremaには便利なテストがついています。仮想のホストをいくつか用意してパケットを飛ばしたり、構築したTremaがどういった挙動をするのかチェックすることができるので、今回はこちらを試してSDNの雰囲気をつかんでいただきたいと思います。
そもそもTremaとは?
SDNフレームワークの一種でRubyで書かれていることが特徴です。
Web開発で言うところのRailsみたいな感じです。
SDNについても説明しておくと、本来ネットワークを制御するためには物理スイッチの設定を直接書き込んだり、LANケーブルを繋ぎ変えたりと作業コストがかかっていました。
この問題を解決するために、ソフトウェアで柔軟にネットワークを制御することができるSDNが提案され一時期注目を浴びました。最近では下火ですが。。。
SDNフレームワークには、Tremaの他にもPythonで書かれたRyuやRestAPIで制御するOpenDaylightなどがあります。
研究ではTremaを使っていますが、選定理由としては、Tremaは日本人が開発したこともあり日本語のドキュメントが豊富でつまりづらいかつテストも容易でRubyについての知見もある程度あったためです。
環境構築
必要な環境
- git
- Ruby2.0〜2.3
まず初めに、TremaはRubyで動作するため、Rubyが実行できる環境を作る必要があります。また、TremaはOSSですが随分と更新されていないため最新のRubyバージョンでは動作できません。Ruby2.3あたりを入れる必要があるのでまずはそこからやっていきましょう。
前準備
Ruby2.3をそのままUbuntuに入れるとご自身の環境を汚しかねないので、anyenvと呼ばれる**env系を管理するツールでRubyのバージョンを管理するrbenvをインストールしたいと思います。
※ rbenvがすでにある方はここは飛ばしてもらっても構いません。
- anyenvを入れるために必要なgitをインストール
$ sudo apt install git
- anyenvをインストールします
$ git clone https://github.com/riywo/anyenv ~/.anyenv
- ターミナル起動時にanyenvを使えるようにするために
~/.bashrc
に以下を追記します。
if [ -d $HOME/.anyenv ]
then
export PATH="$HOME/.anyenv/bin:$PATH"
eval "$(anyenv init -)"
fi
-
~/.bashrc
の変更を適用します
$ source ~/.bashrc
- ANYENV_DEFINITION_ROOT(/home/***/.config/anyenv/anyenv-install) doesn't exist. You can initialize it by:と怒られたら以下のコマンドを実行
$ anyenv install --init
- anyenvがインストールされていることを確認します
$ which anyenv
/home/***/.anyenv/bin/anyenv
- rbenvのインストール
$ anyenv install rbenv
- ターミナルを更新しrbenvを適用します
$ exec $SHELL -l
- rbenvがインストールされていることを確認します
$ which rbenv
/home/***/.anyenv/bin/anyenv
Ruby2.3のインストール
先程インストールしたrbenvを使ってRuby2.3をインストールしたいと思います。
- その前にインストールに必要なパッケージ類を入れておきましょう
$ sudo apt install autoconf bison build-essential libssl1.0-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm5 libgdbm-dev
1分ぐらいかかると思います
- 次に、rbenvを使ってRuby2.3をインストールします
目的のバージョンがあるかどうか確認
$ rbenv inistall --list
・・・
2.3.0
2.3.1
2.3.2
2.3.3
・・・
- 2.3系がいくつかありますが、無難に2.3.0をインストール
$ rbenv install 2.3.0
結構時間かかります。カップラーメン食べれるぐらい
- Rubyがインストールされていることを確認してみます
$ rbenv versions
2.3.0
- Ruby2.3.0をグローバル設定する
$ rbenv global 2.3.0
- Ruby2.3.0がグローバル設定されたかどうか確認してみる
$ rbenv versions
* 2.3.0 (set by /home/***/.anyenv/envs/rbenv/version)
Tremaのインストール
- 適当なディレクトリに移動してTremaをインストールします
$ git clone https://github.com/trema/hello_trema
- クローンしてきたファイルに入る
$ cd hello_trema
- ここで必要なパッケージをインストールするためにbundleがいるのでインストールします
(最新のbundleだと動かないので1.11.2を指定します)
$ rbenv exec gem install bundler -v 1.11.2
- 例のごとくbundleがインストールされたか確認します
$ which bundler
- bundleを使って必要なパッケージをインストール
$ bundle _1.11.2_ install --binstubs
- 仮想ホストや仮想ネットワークを構築するためにopenvswitchをインストール
$ sudo apt install openvswitch-switch
以上で下準備は完了です
ハローワールドしてみる
インストールしたTremaを起動してみます
$ ./bin/trema run lib/hello_trema.rb -c trema.conf
Trema started.
Hello 0xabc!
Helloと出ましたね
無事Tremaを起動することが確認できました
実行ファイルの確認
Tremaでは./lib/hello_trema.rb
にネットワークを制御するためのコントローラを定義します。
中身はこんな感じです
# Hello World!
class HelloTrema < Trema::Controller
def start(_args)
logger.info 'Trema started.'
end
def switch_ready(datapath_id)
logger.info "Hello #{datapath_id.to_hex}!"
end
end
ライフサイクルとしては、Tremaが実行されるとまずはじめにstartメソッドが読み込まれます。
Trema実行時にすぐTrema started.
が表示されたのはそのためです。
その後、switchの接続が確認されると、switch_readyメソッドが呼ばれます。
ここで、お気づきだと思いますが、実行結果では、switchの接続をしていないのにswitch_readyメソッドが呼ばれていることがわかると思います。
理由としては、trema.conf
に仮想のスイッチが定義されているためです。
vswitch { datapath_id 0xabc }
この一行を書くだけで、簡単に仮想スイッチを用意することができます。
ちなみに、datapath_idとはスイッチを識別するためのMACアドレスみたいなものです。
スイッチを追加してみる
試しに、このファイルに新しいスイッチを定義してみましょう
vswitch { datapath_id 0xabc }
vswitch { datapath_id 0xdef }
- Tremaの実行
$ ./bin/trema run lib/hello_trema.rb -c trema.conf
Trema started.
Hello 0xabc!
Hello 0xdef!
新しく追加したスイッチが表示されていることがわかると思います。
おわりに
今回はTremaの一から環境構築をまとめてみました。
物理機器を用意しなくとも簡易的な実験やSDNを手軽に体験できるので、この記事を参考にしてぜひ触ってみてください。