転びながらもネットワーク処理を ソフトウェアで自作していく話

53b88e92e021d7817f13662ba2465f6c?s=47 Mabuchin
July 06, 2019

転びながらもネットワーク処理を ソフトウェアで自作していく話

in BCU30

53b88e92e021d7817f13662ba2465f6c?s=128

Mabuchin

July 06, 2019
Tweet

Transcript

  1. ながらもネットワーク処理を ソフトウェアで⾃作していく話 2019.07.06 Toshiya Mabuchi 開発本部 インフラ室 ネットワーク開発グループ 転 び

  2. ⾃⼰紹介 • ⾺淵 俊弥 / @raibo • 開発本部 インフラ室 ネットワーク開発グループ

    • モンスターストライク等、 事業⽤サービスネットワークの設計/運⽤/開発 • 特定⽤途向けのネットワークデータプレーン開発 今日はこっち
  3. パケット処理、好きですか︖ 1. だいすき 2. 興味ない

  4. ⾃社でパケット処理機能を ⾃作してる話

  5. ⾃社で開発するモチベーション 1. 汎⽤的な機器でネットワークを構築 • x86なLinuxサーバーで動く(すぐに交換/使いまわせる) 2. 冗⻑性の⾼さを保つ • アプライアンス+自作で冗長性の確保 3.

    シンプルな機能は⾃分たちで設計したい • 特定の事業にのみにフォーカスする機能は 小回りを効かせたい
  6. Linux Socketの場合 NIC Rx NIC Tx NIC Kernel UserSpace Rx

    Ring Tx Ring Socket libsocket App sk_buff ProtocolStack IRQ Interrupt RSS syscall
  7. Linux Socketを使ったパケット処理 • Pros • Linuxと各種⾔語の優れた抽象化 • 開発時もネットワークのかなりの部分を意識せず使える • 成熟したプロトコルスタックを利⽤できる

    • TCP等, 複雑なプロトコルに対して先⼈達の肩に乗って利⽤できる • Cons • ネットワーク処理⽤途で10Gbps~等の⼤規模な通信処理が難しい • ネットワーク処理に適⽤すると、1台当たりの処理能⼒が低い • 処理的に遅延が乗ってしまう • TCP/IPのネットワークスタック処理を⾏うからどうしても重くなる • 多段するとより顕著に遅くなる
  8. なぜパフォーマンスが出ない︖遅延が乗る︖ • メモリコピーによるオーバーヘッド • 受信パケットをskbに変換し、ユーザスペースにコピーする段階等で メモリコピーが行われる • Linuxプロトコルスタック処理の重さ • IP/TCPレイヤの解釈にはそれなりの負荷がかかる

    ⽤途によっては、賢いプロトコルスタックは使わなくてもOK メモリコピーも最⼤限減らして、パケットのFowardに特化したい XDP, DPDK等の利用
  9. ⾼速パケット処理技術の概要

  10. ⾼速パケット処理はF1

  11. XDP • eXpress Data Path • Linux Kernel Nativeなパケット処理機能 •

    カーネル内VMの上で動くコードを挿⼊できる機能を利⽤ (eBPF) • XDPはそのbytecodeをKernel NetworkDriverレベルの箇所に差し込む機能 • ユーザ空間からも参照/書き換えができるMAPやArrayが利⽤可能 NIC1 ELF-compiled eBPF NIC2 Management App Protocol Stack ... eBPF Map RX XDP XDP XDP_TX XDP_REDIRECT XDP_PASS r/w Queue JIT Compile UserSpace Kernel Hardware XDP_DROP r/w
  12. DPDK Data Plane Development Kit • 専⽤デバイスドライバ(PMD)と開発⽤の周辺ライブラリセット • 1CPU当たり1スレッドでPolling(CPUをPollingで専有) •

    Hugepageによって⼤きなメモリを確保 • TLBキャッシュミス削減 • 専⽤のメモリアロケータによる⾼速な割当 • 実装⽤ライブラリも多数提供 • Checksum/decap/ACL等 • Docもかなりの充実具合 • https://doc.dpdk.org/ ApplicaKon Kernel Space NIC PMD
  13. ⾃社の取り組み

  14. 取り組んでいるもの ステートレス実装可能なもの中⼼ • Static NAT (DPDK/XDP) • グローバル ↔ プライベートIPの静的変換NAT

    • GRE Decap Endpoint (DPDK/XDP) • ひたすらGREをDecapする • マルチクラウド環境上でのアドレスバッティング対策 • 詳細: モンスターストライクも⽀えるデータプレーン • Tap Payload cutter & sFlow Converter (XDP) • サンプリング&解析に不要なデータを削除 • sFlow変換して別NICからFlowコレクターへ⾶ばす
  15. NATの場合(XDPのパターン) • Static NAT開発 • 1:1のシンプルなIP変換 • 各NATは BPF_MAP_TYPE_PERCPU_HASH でCPU毎にテーブル管理

    • GRPCによる複数台NATテーブルの管理&Stat取得 • 1台双⽅向で12Mpps(10Gbps程度)まで処理可能 Controll Server Backbone Private default Static NAT Static NAT StaKc NAT 192.0.2.0/24 ↔ 198.51.100.0/24 MAP MAP MAP MAP MAP MAP MAP MAP MAP
  16. ペイロードカッター For pcap/sflow • Tapでトラブルシュートを⾏いつつ、必要ない情報はカットしたい • トラブルシュート時は所定のヘッダまで取れればOK • L4~L7以下のPacketのペイロードカットしてからユーザスペースへ •

    カットした部分をsFlowに変換して⾶ばす(WIP) • Flow対応してない区間でも取れる • bpf_xdp_adjust_tailでヘッドルーム縮小によってコピーしない Tap Static NAT Tap Aggregation Flow Collector .pcap XDP server Flow Dissect Payload Cutter Sampling XDP_DROP
  17. 作りはシンプル パケット処理部は200⾏いかない でも...考慮すべき点は結構ある

  18. トラブルや課題

  19. NAT実装時トラブル 謎のパケットロス • ある⽇パケットがロスし始めた ログを仕込んでも異常が観測されない • NICのFirmwareかドライバ周り? • でも試験では⼤丈夫だったけど.... ...テストサーバーとデプロイ⽤でドライバ違う...︕︕

    • 試験 : ixgbe , 本番 : i40e 同じメーカーでもドライバ/ファームが違えば別機器と思うべし 適切な期間の性能試験を必ず実施しましょう
  20. さらに沢⼭ハマる • 特定NICのVlan消失 • 数台のうち1つのNICで切りたい特定オフロードを切れなかった • オフロードをoffにできない(fixed)箇所はNIC毎に結構違う • 1週間でQueueが枯渇してパケットを送れなくなる •

    NICファームとKernel Driverの乖離が原因で 不要なパケットが溜まっていっていた... • ファームが絡むと、本当のところが明確には分からない...つらい • メニーコアマシンでXDP起動後、少しするとHang • Combinedで利⽤コアを抑制しないといけない • ⽤意できるXDP Ringの限界数は96個 • 参考: https://www.mail-archive.com/netdev@vger.kernel.org/msg246813.html
  21. 事前にも気を配る点は沢⼭ • 可能な限りロックを少なくしてる︖ • ロックレスなアーキテクチャを⽬指していこう • GlobalSharedな領域は減らしていこう • Affinityを意識して動かしているか︖ •

    NumaNodeを考慮したCPU割当してる? • CPU L2 cacheを意識した構成で使えている︖
  22. 気をつける点まとめ • サーバーのファームが⼊れ替え可能か確認しておくべし • 切り分けが相当しやすくなる • NICもサーバーのOEM提供だとファームが上げづらいことも • XDPはカーネルVerによって実装状況が結構違う •

    実⾏時警告とかほぼ無いので、普通にパケット落ちます • ソースやPatchを確認しておこう • 例: mlx5のNIC XDP_REDIRECTは4.19~ • LinuxのKernelやドライバの知識が超重要 • NAPI/ドライバ/IRQ Balancer/numa/CPU cache/RSS/RFS等、 ある程度知らないとチューニングできない
  23. まあ、様々な問題が起こるんです

  24. カーネルという最高の抽象化を跨ぐには こういった問題とも向き合うことが必要

  25. 転ばぬ先の杖

  26. テストと計測 • テスト駆動な開発 • OK/Failパターンのパケットを実装前に定義 • 実装物に関わるRFCからパケットパターンを決めて⽤意 • RFC2663, 3022,

    7857 4787, 5382, 5508... • 全部通れば機能要件を概ね満たしている • 後から追加より実装上の⼿戻りも圧倒的に少ない • CircleCIで機能単位のテストを実施 • DPDK : Gtest • XDP : xdp_prog_run def test_egress_ether_vlan_ipv4_icmp_packet(self): i_pkt = Ether()/Dot1Q(vlan=10)/IP(src=”198.18.0.1", dst=”198.19.0.1")/ICMP() o_pkt = Ether()/Dot1Q(vlan=20)/IP(src=”198.18.1.1", dst=”198.19.0.1")/ICMP() self.xdp_test(self.egress, i_pkt, o_pkt, BPF.XDP_REDIRECT) ↑こんな感じで仮想的に実⾏して結果を確認可能
  27. テストと計測 • 性能試験: T-Rex • Python APIを使ってシナリオ作成 • リリース毎(PR毎)に性能評価を試験 •

    ⾃動レポートして性能を⽐較 駄⽬な実装もこれで分かる!
  28. 1. 適切な利用シーン 2. 保守するというチームでの覚悟 3. リターンが見込めるケースでの利用 プロダクションに使うには、それなりのコスト(メンテ等)を支払うことになる 自社で開発するからといって必ず安く済むとは限らない でやっていかないと爆死しちゃいます 最後に...

  29. まとめ • XDP/DPDK等で⾼速パケット処理開発 • 使うべき箇所と選定は⾒極めてやっていきましょう • チューニングやトラブル時にLinux Kernelや コンピュータアーキテクチャの基礎な知識は必須 •

    NICが違えば全く違う機器 • 同じx86でしょ︖は通⽤しない • Linuxの抽象化の隙間に潜り込むというのはそういうこと • ハマればハマるほどLinuxの深みを知ることになる
  30. Thanks!