ネットワーク仮想化技術の実践活用(2) 〜OpenvSwitch管理プロトコル(OVSDB)編〜
ネットワーク仮想化環境の特徴は、VxLAN等のオーバレイ技術を活用して多拠点間をトンネルで接続するモデルだと思います。
ただ、拠点数(n)に対して、拠点間をフルメッシュn*(n − 1)本のトンネルを構築する必要があります。
前回のブログ記事では、2拠点をVxLANトンネルで構築する程度のため、OpenvSwitchのコマンドラインで構築しましたが、拠点数が多くなると、やっぱり、集中管理的に拠点間トンネル設定を行いたくなりますよね。ということで、今回は、OpenvSwitch管理プロトコル「OVSDB」に着目したいと思います。
◆OVSDBとは ?
OVSDBとは、OpenvSwitchのデータモデルを管理する手法です。
RDBMSにおけるSQL的な役割で、DDL(Data Definition Language:データ定義言語)の側面と、DML(Data Manipulation Language:データ操作言語)の側面を併せ持っているものです。
ざっと、OpenvSwitchのテーブル構成は、以下のようになってます。
Open_vSwitch --> Open vSwitch configuration.
Bridge --> Bridge configuration.
Port --> Port configuration.
Interface --> One physical network device in a Port. Flow_Table OpenFlow table configuration
QoS --> Quality of Service configuration Queue QoS output queue.
Mirror --> Port mirroring.
Controller --> OpenFlow controller configuration. Manager OVSDB management connection. NetFlow NetFlow configuration.
SSL --> SSL configuration.
sFlow --> sFlow configuration.
IPFIX --> IPFIX configuration. Flow_Sample_Collector_Set
Flow_Sample_Collector_Set --> configuration.
また、OpenvSwitchデータベースのスキーマ定義などの詳細は、以下のリンクが参考になります。
http://openvswitch.org/ovs-vswitchd.conf.db.5.pdf
Open_vSwitchテーブル構造
OpenvSwitchデータベースを構成する多数のテーブルのうち、「Open_vSwitch」テーブル構造を、確認してみます。
tsubo@OFS1:~$ sudo ovs-vsctl list Open_vSwitch _uuid : 82524775-43a3-4838-90ae-61e2cbd10820 bridges : [55d71da8-cd33-4117-b7a3-de8a5b4222a3] cur_cfg : 12 db_version : "7.3.0" external_ids : {system-id="a7812d37-5389-4ae6-b003-42a66a6e05fe"} manager_options : [0cc00f03-5c47-404a-9a31-66e5105f48d2] next_cfg : 12 other_config : {} ovs_version : "2.0.1" ssl : [] statistics : {} system_type : Ubuntu system_version : "12.04-precise"
ovs-vsctlコマンドと、いろいろと引数を指定してあげれば、様々なテーブル情報を参照できるようです。
◆外部からOpenvSwitchデータベースにアクセスするには ?
1. OpenvSwitch管理プロトコル
VMware社により、IETFのInformational RFC化されているようですが、OpenvSwitch専用だと思います。
他の類似技術として、OpenFlowスイッチ管理プロトコル「OF-Config」があります。
OVSDB管理手法の特徴としては、JSON-RPCをベースとしたデータモデリングを前提としている点です。
データ検索クエリのデータフォーマットとしては、"method", "params", "id"という構造となるようです。
RFC 7047 :The Open vSwitch Database Management Protocol 4.1.5. Monitor The "monitor" request enables a client to replicate tables or subsets of tables within an OVSDB database by requesting notifications of changes to those tables and by receiving the complete initial state of a table or a subset of a table. The request object has the following members: o "method": "monitor" o "params": [<db-name>, <json-value>, <monitor-requests>] o "id": <nonnull-json-value> The <json-value> parameter is used to match subsequent update notifications (see below) to this request. The <monitor-requests> object maps the name of the table to be monitored to an array of <monitor-request> objects. Each <monitor-request> is an object with the following members: "columns": [<column>*] optional "select": <monitor-select> optional The columns, if present, define the columns within the table to be monitored. <snip>
2. 外部機器からデータ操作するための事前準備
外部機器から、OpenvSwitchデータベースにアクセスするために、事前に、以下のコマンドを実施しておきます。
$ sudo ovs-vsctl set-manager ptcp:6632
ポート番号は、今回は、とりあえず、"6632"としました。
3. 実際に「Open_vSwitchテーブル」を参照してみる
それでは、外部装置から、以下のPythonプログラムで「Open_vSwitchテーブル」を参照してみます。
#-*- coding: utf-8 -*- import socket import json OVSDB_IP = '192.168.0.1' OVSDB_PORT = 6632 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((OVSDB_IP, OVSDB_PORT)) monitor_query = \ {"method":"monitor", "params":["Open_vSwitch","null",{"Open_vSwitch":{"columns":["bridges","cur_cfg","db_version","external_ids","manager_options","next_cfg","other_config","ovs_version","ssl","statistics","system_type","system_version"]}}], "id":0} print "----------------------------------" print "json rpc request" print "----------------------------------" print json.dumps(monitor_query, sort_keys=False, indent=1) s.send(json.dumps(monitor_query)) print "----------------------------------" print "json rpc reply" print "----------------------------------" response = s.recv(8192) result = json.loads(response) print json.dumps(result, sort_keys=False, indent=1)
Pythonプログラムの実行結果は、こんな感じです。
さきほど、"sudo ovs-vsctl list Open_vSwitch"の実行結果と対比してみると、OVSDBの挙動がイメージしやすいかもしれません。
$ python ovsdb_show.py ---------------------------------- json rpc request ---------------------------------- { "params": [ "Open_vSwitch", "null", { "Open_vSwitch": { "columns": [ "bridges", "cur_cfg", "db_version", "external_ids", "manager_options", "next_cfg", "other_config", "ovs_version", "ssl", "statistics", "system_type", "system_version" ] } } ], "method": "monitor", "id": 0 } ---------------------------------- json rpc reply ---------------------------------- { "error": null, "id": 0, "result": { "Open_vSwitch": { "82524775-43a3-4838-90ae-61e2cbd10820": { "new": { "bridges": [ "uuid", "55d71da8-cd33-4117-b7a3-de8a5b4222a3" ], "statistics": [ "map", [] ], "db_version": "7.3.0", "next_cfg": 12, "ovs_version": "2.0.1", "other_config": [ "map", [] ], "ssl": [ "set", [] ], "system_type": "Ubuntu", "external_ids": [ "map", [ [ "system-id", "a7812d37-5389-4ae6-b003-42a66a6e05fe" ] ] ], "system_version": "12.04-precise", "cur_cfg": 12, "manager_options": [ "uuid", "0cc00f03-5c47-404a-9a31-66e5105f48d2" ] } } } } }
◆集中管理的にVxLANトンネルを設定してみる
OpenvSwitch管理プロトコル概要が理解できたところで、それでは、もう少し実用的なOVSDB活用にチャレンジしてみます。
1. 検証構成
基本的な検証構成は、前回のブログ記事と同様です。
ただし、今回は、OpenFlowコントローラを使用せず、OVSDBコントローラとして、Ryuコントローラを活用しました。
2. VxLANトンネル設定プログラム
OVSDBを制御するPythonプログラムは、以下になります。OVSDBコントローラのNorthBoundインタフェースとして、REST-APIを採用しております。
import json from webob import Response from ryu.base import app_manager from ryu.app.wsgi import ControllerBase, WSGIApplication, route from ryu.lib.dpid import DPID_PATTERN from ryu.lib.ovs import bridge OVSDB_ADDR1 = 'tcp:192.168.0.1:6632' OVSDB_ADDR2 = 'tcp:192.168.0.2:6632' class SetOvsdb(app_manager.RyuApp): _CONTEXTS = { 'wsgi': WSGIApplication } def __init__(self, *args, **kwargs): super(SetOvsdb, self).__init__(*args, **kwargs) wsgi = kwargs['wsgi'] wsgi.register(OvsdbController, {'SetOvsdb' : self}) def setTunnel(self, id, name, type, local_ip, remote_ip): if id == 1: ovs_bridge = bridge.OVSBridge(id, OVSDB_ADDR1) elif id == 2: ovs_bridge = bridge.OVSBridge(id, OVSDB_ADDR2) else: return 1 ovs_bridge.init() ovs_bridge.add_tunnel_port(name, type, local_ip, remote_ip) return 0 class OvsdbController(ControllerBase): def __init__(self, req, link, data, **config): super(OvsdbController, self).__init__(req, link, data, **config) self.ovsdb_spp = data['SetOvsdb'] @route('router', '/ovsdb/{dpid}/tunnel', methods=['POST'], requirements={'dpid': DPID_PATTERN}) def set_tunnel_port(self, req, dpid, **kwargs): tunnel_param = eval(req.body) result = self.setTunnel(int(dpid, 16), tunnel_param) message = json.dumps(result) return Response(status=200, content_type = 'application/json', body = message) def setTunnel(self, id, tunnel_param): simpleOvsdb = self.ovsdb_spp name = tunnel_param['tunnel']['name'] type = tunnel_param['tunnel']['type'] local_ip = tunnel_param['tunnel']['local_ip'] remote_ip = tunnel_param['tunnel']['remote_ip'] simpleOvsdb.setTunnel(id, name, type, local_ip, remote_ip) return { 'id': '%016d' % id, 'tunnel': { 'name': '%s' % name, 'type': '%s' % type, 'local_ip': '%s' % local_ip, 'remote_ip': '%s' % remote_ip } }
3. OVSDBコントローラ上でのプログラム動作イメージ
実際に、プログラムを動作させてみました。REST-API経由で、VxLANトンネル設定パラメータを受信した様子がわかると思います。
$ ryu-manager setOvsdb.py loading app setOvsdb.py creating context wsgi instantiating app setOvsdb.py of SetOvsdb (4017) wsgi starting up on http://0.0.0.0:8080/ (4017) accepted ('127.0.0.1', 37197) 127.0.0.1 - - [23/Mar/2014 17:35:17] "POST /ovsdb/0000000000000001/tunnel HTTP/1.1" 200 250 0.285298 (4017) accepted ('127.0.0.1', 37201) 127.0.0.1 - - [23/Mar/2014 17:35:21] "POST /ovsdb/0000000000000002/tunnel HTTP/1.1" 200 250 0.287827
4. OFS1へのVxLANトンネル設定
実際に、OVSDBコントローラの上位より、REST-APIを経由してOFS1用のVxLANトンネル設定パラメータを指定しました。
$ curl -s -X POST -d '{"tunnel": {"name": "vxlan1", "type": "vxlan", "local_ip": "172.16.0.1", "remote_ip": "172.16.0.2"}}' http://localhost:8080/ovsdb/0000000000000001/tunnel | python -mjson.tool { "id": "0000000000000001", "tunnel": { "local_ip": "172.16.0.1", "name": "vxlan1", "remote_ip": "172.16.0.2", "type": "vxlan" } }
結果として、OFS1上で、想定どおりにVxLANトンネルが構築できました。
tsubo@OFS1:~$ sudo ovs-vsctl show 82524775-43a3-4838-90ae-61e2cbd10820 Manager "ptcp:6632" Bridge "br0" Controller "tcp:192.168.0.100:6633" Port "eth1" Interface "eth1" Port "br0" Interface "br0" type: internal Port "vxlan1" Interface "vxlan1" type: vxlan options: {local_ip="172.16.0.1", remote_ip="172.16.0.2"} ovs_version: "2.0.1"
5. OFS2へのVxLANトンネル設定
同様に、OVSDBコントローラの上位より、REST-APIを経由してOFS2用のVxLANトンネル設定パラメータを指定しました。
$ curl -s -X POST -d '{"tunnel": {"name": "vxlan2", "type": "vxlan", "local_ip": "172.16.0.2", "remote_ip": "172.16.0.1"}}' http://localhost:8080/ovsdb/0000000000000002/tunnel | python -mjson.tool { "id": "0000000000000002", "tunnel": { "local_ip": "172.16.0.2", "name": "vxlan2", "remote_ip": "172.16.0.1", "type": "vxlan" } }
結果として、OFS2上で、想定どおりにVxLANトンネルが構築できました。
tsubo@OFS2:~$ sudo ovs-vsctl show 845f5da2-fb63-4273-b32a-c4cf77b0b943 Manager "ptcp:6632" Bridge "br0" Controller "tcp:192.168.0.100:6633" Port "br0" Interface "br0" type: internal Port "eth2" Interface "eth2" Port "vxlan2" Interface "vxlan2" type: vxlan options: {local_ip="172.16.0.2", remote_ip="172.16.0.1"} ovs_version: "2.0.1"
6. VxLANトンネル上での通信確認
VxLANトンネル構築が完了したので、ちゃんと動作できるかの確認として、MacBook Airからインターネットに接続して、Ustream映像を閲覧してみました。ustream映像も問題なく再生できておりました。あと、余談ですが、ustream映像の「BABYMETAL」は、要注目ですよ。
7. 留意事項
VxLANトンネルの登録・削除を繰り返すと、OFポート番号が、インクリメントしてしまうようです。
OpenFlowでVxLANトンネルを制御する際には、考慮が必要となりますね。
tsubo@OFS1:~$ sudo ovs-ofctl dump-ports-desc br0 --protocols=OpenFlow13 OFPST_PORT_DESC reply (OF1.3) (xid=0x2): 1(eth1): addr:00:10:f3:1d:3d:1d config: 0 state: 0 current: 1GB-FD COPPER AUTO_NEG advertised: 10MB-HD 10MB-FD 100MB-HD 100MB-FD 1GB-FD COPPER AUTO_NEG supported: 10MB-HD 10MB-FD 100MB-HD 100MB-FD 1GB-FD COPPER AUTO_NEG speed: 1000 Mbps now, 1000 Mbps max 5(vxlan1): addr:de:be:49:23:35:a6 config: 0 state: 0 speed: 0 Mbps now, 0 Mbps max LOCAL(br0): addr:00:10:f3:1d:3d:1d config: 0 state: 0 speed: 0 Mbps now, 0 Mbps max
◆終わりに
以前から、VxLANトンネル等のネットワーク仮想化の構成管理って、OpenvSwitchコマンド主体だと煩雑になる懸念がありました。OVSDBプロトコル自体の活用シーンは、OpenvSwitch専用ツールが前提となります。ただし、今後も、SDN技術領域におけるOpenvSwitchの役割りは大きなウエイトを占めると予想されますので、もっとちゃんと使いこなせるように調査探求していきたいです。