Neco プロジェクトの ymmt です。本記事では Neco のネットワークの実装を理解するために必要となる範囲で Border Gateway Protocol (BGP)の基礎知識を解説します。
BGP はインターネット全域の経路制御に使われているプロトコルで、非常に複雑なルーティング要件を実装可能ですが、本記事では詳説しません。対象読者は
「BGP? 知ってる知ってる、インターネットのあれでしょ!」
という程度のソフトウェアエンジニアです。
以下、社内向けの解説文書からコピペしているので文体が変わります。悪しからずご了承ください。
ルーティングプロトコル
ルーティングプロトコルとは、簡単に言えば目的の IPv4/IPv6 アドレスへパケットを送り届けるのにどのような経路で送れば良いか情報交換するプロトコルを指す。経路の情報交換なので、シンプルに「経路交換」とも言う。
BGP はインターネット全体のルーティングプロトコルである。データセンター内での利用については後述する。BGP 以外のルーティングプロトコルは IGP (Interior Gateway Protocol) と総称され、例えば RIP や OSPF を指す。
スタティックルーティング
ルーティングプロトコルによらず、手動でパケットの宛先情報を登録するやりかたはスタティックルーティングと呼ばれる。変更コストが高いため、非常に自明な場合(例えば単独のデフォルトゲートウェイの指定)を除き、多用はされない。
IGP の存在理由
BGP は大規模な運用ができ、障害耐性にも優れる。それなのになぜ IGP を利用する場合があるかというと、プロトコルごとに経路の収束時間やリソース消費、運用の手間などの特性が異なるため。以下の資料に良い比較表がある。
c.f. Protocol Comparison
BGP の概念
AS / ASN
BGP は Autonomous System (AS) と呼ばれるネットワーク事業者が、相互に経路交換をするよう設計されている。各 AS は一意に特定できるAS 番号 (ASN)を JPNIC などの RIR から割り当てられている。
プライベート IP アドレスのように、ネットワーク内部でプライベートに割り当てられる AS 番号もある。
c.f. RFC6996
eBGP と iBGP
BGP は大きく eBGP と iBGP に大別される。
- 異なる ASN を持つ BGP ルータ同士の接続が eBGP (exterior BGP)
- 同一の ASN を持つ BGP ルータ同士の接続が iBGP (interior BGP)
一つの AS が複数のルータ機器を持つことは冗長化のためにごく一般的に行われる。すると同一の ASN を持つ BGP ルータが存在することになり、これらを接続するプロトコルが iBGP となる。
後述するが、eBGP と iBGP では様々な点で動作が異なる。
ピアリングとトランジット
各 AS は各々で決めたポリシーで他 AS と経路交換したりトラフィックを流す。この点をもって、自律した分散システムを構成していると言える。他の AS と経路交換をすることをピアリングと言う。
c.f. ピアリング/トランジットとは
BGP の特徴
パスベクター型
この後説明するが、BGP で交換される経路には様々な属性(attribute)が付いている。その一つにパスベクター(path vector)がある。パスベクターとは、その経路がどのAS を経由していくか列挙したもの。ASN のリストと思って良い。
パスベクターは受け取った経路がループしているかの判別などに利用される。ループの有無は自分の ASN がパスベクターに含まれているか否かで容易に判定できる。
様々な属性に基く経路選択
BGP で交換される経路には様々な必須ないしオプションの属性がある。単純に経路の長さだけでなく、各種属性に基いて柔軟に経路を選択できる。
代表的なものを以下に挙げる。
NEXT_HOP
宛先にパケットを送るための BGP ルータのアドレス。後述する iBGP の場合、必ずしも経路交換している BGP ルータのアドレスとはならない。
AS_PATH
前述のパスベクター。
LOCAL_PREF
AS 内で受け取った経路に自由に優先度を付けられる。その値。
c.f. BGP Attributes List
差分更新と keepalive
インターネット上の全経路(フルルート)を扱うため、経路情報の更新は差分のみを送るようになっている。またパケット落ちなどに対処するため、TCP 接続を用いる。
すると、更新頻度が少ない場合にピアが落ちていることに気付けない可能性がある。そのため定期的にピア間で死活確認を行うための KEEPALIVE 通信を行う。
比較的遅い経路収束
上述したようにピア間の経路の障害検出は KEEPALIVE 通信で行うが、60 秒に一回の通信が連続 3 回といった条件で障害判定するため、故障したピアを外して経路を収束させるのに比較的時間を要する。
KEEPALIVE 間隔の調整や、BFD の併用などで素早く収束させる方法がある。
iBGP の動作
スプリットホライズン
iBGP は同一 ASN を持つルータ同士の通信であるため、経路交換時に AS_PATH
を延ばさない。ということは AS_PATH
を利用したループ検出はできないことになる。
そこで、iBGP ピアから受け取った経路は他の iBGP ピアに広報しないというシンプルなルールを導入することで、ループを防止する。このルールをスプリットホライズンと呼ぶ。
c.f. BGP Split Horizon
フルメッシュ接続
スプリットホライズンルールがあるため、iBGP ルータは全てが相互にピアリングをしなければ、各 iBGP ルータが持っている経路を共有することができない。このように iBGP ルータ全てを相互接続することをフルメッシュ接続と呼ぶ。
一般に iBGP ルータはフルメッシュをする必要があるとされているが、そうしなければ経路を全て共有できないというだけの話である。動作に必要な経路が揃うなら、フルメッシュ構成にしなくても良い。
ルートリフレクター
フルメッシュ接続は n 台のルータがいると n * (n-1) / 2
の数の BGP セッションを必要とする。ルータの数が増えると n の二乗に比例してセッション数が増加し、負荷が高くなる。また、単純にピアを定義してまわる運用コストもかかる。
この問題を解決するために、iBGP ルータの一部をルートリフレクターにする方法がある。ルートリフレクターはピアする相手ごとにルートリフレクトクライアントかどうかの設定をもつ。ルートリフレクターがピアから経路を学習すると、その経路を全てのルートリフレクトクライアントにそのまま伝える。
(注) ルートリフレクトクライアントではない iBGP ピアには原則通り伝搬しない。
クライアントルータはルートリフレクターとのみ BGP セッションを持てば済み、負荷の増加を避けることができる。
NEXT_HOP を書き換えない
AS_PATH
を書き換えないのと同様、iBGP では NEXT_HOP
も書き換えられない。そのため、eBGP で受け取ったエッジルータに見えている NEXT_HOP
アドレスがAS 内部の iBGP ピアにそのまま伝わる。
c.f. A fresh look at BGP’s NEXT_HOP
受け取った経路の NEXT_HOP
が到達不能なアドレスであった場合、その経路は破棄されてしまう。そのため、以下のどちらかで対処しなければならない。
eBGP ピアと接続しているネットワークを AS 内で共有する
IGP, BGP, スタティックルーティングなどで事前もしくは同時に共有しておく。 ただし BIRD version 2.0.2 では未知な
NEXT_HOP
アドレスを BGP で同時配布しても破棄される。iBGP ピアに伝える
NEXT_HOP
をエッジルータ自身のアドレスに書き換えるnext hop self
というルータ設定で書き換えられるだろう。ただし、これは eBGP ピアから受け取った経路以外のNEXT_HOP
も書き換える動作をするので、例えば iBGP ピアから受け取った経路をルートリフレクトする場合に望ましくない動作となりえる。
データセンター内での BGP 利用
旧来は BGP はインターネットでの経路制御のためのもので、データセンター内で利用する場合も IGP を併用するのが普通であった。しかしながら BFD による高速な経路収束や ADDPATH 拡張など BGP の欠点を補完する機能が揃い、また BGP を実装した比較的安価なスイッチ機材が増えたため、MC-LAG のようなベンダー依存技術や IGP を排して BGP のみでデータセンター内ネットワークを構築するのが昨今の技術的な方向性となっている。
IGP や MC-LAG をどこまで排するかで技術的な難易度は変わってくる。Calico や Romana, MetalLB など Kubernetes 周辺のベアメタルネットワーク技術は全サーバーを BGP ルータとして利用する設計である。
Neco では以上の背景を元に、OS でも IGP や MC-LAG を一切利用せず BGP + BFD で耐障害性に優れ、帯域も ECMP で活用できるネットワークを構築する。
まとめ
Neco にはネットワークを専門とするエンジニアはいなかったので、プロジェクト開始時は全員
「BGP? 知ってる知ってる、インターネットのあれでしょ!」
という程度でした。
オンプレミスの Kubernetes ネットワークで BGP を採用したミドルウェアが多いことと、ネットワークチームのエンジニアから CLOS アーキテクチャでの構築を提案されて、学んだことが本記事の内容です。これから BGP を学ぶかたの一助になれれば幸いです。