Slide 1

Slide 1 text

NUMA環境 とコンテナランタイム 筑波大学 情報科学類 3年 川崎晃太朗 youki における Linux Memory Policy 実装

Slide 2

Slide 2 text

contents はじめに 01 02 03 Linux Memory Policy とは youki への実装 youki のテスト環境と Memory Policy 特有の悩み 04 05 おわりに 目次

Slide 3

Slide 3 text

はじめに 01 自己紹介 筑波大学 情報科学類 3 年 興味: コンテナ、クラウド技術、自作OS、コンパイラ、Web など 個人開発・車輪の再発明が大好きです n4mlz (川崎晃太朗)

Slide 4

Slide 4 text

はじめに 01 話すこと 先日、OCI Runtime Spec に新たに Linux Memory Policy に関する仕様が追加された 追加された新しい仕様を Rust 製コンテナランタイム youki に実装した経験を共有したい 実は人生初の OSS コントリビュート (注: まだマージされていないです) PR: https://github.com/youki-dev/youki/pull/3230

Slide 5

Slide 5 text

はじめに 01 この発表で得られること NUMA / UMA のかんたんな概要 仕様の決定から実際にランタイムに実装するまでの過程 実装する上で感じた Memory Policy 特有の大変さ 人生初の OSS コントリビュート経験を、これから OSS に関わっていく方への一例として提供

Slide 6

Slide 6 text

Linux Memory Policy とは

Slide 7

Slide 7 text

NUMA: Non-uniform Memory Access 「CPU+ローカルメモリ」 を持つ複数のノードによって構成されるアーキテクチャ メモリアドレス空間は同一なので他のノードのメモリにも同様にアクセスできる しかし 「遠いノードのメモリにアクセスするとレイテンシが伸びる」 という特徴 データセンターおよびエンタープライズ環境など 大規模データベースやHPC等 (普通の PC は基本的に UMA) Linux Memory Policy とは 02 UMA と NUMA https://www.designworldonline.com/what-is-non-uniform-memory-access-in-industrial-controls/

Slide 8

Slide 8 text

Linux Memory Policy とは 02 Memory Policy とは? プロセスに対し「どのノードからメモリを割り当てるか」を OS に指示する仕組み set_mempolicy() システムコールにより設定する NUMA 環境では、どのノードからメモリを割り当てるかによって性能が大きく変わる OCI Spec で規定される Memory Policy OCI Runtime Spec に新たに追加された linux.memory_policy フィールド コンテナのプロセスがどのような Memory Policy を使用するかを指定する 基本的には、 linux.memory_policy に書かれた内容を使って適切なタイミングで set_mempolicy() を呼べばよい

Slide 9

Slide 9 text

youki への実装

Slide 10

Slide 10 text

youki への実装 03 パーサーでの Memory Policy サポート OCI Runtime Spec には Go の構造体定義がある runc (Go) はこれをそのまま利用している youki (Rust) では oci_spec_rs という OCI Spec パーサーを別リポジトリで用意 まずはここに新しい Memory Policy の構造体定義を追加した https://github.com/youki-dev/oci-spec-rs/pull/290 https://github.com/youki-dev/oci-spec-rs/pull/292

Slide 11

Slide 11 text

youki への実装 03 set_mempolicy() を呼ぶ パースした Memory Policy の情報をもとに コンテナ起動時に set_mempolicy() を呼び出す ここまではそんなに難しくない このへんで set_mempolicy() を呼ぶ 引用: https://github.com/youki-dev/youki

Slide 12

Slide 12 text

テストと Memory Policy 特有の悩み

Slide 13

Slide 13 text

モードとフラグが多すぎる モード, フラグ: set_mempolicy() の引数のひとつ モードの例: MPOL_DEFAULT, MPOL_BIND, MPOL_INTERLEAVE, MPOL_WEIGHTED_INTERLEAVE, MPOL_PREFERRED, MPOL_PREFERRED_MANY, MPOL_LOCAL フラグの例: MPOL_F_STATIC_NODES, MPOL_F_RELATIVE_NODES, MPOL_F_NUMA_BALANCING 本当に大変だったもの: テスト 04 オプション多すぎ問題 https://man7.org/linux/man-pages/man2/set_mempolicy.2.html

Slide 14

Slide 14 text

指定するノードの集合 (nodemask) が必須 / 任意 / 空でないといけない など 排他的なフラグ 一部の mode でのみ有効なフラグ フラグの指定によって同じ引数でも解釈方法が変わる エラーとして落とす例: MPOL_DEFAULT なのに nodemask が空でない、 MPOL_BIND または MPOL_INTERLEAVE なのに nodemask が空 MPOL_F_STATIC_NODES と MPOL_F_RELATIVE_NODES を同時指定 (これらは排他的) MPOL_F_NUMA_BALANCING を MPOL_BIND 以外のモードで指定 等々... 本当に大変だったもの: テスト 04 他の引数との組み合わせ・制約が複雑 テスト項目が本当に多い

Slide 15

Slide 15 text

ノード指定用の文字列の簡易的なパーサーを実装する必要があった 例: "0-3,5,7-9" → [0,1,2,3,5,7,8,9] ここにもテストを追加する必要がある 無効な形式、無効な文字列 など コードの変更量がどうしても大きくなりすぎてしまう 本当に大変だったもの: テスト 04 引数に対する簡易的なパーサーの実装 https://github.com/opencontainers/runtime-spec/blob/main/config-linux.md

Slide 16

Slide 16 text

youki のテスト環境とMemory Policy 特有の悩み 04 CI 環境で NUMA に関するテストはどうする? NUMA 環境でしかテストできないケースがあるのに CI は UMA UMA 環境では Memory Policy の効果が確認できない 確認できるテストに限りがある どこまでテストで確認するか、runc がどうしているのか比較 runc の CI Test は UMA のもののみであった CI のテストは割り切って runc と同様 UMA のみ検証しつつ、NUMA のテストも用意する テストは UMA 用/NUMA 用両方用意し、CI では NUMA 用をスキップ

Slide 17

Slide 17 text

おわりに

Slide 18

Slide 18 text

おわりに 05 この体験を通して得られたこと syscall 一つ呼ぶだけじゃん! と思っていたが、思ったより規模が大きく大変だった 仕様を読むだけでは見えない地雷が実装時に大量に出てくる テストの粒度と実装量のトレードオフ、他の実装 (runc) との比較など OSS ならではの悩み OSS コントリビュートのすすめ 新しい仕様の追加は「最初の実装者」になれるチャンス コードの品質や設計に関して多くのフィードバックをいただき、非常に勉強になった

Slide 19

Slide 19 text

ご清聴 ありがとうございました! @n4mlz @n4mlz