Open vSwitch 概要
Open vSwitch (OVS) は、仮想化環境において標準的に利用されるマルチレイヤスイッチの実装です。本稿では、OVS の環境構築方法から、ブリッジやポートの管理、フローテーブルを用いたトラフィック制御、およびデバッグ手法について解説します。
環境構築 (CentOS)
CentOS 環境において、標準リポジトリ経由で OVS をインストールする手順は以下の通りです。systemd を利用してサービスの有効化および起動を行います。
yum install -y centos-release-openstack-newton
yum install -y openvswitch
systemctl enable openvswitch
systemctl start openvswitch
最新の開発版を利用したい場合は、外部リポジトリを追加することで master ブランチのビルドをインストール可能です。
wget -O /etc/yum.repos.d/ovs-master.repo https://copr.fedorainfracloud.org/coprs/leifmadsen/ovs-master/repo/epel-7/leifmadsen-ovs-master-epel-7.repo
yum install -y openvswitch openvswitch-ovn-*
ブリッジとポートの管理
仮想スイッチであるブリッジの作成、削除、およびポートの接続操作は ovs-vsctl コマンドで行います。
# ブリッジの作成と確認
ovs-vsctl add-br br-ex
ovs-vsctl list-br
# ポートの追加と VLAN 設定
ovs-vsctl add-port br-ex ens33
ovs-vsctl set port ens33 tag=100
# ポートの削除
ovs-vsctl del-port br-ex ens33
ovs-vsctl del-br br-ex
# 構成情報の表示
ovs-vsctl show
内部ポートを作成し、IP アドレスを割り当てることで、ホスト側から OVS ブリッジをゲートウェイとして利用できます。
ovs-vsctl add-port br-ex int-port -- set Interface int-port type=internal
ifconfig int-port 10.10.10.1 netmask 255.255.255.0 up
トラフィックの可視化と制御
ポートミラーリング
特定のポートを通過するトラフィックを別のポートへ複製し、パケットキャプチャなどに利用できます。
# ミラーリング設定
ovs-vsctl -- set Bridge br-int mirrors=@m \
-- --id=@tap-src get Port tap-vm-01 \
-- --id=@tap-dst get Port tap-vm-02 \
-- --id=@tap-mon get Port tap-monitor \
-- --id=@m create Mirror name=mirror0 select-dst-port=@tap-src,@tap-dst select-src-port=@tap-src,@tap-dst output-port=@tap-mon
# 設定解除
ovs-vsctl clear Bridge br-int mirrors
ダミーインターフェースを用意し、そこを監視ポートとして設定することで、tcpdump 等による解析が可能になります。
ip link add name mon0 type dummy
ip link set dev mon0 up
ovs-vsctl add-port br-int mon0
# 上記と同様に Mirror を作成し output-port に mon0 を指定
tcpdump -i mon0
QoS 設定
ポートに対して帯域制限やキューイングを設定し、トラフィックの品質を制御します。
ovs-vsctl -- set Port ens34 qos=@newqos \
-- --id=@newqos create QoS type=linux-htb other-config:max-rate=500000000 queues=0=@q0 \
-- --id=@q0 create Queue other-config:min-rate=100000000 other-config:max-rate=500000000
# 設定確認と削除
ovs-vsctl list qos
ovs-vsctl clear Port ens34 qos
sFlow によるモニタリング
sFlow エージェントを設定し、外部コレクターへ統計情報を送信します。
ovs-vsctl -- --id=@s create sFlow agent=ens33 target="10.20.30.5:6343" header=128 sampling=64 polling=10 \
-- set Bridge br-int sflow=@s
フローテーブルの制御
OVS の核となる機能は OpenFlow プロトコルに基づくフロー制御です。フローエントリはマッチ条件とアクションの組で構成されます。
フローエントリの構成
- 基本属性: 優先度 (priority)、テーブル ID (table_id)、タイムアウト (idle_timeout) など。
- マッチ条件: 入力ポート (in_port)、MAC アドレス (dl_src/dl_dst)、IP アドレス (nw_src/nw_dst)、プロトコル (nw_proto) など。下位層の条件が unspecified の場合、上位層の条件を指定することはできません。
- アクション: 転送 (output)、廃棄 (drop)、フィールド書き換え (mod_xx) など。複数のアクションを順序付けて実行可能です。
ワイルドカードとして * または ANY が利用できます。また、プロトコル名による簡略記法 (ip, icmp, tcp など) もサポートされています。
具体的な制御例
特定の IP アドレスからの通信を遮断します。
ovs-ofctl add-flow br-ex idle_timeout=0,dl_type=0x0800,nw_src=203.0.113.10,actions=drop
ICMP パケットを特定のポートへ転送します。
ovs-ofctl add-flow br-ex idle_timeout=0,dl_type=0x0800,nw_proto=1,actions=output:5
VLAN タグを除去し、正常転送します。
ovs-ofctl add-flow br-ex idle_timeout=0,in_port=4,actions=strip_vlan,normal
送信元 IP アドレスを書き換えて転送します (NAT 類似動作)。
ovs-ofctl add-flow br-ex idle_timeout=0,in_port=4,actions=mod_nw_src:192.0.2.1,normal
主要なマッチフィールドとアクション
in_port: 受信ポート番号dl_vlan: VLAN ID (0xffff はタグなし)dl_type: イーサタイプ (0x0800=IPv4, 0x86dd=IPv6, 0x0806=ARP)nw_src/dst: IP アドレス (CIDR マスク対応)output:port: 指定ポートへ出力mod_xx: ヘッダフィールドの書き換えresubmit: 再マッチング
デバッグとパケット注入
フロートレース
仮想的なパケットをスイッチに入力し、どのように処理されるかを追跡できます。
ovs-appctl ofproto/trace br-ex in_port=3,tcp,nw_src=10.0.0.5,tcp_dst=80
パケットの注入 (Packet-out)
コントローラー側からスイッチへパケットを送出するには packet-out メッセージを使用します。以下は Python の Scapy ライブラリを用いてパケットを生成し、16 進数形式で注入する例です。
from scapy.all import Ether, IP, ICMP
import binascii
# パケット生成
pkt = Ether(dst="aa:bb:cc:dd:ee:01", src="aa:bb:cc:dd:ee:02") / \
IP(dst="192.168.50.10", src="192.168.50.20", ttl=64) / \
ICMP()
# 16 進数変換
hex_payload = binascii.hexlify(bytes(pkt)).decode('utf-8')
print(hex_payload)
# OVS へ注入 (br-int のポート 5 から normal 処理として送出)
# ovs-ofctl packet-out br-int 5 "normal" <hex_payload>
ovs-ofctl packet-out br-int 5 "normal" AABBCCDDEE02AABBCCDDEE0108004500001C0001000040010000C0A83214C0A8320A0800F7FF00000000