引用する2013年、systemdは新しい制御グループインターフェースを発表しました。(強調追加):
現在、セル属性として公開されているcgroup属性の数は制限されています。後でカーネルインターフェイスが整理され、拡張される予定です。例えばカーネルロジックの継承セマンティクスが壊れているため、現在cpusetまたはFreezeはまったく公開されていません。さらに、実行時にユニットを別のスライスに移行すること(つまり、実行中のユニットのSlice =属性の変更)は、現在のカーネルにアトミックcgroupサブツリー移動がないためサポートされていません。
それでは、カーネルロジックの継承セマンティクスにはどのような問題がありますかcpuset
(たとえば、他のcgroupコントローラには適用されませんcpu
)。
持つRedHatウェブサイトの記事簡単に管理できるシステム単位属性のサポートが不足していても、RHEL 7でcgroup CPUsetを使用する方法の実績のないソリューションがありますが、これは良い考えですか?上記の太字の引用が懸念されます。
つまり、ここで参照されているcgroup v1 cpusetを使用すると、どのような「gotchas」(gotchas)が可能になりますか?
私はこれのために賞金を始めます。
この質問に答えることができる情報源は次のとおりです(特定の順序はありません)。
- cgroup v1ドキュメント;
- カーネルソースコード;
- テスト結果
- 実際の世界経験。
上記の引用で太字の可能な意味の1つは、新しいプロセスが分岐したときに親プロセスと同じcpuset cgroupに残っていないか、同じcgroupにあるが「強制されていない」状態にあることです。実際には、cgroupが許可するものとは異なるCPUで実行されている可能性があります。しかし、これは純粋に私の推測だ。明確な答えが必要です。
答え1
ここにあるカーネルバグトラッカーには、明確で解決されていないCPUsetの問題が1つ以上文書化されています。
エラー42789- cpuset cgroup:CPUがオフライン状態になると、すべてのcgroupのcpuset.cpusから削除されますが、オンライン状態になるとルートcpuset.cpusにのみ戻ります。
見積もりコメントチケットから(実際の送信にハイパーリンクを追加し、スパムボットを防ぐためにIBMメールアドレスを削除しました):
これはPrashanth Nageshappaによって独立して報告され、コミットで修正されました。8f2f748b0656257153bcf0941df8d6060acc5ca6しかし、後でLinusによってコミットに戻りました。4293f20c19f44ca66e5ac836b411d25e14b9f185。約束したように、修正によって他の場所で回帰が発生しました。
修正コミット(後で元に戻す)は問題をよく説明します。
現在のCPUホットプラグ中に、cpusetコールバックはシステム状態を反映するようにcpusetを変更し、この処理は非対称です。つまり、CPUがオフラインになると、すべてのCPUセットから削除されます。ただし、再びオンラインになると、ルートCPUsetにのみ再配置されます。
これにより、一時停止/再開中に深刻な問題が発生しました。一時停止中は、起動しないすべてのCPUをオフラインにし、再起動中にオンラインに戻します。つまり、回復後、すべてのcpuset(ルートcpusetを除く)は1つのCPU(boot CPU)に制限されます。ただし、一時停止/再開の全体的な目的は、システムを一時停止前の状態にできるだけ近づけて復元することです。
次のように、継承との関係に関する追加の洞察とともに、同じ非対称ホットプラグの問題を説明します。
エラー188101- cgroupのcpusetのプロセススケジューリングが正しく機能しません。
そのチケットを引用するには:
コンテナのcpuset(docker / lxcはすべてデフォルトのcgroupを使用)が空になると(hotplug / hotunplugのため)、そのコンテナで実行されているプロセスは、最も近い空でない祖先のCPUsetに予約できます。
ただし、実行中のコンテナのcpusetを更新(echoメソッドを使用)して、実行中のコンテナ(docker / lxc)のcpusetが空の状態から空でない状態に変更された場合(空のcpusetにCPUを追加)、そのコンテナで実行される操作は次のようになります。プロセスは、まだ最も近い空でない祖先と同じCPUSetを使用します。
cpusetには他の問題があるかもしれませんが、上記は「カーネルロジックの継承セマンティクスが破損しているため」systemdがcpusetを公開または使用しないことを理解して理解するのに十分です。
この2つのバグレポートで判断すると、回復後にCPUがCPUsetに再追加されることはありません。はい(手動で)追加すると、そのcgroupのプロセスはcpusetが許可しないCPUで実行され続けます。
私が見つけたLennart Petlingによるメッセージこれはその理由を直接確認します(太字)。
Lennart Poetteringは、2016年8月3日水曜日16:56 +0200に次のように書きました。
2016年8月3日水曜日14:46に、Werner Fink博士(suse.deのwerner)が次のように書きました。
v228の問題(現在のgitログ以降のAFAICSのようです)は、繰り返しCPUホットプラグイベント(オフライン/オンライン)です。根本的な原因は、CPUset.cpusを加工に復元できないことです。 libvirtは許可されていないため、これを行うことはできません。
これはカーネルcpusetインタフェースの制限です。これが現在systemdでcpusetを公開していない理由の1つです。幸いにも、systemdのCPUAffinity =を介して公開されるCPUアフィニティコントロールであるcpusetに代わるものがあります。これは本質的に同じことを行いますが、意味がありません。
私たちはsystemdでcpusetを直接サポートしたいのですが、カーネルインタフェースが退屈であればそうしません。例えば、現在のシステムが一時停止/再開周期を経ると、CPUセットは完全にフラッシュされます。
答え2
私は明確な答えを提供するためにcgroupについて十分に知っていませんが(そして確かに2013年にcgroupについての経験はありません!)Ubuntu 16.04 cgroups v1では一緒に動作するようです。
sudo /bin/bash
私はルートから分離されたサブプロセスを使用して他のユーザーにフォークを強制する小さなテストを設計しました。&
この-H
フラグは重度の編集証で、sudo
ルートのホーム環境での実行を強制します。
cat <(whoami) /proc/self/cgroup >me.cgroup && \
sudo -H /bin/bash -c 'cat <(whoami) /proc/self/cgroup >you.cgroup' & \
sleep 2 && diff me.cgroup you.cgroup
これは以下を生成します。
1c1
< admlocal
---
> root
ちなみに、私のシステムのcgroupマウント構造は次のとおりです。
$ mount | grep group
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
lxcfs on /var/lib/lxcfs type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
$
答え3
Linuxカーネルでcpuset cgroup継承セマンティクスに関連する「問題」とは何ですか?
「現在のユニット属性として公開されるcgroup属性の数は制限されています。後でカーネルインターフェースがクリーンアップされると拡張される予定です。カーネルロジックの継承の意味が壊れているので、現在はcpusetやFreezeはまったく公開されていません。。さらに、実行時にユニットを別のスライスに移行すること(つまり、実行中のユニットのSlice =属性の変更)は、現在のカーネルにアトミックcgroupサブツリー移動がないためサポートされていません。 」
それでは、cpusetカーネルロジックの継承セマンティクスにはどのような問題がありますか(それはCPUなどの他のcgroupコントローラには適用されません)。
上記の太字の引用が懸念されます。つまり、ここで参照されているcgroup v1 cpusetを使用すると、どのような「gotchas」(gotchas)が可能になりますか?
非常に短い答え:コードは複数の処理でうまく機能しないため、他のプロセスはPIDを使用して解放し、子プロセスのPIDが終了する前にプールに返します。したがって、アップストリームでは、PIDのサブプロセスが生きていると信じられます。したがって、PIDは次のようになります。スキップしましたが、子を終了する前にPIDを再公開しないでください。簡単に言えば、ロックは良くありません。
サービス、範囲、およびフラグメントは、管理者が自由に作成したり、プログラムを介して動的に作成したりできます。これは、起動中にオペレーティングシステムによって設定されたデフォルトのスライスを妨げる可能性があります。
Cgroup を使用すると、プロセスとすべての子プロセスは包含グループからリソースを取得します。
そしてもっとたくさんあります...長い答えにつながります...
多くの人々が懸念を表明した。
」Linux制御グループが機能しない"(2016) ジョナサン・デ・ボイン・ポラード:
「作業」抽象化を提供するオペレーティングシステムカーネルは、「作業」全体をキャンセル/終了する方法を提供します。証人Win32TerminateJobObject()例えば、メカニズム。
systemdがcgroup内のすべてのプロセスを終了すると、単一の「ジョブ終了」システムコールは実行されません。そのようなことはありません。しかしそれはアプリケーションパターンコードのループ内cgroup内のすべてのプロセスIDを繰り返しスキャンし(PID番号でいっぱいのファイルを再読み込み)、以前に見られなかった新しいプロセスにシグナルを送信します。これにはいくつかの問題があります。
- systemdは、プロセスグループから子プロセスを取得するプロセスよりも遅く、終了信号が正確に間違ったプロセスに送信される可能性があります。 systemdはcgroupのプロセスリストファイルを読み込み、実際にプロセスリストにシグナルを送信し始めます。 ...
...
cgroup内で新しいプロセスを素早くフォークするプログラムは、理論的に正しい「天気」が優勢である限り、長い時間システムの実行を維持することができます。各ループ反復でプロセスを終了する必要があるためです。これは必ずしもフォーク爆弾である必要はないことに注意してください。 systemdがループを実行するたびに、cgroupに少なくとも1つの新しいプロセスIDを表示するのに十分なフォークが必要です。
systemd は、シグナルを送信したプロセスのプロセス ID をセットに保ち、どのプロセスがシグナルを再送信しようとしないかを判断します。 ID Nを持つプロセスはreaper /親プロセスによってシグナルを受け取り、プロセステーブルからクリアされ、cgroupの何かが新しいプロセスを再フォークし、同じプロセスID Nを再割り当てできます。 systemd は cgroup のプロセス ID のリストを再び読み込み、新しいプロセスにシグナルを送信したと考え、まったくシグナルを送信しません。
これらの問題はすべて、実際の「作業」メカニズムによって解決されます。しかし、cgroupsではそうではありません。 cgroup は、既存の Unix リソース制限メカニズムを改善し、長く続いてよく知られているいくつかの設計上の欠陥を解決するように設計されています。 VMSと同じように設計されていないWindows NTジョブオブジェクト。
いいえ、冷蔵庫は答えではありません。 systemdはFreezerを使用しないだけでなく、systemd「とはっきり説明されています。カーネルロジックの継承セマンティクスが壊れています。「それはどういう意味なのか尋ねなければならない。しかし、彼らにとって、Freizerは魔法のようにcgroupを動作メカニズムに変換しません。
また、Dockerや他の人が自分の目的のために制御グループの固定状態を操作し、原子の読み取りや更新など、この設定を複数の所有者間で共有できる実際の競合メカニズムがないことは言うまでもありません。
最後に変更された日付スタンプが保持されている限り、このWebページを変更されていない元の形式にコピーして配布する権限が付与されます。-
Terminates all processes currently associated with the job. If the job is nested, this function terminates all processes currently associated with the job and all of its child jobs in the hierarchy.
-
A job object allows groups of processes to be managed as a unit. Job objects are namable, securable, sharable objects that control attributes of the processes associated with them. Operations performed on a job object affect all processes associated with the job object. Examples include enforcing limits such as working set size and process priority or terminating all processes associated with a job.
これ 回答 供給ジョナサンの説明は次のとおりです。
Systemdのリソース制御の概念
...
サービス、範囲、およびスライス単位は、cgroupツリーのオブジェクトに直接マップされます。これらのユニットがアクティブになると、各ユニットはユニット名から生成されたcgroupパスに直接マップされます(一部の文字エスケープモジュールとして)。たとえば、foobar-waldo.slice スライスの quux.service サービスは、cgroup foobar.slice/foobar-waldo.slice/quux.service/ にあります。
サービス、範囲、およびフラグメントは、管理者が自由に作成したり、プログラムを介して動的に作成したりできます。ただし、デフォルトでは、オペレーティングシステムはシステムの起動に必要ないくつかの組み込みサービスを定義します。さらに、デフォルトでは4つのスライスが定義されています。最初のものは、ルートスライス、.slice(上記のように)とsystem.slice、machine.slice、およびuser.sliceです。デフォルトでは、すべてのシステムサービスは最初のスライスに配置され、すべての仮想マシンとコンテナは2番目のスライスに配置され、ユーザーセッションは3番目のスライスに配置されます。しかし、これはデフォルト値にすぎず、管理者は自由に新しいスライスを定義し、サービスとスコープを割り当てることができます。さらに、すべてのログインセッションは、VMおよびコンテナプロセスと同様に、別々のスコープ単位に自動的に配置されます。最後に、ログインしたすべてのユーザーには、すべてのセッション範囲が配置される独自の暗黙的なスライスもあります。。
...
ご覧のとおり、サービスとスコープにはプロセスが含まれ、スライスに配置されますが、スライスには独自のプロセスは含まれていません。また、特別な「-.slice」は暗黙的にツリー全体のルートとして識別されるため、表示されません。
サービス、範囲、およびフラグメントに対して同じ方法でリソース制限を設定できます。 ...
完全な説明については、上記のリンクをクリックしてください。
」Cgroups v2:2番目にリソース管理が悪化しました。" (2016年10月14日) davmac 作成:
...
グループが別のグループ内に存在するようにネストされた階層を作成でき、ネストされたグループは親グループのリソースを共有します(追加に制限される可能性があります)。プロセスのPIDをグループの制御ファイルの1つに書き込むことで、プロセスをグループに移動できます。したがって、グループにはプロセスとサブグループを含めることができます。
制限する必要がある2つの確実なリソースはメモリとCPU時間であり、それぞれに「コントローラ」がありますが、他のリソース(I / O帯域幅など)がある可能性があり、一部のCgroupコントローラは実際にリソース使用率を管理しません。 (たとえば、「フリーザー」コントローラ/サブシステム)Cgroups v1インターフェイスを使用すると、さまざまなコントローラが接続されている複数のレイヤを作成できます(この値は疑わしいが可能性があります)。
重要なのは、プロセスが親プロセスからcgroupメンバーシップを継承し、適切な権限がないとcgroupから自分自身に移動できないことです。つまり、プロセスはフォークによって課される制限を避けることはできません。 RLIMIT_AS(アドレス空間)制限を使用してプロセスのメモリ使用量を制限することができますが(たとえば、プロセスを分岐でき、その子がプロセスから開始せずに追加のメモリを消費できるsetrlimitの使用と比較してください。元のリソース抽出プロセス。一方、Cgroup を使用すると、プロセスとすべての子プロセスが包含グループからリソースを取得します。
...
cgroup コントローラは、単にシステム管理の擬似ファイルシステムに制御ノブを追加するため、パブリック API で許可されない多くのノブを実装します。 cgroup は、適切に抽象化された、または洗練されていないインターフェイスノブで終わり、カーネル内部の詳細を直接明らかにします。
これらのノブは、正しく定義されていない委任メカニズムを介して個々のアプリケーションに公開され、必要な調査なしにパブリックAPIを実装するための近道でcgroupを効果的に乱用します。
...
cgroup v1では、スレッドがすべてのcgroupに存在することを許可します。これにより、親 cgroup に属するスレッドとそのサブスレッドがリソースを配置して競合する興味深い問題が発生します。 2つの異なるタイプのエンティティ間に競争があり、これを解決するための確実な方法がないため、これは迷惑です。コントローラごとに異なる操作を実行します。
cgroup v2 ドキュメントも参照してください: "v1の問題とv2の基本原理":
複数の階層
cgroup v1は複数の層を受け入れ、各層は必要な数のコントローラをホストできます。これは高いレベルの柔軟性を提供するように見えますが、実際にはあまり役に立ちません。
たとえば、すべての層で利用可能な冷蔵庫などのユーティリティコントローラは、各コントローラのインスタンスが1つしかないため、1つの層でのみ使用できます。この問題は、階層がいっぱいになると、コントローラが別の階層に移動できないという事実によってさらに悪化します。別の問題は、階層にバインドされているすべてのコントローラがまったく同じ階層ビューを持つように強制されることです。特定のコントローラに基づいて粒度を変更する方法はありません。
実際、これらの問題は同じ階層に配置できるコントローラを厳しく制限し、ほとんどの構成は各コントローラを独自の階層に配置することに依存します。密接に関連するコントローラ(CPUやCPUACCTコントローラなど)のみが同じ階層にあるのが妥当です。これは、多くの場合、ユーザースペースが階層管理タスクを必要とするたびに各階層で同じステップが繰り返され、複数の同様の階層を管理することを意味します。
また、複数の階層をサポートするには高価です。これはコアcgroupの実装を大幅に複雑にしますが、より重要なのは、マルチレイヤーのサポートがcgroupが一般的に使用される方法とコントローラが実行できる操作を制限することです。
存在できる階層の数に制限はありません。これは、スレッドのcgroupメンバーシップを有限の長さで説明できないことを意味します。キーには、必要な数のアイテムを含めることができ、長さが無制限なので、操作が非常に難しく、メンバーを識別するためのコントローラが追加され、階層数が爆発的に増加する元の問題が悪化します。
さらに、コントローラは他のコントローラが配置できる階層のトポロジには期待できないため、各コントローラは他のすべてのコントローラが完全に直交する階層に接続されていると想定する必要があります。これにより、コントローラ間のコラボレーションが不可能になるか、少なくとも非常に面倒になります。
ほとんどのユースケースでは、互いに完全に直交する階層にコントローラを配置する必要はありません。多くの場合、特定のコントローラに応じてさまざまなレベルの粒度を持つ機能です。つまり、特定のコントローラから見た場合、階層がリーフからルートに縮小される可能性があります。たとえば、特定の構成では、特定のレベルを超えてメモリが割り当てられる方法には興味がありませんが、CPUサイクルが割り当てられる方法を依然として制御したい場合があります。
詳しくはパート3リンクをご覧ください。
2016年7月20日水曜日12:53にLennart Poettering(システム開発者)とDaniel P. Berrange(Redhat)間の通信、検索systemd-develファイルタイトルは「[systemd-devel] cpusetコントローラを介してすべてのプロセスをCPU / RAMに制限する":
2016年7月20日水曜日午後12時53分にDaniel P. Berrange(redhat.comのberrange)が次のように書きました。
仮想化ホストでは、すべてのホストオペレーティングシステムプロセスをCPU / RAMノードのサブセットに制限し、残りはQEMU / KVMでのみ使用できるようにすることが望ましい場合があります。歴史的に、人々はこのタスクを実行するために "isolcpus"カーネルパラメータを使用していましたが、昨年はその意味が変わり、ここにリストされているすべてのCPUもスケジューラによるロードバランシングから除外され、一般的にリアルタイム使用に非常に役立ちました。 QEMUスレッドがCPU間のロードバランシングを望む場合。
したがって、唯一のオプションは、cpuset cgroupコントローラを使用してプロセスを制限することです。 AFAIK、systemdは現在cpusetコントローラを明示的にサポートしていないため、将来のsystemdバージョンで問題が発生するリスクを最小限に抑えながら、systemdでこれを実装する「最良の」方法を見つけようとしています。
2016年7月20日水曜日午後3時29分30秒+0200にLennart Poetteringが回答しました。
はい、現在はこれをサポートしていませんが、サポートしたいと思います。しかし、問題は、現在のカーネルインタフェースが非常に退屈であることであり、この問題が解決されるまでsystemdがそれをサポートする可能性が低いことです。 (私がTejunを知っている限り、cpusetのmemとCPUの関係は同じままではないかもしれません。)
2016年7月20日水曜日14:49に、Daniel P. Berrange(redhat.comのberrange)は次のように書きました。
cgroupsv2はdistroが切り替えられると多くの問題を引き起こす可能性があるため、小さな更新ではこれは行われません。新しいメジャーディストロバージョンだけなので心配する必要はありません。
これが明確になることを願っています。