Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

今日の話  Cgroup v1 と v2  Cgroup v2 とは何か?  Memory cgroupへの変更を中心にv2への変更を概観  今年加わった機能  gVisor  問題と妄想  不揮発メモリのある世界  L7 networkの威力  組み合わせ爆発の世界 Copyright 2018 FUJITSU LIMITED 2

Slide 4

Slide 4 text

コンテナとカーネル Copyright 2018 FUJITSU LIMITED コンテナ機能 (UserLand) cgroup namespaces 資源管理 (CPU,メモリ,etc…) 名前空間 (ID,ファイルシステム,etc…) SELinux AppArmor seccomp セキュリティ 3

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

ヒエラルキの違い 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

Slide 9

Slide 9 text

混乱しやすかったヒエラルキ(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

Slide 10

Slide 10 text

混乱しやすかったヒエラルキ(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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

cgroup v2 のmemory.high Copyright 2018 FUJITSU LIMITED cgroup v1 cgroup v2 limit usage 使用量がLimitにヒットしたら ヒットしたスレッドで直接メモリ回収 直接メモリ回収 max usage 間接メモリ回収 high 直接メモリ回収 使用量がhighを超えたら バックグラウンド(workqueue)でメモリ回収 使用量がLimitにヒットしたら ヒットしたスレッドで直接メモリ回収 Limitにヒットしてスレッドが遅延することが減った(cpu課金が少し他所に逃げるが…) 12

Slide 14

Slide 14 text

Page Fault  ページフォルト発生の動作(簡易) 1. 物理ページの無い仮想アドレスにCPUがアクセスする 2. カーネルに制御が移る 3. 仮想アドレス情報からページの属性を求める 4. ページをアロケーションする ⇒メモリが無ければ(直接)メモリ回収処理へ 5. ページに課金する ⇒上限に達していたらメモリ回収処理へ 6. 実際に獲得したページを仮想アドレスに貼り付ける 7. ユーザに帰る Copyright 2018 FUJITSU LIMITED 空きメモリが足りないので 解放可能なページを解放 “グローバルリクレイム” 上限に達したので 解放可能なページを解放 メモリ管理のv1->v2のポイントの一つは”グローバルメモリ回収“処理 cgroup v1では保守的な造りになっており、cgroupはメモリ回収を邪魔しない cgroup v2ではチューニングで守ることが出来る 13

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

ページキャッシュ  ページキャッシュの一生(簡易) 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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

最近加わった機能  I/O Latency Protection  OOM Group  PSI  おまけ①:Synchronous swap-in  おまけ②:seccomp Copyright 2018 FUJITSU LIMITED 19

Slide 21

Slide 21 text

I/O Latency Protection  I/O Latencyについてカーネルにヒントを与える (Documentation/admin-guide/cgroup-v2.rst参照)  コントロール #echo Major:Minor us > io.latency file  “平均” Latencyをターゲットに向けて制御  平均レイテンシが目標値を超えている場合、他のI/Oより優遇して処理される Copyright 2018 FUJITSU LIMITED A C B D F E この間でバランス この間でバランス • ライバルのQueueを浅くする • ライバルに遅延を挿入する 20

Slide 22

Slide 22 text

OOM Group Memory cgroupの機能の一部 OOM-Killer発生時、cgroup内のプロセスを纏めてKill OOM-Killer メモリ枯渇時にプロセスを殺す まとめて殺す意味 例えば、あるコンテナのなかに複数のプロセスが居る場合 •一つが殺されただけで、そのコンテナの担う業務がまともに動作しない •監視対象になっていないプロセスが殺された場合、検知が遅れる ⇒まとめて殺した方が良い Copyright 2018 FUJITSU LIMITED 21

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

おまけ①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

Slide 25

Slide 25 text

おまけ②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

Slide 26

Slide 26 text

セキュアなコンテナ コンテナを取り巻くセキュリティの問題 そもそものイメージの信頼性 セキュアな情報の渡し方 “root”権限で動きたいアプリケーション達 呼んでほしくないシステムコール Spectreのような “snoop”リスク Copyright 2018 FUJITSU LIMITED CNCFでTUF/Notaryという プロジェクトを支援 暗号化 権限細分化 seccomp 完全仮想化 今日はgVisorの話 25

Slide 27

Slide 27 text

gVisor システムコールを横取りする Copyright 2018 FUJITSU LIMITED Application gVisor Kernel Systemcallを横取り ※いまのところcgoupv2に対応していない 26

Slide 28

Slide 28 text

システムコールを横取りする 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

Slide 29

Slide 29 text

基本形 KVM等と構造は同じ Copyright 2018 FUJITSU LIMITED アプリ実行 Sentry トラップ 継続 システムコール代行 CPUID命令のエミュレーション シグナル処理 …… Ptrace() or KVM 28

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

GoferのI/O(read) Copyright 2018 FUJITSU LIMITED アプリのread() エミュレート トラップ Sentry App v9fs server Network conn tmpfsや/sys, /proc等ほぼエミュレート。 例えば cpuinfoもモデル名なども見せない Gofer Mountの際にセットアップ ※v9fs protocol ホストアクセス 31

Slide 33

Slide 33 text

Network横取り  Sentry起動時にはIP Addressを扱うためのデバイスは準備  アプリケーションがsocket()でTCPソケットを作る  Ptrace()がsocket() システムコールを横取り、内部実装へ飛ばす  Netstackライブラリ がtcpipを初期化する  Userlandでtcpが処理される Copyright 2018 FUJITSU LIMITED 32

Slide 34

Slide 34 text

気になる所 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

Slide 35

Slide 35 text

Checkpoint/Restart gVisorがsystemcallを再実装している大きな恩恵  必要なステートも全てgVisor内にある https://github.com/google/gvisor/tree/master/pkg/sentry/kernel Copyright 2018 FUJITSU LIMITED 34

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

不揮発メモリのある世界 不揮発メモリの使われ方は主に3種類 ストレージの代替品 メモリの代替品 ファイルシステム直接アクセス(DAX) コンテナ的・メモリ管理的に気になる所 よくあるケース:“永続”ストレージはリモート。ローカルストレージは不揮発メモリで高速 ジレンマ •データをローカルに置くとコンテナの位置が縛られる •Swapの方がファイルキャッシュより安価? •I/OコントローラはNetwork 経由のI/Oをどう扱うか?扱えないか? •何をDIMMに置いて、何を不揮発メモリに置くべきか? •cgroup制御はどうあるべき? Copyright 2018 FUJITSU LIMITED 36

Slide 38

Slide 38 text

L7 networkの威力 インターネットはオープン 特に企業内・企業間ネットワークでは“閉じた”インターネットを使いたい インフラ屋の発想⇒ SDN(L2/L3) アプリ屋の発想⇒サービスメッシュ/Queue “つなぐ”というのは単にデータが通るだけではなく、末端やアプリから見た機能が大事 L7 networkベースの発想がますます重要に コネクション接続のコストがバカにできない 暗号化された世界でのキャッシュのさばき方 遠距離のコネクション UDPベースのHTTP/3 も登場 Copyright 2018 FUJITSU LIMITED 37

Slide 39

Slide 39 text

アジリティ? Copyright 2018 FUJITSU LIMITED 設計 開発 運用 検証 評価 コンテナ/クラウド:検証を早くする トライアンドエラー X ビジネス日程 一日に何度もトライできるとして・・・・ どう設計する?? 38

Slide 40

Slide 40 text

組み合わせ爆発の世界  NUMA、マルチラック、マルチクラスタ、マルチデータセンタ、マルチクラウド  揺らぎ  マシン配置・インターネット・NUMA・キャッシュ ………  共有リソース  制約条件  性能要件  安全性要件  コスト要件  データ・サービス間のアフィニティ  キャパシティ ………..  GoogleのAuxon  超大規模のトポロジ―パターン数でモンテカルロシミュレーション  https://ai.google/research/pubs/pub45385 Copyright 2018 FUJITSU LIMITED 39

Slide 41

Slide 41 text

https://ai.google/research/pubs/pub45385 Copyright 2018 FUJITSU LIMITED 40

Slide 42

Slide 42 text

今日のまとめ cgroup v2 では v1の問題点を積極的な変更で改善 gVisor はLinuxで動き、Linux ABIを持つ新OS。面白いので読んでみると◎ 今は使いどころを選ぼう サポートしろと言われると頭が痛い 全体的に見て、まだまだやることはありそう。 OS観点だと新ハードが出るとやることが増える アプリ観点だとインフラに依存しないやり方が結局効くのか? クローズドな環境で確率的に安定状態を取る世界をどう取り扱うか? OS屋の花形がスケジューラだとすると、お題としては挑戦的かもしれない Copyright 2018 FUJITSU LIMITED 41

Slide 43

Slide 43 text

No content