SDNの心臓部を覗く:Open vSwitchとOpenFlowが奏でる「パケットの旅」の正体
クラウドインフラを設計していると、どうしても抽象化されたクラウドベンダーのネットワーク機能に頼りがちになります。しかし、その裏側で何が起きているのかを知っているかどうかで、トラブルシューティングの「勘」は劇的に変わります。
今日は、現代の仮想ネットワークの黒幕とも言える Open vSwitch (OVS) と、その指揮者である OpenFlow プロトコルについて、現場の視点から深掘りしていきましょう。教科書的な概念解説はそこそこに、パケットがどう判定され、どこへ向かうのか。その泥臭い仕組みを紐解きます。
—
1. OVSにおける「フローテーブル」という名の裁き
OVSを単なる仮想L2スイッチだと思っているなら、それは大きな誤解です。OVSは、いわば「パケットが到着するたびにルールブックをめくる、非常に仕事熱心な検問官」です。
パケットがOVSに入力されると、まず「フローテーブル」と呼ばれる照合表が参照されます。ここには、以下の要素からなる「マッチング条件」が書かれています。
in_port: どのインターフェースから来たかdl_src/dl_dst: 送信元/宛先MACアドレスnw_src/nw_dst: 送信元/宛先IPアドレスtp_src/tp_dst: 送信元/宛先ポート番号
この条件に合致(マッチ)した際、OpenFlowコントローラが指示した「アクション」が実行されます。アクションは output:1(ポート1へ転送)のような単純なものから、set_field:192.168.1.10->ip_dst(宛先IPの書き換え、いわゆるNAT)といった高度なものまで多岐にわたります。
—
2. パケット転送のシーケンス:脳と手足の関係
OpenFlow環境では、OVS(手足)とOpenFlowコントローラ(脳)が分離されています。通信のライフサイクルは以下のようなシーケンスで動きます。
1. Packet-In: OVSに知らないパケット(マッチするフローがない)が届く。OVSはパケットのヘッダー情報をコントローラに「これどうすればいい?」と問い合わせる(Packet-In メッセージ)。
2. Flow-Mod: コントローラが判断を下す。この通信を今後どう扱うかのルールをOVSに書き込む(Flow-Mod メッセージ)。
3. Packet-Out: 待機させていたパケットを、コントローラの指示通りに転送する(Packet-Out メッセージ)。
この一連のやり取りを TCP 通信(デフォルトは 6633 や 6653 ポート)で行うため、コントローラがダウンするとネットワーク全体が「思考停止」に陥るリスクがある。これがSDN運用の最大の注意点です。
—
3. 実践:フローテーブルを操作する
現場で最もよく使うのが ovs-ofctl コマンドです。まずは現在のフローテーブルを確認してみましょう。
# 現在のフローテーブルを表示。優先度(priority)とマッチ条件、アクションが確認できる
sudo ovs-ofctl dump-flows br-int
フローの追加例
特定のIPからの通信を別のポートへ飛ばすような、制御ルールを追加してみます。
# 優先度100で、宛先IPが10.0.0.5のパケットをポート2に転送するルール
sudo ovs-ofctl add-flow br-int \
"table=0, priority=100, ip, nw_dst=10.0.0.5, actions=output:2"
—
4. API経由で制御する:コントローラの自作という選択肢
クラウドネイティブな環境では、CLIを叩くのではなく、REST APIを介してネットワークを動的に再構成したい場面があります。Pythonの ryu フレームワークなどを使えば、独自のSDNコントローラを構築可能です。
以下は、curl で直接コントローラのREST APIを叩くイメージ(架空のコントローラAPI)です。
# Pythonのrequestsライブラリでやるならこんな感じ
import requests
# コントローラのAPIエンドポイント
url = "http://sdn-controller:8080/stats/flowentry/add"
# フローの定義
flow_rule = {
"dpid": 1,
"priority": 10,
"match": {"nw_dst": "192.168.1.10", "dl_type": 0x0800},
"actions": [{"type": "OUTPUT", "port": 3}]
}
# 実行
response = requests.post(url, json=flow_rule)
print(f"Status Code: {response.status_code}")
—
5. 現場のSREが教えるデバッグTips
ネットワークのトラブルで最も多いのは「ルールはあるのに転送されない」ケースです。そんな時は、迷わずパケットをキャプチャしましょう。tcpdump を使うのが手っ取り早いですが、OVS内の特定のポートで何が起きているかを見るなら、ovs-appctl が強力です。
# OVS内部のパケットの動きをトレースする(非常に強力)
sudo ovs-appctl ofproto/trace br-int in_port=1,dl_src=00:11:22:33:44:55,dl_dst=aa:bb:cc:dd:ee:ff
このコマンドは、実際にパケットを流さなくても「もしこのパケットが来たら、どのフローテーブルにマッチして、どのポートから出るか」をシミュレーションしてくれます。本番環境で障害が起きたとき、切り分けの初動として必ず行うべき作業です。
最後に
OVSとOpenFlowは、魔法のように見えて、実は非常に論理的なパケットの「仕分け作業」です。もし皆さんが担当する環境でネットワークが遅延したり、特定の通信だけが通らないという事象に遭遇したら、まずは ovs-ofctl dump-flows で、誰がそのパケットを「ドロップ(破棄)」しているのか、あるいは「本来意図しないアクション」を指示しているのかを探ってみてください。
ネットワークが見えるようになると、インフラエンジニアとしての視界は格段に広がります。頑張ってください。
コメント