従来のレイヤー2ネットワークが限界を迎えるとき
数年前、スタートアップで小規模なサーバークラスターを管理していた際、ある難題に直面しました。システム要件として、2台の異なる物理サーバー上にある仮想マシン(VM)がレイヤー2で直接通信する必要がありました。複雑なルーターを経由せずに、ブロードキャストや相互認識ができるよう、同じ内部IPセグメントに配置したかったのです。
最初に思いついた解決策はVLAN(802.1Q)でした。しかし、すぐに問題が発生しました。VLANの設定には、トランクポートを設定するために物理スイッチを操作する権限が必要です。AWSやGoogle CloudでVPSを借りている場合、これは不可能です。アプリケーションはイーサネットのレイヤー2を求めているのに、レイヤー3(IP)で足止めを食らってしまいます。
さらに、VLANは4096個のIDという制限があります。多くの顧客のために数千ものコンテナを運用するシステムでは、この数字はすぐに枯渇します。既存のIPインフラの上に仮想ネットワークを構築する、別の手法が必要だと痛感しました。それがオーバーレイネットワークです。
なぜ現代のインフラにVLANだけでは不十分なのか?
VLANは、イーサネットフレームにタグを挿入することで動作します。経路上のすべてのスイッチがこのタグを理解し、サポートしている必要があります。2台のサーバー間にルーターが1つでもあると、VLANタグは削除され、レイヤー2の接続は途切れてしまいます。
DockerやKubernetesの環境では、ノードは異なるサブネットに分散していることが一般的です。これらをフラットなネットワーク(flat network)として接続するには、オーバーレイネットワーク(Overlay Network)という技術が必要です。仮想的なケーブルを引く代わりに、イーサネットフレーム全体をUDP/IPパケットにカプセル化(encapsulate)します。これにより、レイヤー2フレームはレイヤー3インフラを「間借り」して、安全に目的地まで到達できます。
実装手法の比較
VXLANを選択する前に、3つの有力な候補を検討しました。
- GREトンネル: ポイント・ツー・ポイントの接続を非常に素早く確立できます。しかし、GREはブロードキャスト/マルチキャストパケットの処理が苦手で、ノード数が増えてフルメッシュ構成になると管理が極めて困難になります。
- VPN (WireGuard/OpenVPN): セキュリティは優れていますが、CPUリソースを消費します。暗号化によるオーバーヘッド(余剰データ)が大きく、同じラック内のサーバー間で重いデータベーストラフィックを流すと、帯域幅が大幅に低下します。
- VXLAN (Virtual Extensible LAN): これが現在のゴールデンスタンダードです。最大1600万個の仮想ネットワーク(VNI)をサポートし、あらゆるIPインフラ上でスムーズに動作します。
LinuxでのVXLAN実装
VXLANは、VTEP (VXLAN Tunnel End Point)と呼ばれる終端点を作成します。各サーバーがVTEPの役割を果たします。パケットがVXLANインターフェースに入ると、UDPポート4789にカプセル化され、宛先サーバーのIPへ送信されます。受信側では、サーバーがUDPヘッダーを解除して、元のイーサネットフレームを取り出します。
1. 環境のセットアップ
2台のUbuntuサーバーがあると仮定します:
- Host A: 物理IP
192.168.1.10 - Host B: 物理IP
192.168.1.20
目標:2つのホストを接続する 10.0.0.0/24 セグメントの仮想ネットワークを構築する。
2. Host Aでの設定
ID(VNI)が100のVXLANインターフェースを作成します。ポート 4789 は、IANAによって規定されたVXLANの標準ポートです。
# vxlan100インターフェースの作成
sudo ip link add vxlan100 type vxlan id 100 remote 192.168.1.20 dev eth0 dstport 4789
# 内部IPの割り当て
sudo ip addr add 10.0.0.1/24 dev vxlan100
# インターフェースの有効化
sudo ip link set vxlan100 up
3. Host Bでの設定
Host Bでも同様の操作を行いますが、remote にはHost AのIPを指定します。
# vxlan100インターフェースの作成
sudo ip link add vxlan100 type vxlan id 100 remote 192.168.1.10 dev eth0 dstport 4789
# 内部IPの割り当て
sudo ip addr add 10.0.0.2/24 dev vxlan100
# インターフェースの有効化
sudo ip link set vxlan100 up
4. 接続確認
Host Aから、Host Bの仮想IPに対してpingを試してみましょう:
ping 10.0.0.2 -c 4
レスポンスがあれば、レイヤー3環境を貫通するレイヤー2の「パイプ」の作成に成功しています。
Linux BridgeによるコンテナとVMの最適化
実際には、VXLANインターフェースに直接IPを割り当てることは稀です。代わりに、Linux Bridgeを作成し、そこにVXLANインターフェースと仮想マシンのインターフェース(tapインターフェース)を接続します。この方法により、複数の物理サーバー上のVMが、まるで1つの物理スイッチに接続されているかのように通信できます。
# 新しいブリッジの作成
sudo ip link add br-overlay type bridge
sudo ip link set br-overlay up
# vxlan100をブリッジに追加
sudo ip link set vxlan100 master br-overlay
このモデルをKVMのラボ環境に適用したところ、ネットワーク管理が非常に楽になりました。新しいネットワークセグメントを顧客ごとに追加するたびに、インフラ管理者にVLAN設定を依頼して待つ必要がなくなったからです。
運用における重要な注意点
- MTUの落とし穴: これは最も一般的なミスです。VXLANはパケットに50バイトのヘッダーを追加します。物理インターフェースのMTUが1500の場合、VXLANインターフェースのMTUを1450に下げる必要があります。そうしないと、大きなパケットがドロップされ、ウェブサイトの読み込みが遅くなったり、SSHがフリーズしたりする現象が発生します。
- ファイアウォール (Firewall):
UDP 4789ポートが開放されていることを確認してください。ufwがこのポートをブロックしていたために、何時間もデバッグに費やすことがよくあります。 - スケーリング: 上記の例では簡略化のためにユニキャスト(リモートIP指定)を使用しました。大規模なシステムでは、MACアドレス学習を自動化するために、マルチキャストやBGP EVPNの利用を検討してください。
VXLANは物理ネットワークと仮想化の間の壁を取り払います。柔軟で拡張性が高く、ハードウェアに依存しないネットワークインフラを構築したい場合、これは欠かせないツールです。

