帯域の魔術師:LACPで実現する「論理的帯域拡張」とハッシュ計算の深淵
ネットワークインフラの現場で、「帯域が足りない」という悲鳴を聞いたとき、あるいは「物理回線を冗長化したい」と相談されたとき、真っ先に頭に浮かぶのが IEEE 802.3ad(現在はIEEE 802.1AXに統合)こと、リンクアグリゲーション(LAG)です。
単に物理ケーブルを挿せば良いという単純なものではありません。今回は、LACP(Link Aggregation Control Protocol)の泥臭い仕様と、エンジニアが最も頭を悩ませる「ロードバランシングのハッシュアルゴリズム」の真実について、現場の視点から紐解いていきましょう。
—
1. LACP:ただの「束ね」ではない、対話による信頼の構築
LACPの目的は、単なる物理リンクの束ねではありません。「対向機器との間で、正しく論理的なグループを構成できているか?」を定期的に確認し合う制御プロトコルです。
LACPでは、LACPDU(LACP Data Unit)と呼ばれる制御パケットが、マルチキャストアドレス 01:80:c2:00:00:02 を宛先として、デフォルトで30秒間隔(Slow Periodic)で交換されます。
実務で知っておくべきパラメーター
- Actor/Partner: LACPDUを送信する側をActor、受信する側をPartnerと呼びます。
- System Priority: どちらの機器を「主」とするかを決める値。小さいほど優先度が高い。
- Port Priority: どのポートを優先的にアグリゲーションに組み込むかの優先度。
- Key: ポートが持つ「属性値」。同じKeyを持つポート同士しか束ねることはできません。
この対話があるおかげで、誤配線によってループが発生したり、片側のポートだけが死んでいるのに「リンクアップしているから大丈夫」と勘違いしてトラフィックをブラックホールに吸い込ませるような事故を未然に防げるのです。
—
2. ロードバランシングの正体:ハッシュ計算の「偏り」
多くのエンジニアが「LACPを組めば帯域が2倍になる」と誤解しています。しかし、実際には 「1つのフロー(送信元・宛先のペア)は、必ず1つの物理リンクを通り続ける」 という大原則があります。もし順序が入れ替わったら、TCPは再送の嵐に見舞われ、Web API通信はタイムアウトの連鎖に陥るからです。
そこで使われるのが「ハッシュアルゴリズム」です。
ハッシュ化の対象要素
スイッチは、パケットの以下の情報をハッシュ関数に放り込み、その結果(0〜n)で物理リンクを決定します。
Src MAC/Dst MACSrc IP/Dst IPSrc Port/Dst Port
もしWeb APIサーバーへのトラフィックを分散させたい場合、Src IP と Dst IP だけをハッシュ対象にすると、「特定のクライアントからの大量リクエストが、特定のリンクに集中する」 という偏りが生じます。これを防ぐには、L4ポート番号を含めたハッシュ計算を行うのが定石です。
—
3. 実践:Ciscoスイッチでの設定例
現場でよく見るCisco IOSでの構成例です。channel-group を mode active で設定することで、LACPによるネゴシエーションが有効になります。
# インターフェースをポートチャネルに集約する設定例
interface Range GigabitEthernet0/1 - 2
description ## Link to App-Server-01 ##
switchport mode trunk
# LACPを有効にし、対向とのネゴシエーションを開始
channel-group 1 mode active
# ロードバランシング方式の指定(グローバル設定)
# 送信元/宛先のIPとポート番号をハッシュ計算に含める
port-channel load-balance src-dst-mixed-ip-port
—
4. トラブルシューティング:偏りをどう検知するか
「LACPを組んだのに、片方のリンクばかりパンクしている」という相談は後を絶ちません。このとき、まずは統計情報を確認します。
# ポートチャネルの統計を確認するコマンド
show interface port-channel 1
もし、特定のリンクだけにカウンターが偏っている場合、それは「ハッシュの衝突」か「フローの偏り」です。例えば、社内から特定のDBサーバーへのバックアップ通信が巨大な1フローであれば、どれだけリンクを束ねても、そのリンクの帯域上限を超えて他のポートへ分散することはありません。
Pythonによるトラフィックシミュレーション(概念)
負荷分散が意図通りかを確認するために、ハッシュ計算をシミュレートする簡単なコードを書いてみるのも手です。
import hashlib
def calculate_link(src_ip, dst_ip, src_port, dst_port, num_links):
# 接続情報を結合してハッシュ化
data = f"{src_ip}{dst_ip}{src_port}{dst_port}".encode()
hash_val = int(hashlib.md5(data).hexdigest(), 16)
return hash_val % num_links
# 2本のリンクに対して、どのリンクに割り当てられるかを確認
print(f"Link ID: {calculate_link('192.168.1.10', '192.168.1.50', 54321, 80, 2)}")
—
結びに:教科書にはない現場の教訓
最後に、シニアエンジニアとして一つだけ助言を。「LACPの設定変更は慎重に」。特に本番環境で mode active を mode on(強制束ね)に変更したり、その逆を行うと、一瞬の通信断やリンクのフラッピングを誘発し、最悪の場合、広範囲のネットワークループを引き起こします。
LACPは非常に強力なツールですが、物理層の泥臭い仕様を理解していないと牙を剥く諸刃の剣です。パケットがどのポートを通るのか、脳内で常にフローをイメージできるようになれば、あなたはもう一人前のインフラエンジニアです。
次回のブログでは、このLACPの上に構築される VPC や MLAG といった、より高度な冗長化技術の深淵に触れたいと思います。それでは、良いネットワークライフを!
コメント