背景と導入の理由
午前2時15分、ポケットベルが甲高いアラート音を響かせます。「Critical: Database cluster split-brain across rack 3 and rack 7(重大: ラック3とラック7間でデータベースクラスタのスプリットブレインが発生)」。踏み台ホストにログインし、目をこすりながら原因を特定すると、犯人はすぐに判明しました。レガシーなデータベースクラスタが、まったく同一のLayer 2ブロードキャストドメイン内に存在しなければならないハードコードされたIPアドレスに依存していたのです。あるエンジニアが2台のレプリカVMを異なるToR(Top-of-Rack)リーフスイッチへ移行した結果、ラック間のルーティングされたLayer 3境界によってクラスタのハートビートがサイレントに切断されていました。
従来のVLANは、現代の大規模環境では破綻をきたします。40台ものスイッチにわたって802.1Qのトランクを設定すると、スパニングツリーの不安定化を招き、ネットワークセグメント数は最大4,094個に制限され、さらにはスパインリンク全体にブロードキャストフレームがフラッディングしてしまいます。静的なVXLANポイントツーポイントトンネルを使えば4,000の制限は回避できますが、50台ものハイパーバイザにわたって静的なフラッドリストを保守し、リモートMACアドレスを手動でマッピングすることは、ホスト移行のたびに運用上の重大なリスクを伴います。
Border Gateway Protocol(BGP)を組み合わせたEthernet VPN(EVPN)は、この問題をスマートに解決します。ここでは、BGP EVPNが基盤となるVXLANデータプレーンのコントロールプレーンとして機能します。エンドポイントを検出するためにブロードキャストのフラッディングに頼るのではなく、LinuxホストがBGP Type-2ルートを使用してMACアドレスとIPアドレスのバインディングをプロアクティブに交換します。ベアメタルのKubernetesノード、マルチテナントのProxmox環境、あるいはプライベートクラウドを運用しているなら、このアーキテクチャの習得はオンコール担当時の救世主となるはずです。
インストール
今回は2台のUbuntu 22.04 LTSホスト、Leaf-01とLeaf-02を構成します。各ノードはVTEP(Virtual Tunnel Endpoint)として機能します。アンダーレイネットワークは標準的なIPv4ルーティング経路で両者を接続し、FRRouting(FRR)がEVPNの到達性情報を配信します。
まず、カーネルにVXLANモジュールがロードされていることを確認します。
modprobe vxlan
lsmod | grep vxlan
公式のアップストリームリポジトリからFRRoutingをインストールします。ディストリビューション標準のパッケージでは不足しがちな最新のEVPNアドレスファミリ機能も、アップストリームのパッケージなら利用できます。
sudo apt-get update && sudo apt-get install -y curl gnupg2 lsb-release
# FRRのGPGキーとリポジトリを追加
curl -s https://deb.frrouting.org/frr/keys.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/frr.gpg
FRRVER="frr-stable"
echo "deb https://deb.frrouting.org/frr $(lsb_release -s -c) $FRRVER" | sudo tee /etc/apt/sources.list.d/frr.list
sudo apt-get update && sudo apt-get install -y frr frr-pythontools
次に、/etc/frr/daemonsを編集してBGPデーモンを有効化します。
sudo sed -i 's/bgpd=no/bgpd=yes/' /etc/frr/daemons
sudo systemctl restart frr
設定
1. ホストネットワークとアンダーレイのセットアップ
今回の検証環境の構成は次のとおりです。Leaf-01はアンダーレイのループバックIPとして10.0.0.1/32を使用し、Leaf-02は10.0.0.2/32を使用します。両ホストは物理インターフェース(eth0)経由で相互に通信可能です。ローカルブリッジ(br10)を作成し、それをVNI 10010のVXLANインターフェースにバインドします。
Leaf-01でブリッジとトンネルインターフェースを作成します。
# L2ブリッジを作成
sudo ip link add br10 type bridge
sudo ip link set br10 up
# アンダーレイ送信元10.0.0.1にマッピングしたVXLANデバイス(VNI 10010)を作成
sudo ip link add vxlan10 type vxlan \
id 10010 \
local 10.0.0.1 \
dstport 4789 \
nolearning
# VXLANをブリッジに接続して有効化
sudo ip link set vxlan10 master br10
sudo ip link set vxlan10 up
ここでnolearningフラグに注目してください。このフラグは、従来のフラッド&ラーンによるデータパスのスヌーピングを抑止するようLinuxカーネルに指示します。MACアドレスの登録は、FRRoutingが転送データベース(FDB)に直接書き込むことで処理されます。
Leaf-02でも、自身のローカルループバックIPを指定して同様のコマンドを実行します。
sudo ip link add br10 type bridge
sudo ip link set br10 up
sudo ip link add vxlan10 type vxlan \
id 10010 \
local 10.0.0.2 \
dstport 4789 \
nolearning
sudo ip link set vxlan10 master br10
sudo ip link set vxlan10 up
2. FRRoutingのBGP EVPN設定
Leaf-01でFRRのインタラクティブ管理シェルを起動します。
sudo vtysh
設定モード(conf t)に入り、BGPピアリングを定義します。
router bgp 65001
bgp router-id 10.0.0.1
no bgp default ipv4-unicast
neighbor 10.0.0.2 remote-as 65002
neighbor 10.0.0.2 description Leaf-02
neighbor 10.0.0.2 update-source 10.0.0.1
address-family l2vpn evpn
neighbor 10.0.0.2 activate
advertise-all-vni
exit-address-family
exit
続いてLeaf-02に切り替え、vtyshに入って対向のセッションを設定します。
router bgp 65002
bgp router-id 10.0.0.2
no bgp default ipv4-unicast
neighbor 10.0.0.1 remote-as 65001
neighbor 10.0.0.1 description Leaf-01
neighbor 10.0.0.1 update-source 10.0.0.2
address-family l2vpn evpn
neighbor 10.0.0.1 activate
advertise-all-vni
exit-address-family
exit
再起動後も設定を維持できるよう、両方のマシンでwrite memoryを実行して保存します。
動作確認とモニタリング
インシデント発生時には、体系的な検証手順を踏むことで貴重な時間を節約できます。以下の3段階のチェックを実施して、コントロールプレーンとデータプレーンの状態を確認しましょう。
1. BGP EVPNコントロールプレーンの確認
vtysh内でshow bgp summaryを実行し、セッション状態を確認します。
show bgp summary
出力結果のState/PfxRcd列に、セッションが確立(Established)され、EVPNプレフィックスを受信していることが示されている必要があります。
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt
10.0.0.2 4 65002 42 45 0 0 0 00:18:12 2 2
次に、ローカルホストがどのEVPN Type-2(MAC/IP)ルートを学習したかを確認します。
show bgp l2vpn evpn
VNI 10010 #
Route Distinguisher: 10.0.0.1:2
*> [2]:[0]:[48]:[52:54:00:12:34:56]
10.0.0.2 0 32768 ?
*> [2]:[0]:[48]:[52:54:00:12:34:56]:[32]:[192.168.10.20]
10.0.0.2 0 32768 ?
2. LinuxカーネルFDBの確認
FRRはこれらのBGPルートを解析し、Linuxカーネルの転送データベース(FDB)に直接書き込みます。vtyshを終了し、Leaf-01でFDBエントリを確認します。
bridge fdb show dev vxlan10
対象のMACアドレスがリモートのVTEP IPに直接マッピングされていることを確認します。
52:54:00:12:34:56 dst 10.0.0.2 self permanent
00:00:00:00:00:00 dst 10.0.0.2 self permanent
3. エンドツーエンドの接続性テストの実施
両ノードのbr10にテスト用のネットワーク名前空間またはvethインターフェースを接続します。Leaf-01側に192.168.10.10/24、Leaf-02側に192.168.10.20/24を割り当てます。ICMP pingを開始し、中継インターフェース上でパケットをキャプチャします。
sudo tcpdump -ni eth0 udp port 4789 -vv
内部のLayer 2フレームをカプセル化したポート4789の標準UDPパケットが確認できるはずです。ペイロードにはVNI 10010タグが付与され、ICMPリクエストおよびリプライパケットを包み込んでいます。これで、両ホストは物理的なラックの境界やスパインルータの制約から完全に解放され、統合されたL2ブロードキャストドメインを介して通信できるようになりました。

