> [!abstract] 概要 > インターネットサービスは、異なる場所にある複数のサーバーで稼働し、モバイルかつマルチホーミングされたクライアントにサービスを提供する。この状況は、トポロジー依存のアドレスを持つ固定ホスト間の通信を想定して設計された現在のネットワークスタックとは適合しない。 > その結果、オンラインサービス事業者は、仮想サーバー移行のために階層型アドレスのスケーラビリティを犠牲にする、すべてのクライアント通信を専用ロードバランサーへ通す、ホスト移動時に接続を再起動するといった、扱いにくく管理負荷の高い回避策に頼っている。 > 本論文は、オンラインサービスの要件に合わせてネットワークスタックを再設計する。中心となる Serval アーキテクチャは、変更されていないネットワーク層の上に Service Access Layer(SAL)を置き、アプリケーションがサービス名を直接使って通信できるようにする。 > SAL はサービスレベルの制御プレーンとデータプレーンを明確に分離し、ポリシー、制御、スタック内の名前ベースルーティングによって、さまざまな発見方式でクライアントをサービスへ接続する。 > アクティブソケットを制御プレーンへ結び付けることで、アプリケーションがソケット呼び出しを行った際にサービスルーティング状態を更新し、最新のサービス解決を維持する。 > Serval により、エンドポイントはネットワークアドレスをシームレスに変更し、インターフェース間でフローを移行し、効率的で中断のないサービスアクセスのために追加フローを確立できる。 > 高性能なカーネル内プロトタイプと複数の例示アプリケーションによる実験は、オンラインサービスのための統一ネットワークソリューションの価値を示す。(Source: [[.raw/papers/nsdi12-final33.pdf]]) ## 論文情報 - タイトル: Serval: An End-Host Stack for Service-Centric Networking - 著者: [[Erik Nordström]]、[[David Shue]]、[[Prem Gopalan]]、[[Robert Kiefer]]、[[Matvey Arye]]、[[Steven Y. Ko]]、[[Jennifer Rexford]]、[[Michael J. Freedman]] - 媒体: 9th USENIX Symposium on Networked Systems Design and Implementation(NSDI 12)、pp. 85–98 - 所属: [[Princeton University]]、[[University at Buffalo]] - 発表年: 2012 - 公式ページ: https://www.usenix.org/conference/nsdi12/technical-sessions/presentation/nordstrom - プロジェクトページ: http://www.serval-arch.org ## 概要 従来の TCP/IP スタックは、IP アドレスとポート番号にサービス、フロー、インターフェースの役割を重ねている。そのため、サービスの複製・移行・障害復旧と、クライアントの移動・マルチホーミングを同時に扱うと、DNS の早期束縛、ロードバランサー、トンネルなどの個別対策が必要になる。 Serval は、サービスを `ServiceID`、通信コンテキストを `FlowID`、到達位置を IP アドレスとして分離し、トランスポート層とネットワーク層の間に SAL を導入する。サービスへの初回接続は `ServiceID` に基づき遅延束縛し、接続後のデータは `FlowID` によってエンドポイント間で直接配送する。(Source: [[.raw/papers/nsdi12-final33.pdf]]) ## 問題設定 現代のサービスは、複数のレプリカ、複数のホストインターフェース、複数の経路を持ち、レプリカ障害・復旧・サービス移行・クライアント移動によって動的に変化する。しかし TCP/IP の識別子は次の役割を同時に担う。 - IP アドレス: インターフェースの識別、パケット転送、ソケットの識別 - ポート番号: パケットの多重分離、サービスエンドポイントの識別、アプリケーションプロトコルの識別 - 5-tuple: 接続を特定のインターフェースと位置へ束縛 DNS はクライアント側でサービスを位置へ早期束縛し、キャッシュと TTL 無視によってフェイルオーバーを遅らせる。ロードバランサーは、すべてのパケットを通過させることで、複雑性・コスト・帯域消費を増やす。インターフェース変更や VM 移行では、アドレスを変更すると接続が切れる。(Source: [[.raw/papers/nsdi12-final33.pdf]]) ## 提案手法 ### 識別子の分離 Serval は、サービスを同一機能を提供するプロセス群として識別する `ServiceID`、ホスト内で各フローを一意に識別する一時的な `FlowID`、位置とインターフェースを表す IP アドレスを分ける。サービス名は誰と通信するか、フロー名はどの通信コンテキストを使うか、アドレスはどこへ届けるかを表す。 `ServiceID` は複数のサービスインスタンスをまとめるグループ名であり、単一の SSH デーモン、LAN 上のプリンター群、ファイル配布ピア群、分散ストレージの複製パーティション、分散 Web サービス全体などを表せる。サービスの粒度をクライアントから隠すことで、サービス提供者がインスタンス選択を制御できる。 サービス識別子は、プロバイダープレフィックスによる階層型割り当て、プロバイダー固有部分、自己証明部分から構成する案が示される。プレフィックスは集約と最長プレフィックス一致(LPM)に使え、自己証明部分はサービス公開鍵のハッシュを用いた認証の基盤になり得る。ただし、識別子の登録権限や広告経路の認証は別途必要であり、Serval は人間可読名から `ServiceID` への解決方式を固定しない。(Source: [[.raw/papers/nsdi12-final33.pdf]]) **図1: TCP/IP と Serval の識別子・操作の比較** ![[_attachments/nsdi12-final33/fig01-identifiers.png]] (Figure 1. TCP/IP では IP アドレスとポートが複数の役割を兼ねるのに対し、Serval ではサービス解決・フロー多重分離・IP 転送を別層へ分ける。Source: [[.raw/papers/nsdi12-final33.pdf]]) | 操作 | PF_INET | PF_SERVAL | |---|---|---| | bind | `bind(s, locIP:port)` | `bind(s, locSrvID)` | | 接続なしデータグラム送信 | `sendto(s, IP:port, data)` | `sendto(s, srvID)` | | ストリーム接続 | `connect(s, IP:port)` | `connect(s, srvID)` | | 接続受付 | `accept(s, &IP:port)` | `accept(s, &srvID)` | (Table 1. BSD ソケットプロトコルファミリの比較。INET は IP アドレスとポートを使い、Serval は `ServiceID` を使う。Source: [[.raw/papers/nsdi12-final33.pdf]]) **図2: Serval パケットに現れる識別子** ![[_attachments/nsdi12-final33/fig02-packet-identifiers.png]] (Figure 2. ネットワークヘッダーとトランスポートヘッダーの間に、送受信 `FlowID`、トランスポートプロトコル、フラグ、シーケンス番号、Nonce、`ServiceID` を配置する。Source: [[.raw/papers/nsdi12-final33.pdf]]) ### Service Access Layer SAL はトランスポート層とネットワーク層の間に位置し、アプリケーションからサービスへの接続と接続維持を担う。ネットワーク層は変更せず IP による転送を続け、SAL がサービスレベルの遅延束縛・ルーティング・フロー多重分離を引き受ける。 ユーザー空間のサービスコントローラは、サービス解決ポリシー、サービス関連イベント、サービス性能の監視、他コントローラとの通信を扱う。SAL はサービス表に従ってパケットを転送し、接続済みのフローをフロー表からソケットへ多重分離する。サービスコントローラと SAL の境界を明確にすることで、エンドホストとサービスルータを同じ実装部品で構成し、役割の違いをポリシーとして表現できる。 **図3: Serval のエンドホストネットワークスタック** ![[_attachments/nsdi12-final33/fig03-stack-architecture.png]] (Figure 3. サービスコントローラがサービス表を制御し、SAL がフロー表とサービス表を使ってデータを配送する。IP 転送表はネットワーク層に残る。Source: [[.raw/papers/nsdi12-final33.pdf]]) サービス表のルールには次のアクションがある。 - `FORWARD`: 一つ以上のユニキャストまたはブロードキャスト IP アドレスへ転送する。全宛先への送信または重み付き選択が可能 - `DEMUX`: `ServiceID` を待受ソケットへ多重分離する - `DELAY`: パケットをキューに入れ、サービスコントローラへ通知する - `DROP`: 一致したパケットを破棄する ルールは `ServiceID` の最長プレフィックス一致で選択する。プレフィックスを使うことで、複数サービスやサービス内部のパーティションを少数のルールで表現し、ルーティング更新の状態量と頻度を抑える。 **図4: サービスルータを経由する転送** ![[_attachments/nsdi12-final33/fig04-service-router-forwarding.png]] (Figure 4. クライアント側の `FORWARD`、中間サービスルータの `FORWARD`、サーバー側の `DEMUX` を連鎖させ、最終的に待受ソケットへ届ける。Source: [[.raw/papers/nsdi12-final33.pdf]]) ### 接続確立とサービス解決 サーバーが `bind` と `listen` を呼ぶと、ローカルサービス表へ `DEMUX` ルールが追加され、サービスコントローラへ登録イベントが渡る。`close`、プロセス終了、タイムアウトでは登録を解除する。これにより、DNS やロードバランサーを手動更新する代わりに、ソケット操作がサービス登録状態を直接更新する。 クライアントが `connect(ServiceID)` を呼ぶと、SAL はローカル `FlowID` と乱数 Nonce を割り当て、最初の SYN を `ServiceID` とともに送る。サービス表に既知の宛先がなければ、デフォルトの `FORWARD` ルールでサービスルータへ送る。中間サービスルータは `ServiceID` に対するルールを再評価し、最終的なサービスインスタンスへ到達させる。SYN-ACK 後は両端のアドレスと `FlowID` が確定し、以後のデータパケットはサービスルータを経由せず直接配送する。 **図5: `ServiceID` に基づく接続確立** ![[_attachments/nsdi12-final33/fig05-service-connection.png]] (Figure 5. 初回 SYN だけをサービスルータの連鎖で解決し、サービスインスタンスからの SYN-ACK と後続データをエンドポイント間で直接配送する。Source: [[.raw/papers/nsdi12-final33.pdf]]) サービス解決には、階層型の広域サービスルーティング、DHT に基づくピアツーピア解決、ローカルブロードキャストによるアドホック解決、DNS などのディレクトリサービスを使う遅延解決を組み合わせられる。`DELAY` ルールで未解決パケットを一時保持し、コントローラが解決後に `FORWARD` ルールを追加して再評価する方式も可能である。 ### 複数フローとフロー移行 SAL は一つのソケットに複数のフローを関連付け、異なるインターフェースや経路へデータを分散できる。`FlowID` による多重分離はネットワーク層のアドレスを必要としないため、IPv4 と IPv6 の違いをアプリケーションへ露出せず、アドレス変更後も同じ通信コンテキストを維持できる。 一方のエンドポイントが利用可能なインターフェースを SAL 拡張ヘッダーで通知すると、相手側は追加フローを確立できる。既存フローを別アドレスへ移すときは、送信側が `RSYN`、受信側が `RSYN-ACK`、最終確認が `ACK` を交換する。制御メッセージはデータストリームと別のシーケンス番号を持つため、複数の移行メッセージが順不同で届いても識別子の更新順序を検証できる。論文はこの再同期プロトコルを Promela と SPIN で形式検証した。 **図6: ソケット、フロー、インターフェース、アドレス、経路の関係** ![[_attachments/nsdi12-final33/fig06-flow-relationships.png]] (Figure 6. 一つのソケットが複数の `FlowID` を持ち、各フローが異なるインターフェースと経路に対応する。Source: [[.raw/papers/nsdi12-final33.pdf]]) この設計は、クライアントの Wi-Fi と携帯網の切り替え、サーバーの NIC 間負荷分散、異なる L3 サブネットをまたぐ VM 移行に適用できる。双方が同時に移動する稀な場合は、旧サービスルータを一時的なホームエージェントとして使う再確立方式を想定する。Nonce はオフパス攻撃によるフロー乗っ取りを防ぐが、オンパス攻撃は防がない。旧来の NAT には、FlowID とアドレスの変換、必要に応じた UDP カプセル化で対応する。 ## 実装 Serval プロトタイプは約 28,000 行の C で実装され、変更されていない Linux カーネルへロードできるカーネルモジュールとして動作する。Android 上では Wi-Fi と携帯網の間で接続を移行できる。カーネルモジュールを利用できない BSD や PlanetLab では、raw IP ソケット上のユーザー空間デーモンとして動かせる。 ソケット API には BSD ソケットを拡張した `PF_SERVAL` と `AF_SERVAL` を用い、標準の `PF_INET` ソケットと同時に利用できる。SAL、サービス表、サービス解決、エンドポイントシグナリングを実装する一方、プロトタイプ時点ではマルチパス機能を未実装とした。レガシーアプリケーションとレガシーサービスの間には TCP-to-Serval / Serval-to-TCP・UDP トランスレータを置ける。レガシー NAT やミドルボックスを通過するため、SAL ヘッダーの UDP カプセル化も実装する。(Source: [[.raw/papers/nsdi12-final33.pdf]]) ## 実験結果 ### マイクロベンチマーク iperf による TCP 転送は、2.4 GHz Intel E5620 4 コア CPU と GigE インターフェースを持つ 2 ノード、Ubuntu 11.04 上で、10 秒転送を 10 回平均した。Serval TCP は TCP/IP とほぼ同等の 933.8 Mbit/s であった。ハードウェアチェックサム、セグメンテーションオフロード、SACK、FACK、DSACK、タイムスタンプなどを省略しているため、実装の最適化余地が残る。 | スタック / ルータ | TCP 平均(Mbit/s) | TCP 標準偏差(Mbit/s) | UDP スループット(Mbit/s) | UDP パケットレート(Kpkt/s) | 損失率(%) | |---|---:|---:|---:|---:|---:| | TCP/IP / IP forwarding | 934.5 | 2.6 | 957 | 388.4 | 0.79 | | Serval / Serval | 933.8 | 0.03 | 872 | 142.8 | 0.40 | | Translator | 932.1 | 1.5 | | | | (Table 2. TCP/IP、Serval、トランスレータの TCP 性能と、IP 転送・Serval サービスルータの UDP 転送性能。Serval の UDP スループットは IP 転送の約 91%だが、小さいパケットの処理率はサービス表検索のオーバーヘッドで低下する。Source: [[.raw/papers/nsdi12-final33.pdf]]) サービス表はビットワイズトライによる LPM で実装され、48 バイトペイロード相当の小パケットではサービス表検索のコストが支配的になる。レベル圧縮トライ、キャッシュ、専用サービスルータでの TCAM などを適用すれば差を縮められると論文は述べる。 ### サービスのケーススタディ 複製 Web サービスでは、サービスインスタンスの登録・解除をサービスルータが受け取り、サービス表の状態だけを更新する。4 クライアントが 3 MB ファイルを要求し、各クライアントが 20 件の HTTP 要求を開いた実験で、サーバー数が増減すると要求率とスループットが比例して変化した。時刻 0〜60 秒は 2 インスタンスで約 80 req/s、60 秒時点で 2 インスタンスを追加すると約 160 req/s・3,600 Mbps、120 秒で 2 インスタンスを停止すると元の水準へ戻り、180 秒で 1 インスタンスを追加すると約 120 req/s・2,700 Mbpsとなった。 **図7: 複製 Web サービスの要求率とスループット** ![[_attachments/nsdi12-final33/fig07-replicated-web-service.png]] (Figure 7. サービスインスタンスの参加・離脱に応じて、要求率とスループットが段階的に変化する。各インスタンスは 1 GigE リンクを飽和させる。Source: [[.raw/papers/nsdi12-final33.pdf]]) 動的 Memcached では、共通プレフィックスとキーを結合した `ServiceID` を使い、LPM でキー空間のパーティションをサービスインスタンスへ割り当てた。4 サーバー・16 パーティション・1,024 バイトのデータオブジェクト・毎秒 100,000 件の SET 要求を用い、サーバーの参加・離脱に応じてパーティションを再割り当てできることを示した。 **図8: Memcached インスタンスの参加・離脱に伴う再分配** ![[_attachments/nsdi12-final33/fig08-memcached-rebalancing.png]] (Figure 8. サーバーの離脱時にパーティションを残存サーバーへ移し、復帰時に再び分散する。クライアント側の固定的なサーバー一覧を更新せずに再構成できる。Source: [[.raw/papers/nsdi12-final33.pdf]]) ### インターフェース負荷分散と VM 移行 2 本の GigE インターフェースを持つサーバーで 2 本の iperf 接続を開始し、6 秒時点で一方のフローを第 2 インターフェースへ移行した。両フローが同じインターフェースを使う間は各約 500 Mbpsであったが、移行後は両フローが約 1 Gbpsへ上昇した。 **図9: フロー移行によるインターフェース負荷分散** ![[_attachments/nsdi12-final33/fig09-interface-migration.png]] (Figure 9. 一方のフローを `eth0` から `eth1` へ移すことで、2 本のフローが異なるインターフェースを使い、双方のスループットが上がる。Source: [[.raw/papers/nsdi12-final33.pdf]]) 異なるサブネットにある物理ホスト間で VM をライブ移行する実験では、VM が新アドレスを取得した時点で短い停止が発生し、RSYN 交換後にフローを新アドレスへ移した。移行後のフローは約 150〜180 Mbpsへ回復した。 **図10: サブネットをまたぐ VM 移行** ![[_attachments/nsdi12-final33/fig10-vm-migration.png]] (Figure 10. VM のアドレス変更とフロー再同期の間に短いデータ停止が発生し、その後新アドレスへの通信を再開する。Source: [[.raw/papers/nsdi12-final33.pdf]]) ### アプリケーションの移植性 既存アプリケーションの多くは複数のアドレス種別を抽象化しているため、`sockaddr_sv` をソケット呼び出しへ渡す変更だけで Serval 対応できた。実装方式による差はあるが、著者らの経験では移植には数時間から 1 日を要した。 | アプリケーション | バージョン | コードベース(行) | 変更行数 | |---|---|---:|---:| | Iperf | 2.0.0 | 5,934 | 240 | | TFTP | 5.0 | 3,452 | 90 | | PowerDNS | 2.9.17 | 36,225 | 160 | | Wget | 1.12 | 87,164 | 207 | | Elinks browser | 0.11.7 | 115,224 | 234 | | Firefox browser | 3.6.9 | 4,615,324 | 70 | | Mongoose webserver | 2.10 | 8,831 | 425 | | Memcached server | 1.4.5 | 8,329 | 159 | | Memcached client | 0.40 | 12,503 | 184 | | Apache Bench / APR | 1.4.2 | 55,609 | 244 | (Table 3. Serval へ移植したアプリケーション。Source: [[.raw/papers/nsdi12-final33.pdf]]) ## 新規性 HIP、DOA、LISP、LNA、HAIR、i3 はホスト識別子と位置を分離するが、サービス抽象化やサービスレベルのデータプレーンを提供しない。DONA は遅延束縛を提供するが、ポート番号を残す。TCP Migrate はホスト移動、MPTCP は複数経路、SCTP はマルチホーミングを扱うが、いずれも特定のトランスポートプロトコルに結び付いている。 Serval の違いは、サービス名・フロー・ネットワークアドレスをスタックの役割として一体的に分離し、SAL を共通層として複数トランスポートへ適用する点にある。サービス登録・解決・転送・フロー移行を同じサービスレベルの制御/データプレーンで扱うため、個別機構の単純な合成ではなく、サービスアクセス全体の設計として提示される。(Source: [[.raw/papers/nsdi12-final33.pdf]]) 発表スライドでは、この位置づけを「SDN をネットワークエッジへ拡張する」と表現し、サービス、フロー、ホスト、インターフェースを新しいプログラミング抽象として扱うこと、サービスとネットワークの制御を統合することを強調する。(Source: [[.raw/slides/serval-nsdi12-talk/serval-nsdi12-talk.pdf]]) **スライド補足: エンドホストアーキテクチャ** ![[_attachments/nsdi12-final33/slide-end-host-architecture.png]] (Source: Serval 発表スライド。アプリケーション、サービスコントローラ、SAL のサービス表・フロー表、IP 転送表の関係を示す。) ## 強み / 弱点・課題 ### 強み - サービスの複製・移行・障害復旧を、アプリケーションへ IP アドレスを露出せずに扱える。 - 初回 SYN だけをサービスルータへ通し、データ経路をエンドポイント間へ戻すため、従来のロードバランサーが持つ全パケット通過の帯域制約を避けられる。 - フロー移行と追加フローをトランスポート非依存の SAL へ集約し、TCP 以外にも同じ仕組みを適用できる。 - `PF_INET` と共存し、トランスレータで未変更アプリケーション・未変更サービスを段階的に接続できる。 ### 弱点・課題 - プロトタイプはマルチパス機能を未実装であり、ハードウェアチェックサムや各種 TCP 最適化も省略している。 - サービス表の小パケット処理率は IP 転送より低く、LPM 実装とサービスルータの状態量が性能上の課題になる。 - 人間可読サービス名から `ServiceID` への解決、登録権限、広域広告経路の認証は Serval の外部に残る。 - 移行による RTT・帯域の変化はトランスポートの輻輳制御へ影響する。SAL から移行イベントを通知してタイマーを凍結する案はあるが、現代の多経路・暗号化トランスポートとの統合は未検証である。 - 同時移動、NAT、レガシーミドルボックス、サービスコントローラの可用性を含む広域展開の運用コストは、プロトタイプ評価からは判断できない。 **スライド補足: フロー移行** ![[_attachments/nsdi12-final33/slide-flow-migration.png]] (Source: Serval 発表スライド。`RSYN`、`RSYN-ACK`、`ACK` によるフロー移行を時系列で示す。) ## 関連する実験スライド **スライド補足: インターフェース間の負荷分散** ![[_attachments/nsdi12-final33/slide-interface-load-balancing.png]] (Source: Serval 発表スライド。6 秒付近で一方のフローを `eth1` へ移し、各フローのスループットが約 450 Mbps から約 930 Mbps へ上がる様子を示す。) **スライド補足: サブネットをまたぐ VM 移行** ![[_attachments/nsdi12-final33/slide-vm-migration.png]] (Source: Serval 発表スライド。VM のサブネット変更時にスループットが一時的に 0 Mbps へ落ち、新アドレスへの移行後に回復する。) ## 出典 - [[.raw/papers/nsdi12-final33.pdf]] — USENIX NSDI 12 掲載論文。本文、図1〜10、表1〜3の根拠。 - [[.raw/papers/nsdi12-final33.txt]] — PDF のレイアウト保持テキスト。 - [[.raw/slides/serval-nsdi12-talk/serval-nsdi12-talk.pdf]] — 発表スライド。論文本文にない説明順序、SDN エッジ拡張、移行例の補足。