クイックスタート:Open vSwitchでSTPを5分で設定する
理論は後回しでいい。LinuxマシンにOpen vSwitch(OVS)でSTPを動かすための最速手順を紹介する。OVSをまだインストールしていない場合:
sudo apt-get install openvswitch-switch -y
sudo systemctl start openvswitch-switch
sudo systemctl enable openvswitch-switch
ブリッジを作成してSTPを有効にする:
# OVSブリッジを作成する
sudo ovs-vsctl add-br br0
# ブリッジでSTPを有効にする
sudo ovs-vsctl set bridge br0 stp_enable=true
# STPが有効であることを確認する
sudo ovs-vsctl get bridge br0 stp_enable
完了。STPがbr0で有効になった。ポートを追加すれば、OVSが残りを処理してくれる — ルートブリッジを選出し、冗長パスを自動的にブロックする:
# ブリッジにポートを追加する
sudo ovs-vsctl add-port br0 eth1
sudo ovs-vsctl add-port br0 eth2
# ポートのSTP状態を確認する
sudo ovs-ofctl show br0
詳細解説:STPが実際に何をするのか、なぜ必要なのか
OVSを使ってラボやクラウド環境で仮想スイッチを動かす場合、ほぼ必ずどこかに冗長パスが存在する。可用性のためには正しい選択だが、STPがなければそれらの冗長パスはいずれブロードキャストストームを引き起こす。すべてのスイッチがフレームをフラッドし、それが返ってきて、また再びフラッドされる。1Gbpsリンクでは、3秒以内にセグメント全体を飽和させることができる。
STP(IEEE 802.1D)はいくつかのポートをブロックすることでこの問題を解決する。任意の2つのブリッジ間に存在するアクティブなパスは常に1つだけだ。障害が発生すると、STPは再計算して代替パスを開く — ただし、クラシックSTPの収束には30〜50秒かかり、アクティブなセッションが切断されてサポートへの問い合わせが発生するには十分な時間だ。
STP vs RSTP vs MSTP — 適切なものを選ぶ
Open vSwitchは3つすべてをサポートしている:
- STP (802.1D) — クラシック、収束が遅い(〜50秒)、本番環境向けでは避けること
- RSTP (802.1w) — 高速収束(1〜2秒)、STPと後方互換性あり、ほとんどの設定で合理的なデフォルト
- MSTP (802.1s) — 複数のスパニングツリーインスタンス、VLANを異なるツリーにマッピング、冗長アップリンク間で本格的な負荷分散が必要な複雑なマルチVLAN環境に最適
RSTPはほとんどのOVSデプロイメントに適している。ボンディングアップリンクを持つKVMハイパーバイザークラスターの本番環境で実際に使用した経験があるが、ブロードキャストストームはゼロで、アップリンクが落ちた際もフェイルオーバーは2秒以内に完了した。シンプルに機能する。
STPポート状態の解説
STPで管理される各ポートはこれらの状態を経る:
- Blocking(ブロッキング) — BPDUを受信しているが、トラフィックを転送しない
- Listening(リスニング) — ルートブリッジ選出に参加している
- Learning(ラーニング) — MACアドレステーブルを構築中、まだ転送しない
- Forwarding(フォワーディング) — 完全にアクティブ、通常通りトラフィックを転送
- Disabled(無効) — 管理上シャットダウンされている
RSTPは適切な条件下でフォワーディングに直接スキップできる。エンドデバイスに接続するエッジポートとスイッチ間のポイントツーポイントリンクはすぐにアクティブになる — 待機不要だ。これが収束を50秒から2秒以内に短縮する理由だ。
ルートブリッジ選出
STPはブリッジIDを比較してルートブリッジを選出する — 優先度(デフォルト32768)とMACアドレスの組み合わせだ。最小値が勝つ。MACアドレスは制御できないため、優先度をデフォルトのままにするとルートブリッジの選出は事実上ランダムになる。明示的に設定しよう:
# 優先度が低いほどルートブリッジになりやすい
# 優先度は4096の倍数でなければならない(0、4096、8192...61440)
sudo ovs-vsctl set bridge br0 other-config:stp-priority=4096
# 確認する
sudo ovs-vsctl get bridge br0 other-config
応用設定:RSTPとMSTPの設定
RSTPへの切り替え
OVSはRSTPをクラシックSTPとは別のフラグとして扱う — モードを切り替えるだけではない。明示的に有効にする必要がある:
# 有効になっていた場合はまずSTPを無効にする
sudo ovs-vsctl set bridge br0 stp_enable=false
# RSTPを有効にする
sudo ovs-vsctl set bridge br0 rstp_enable=true
# 確認する
sudo ovs-vsctl get bridge br0 rstp_enable
ポートのパスコストと優先度の調整
パスコストはSTPにどのルートを優先するかを伝える。コストが低いほど、そのポートが転送に優先される。ポート優先度は2つのポートのパスコストが同一の場合にタイを破る:
# パスコストを低く設定してeth2よりeth1を優先する
sudo ovs-vsctl set port eth1 other-config:rstp-path-cost=100
sudo ovs-vsctl set port eth2 other-config:rstp-path-cost=200
# ポート優先度を設定する(低いほど優先、デフォルト128)
sudo ovs-vsctl set port eth1 other-config:rstp-port-priority=64
# ポートをエッジとしてマークする(サーバー/VMへの接続 — ラーニング遅延をスキップ)
sudo ovs-vsctl set port eth1 other-config:rstp-port-admin-edge=true
sudo ovs-vsctl set port eth1 other-config:rstp-port-auto-edge=true
マルチVLAN環境向けMSTP
MSTPはVLANを個別のスパニングツリーインスタンス(MSTI)にマッピングする。VLAN 10は一方の物理パスを使用し、VLAN 20は別のパスを使用する — フェイルオーバーだけでなく、冗長リンク間での実際の負荷分散だ。OVSでは、基本的なMSTPはRSTPとrstp_enableフラグを共有する:
# RSTP/MSTPを有効にする
sudo ovs-vsctl set bridge br0 rstp_enable=true
# 現在のスパニングツリートポロジーを表示する
sudo ovs-appctl rstp/show br0
OVSでのVLAN単位の完全なインスタンス管理には通常SDNコントローラーが必要だ。スタンドアロンのOVSでは、RSTPが複雑さを加えることなく大多数のケースに対応できる。
スパニングツリートポロジーの確認
# すべてのブリッジの詳細なRSTP状態
sudo ovs-appctl rstp/show
# 特定のブリッジに絞り込む
sudo ovs-appctl rstp/show br0
# OVS設定の全体概要
sudo ovs-vsctl show
rstp/showの出力はどのブリッジがルートか、ポートの役割(ルート、指定、代替)、フォワーディングとブロッキングの状態、パスコストを示す。何か問題があった場合はここから確認を始めよう。
実践的なヒント:現場での経験から
1. 常にブリッジ優先度を明示的に設定する
デフォルト優先度(32768)ではMACアドレスがルートを決める — 事実上ランダムだ。最も信頼性の高いスイッチが常に選ばれるよう、意図的に優先度を設定しよう:
# コアブリッジ — ルート
sudo ovs-vsctl set bridge core-br other-config:rstp-priority=4096
# ディストリビューションブリッジ — バックアップルート
sudo ovs-vsctl set bridge dist-br other-config:rstp-priority=8192
# アクセスブリッジ — ルートにしない
sudo ovs-vsctl set bridge access-br other-config:rstp-priority=32768
2. VM/サーバーポートをエッジポートとしてマークする
VMポートとサーバー向けポートはループを作らない — 他のスイッチではなくエンドポイントに接続するからだ。エッジポートとしてマークすれば、STPのラーニング遅延を完全にスキップし、即座にアップする:
# すべてのtapインターフェース(VMポート)にエッジポート設定を適用する
for port in $(sudo ovs-vsctl list-ports br0 | grep tap); do
sudo ovs-vsctl set port "$port" other-config:rstp-port-admin-edge=true
sudo ovs-vsctl set port "$port" other-config:rstp-port-auto-edge=true
done
3. トポロジー変更通知を監視する
頻繁なトポロジー変更(TCN)はMACテーブルをフラッシュし、一時的なフラッディングを引き起こす。これが繰り返し発生している場合は何か問題がある — フラッピングリンク、設定ミスのポート、またはまだ検出されていないループだ。ログを監視しよう:
# STP/RSTPイベントをリアルタイムで監視する
sudo tail -f /var/log/openvswitch/ovs-vswitchd.log | grep -i "rstp\|stp\|topology"
# ポートの役割と状態をまとめる
sudo ovs-appctl rstp/show br0 | grep -E "role|state|cost"
4. 意図的なループでテストする
最良の動作確認:vethペアを使って手動でループを作成し、OVSが自動的にポートの1つをブロックするのを確認する:
# 2つのブリッジを作成する
sudo ovs-vsctl add-br br-test1
sudo ovs-vsctl add-br br-test2
# 2つのvethペアを作成する(ブリッジ間の2つのパス = ループ)
sudo ip link add veth1a type veth peer name veth1b
sudo ip link add veth2a type veth peer name veth2b
# 両方のペアを2つのブリッジ間に接続する
sudo ovs-vsctl add-port br-test1 veth1a
sudo ovs-vsctl add-port br-test2 veth1b
sudo ovs-vsctl add-port br-test1 veth2a
sudo ovs-vsctl add-port br-test2 veth2b
# 両方でRSTPを有効にする
sudo ovs-vsctl set bridge br-test1 rstp_enable=true
sudo ovs-vsctl set bridge br-test2 rstp_enable=true
# すべてのインターフェースを起動する
sudo ip link set veth1a up; sudo ip link set veth1b up
sudo ip link set veth2a up; sudo ip link set veth2b up
# 数秒待ってから確認する
sudo ovs-appctl rstp/show br-test1
一方のvethポートはAlternate(代替)(ブロッキング)を示し、もう一方はDesignated(指定)(フォワーディング)を示す。物理ループはまだ存在している — STPが論理的にそれを断ち切ったのだ。これが求めていた確認だ。
クイックリファレンス:よく使うOVS STPコマンド
# クラシックSTPの有効化/無効化
sudo ovs-vsctl set bridge br0 stp_enable=true|false
# RSTPの有効化/無効化
sudo ovs-vsctl set bridge br0 rstp_enable=true|false
# ブリッジ優先度の設定(4096の倍数)
sudo ovs-vsctl set bridge br0 other-config:rstp-priority=4096
# ポートパスコストの設定
sudo ovs-vsctl set port eth0 other-config:rstp-path-cost=100
# スパニングツリー状態の表示
sudo ovs-appctl rstp/show [bridge-name]
# OVSバージョンの確認
sudo ovs-vswitchd --version
OVS上でのSTP設定は華やかな作業ではない。しかし、優先度を正しく設定し、VMポートをエッジポートとしてマークし、ループテストを一度実行して動作を確認すれば、あとはより興味深い問題に取り組んでいる間も、静かにネットワークを守り続けてくれる。

