Save 37% off PRO during our Black Friday Sale! »

cgroup v2とgVisor

11cc6d1632f92751debe9a3b7cae36c6?s=47 Hiro.Kamezawa
November 30, 2018

cgroup v2とgVisor

ComSys 2018でしゃべったスライドです。音声なしでは非常に不親切なスライドかとは思いますが公開しないのも違うかなと言うことで公開します。

11cc6d1632f92751debe9a3b7cae36c6?s=128

Hiro.Kamezawa

November 30, 2018
Tweet

Transcript

  1. Copyright 2018 FUJITSU LIMITED コンテナ技術とLinux 2018.11.29 ComSys 2018 富士通株式会社 亀澤

    寛之 <kamezawa.hiroyu@jp.fujitsu.com> 0
  2. Copyright 2018 FUJITSU LIMITED  名前: 亀澤 寛之  勤務先:

    富士通株式会社 (武蔵中原)  部門: Linux開発統括部  現在の業務: サービスの開発  来歴 ~2003年:東京大学(OS研究) 2003~2012: Linux Kernel(x86)のOSS開発(コミッタ) 2013~2017: コンテナ関連技術のOSS開発(マネージャ) 2018~: 新サービス検討・開発(マネージャ)  Linux開発でコミッタとして主に貢献した機能  Memory管理⇒ Sparse Memory, Memory Migration, Hotplug.  Cgroup (v1) ⇒ Memory cgroup の性能チューニング、メンテナ(~2012)  ps コマンド修正、 /procの表示高速化、oom-killerの改善等 自己紹介 1
  3. 今日の話  Cgroup v1 と v2  Cgroup v2 とは何か?

     Memory cgroupへの変更を中心にv2への変更を概観  今年加わった機能  gVisor  問題と妄想  不揮発メモリのある世界  L7 networkの威力  組み合わせ爆発の世界 Copyright 2018 FUJITSU LIMITED 2
  4. コンテナとカーネル Copyright 2018 FUJITSU LIMITED コンテナ機能 (UserLand) cgroup namespaces 資源管理

    (CPU,メモリ,etc…) 名前空間 (ID,ファイルシステム,etc…) SELinux AppArmor seccomp セキュリティ 3
  5. cgroup v2とは何か?  cgroup v2 はコンテナ機能を踏まえて、再編されたLinuxのリソースコントローラ  cgroup v1 のデザインでは機能的に難しかったことを実現できるようにする

     cgroup v1 の“実際にユーザが使ってみて”ダメだったところをちゃんと直す  cgroup v1 から v2 への主な変更点 Copyright 2018 FUJITSU LIMITED コントローラ毎のツリー構造 全コントローラ共通のツリー構造 コントローラ毎にバラバラのUI 統一されたUI 統合しきれなかったコントローラ間連携 統合されたコントローラ間連携 v1 v2 v1は汎用のリソースコントローラとして設計されたが (汎用を目指しすぎて)バラバラになったものを “コンテナ”というメジャーなユースケースを踏まえて再デザインしたもの 複雑なヒエラルキ処理 Leaf nodeでのみ制御 4
  6. v1とv2のTree構造の違い cgroup v1 Copyright 2018 FUJITSU LIMITED CPU A B

    C D Memory A B C E I/O A B C 各資源コントローラ毎に バラバラのTree cgroup v2 CPU A B C D Memory I/O Treeは一つ 各グループ毎にコントローラをセット CPU Memory 5
  7. Tree構造変更が解決したバラバラなコントロールの問題 具体的に、CPU、memory, I/Oコントローラがバラバラだった Copyright 2018 FUJITSU LIMITED Memory CPU I/O

    メモリ回収でCPU消費 Swap out Buffered I/O Cgroup v1 の限界 CPUとmemory, I/Oをバラバラにリソースコントロールしようとしてもお互いに影響する。 ところが、cgroup v1のデザイン上、バラバラに動作するように作り込まないといけない 例えば、Process A B が同じmemory cgroupで別のI/O cgroupだったらどうするのか? その上、v1設計時に想定したような自由度の高い使い方は結果的にほぼなかった。 v1ではdirect I/Oのみ 6
  8. ヒエラルキの違い cgroup v1 Copyright 2018 FUJITSU LIMITED A B C

    D process process process cgroup v2 A B C D process process Process 所属不可能 v2ではプロセスは Leaf にのみ所属 7
  9. 混乱しやすかったヒエラルキ(CPUを例にすると) Copyright 2018 FUJITSU LIMITED A B(100) C(100) cpu share

    D(100) E(100) B:C = 1:1 C=D+E D:E=1:1 Then B:D=2:1 上記の通りに分配されるのその通りなのだが、 Cの直下にプロセスが居る場合、 D+E+Process(C)=Cになり、計算がものすごく面倒 cgroup v1 8
  10. 混乱しやすかったヒエラルキ(memory) Copyright 2018 FUJITSU LIMITED cgroup v1 A B(1G) C(1G)

    D(500M) E(500M) F(1G) use_hierarchy=1 use_hierarchy=0 G(500M) H(300M) Memory cgroupの場合、サブツリー毎に 親子関係を伝搬させるか設定できた 性能問題が主な理由だったが複雑化 ツリーの途中にプロセスが居る場合に やはり考え方が難しい 9
  11. cgroup v2のメモリ制御 cgroup v2では以下の制御を実装 Copyright 2018 FUJITSU LIMITED 名前 制御

    memory.max メモリ使用量の上限(ハードリミット) ここに達するとフォアグラウンドでメモリ回収実施 memory.high メモリ使用量の上限(ソフトリミット) ここに達するとバックグラウンドでメモリ回収実施 memory.low メモリの下限(ソフトリミット) これ以下の使用量の場合メモリ回収対象になりにくい memory.min メモリの下限(ハードリミット) これ以下の使用量の場合メモリ回収にならない memory.swap.max Swapの上限(ハードリミット) これ以上swapを使わない ※Documentation/admin-guide/cgroup-v2.rst参照 10
  12. メモリの回収  大まかに3種類のメモリ  ユーザメモリ(ANON) ...... malloc()等で確保され、Page Faultを通して利用  ページキャッシュ

    …… ファイルのキャッシュ  カーネルメモリ …… カーネルが利用する細々とした管理構造やページテーブル・ネットワークバッファ等  回収法も3通り  ユーザメモリ …… 参照を全て外して(page tableを書き換えて)スワップアウトし、解放  ページキャッシュ …… 必要ならストレージに内容を書き戻し、参照を全て外して解放  カーネルメモリ …… アクティブな参照がないオブジェクトのみのページを解放  回収の契機  ページアロケーションの延長、kswapd(カーネルスレッド)、memory limit 歴史的にはページキャッシュがまず解放候補で、ページキャッシュを管理するためのカーネルメモリなどを 追い出すのが優先。ただし、“アクセスされない”ユーザメモリのほうが“アクセスのある”ページキャッシュ よりも価値は高い(それでもswapは一方的に嫌われるが)。 Copyright 2018 FUJITSU LIMITED 11
  13. cgroup v2 のmemory.high Copyright 2018 FUJITSU LIMITED cgroup v1 cgroup

    v2 limit usage 使用量がLimitにヒットしたら ヒットしたスレッドで直接メモリ回収 直接メモリ回収 max usage 間接メモリ回収 high 直接メモリ回収 使用量がhighを超えたら バックグラウンド(workqueue)でメモリ回収 使用量がLimitにヒットしたら ヒットしたスレッドで直接メモリ回収 Limitにヒットしてスレッドが遅延することが減った(cpu課金が少し他所に逃げるが…) 12
  14. Page Fault  ページフォルト発生の動作(簡易) 1. 物理ページの無い仮想アドレスにCPUがアクセスする 2. カーネルに制御が移る 3. 仮想アドレス情報からページの属性を求める

    4. ページをアロケーションする ⇒メモリが無ければ(直接)メモリ回収処理へ 5. ページに課金する ⇒上限に達していたらメモリ回収処理へ 6. 実際に獲得したページを仮想アドレスに貼り付ける 7. ユーザに帰る Copyright 2018 FUJITSU LIMITED 空きメモリが足りないので 解放可能なページを解放 “グローバルリクレイム” 上限に達したので 解放可能なページを解放 メモリ管理のv1->v2のポイントの一つは”グローバルメモリ回収“処理 cgroup v1では保守的な造りになっており、cgroupはメモリ回収を邪魔しない cgroup v2ではチューニングで守ることが出来る 13
  15. Global Reclaimを邪魔しない……の変更  cgroup v1 Copyright 2018 FUJITSU LIMITED 

    cgroup v2 メモリを獲得しようとして 十分にメモリが足らない cgroupを 一つ選択 メモリを追い出し 例えば、cgroup v1では memory+swapの総量でLimitをかけていたので 意図的にswapを小さくしてメモリ固定はできない メモリを獲得しようとして 十分にメモリが足らない cgroupを 一つ選択 追い出し対象に なり得るかチェック メモリを追い出し 例えば、cgroup v2では swapの量をLimitできるの 意図的にswap=0の設定が可能 保守的にデザインした結果(実装も複雑) ユーザは多分賢い 14
  16. ページキャッシュ  ページキャッシュの一生(簡易) 1. processがread()を出す 2. メモリがアロケートされる。ページキャッシュ(read中)として登録。 3. ファイルシステム経由でディスクからデータ転送。ページキャッシュ(clean)に。 4.

    誰かがデータを書き込むとページキャッシュ(dirty)になる A) 後からカーネルスレッドでwritebackされるとcleanになる 5. メモリ回収の延長でページキャッシュを解放する A) Cleanなら速やかに解放する B) DirtyならCleanになるのを待ってから解放する Copyright 2018 FUJITSU LIMITED ここで、Cleanにする際、I/O連携できないのがcgroup v1で困ったポイント cgroup v1の場合、pageを最初に読んだ人が”owner”として紐づけされているが blkio cgroupとの関係が不明/流動的でI/Oの課金を誰につけていいのかわからなくなった cgroup v2ではTreeが同じことが強制されているので メモリのowner=I/Oのownerと捉えて課金する。 メモリに課金 I/Oに課金 I/Oに課金 15
  17. Writeback  cgroup管理はMemory cgroupとI/O cgroupで連動 1. inode を読み込んだ時に、inodeを読み込んだプロセスのmemory cgroupをownerとして登録 2.

    memory cgroupのdirty_ratioをトリガにwritebackを起動 3. memory cgroupがownerのinodeをscan、dirty pageをI/Oに引き渡し 4. I/Oではmemcg にマッチするblock cgroupを参照し、帯域制御を実施 ※memcg<->blkcgの関係がcgroup v2では自明になる。 Copyright 2018 FUJITSU LIMITED background_dirty_ratio Dirty dirty_ratio Buffered I/Oではプロセスが利用可能なメモリ の一定比率(dirty_ratio)をトリガに Writebackを開始 Writeback起動 Write()を停止 16
  18. cgroupv2のメモリ保護と最低保証 Copyright 2018 FUJITSU LIMITED 回収すべきNode(Zone)選択 回収すべきcgroup選択 回収すべきpage選択 mem_cgroup_protected() MEMCG_PROT_NONE

    - メモリcgroupは保護されていない MEMCG_PROT_LOW - usage < memory.low - メモリcgroupは保護されているが、他から メモリ回収できてないなら回収対象となる MEMCG_PROT_MIN - usage < memory.min - メモリcgroupは保護されている 17
  19. memory.lowのovercommit(minも同じ)  Tree構造と使用量を計算、実際のmemory.low (effective-low)は以下の計算になる (mm/memcontrol.cのコメントとコード参照) Copyright 2018 FUJITSU LIMITED A

    C B D E Low=2G Cur=6G low_usage elow = min( memory.low, parent->elow * -------------------------- ) siblings_low_usage | memory.current, if memory.current < memory.low low_usage = | | memory.low, otherwise. Low=3G,Cur=2G Low=1G,Cur=2G Low=0G,Cur=2G Low=10G,Cur=0G 今この瞬間だと B:elow=約1.3G C:elow=約0.7G D:elow=約0G 均等に回収できたとすると、この数値に向かって メモリ回収されていく ※もちろん動的に再計算される 18
  20. 最近加わった機能  I/O Latency Protection  OOM Group  PSI

     おまけ①:Synchronous swap-in  おまけ②:seccomp Copyright 2018 FUJITSU LIMITED 19
  21. I/O Latency Protection  I/O Latencyについてカーネルにヒントを与える (Documentation/admin-guide/cgroup-v2.rst参照)  コントロール #echo

    Major:Minor <latency>us > io.latency file  “平均” Latencyをターゲットに向けて制御  平均レイテンシが目標値を超えている場合、他のI/Oより優遇して処理される Copyright 2018 FUJITSU LIMITED A C B D F E この間でバランス この間でバランス • ライバルのQueueを浅くする • ライバルに遅延を挿入する 20
  22. OOM Group Memory cgroupの機能の一部 OOM-Killer発生時、cgroup内のプロセスを纏めてKill OOM-Killer メモリ枯渇時にプロセスを殺す まとめて殺す意味 例えば、あるコンテナのなかに複数のプロセスが居る場合 •一つが殺されただけで、そのコンテナの担う業務がまともに動作しない

    •監視対象になっていないプロセスが殺された場合、検知が遅れる ⇒まとめて殺した方が良い Copyright 2018 FUJITSU LIMITED 21
  23. PSI  ワークロードのサイジングのヒント情報の表示。cgroup単位にも表示  Documentation/accounting/psi.txt  /kernel/sched/psi.c  PSI: Pressure

    Stall Information  CPUやメモリ、I/O がリソース競合状態になったかどうかを報告 具体的には以下の状況が起きている時間をカウントし、全体の時間に対する比率を報告する  SOME, FULLの2つの指標について報告される  SOME : IDLEではないいくつかのタスクがStallしている  FULL: 全てのIDLE出ないタスクがStallしている Copyright 2018 FUJITSU LIMITED cpu: some tasks are runnable but not executing on a CPU memory: tasks are reclaiming, or waiting for swapin or thrashing cache io: tasks are waiting for io completions どう見ればいいかは 自分で探す 22
  24. おまけ①Synchronous swap-in 従来のswap-in 1. Page faultする 2. メモリ獲得 3. SwapCacheとして登録

    4. 非同期I/O(readahead付) 5. メモリにマップ Copyright 2018 FUJITSU LIMITED Synchronous swap-in 1. Page faultする 2. メモリ獲得 3. 同期I/O 4. メモリにマップ メモリ系デバイスをswap deviceに設定すると自動で有効化 スワップインのコストを削減 (パッチのレポートでは45%削減とのこと) 23
  25. おまけ②seccomp https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt SECCOMP_FILTER BPFを利用してシステムコールにフィルタプログラムを仕込む prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog); do_syscall64()->syscall_trace_enter()からキャッチ 利用にはライブラリの利用が一般的 https://github.com/seccomp/libseccomp

    https://github.com/seccomp/libseccomp-golang Copyright 2018 FUJITSU LIMITED ※getpid()にエラーを返させる call, err := GetSyscallFromName("getpid") err = filter1.AddRule(call, ActErrno.SetReturnCode(0x1)) err = filter1.Load() pid := syscall.Getpid() 24
  26. セキュアなコンテナ コンテナを取り巻くセキュリティの問題 そもそものイメージの信頼性 セキュアな情報の渡し方 “root”権限で動きたいアプリケーション達 呼んでほしくないシステムコール Spectreのような “snoop”リスク Copyright 2018

    FUJITSU LIMITED CNCFでTUF/Notaryという プロジェクトを支援 暗号化 権限細分化 seccomp 完全仮想化 今日はgVisorの話 25
  27. gVisor システムコールを横取りする Copyright 2018 FUJITSU LIMITED Application gVisor Kernel Systemcallを横取り

    ※いまのところcgoupv2に対応していない 26
  28. システムコールを横取りする Copyright 2018 FUJITSU LIMITED Application System Call Ptrace フック(PTRACE_EMU)

    Sentry Kernel Gofer ファイルアクセスを代行 seccomp 再実装したシステムコール gVisorのUserLand IP層 ネットワーク • Ptrace()の場合,UML みたいなもの • システムコールを代行 • 書き換えて独自発行 • フィルタリング • ネットワークスタック独自実装 • DHCP/TCP等を実装 • Checkpoint/restart実装 GoferとSentryで seccomp設定が異なる Raw socket 27
  29. 基本形 KVM等と構造は同じ Copyright 2018 FUJITSU LIMITED アプリ実行 Sentry トラップ 継続

    システムコール代行 CPUID命令のエミュレーション シグナル処理 …… Ptrace() or KVM 28
  30. Sentryでのシステムコールの代行 単にカーネルに渡すのではなく再実装的 getrandom(2) _GRND_NONBLOCK|_GRND_RANDOMを無視 syslog(2) 非破壊的なカーネルバッファの読み出しのみ許可 mount(2) remountやbind mountなどを不許可 madvise(2)

    ユーザからカーネルに与えるヒントは色々無視 他にmsync(2)でMS_INVALIDATEを無視するなど Copyright 2018 FUJITSU LIMITED 29
  31. mmapとpage faultの概略 1. mmap() : Sentry内にセグメントのオブジェクトを作成 1. Sentry 内でfilemapを獲得、PTRACE_SYSCALLでゲストのコンテキストでmmap() 2.

    App 側で同じものをマップする。 2. page fault 発生 カーネルがページフォルトを処理 Copyright 2018 FUJITSU LIMITED Sentry VMA: VA:0x400000 -> /tmp/foo:0x0 Sentry filemap: /tmp/foo:0x0 -> host:memory-file:0x3000 Host VMA: VA:0x400000 -----------------> host:memory-file:0x3000 Sentry VMA: VA:0x400000 -> /tmp/foo:0x0 Sentry filemap: /tmp/foo:0x0 -> host:memory-file:0x3000 Host VMA: VA:0x400000 -----------------> host:memory-file:0x3000 Host filemap: host:memory-file:0x3000 -> PA:0x2fb000 Host PTE: VA:0x400000 --------------------------------------------------> PA:0x2fb000 30
  32. GoferのI/O(read) Copyright 2018 FUJITSU LIMITED アプリのread() エミュレート トラップ Sentry App

    v9fs server Network conn tmpfsや/sys, /proc等ほぼエミュレート。 例えば cpuinfoもモデル名なども見せない Gofer Mountの際にセットアップ ※v9fs protocol ホストアクセス 31
  33. Network横取り  Sentry起動時にはIP Addressを扱うためのデバイスは準備  アプリケーションがsocket()でTCPソケットを作る  Ptrace()がsocket() システムコールを横取り、内部実装へ飛ばす 

    Netstackライブラリ がtcpipを初期化する  Userlandでtcpが処理される Copyright 2018 FUJITSU LIMITED 32
  34. 気になる所 GAEだとプロダクション インプリされてないので使えないシステムコールがある システムコールが(まだインプリされてないので)動きが変わる fdatasync()がfsync()になる、syncfs()がsync()になるとか  アプリのコアダンプがない  TCP/UDPがユーザランド実装なので例えば/procに情報が出ない 

    Mlock系がない(swapないけど)、madvise()系もない、splice()系がない  SYSVIPCのshm/semはあってmqueueがない  SOCK_RAWは使えないので pingやtcpdumpが困る Copyright 2018 FUJITSU LIMITED LinuxのABIを持つ別のOS. 今使うなら用途は選ぼう 33
  35. Checkpoint/Restart gVisorがsystemcallを再実装している大きな恩恵  必要なステートも全てgVisor内にある https://github.com/google/gvisor/tree/master/pkg/sentry/kernel Copyright 2018 FUJITSU LIMITED 34

  36. 今回、この資料を作っていて考えたコト 問題と妄想 Copyright 2018 FUJITSU LIMITED 35

  37. 不揮発メモリのある世界 不揮発メモリの使われ方は主に3種類 ストレージの代替品 メモリの代替品 ファイルシステム直接アクセス(DAX) コンテナ的・メモリ管理的に気になる所 よくあるケース:“永続”ストレージはリモート。ローカルストレージは不揮発メモリで高速 ジレンマ •データをローカルに置くとコンテナの位置が縛られる •Swapの方がファイルキャッシュより安価?

    •I/OコントローラはNetwork 経由のI/Oをどう扱うか?扱えないか? •何をDIMMに置いて、何を不揮発メモリに置くべきか? •cgroup制御はどうあるべき? Copyright 2018 FUJITSU LIMITED 36
  38. L7 networkの威力 インターネットはオープン 特に企業内・企業間ネットワークでは“閉じた”インターネットを使いたい インフラ屋の発想⇒ SDN(L2/L3) アプリ屋の発想⇒サービスメッシュ/Queue “つなぐ”というのは単にデータが通るだけではなく、末端やアプリから見た機能が大事 L7 networkベースの発想がますます重要に

    コネクション接続のコストがバカにできない 暗号化された世界でのキャッシュのさばき方 遠距離のコネクション UDPベースのHTTP/3 も登場 Copyright 2018 FUJITSU LIMITED 37
  39. アジリティ? Copyright 2018 FUJITSU LIMITED 設計 開発 運用 検証 評価

    コンテナ/クラウド:検証を早くする トライアンドエラー X ビジネス日程 一日に何度もトライできるとして・・・・ どう設計する?? 38
  40. 組み合わせ爆発の世界  NUMA、マルチラック、マルチクラスタ、マルチデータセンタ、マルチクラウド  揺らぎ  マシン配置・インターネット・NUMA・キャッシュ ………  共有リソース

     制約条件  性能要件  安全性要件  コスト要件  データ・サービス間のアフィニティ  キャパシティ ………..  GoogleのAuxon  超大規模のトポロジ―パターン数でモンテカルロシミュレーション  https://ai.google/research/pubs/pub45385 Copyright 2018 FUJITSU LIMITED 39
  41. https://ai.google/research/pubs/pub45385 Copyright 2018 FUJITSU LIMITED 40

  42. 今日のまとめ cgroup v2 では v1の問題点を積極的な変更で改善 gVisor はLinuxで動き、Linux ABIを持つ新OS。面白いので読んでみると◎ 今は使いどころを選ぼう サポートしろと言われると頭が痛い

    全体的に見て、まだまだやることはありそう。 OS観点だと新ハードが出るとやることが増える アプリ観点だとインフラに依存しないやり方が結局効くのか? クローズドな環境で確率的に安定状態を取る世界をどう取り扱うか? OS屋の花形がスケジューラだとすると、お題としては挑戦的かもしれない Copyright 2018 FUJITSU LIMITED 41
  43. None