コントロールグループ(cgroup)は Linux タスクの集合を計上・制御します。cgroup は プロセスツリーのノードではありません。タスクは fork 時に親の cgroup を継承しますが、 管理者は後から移動できます。したがって cgroup はサービスマネージャーとコンテナー の背後にあるリソース境界を提供し、名前空間はグローバルリソースのビューを提供します。
この記事では cgroup バージョン 2(cgroup v2)を説明します。文書化されたインター
フェイスは cgroup2 ファイルシステムです。ファイルとサポートされるコントローラー
は、実行中のカーネル設定と利用可能なハードウェアに依存します。
統合階層とメンバーシップ #
cgroup v2 には 1 つの統合階層があります。名前のない root cgroup を含め、すべての タスクはその階層のちょうど 1 つの cgroup に属します。子 cgroup は祖先が許可した 制約とコントローラー設定を継承するため、親が委譲していない CPU、メモリ、デバイスを 取得できません。
The hierarchy is represented by a cgroup2 mount, conventionally
/sys/fs/cgroup:
findmnt -t cgroup2
cat /proc/self/cgroup
ps -o pid,cgroup,comm -p $$各ディレクトリは cgroup です。ディレクトリを作成すると子 cgroup が作成され、
cgroup.procs に PID を書き込むとプロセスのスレッドグループが移動します。
sudo mkdir /sys/fs/cgroup/build
printf '%s\n' "$$" | sudo tee /sys/fs/cgroup/build/cgroup.procs自身のプロセスを手動で移動するのではなく、サービスマネージャーを使います。たとえば systemd は slice、scope、サービスの cgroup を作成・管理します。手動移動はマネージャー の計上とライフサイクルの前提に違反する可能性があります。
ドメイン cgroup とスレッド cgroup #
通常の階層は ドメイン cgroup で構成され、コントローラーはプロセス単位で適用されます。 内部プロセス禁止ルールにより、root 以外のドメイン cgroup がプロセスを含みながら 子へドメインコントローラーを配布することを防ぎます。ワークロードをリーフへ移し、 空の中間ノードを使って子 cgroup 間にコントローラーを割り当てます。
root は例外です。cgroup.type で設定されたスレッドサブツリーでは、cgroup.threads
を使って個々のスレッドを配置できます。スレッド対応コントローラー向けで、追加の
構造制約があります。すべてのコントローラーをスレッドごとの制限に変えるものでは
ありません。スレッドサブツリーとドメインサブツリーを混在させる前に、cgroup.type
とカーネル文書を確認します。
コントローラーと有効化 #
コントローラーはリソースポリシーを実装するカーネルコードです。利用可能性と有効化 は別です。
cgroup.controllersは親が cgroup の子に利用可能にしたコントローラーを列挙します。cgroup.subtree_controlは子を制御するために有効化されたコントローラーを列挙します。+nameまたは-nameを書き込んで変更します。- コントローラーインターフェイスファイルは、コントローラー、設定、デバイスコンテキスト が適用可能な場所にだけ現れます。
新しいサブツリーでは、まず親でコントローラーを有効化し、次に子 cgroup を設定します。 root 以外のドメイン cgroup は、子向けドメインコントローラーを有効化する間、プロセス を含んではなりません。
cd /sys/fs/cgroup
cat cgroup.controllers
sudo sh -c 'printf "+cpu +memory +pids\n" > cgroup.subtree_control'
sudo mkdir build
sudo sh -c 'printf "50000 100000\n" > build/cpu.max'
sudo sh -c 'printf "2G\n" > build/memory.max'
sudo sh -c 'printf "512\n" > build/pids.max'例の cpu.max は 100,000 マイクロ秒の期間ごとに 50,000 マイクロ秒の CPU 時間を
許可します。集約 CPU 帯域をスロットルしますが、専用 CPU を予約するものではありません。
実効コントローラー集合はすべての祖先によって制限されます。
コントローラーインターフェイス #
Controller names at the root identify what a particular kernel exposes. Current v2 documentation covers the following resource-controller families:
| Controller | Representative files | Policy |
|---|---|---|
| CPU | cpu.weight, cpu.max, cpu.stat | Proportional sharing, bandwidth caps, and throttling statistics. |
| Memory | memory.current, memory.min, memory.low, memory.high, memory.max, memory.swap.max, memory.events | Accounting, protection, throttling/reclaim pressure, hard limits, swap limits, and OOM events. |
| I/O | io.weight, io.max, io.stat, io.pressure | Proportional and per-device bandwidth/IOPS controls plus statistics. |
| Cpuset | cpuset.cpus, cpuset.cpus.effective, cpuset.mems, cpuset.mems.effective | Requested and effective CPU and NUMA-node placement. |
| PIDs | pids.current, pids.max, pids.events | Current process count, a hard process limit, and limit-hit events. |
| HugeTLB | hugetlb.<size>.current, hugetlb.<size>.max, hugetlb.<size>.events | Per-huge-page-size usage and limits. |
| RDMA | rdma.max, rdma.current, rdma.events | Per-RDMA-device HCA-object and handle limits, usage, and failures. |
| Misc | misc.current, misc.max, misc.events | Limits for registered scalar resources. |
memory.high は reclaim とスロットルの境界であり、memory.max は reclaim が進まない
場合に cgroup ローカルの OOM 処理につながるハード制限です。memory.oom.group は
ワークロードに対するグループ単位の kill を要求できます。制限変更前に memory.events、
memory.stat、プレッシャーストール情報を読み取ります。定常状態 RSS に収まる制限でも、
ページフォールト、fork、キャッシュ増加時には失敗する可能性があります。
cpuset.cpus と cpuset.mems は親の制約を受ける要求を表します。*.effective
対応属性は、hotplug の影響を含め、実際に許可された CPU と NUMA ノードを示します。
CPU アフィニティと cpuset は積集合になるため、どちらの仕組みでもタスクの実行場所
を減らせます。
Common Cgroup Files #
In addition to controller files, cgroup v2 supplies hierarchy-wide files:
cgroup.procslists thread-group IDs in a cgroup and accepts a PID migration.cgroup.threadslists threads in a threaded subtree and accepts thread IDs.cgroup.eventsreports state such as whether the cgroup or its descendants are populated; poll or inotify can observe changes.cgroup.freezestops and resumes execution in a non-root subtree, andcgroup.killkills all processes in a non-root subtree.cgroup.max.depthandcgroup.max.descendantsbound hierarchy growth.cgroup.stat,cgroup.type, andcgroup.controllersexpose hierarchy and controller state.
File writes are operations, not configuration transactions. A manager must
handle EBUSY, permission failures, hotplug changes, concurrent migration, and
partial setup. Limits may be written as max where the interface permits an
unbounded value.
Delegation, Namespaces, and Containers #
Delegation gives a subordinate manager control of a subtree without granting control of its ancestors. A delegator creates an empty cgroup, enables the necessary controllers on its parent, assigns ownership or access rights to the subtree, and allows the delegate to create and manage descendants. The delegate must operate only below that boundary because ancestor configuration determines its available resources.
systemd’s Delegate=yes is a common way to establish such a boundary. A
container runtime then composes several mechanisms:
- create or select the cgroup and apply host resource policy;
- create user, mount, PID, network, and other namespaces;
- arrange a private mount view and mount
/procafter the PID namespace exists; - execute the workload and retain a host-side handle for lifecycle operations.
A cgroup namespace changes the cgroup-path view seen by a process: /proc/PID/cgroup
and cgroup filesystem paths are rooted relative to that namespace. It does not
create a separate controller hierarchy, relax ancestor limits, or isolate
resource accounting. Host-side managers retain the authoritative hierarchy.
Kernel Representation #
The user-visible tree is backed by cgroup objects in the kernel. task_struct
points to a css_set; a css_set groups the task’s
cgroup_subsys_state (CSS) references for the active controllers. A controller
embeds or associates its state with a CSS and uses that association in its
accounting and enforcement paths. Tasks can share a css_set, which avoids
duplicating an identical controller-state combination for every task.
These implementation details explain why migration must update controller
membership consistently, but they are not a stable userspace ABI. Consult
kernel/cgroup/cgroup.c
and include/linux/cgroup-defs.h
for a particular kernel revision.
Contrast with Cgroup Version 1 #
Version 1 permits multiple independent hierarchies and controller attachment to different hierarchies. Therefore a task can have distinct memberships for different controllers, which makes an application’s resource boundary difficult to reason about. Cgroup v2 uses one hierarchy, common delegation rules, and consistent controller interfaces. Systems can mount v1 and v2 during migration, but a controller cannot be simultaneously bound to both versions.
The authoritative, version-specific reference is the
cgroup v2 kernel documentation.
Check the target kernel’s cgroup.controllers and that document rather than
assuming a controller or interface file exists.
コメント
GitHub で閲覧・コメントする(投稿にはログインが必要です)