「コントロールグループ」の版間の差分
同期 |
Kusanaginoturugi (トーク | 投稿記録) update TranslationStatus. |
||
| (3人の利用者による、間の27版が非表示) | |||
| 1行目: | 1行目: | ||
{{Lowercase title}} |
|||
[[Category:カーネル]] |
[[Category:カーネル]] |
||
[[Category:仮想化]] |
[[Category:仮想化]] |
||
[[en:Cgroups]] |
[[en:Cgroups]] |
||
[[pt:Cgroups]] |
|||
{{Related articles start}} |
{{Related articles start}} |
||
{{Related|Linux |
{{Related|Linux コンテナ}} |
||
{{Related|systemd-nspawn}} |
{{Related|systemd-nspawn}} |
||
{{Related|Docker}} |
{{Related|Docker}} |
||
{{Related|limits.conf}} |
{{Related|limits.conf}} |
||
{{Related articles end}} |
{{Related articles end}} |
||
'''cgroups''' (別名 '''control groups''') は特定のプロセス (プロセスグループ) のリソースの使用量を制限・監視する Linux カーネルの機能です。'nice' コマンドや {{ic|/etc/security/limits.conf}} などの他の方法と比べて、cgroups は柔軟性が優れています。 |
|||
'''Control groups''' (一般的には '''cgroup''' と知られています) とは、プロセスのグループを管理、制限、監査するための、Linux カーネルによって提供されている機能です。cgroup はプロセスの集合 (およびその部分集合) に対して操作することができる (また、異なるシステムユーザを用いることもできる) ので 、{{man|1|nice}} コマンドや {{ic|/etc/security/limits.conf}} のような他のアプローチと比べて、cgroup はより柔軟です。 |
|||
Control groups には使い方が複数存在します: |
|||
* {{ic|cgroup}} ファイルシステムを直接操作する。 |
|||
* {{ic|cgm}} クライアントを使用する ({{Pkg|cgmanager}} パッケージに入っています)。 |
|||
* ({{AUR|libcgroup}} パッケージに含まれている) ''cgcreate'', ''cgexec'', ''cgclassify'' などのツールを使ってグループを作成・管理する。 |
|||
* 特定のユーザーやグループ、コマンドを自動的にグループに移動する"ルールエンジンデーモン" ({{ic|/etc/cgrules.conf}} と {{ic|/usr/lib/systemd/system/cgconfig.service}})。 |
|||
* [[Linux Containers]] (LXC) 仮想化、{{Pkg|playpen}}{{Broken package link|パッケージが存在しません}} や systemd などのツールで使う。 |
|||
コントロールグループは様々なツールによってアクセスできます: |
|||
残念ながら"ハウツー"方式の簡単なドキュメントが存在しないため、Cgroups 機能はあまり評価を受けていません。この記事ではその穴を埋める説明を行います。 |
|||
* [[systemd]] ユニットファイルでディレクティブを使ってサービスやスライスに対する制限を指定する。 |
|||
* {{ic|cgroup}} ファイルシステムに直接アクセスする。 |
|||
* {{ic|cgcreate}}、{{ic|cgexec}}、{{ic|cgclassify}} ({{AUR|libcgroup}} と {{AUR|libcgroup-git}} の一部です) のようなツールを使う。 |
|||
* "Rules Engine Daemon" を使って、特定のユーザ/グループ/コマンドをグループに自動的に移動する ({{ic|/etc/cgrules.conf}} と {{ic|cgconfig.service}}) ({{AUR|libcgroup}} と {{AUR|libcgroup-git}} の一部です)。 |
|||
* [[Linux コンテナ]] (LXC) 仮想化などのような他のソフトウェアを使う。 |
|||
Arch Linux の場合は、systemd がデフォルトのインストールの一部なので、cgroup を起動・管理する方法として systemd が最も簡単で推奨されます。 |
|||
== インストール == |
== インストール == |
||
以下のパッケージを[[インストール]]してください: |
cgroup を自動的に管理するために、以下のパッケージのうち1つを[[インストール]]していることを確認してください: |
||
* {{Pkg|systemd}} - systemd サービスのリソースを管理するために必要です。 |
|||
* {{AUR|libcgroup}} - スタンドアロンツール ({{ic|cgcreate}}, {{ic|cgclassify}}, {{ic|cgconfig.conf}} による永続設定) が含まれています。 |
|||
* {{AUR|libcgroup}}、{{AUR|libcgroup-git}} - スタンドアロンツールのセット ({{ic|cgcreate}}、{{ic|cgclassify}}、永続的な設定は {{ic|cgconfig.conf}})。 |
|||
* {{Pkg|cgmanager}} - デーモン ({{ic|cgmanager}}) を使って cgroups を管理するシンプルなクライアント ({{ic|cgm}})。 |
|||
* {{Pkg|systemd}} - systemd サービスのリソースを制御します。 |
|||
== systemd を使う == |
|||
{{Pkg|cgmanager}} パッケージをインストールしたら {{ic|cgmanager.service}} を[[起動]]することで {{ic|cgm}} クライアントが使えるようになります。 |
|||
=== 階層 === |
|||
== Systemd でリソースグループを管理する == |
|||
systemd を使って ''cgconfig'' サービスを[[systemd#ユニットを使う|有効にする]]ことができます: |
|||
# systemctl enable cgconfig.service |
|||
以下のコマンドを使えば {{ic|cgconfig.conf}} ファイルにエラーがないか簡単に調べることができます: |
|||
$ systemctl status cgconfig.service |
|||
現在の cgroup 階層は {{ic|systemctl status}} コマンドか {{ic|systemd-cgls}} コマンドを使って見ることができます。 |
|||
== シンプルな使い方 == |
|||
=== 手動で使用する === |
|||
次のセクションで説明している ''cgm'' を使う方法の代わりに、このセクションでは手動でメモリ使用量を制限する方法を説明します。 |
|||
{{hc|$ systemctl status|<nowiki> |
|||
''groupname'' という名前の新しい cgroup を作成: |
|||
● myarchlinux |
|||
State: running |
|||
Jobs: 0 queued |
|||
Failed: 0 units |
|||
Since: Wed 2019-12-04 22:16:28 UTC; 1 day 4h ago |
|||
CGroup: / |
|||
├─user.slice |
|||
│ └─user-1000.slice |
|||
│ ├─user@1000.service |
|||
│ │ ├─gnome-shell-wayland.service |
|||
│ │ │ ├─ 1129 /usr/bin/gnome-shell |
|||
│ │ ├─gnome-terminal-server.service |
|||
│ │ │ ├─33519 /usr/lib/gnome-terminal-server |
|||
│ │ │ ├─37298 fish |
|||
│ │ │ └─39239 systemctl status |
|||
│ │ ├─init.scope |
|||
│ │ │ ├─1066 /usr/lib/systemd/systemd --user |
|||
│ │ │ └─1067 (sd-pam) |
|||
│ └─session-2.scope |
|||
│ ├─1053 gdm-session-worker [pam/gdm-password] |
|||
│ ├─1078 /usr/bin/gnome-keyring-daemon --daemonize --login |
|||
│ ├─1082 /usr/lib/gdm-wayland-session /usr/bin/gnome-session |
|||
│ ├─1086 /usr/lib/gnome-session-binary |
|||
│ └─3514 /usr/bin/ssh-agent -D -a /run/user/1000/keyring/.ssh |
|||
├─init.scope |
|||
│ └─1 /sbin/init |
|||
└─system.slice |
|||
├─systemd-udevd.service |
|||
│ └─285 /usr/lib/systemd/systemd-udevd |
|||
├─systemd-journald.service |
|||
│ └─272 /usr/lib/systemd/systemd-journald |
|||
├─NetworkManager.service |
|||
│ └─656 /usr/bin/NetworkManager --no-daemon |
|||
├─gdm.service |
|||
│ └─668 /usr/bin/gdm |
|||
└─systemd-logind.service |
|||
└─654 /usr/lib/systemd/systemd-logind |
|||
</nowiki>}} |
|||
=== プロセスの cgroup を見つける === |
|||
# mkdir /sys/fs/cgroup/memory/''groupname'' |
|||
あるプロセスの cgroup 名は、{{ic|/proc/''PID''/cgroup}} で見ることができます。 |
|||
最大メモリ使用制限を 100MB に設定: |
|||
例えば、現在のシェルの cgroup は: |
|||
# echo 100000000 > /sys/fs/cgroup/memory/''groupname''/memory.limit_in_bytes |
|||
{{hc|$ cat /proc/self/cgroup| |
|||
プロセスを cgroup に移動 (一度に指定できる PID はひとつだけで、複数指定することはできません): |
|||
0::/user.slice/user-1000.slice/session-3.scope |
|||
}} |
|||
=== cgroup のリソース使用量 === |
|||
# echo ''pid'' > /sys/fs/cgroup/memory/''groupname''/cgroup.procs |
|||
{{ic|systemd-cgtop}} コマンドを使用して、cgroup のリソース使用量を見ることができます: |
|||
=== 一時的なグループ === |
|||
cgroups を使って即座に"一時的な"グループを作成することができます。実際に、通常ユーザーにカスタムグループを作成する権限を与えることも可能です。次のコマンドを root で実行してください (''user'' はあなたのユーザー名に、''groupname'' は cgroup に付けたい名前に置き換えてください): |
|||
{{hc|$ systemd-cgtop| |
|||
# cgcreate -a ''user'' -t ''user'' -g memory,cpu:''groupname'' |
|||
Control Group Tasks %CPU Memory Input/s Output/s |
|||
user.slice 540 152,8 3.3G - - |
|||
user.slice/user-1000.slice 540 152,8 3.3G - - |
|||
user.slice/u…000.slice/session-1.scope 425 149,5 3.1G - - |
|||
system.slice 37 - 215.6M - - |
|||
}} |
|||
=== カスタム cgroup === |
|||
もしくは {{ic|cgmanager}} を使用 (ユーザー ID `1000` とシステムグループ ''root'' (GID 0) は適当な値に置き換えてください): |
|||
{{man|5|systemd.slice}} systemd ユニットファイルを使うことで、カスタム cgroup 設定を定義できます。このユニットファイルは、systemd のディレクトリ内 ({{ic|/etc/systemd/system/}} など) に配置しなければなりません。リソースの割り当て可能な管理オプションは、{{man|5|systemd.resource-control}} にてドキュメント化されています。 |
|||
# cgm create memory ''groupname'' |
|||
# cgm chown memory ''groupname'' ''1000'' 0 |
|||
# cgm create cpu ''groupname'' |
|||
# cgm chown cpu ''groupname'' ''1000'' 0 |
|||
# chown ''user'' /sys/fs/cgroup/{memory,cpu}/''groupname''/* |
|||
以下は、1 つの CPU の 30% のみの使用を許可する slice ユニットの例です: |
|||
ユーザーによってグループ ''groupname'' の全ての設定を書き換えることができます: |
|||
{{hc|/etc/systemd/system/my.slice|2= |
|||
$ ls -l /sys/fs/cgroup/memory/groupname |
|||
[Slice] |
|||
total 0 |
|||
CPUQuota=30% |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.event_control |
|||
}} |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.procs |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_period_us |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_runtime_us |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.shares |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 notify_on_release |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 tasks |
|||
=== サービスとして === |
|||
Cgroups は階層式なので、好きなだけサブグループを作成することができます。例えば、通常ユーザーとして、[[bash]] シェルを新しいサブグループ 'foo' 下で動作させたい場合: |
|||
==== サービスユニットファイル ==== |
|||
$ cgcreate -g memory,cpu:''groupname/foo'' |
|||
$ cgexec -g memory,cpu:groupname/foo ''bash'' |
|||
リソースは、サービスの定義で、あるいは[[ドロップインファイル]] として指定可能です: |
|||
同じことを {{ic|cgmanager}} で設定するには: |
|||
[Service] |
|||
$ cgm create memory ''groupname/foo'' |
|||
MemoryMax=1G |
|||
$ cgm create cpu ''groupname/foo'' |
|||
$ bash |
|||
$ cgm movepid memory groupname/foo $pid_of_bash |
|||
$ cgm movepid cpu groupname/foo $pid_of_bash |
|||
この例では、サービスのメモリ使用量を 1 GB に制限します。 |
|||
さあ、確認してみましょう: |
|||
==== スライスでユニットをグループ化 ==== |
|||
$ cat /proc/self/cgroup |
|||
11:memory:/groupname/foo |
|||
6:cpu:/groupname/foo |
|||
サービスは、どのスライス内で実行するかを指定できます: |
|||
このグループの新しいサブディレクトリが作成されています。このグループ内の全てのプロセスのメモリ使用量を 10 MB に制限するには、次を実行します: |
|||
{{bc|1= |
|||
$ echo 10000000 > /sys/fs/cgroup/memory/groupname/foo/memory.limit_in_bytes |
|||
[Service] |
|||
Slice=my.slice |
|||
}} |
|||
=== root として === |
|||
{{ic|cgmanager}} を使用する場合: |
|||
{{ic|systemd-run}} を使うことで、指定されたスライス内でコマンドを実行することができます。 |
|||
$ cgm setvalue memory groupname/foo memory.limit_in_bytes 10000000 |
|||
# systemd-run --slice=''my.slice'' ''command'' |
|||
メモリ制限は RAM の使用にしか適用されないので注意してください -- タスクが制限に達すると、スワップを始めます。しかしながら他のプロセスのパフォーマンスにはあまり影響を与えません。 |
|||
{{ic|1=--uid=''username''}} オプションを使うことで、指定されたユーザとしてコマンドをスポーンできます。 |
|||
同じようにこのグループの CPU 優先度 ("shares") を変更することもできます。デフォルトでは全てのグループは 1024 shares になっています。100 shares のグループは CPU 時間の ~10% だけを使うようになります: |
|||
# systemd-run --uid=''username'' --slice=''my.slice'' ''command'' |
|||
{{ic|--shell}} オプションを使うことで、スライスの中でコマンドシェルをスポーンできます。 |
|||
=== 非特権ユーザとして === |
|||
非特権ユーザは、いくつかの条件を満たせば、そのユーザに与えられたリソースを新しい cgroup に配分することができます。 |
|||
非 root ユーザが cgroup リソースを管理できるようにするには、cgroup v2 を使用しなければなりません。 |
|||
==== コントローラのタイプ ==== |
|||
すべてのリソースがユーザによって制御できるわけではありません。 |
|||
{| class="wikitable" |
|||
! コントローラ !! ユーザによって制御可能か !! オプション |
|||
|- |
|||
| cpu || {{Y|委譲する必要あり}} || CPUAccounting, CPUWeight, CPUQuota, AllowedCPUs, AllowedMemoryNodes |
|||
|- |
|||
| io || {{Y|委譲する必要あり}} || IOWeight, IOReadBandwidthMax, IOWriteBandwidthMax, IODeviceLatencyTargetSec |
|||
|- |
|||
| memory || {{Yes}} || MemoryLow, MemoryHigh, MemoryMax, MemorySwapMax |
|||
|- |
|||
| pids || {{Yes}} || TasksMax |
|||
|- |
|||
| rdma || {{No}} || ? |
|||
|- |
|||
| eBPF || {{No}} || IPAddressDeny, DeviceAllow, DevicePolicy |
|||
|} |
|||
{{Note|技術的には eBPF はコントローラではありませんが、上記の systemd オプションは eBPF を使って実装されており、root のみがそれらのオプションの設定を許可されています。}} |
|||
==== ユーザ委譲 ==== |
|||
ユーザが cpu や io リソースを制御するには、リソースを委譲する必要があります。これは[[ドロップインファイル]]を使うことで可能です。 |
|||
例えば、あなたのユーザ ID が 1000 の場合: |
|||
{{hc|/etc/systemd/system/user@1000.service.d/delegate.conf|2= |
|||
[Service] |
|||
Delegate=cpu cpuset io |
|||
}} |
|||
再起動し、あなたのセッションのスライスが cpu と io コントローラを所有していることを確認してください: |
|||
{{hc|$ cat /sys/fs/cgroup/user.slice/user-1000.slice/cgroup.controllers| |
|||
'''cpuset cpu io''' memory pids |
|||
}} |
|||
==== ユーザ定義のスライス ==== |
|||
ユーザのスライスファイルは {{ic|~/.config/systemd/user/}} に配置できます。 |
|||
特定のスライス下でコマンドを実行するには: |
|||
$ systemd-run --user --slice=''my.slice'' ''command'' |
|||
また、ログインシェルをスライス内で実行することも可能です: |
|||
$ systemd-run --user --slice=''my.slice'' --shell |
|||
=== 実行時の調整 === |
|||
cgroup のリソースは、{{ic|systemctl set-property}} コマンドを使うことで実行時に調整可能です。オプションについては {{man|5|systemd.resource-control}} と同じです。 |
|||
{{Warning|{{ic|--runtime}} オプションを渡さなかった場合、加えた調整は '''永続化''' されます。加えた調整は、システム全体のオプションは {{ic|/etc/systemd/system.control/}} に保存され、ユーザのオプションは {{ic|.config/systemd/user.control/}} に保存されますs。}} |
|||
{{Note|すべてのリソースの変更が即座に反映されるわけではありません。例えば、TaskMax を変更した場合、新しいプロセスを作成したときに変更が適用されます。}} |
|||
例えば、すべてのユーザセッションに対してインターネットアクセスを切断するには: |
|||
$ systemctl set-property user.slice IPAddressDeny=any |
|||
== libcgroup を使う == |
|||
systemd を使って {{ic|cgconfig}} を[[有効化]]できます。これにより、{{ic|cgconfig.conf}} 内のエラーをより簡単に追跡できます。 |
|||
=== 一時的なグループ === |
|||
「一時的な」なグループをその場で作成できます。一般ユーザにカスタムのグループを作成する権限を与えることもできます。以下の {{ic|groupname}} は cgroup 名です: |
|||
# cgcreate -a ''user'' -t ''user'' -g memory,cpu:''groupname'' |
|||
これで、{{ic|groupname}} グループで調整可能なものはすべて、あなたのユーザによって書き込み可能です: |
|||
{{hc|$ ls -l /sys/fs/cgroup/memory/''groupname''| |
|||
total 0 |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.event_control |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.procs |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_period_us |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_runtime_us |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.shares |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 notify_on_release |
|||
-rwxrwxr-x 1 user root 0 Sep 25 00:39 tasks |
|||
}} |
|||
cgroup は階層的なので、好きなだけサブグループを作成できます。通常のユーザが {{ic|bash}} シェルを新しいサブグループ {{ic|foo}} 下で実行したい場合: |
|||
$ cgcreate -g memory,cpu:'''groupname/foo''' |
|||
$ '''cgexec''' -g memory,cpu:groupname/foo '''bash''' |
|||
確認するには (レガシーな (v1) cgroup でのみ意味があります): |
|||
{{hc|$ cat /proc/self/cgroup| |
|||
11:memory:/groupname/foo |
|||
6:cpu:/groupname/foo |
|||
}} |
|||
新しいサブディレクトリがこのグループ用に作成されました。このグループ内のすべてのプロセスのメモリ使用量を 10 MBに制限するには、以下を実行してください: |
|||
$ echo 10000000 > /sys/fs/cgroup/memory/groupname/foo/memory.limit_in_bytes |
|||
メモリ制限は RAM の使用に対してのみ適用されることに注意してください。一度タスクがこの制限に到達すると、タスクはスワップし始めます。しかし、他のプロセスのパフォーマンスに大きな影響を及ぼすことはありません。 |
|||
同じように、このグループの CPU の優先度 ("shares") も変更できます。デフォルトでは、すべてのグループは 1024 shares となっています。100 shares のグループは CPU 時間の約 10 % を獲得します: |
|||
$ echo 100 > /sys/fs/cgroup/cpu/groupname/foo/cpu.shares |
$ echo 100 > /sys/fs/cgroup/cpu/groupname/foo/cpu.shares |
||
cgroup ディレクトリを表示することで |
cgroup のディレクトリを一覧表示することで、より多くのパラメータや統計を見ることができます。 |
||
また、 |
また、すでに実行中のプロセスの cgroup を変更することもできます。すべての 'bash' コマンドをこのグループに移動するには: |
||
$ pidof bash |
$ pidof bash |
||
13244 13266 |
13244 13266 |
||
$ cgclassify -g memory,cpu:groupname/foo `pidof bash` |
$ '''cgclassify''' -g memory,cpu:groupname/foo `pidof bash` |
||
$ cat /proc/13244/cgroup |
$ cat /proc/13244/cgroup |
||
11:memory:/groupname/foo |
11:memory:/groupname/foo |
||
6:cpu:/groupname/foo |
6:cpu:/groupname/foo |
||
=== |
=== グループの設定を永続化する === |
||
{{Note|[[systemd]] 205 以上を使って cgroups を管理する場合、このファイルは''完全に''無視することができます。}} |
|||
{{Note|[[systemd]] ≥ 205 を使って cgroups を管理する場合、このファイルは完全に無視することができます。}} |
|||
起動時に cgroup が作成されるようにしたい場合、代わりに {{ic|/etc/cgconfig.conf}} でグループを定義することができます。例えば、"groupname" に制限を管理しタスクを追加する ''$USER'' のパーミッションとグループ ''$GROUP'' の ''users'' を定義します。''サブグループ''の "groupname/foo" グループの定義は以下のようになります。 |
|||
起動時に cgroup が作成されるようにしたい場合、代わりに {{ic|/etc/cgconfig.conf}} でグループを定義することができます。例えば、"groupname" に制限を管理しタスクを追加する {{ic|$USER}} のパーミッションとグループ {{ic|$GROUP}} の ''users'' を定義します。''サブグループ''の "groupname/foo" グループの定義は以下のようになります: |
|||
{{hc|/etc/cgconfig.conf |2= |
{{hc|/etc/cgconfig.conf |2= |
||
group ''groupname'' { |
group '''groupname''' { |
||
perm { |
perm { |
||
# who can manage limits |
# who can manage limits |
||
admin { |
admin { |
||
uid = ''$USER''; |
uid = '''$USER'''; |
||
gid = ''$GROUP''; |
gid = '''$GROUP'''; |
||
} |
} |
||
# who can add tasks to this group |
# who can add tasks to this group |
||
task { |
task { |
||
uid = ''$USER''; |
uid = '''$USER'''; |
||
gid = ''$GROUP''; |
gid = '''$GROUP'''; |
||
} |
} |
||
} |
} |
||
| 142行目: | 288行目: | ||
} |
} |
||
group ''groupname/foo'' { |
group '''groupname/foo''' { |
||
cpu { |
cpu { |
||
''cpu.shares'' = 100; |
'''cpu.shares''' = 100; |
||
} |
} |
||
memory { |
memory { |
||
''memory.limit_in_bytes'' = 10000000; |
'''memory.limit_in_bytes''' = 10000000; |
||
} |
} |
||
} |
} |
||
}} |
}} |
||
{{Note| |
{{Note|1=<nowiki/> |
||
*コメントは行の |
*コメントは行の先頭から始めてください! コメントを表す '''#''' 文字は行の始めの文字として現れなければなりません。そうしないと、''cgconfigparser'' が解析するときに問題が発生しますが、''cgconfig'' を [[Systemd]] で起動しない限り、エラーとしては {{ic|cgroup change of group failed}} しか報告されません。 |
||
*''permissions'' セクションは任意です。 |
*''permissions'' セクションは任意です。 |
||
*{{ic|/sys/fs/cgroup/}} ディレクトリ階層には ''controllers'' サブディレクトリが全て含まれ、起動時に仮想ファイルシステムとして作成・マウントされます。{{ic| |
*{{ic|/sys/fs/cgroup/}} ディレクトリ階層には ''controllers'' サブディレクトリが全て含まれ、起動時に仮想ファイルシステムとして作成・マウントされます。{{ic|''$CONTROLLER-NAME { }''}} コマンドを使って新しいグループエントリを作成することが可能です。何らかの理由で他の場所に階層を作成・マウントしたいときは、{{ic|/etc/cgconfig.conf}} に以下のようにふたつ目のエントリを書く必要があります: |
||
mount { |
|||
mount { |
|||
cpuset = /your/path/''groupname''; |
|||
cpuset = /your/path/''groupname''; |
|||
} |
|||
} |
|||
これは以下のシェルコマンドと同等です: |
これは以下のシェルコマンドと同等です: |
||
# mkdir /your/path/''groupname'' |
|||
# mount -t /your/path -o cpuset ''groupname'' /your/path/''groupname'' |
|||
<nowiki/>}} |
|||
}} |
|||
== cgroup の仮想ファイルシステムを使う == |
|||
== 活用例 == |
|||
systemd 232 以降では、次のセクションで説明する ''cgm'' メソッドについて説明しますが、このセクションでは代わりにメモリ使用量を制限する手動のメソッドについて説明します。 |
|||
''groupname'' で新しい cgroup を作成してください: |
|||
# mkdir /sys/fs/cgroup/memory/''groupname'' |
|||
例: 最大のメモリ制限を 100MB に設定するには: |
|||
# echo 100000000 > /sys/fs/cgroup/memory/''groupname''/memory.limit_in_bytes |
|||
プロセスを cgroup に移動してください。 |
|||
# echo ''pid'' > /sys/fs/cgroup/memory/''groupname''/cgroup.procs |
|||
{{Note|この最後のコマンドでは、一度に一つの PID しか記述できないため、移動する必要があるプロセスごとにこれを繰り返してください。}} |
|||
== 例 == |
|||
=== コマンドのメモリまたは CPU 使用を制限する === |
|||
以下の例は、指定されたコマンドを 2GB のメモリに制限する ''cgroup'' を示しています。 |
|||
$ systemd-run --scope -p MemoryMax=2G --user ''command'' |
|||
以下の例は、コマンドを 1 つの CPU コアの 20% に制限するものです。 |
|||
$ systemd-run --scope -p CPUQuota="20%" --user ''command'' |
|||
=== Matlab === |
=== Matlab === |
||
Matlab にはマシンのメモリや CPU が全て使われるのに対するプロテクトがありません。膨大な計算を始めてしまうとシステムが使えなくなる可能性があります。以下はそれを防止するために {{ic|/etc/cgconfig.conf}} に配置するファイルです ($USER はあなたのユーザー名に置き換えてください): |
|||
[[MATLAB]] にはマシンのメモリや CPU を食い尽くす事態に対する保護が存在しないため、高負荷な計算を行うとシステムがクラッシュする危険があります。以下の例は、始めの CPU コア 6 つとメモリ 5 GB に制限する ''cgroup'' です。 |
|||
{{hc|/etc/cgconfig.conf |2= |
|||
# Prevent Matlab from taking all memory |
|||
==== systemd で ==== |
|||
{{hc|~/.config/systemd/user/matlab.slice|2= |
|||
[Slice] |
|||
AllowedCPUs=0-5 |
|||
MemoryHigh=6G |
|||
}} |
|||
Matlab を以下のように実行してください (正しいパスを使ってください): |
|||
$ systemd-run --user --slice=matlab.slice /opt/MATLAB/2012b/bin/matlab -desktop |
|||
==== libcgroup で ==== |
|||
{{hc|/etc/cgconfig.conf|2= |
|||
group matlab { |
group matlab { |
||
perm { |
perm { |
||
admin { |
admin { |
||
uid = '' |
uid = ''username''; |
||
} |
} |
||
task { |
task { |
||
uid = '' |
uid = ''username''; |
||
} |
} |
||
} |
} |
||
| 186行目: | 376行目: | ||
} |
} |
||
memory { |
memory { |
||
memory.limit_in_bytes = 5000000000; |
|||
# 5 GiB limit |
|||
memory.limit_in_bytes = 5368709120; |
|||
} |
} |
||
} |
} |
||
}} |
}} |
||
{{Note|$USER を実際に Matlab を動かすユーザーの名前に変えるのを忘れないで下さい。}} |
|||
この cgroup は Matlab が使えるコアをコア0から5までに (Matlab には6つのコアだけが認識されます) そしてメモリの使用量を 5 GiB に制限します。"cpu" リソースの強制を使って CPU 使用量の制限も定義することが可能ですが、"cpuset" で十分だと思われます。 |
|||
{{ic|''username''}} を変更することで、そのユーザとして Matlab を実行できます。 |
|||
matlab を次のようにして起動します: |
|||
また、{{ic|cpu}} 制限によって CPU share を制限することもできます。 |
|||
以下のように Matlab を実行してください (正しいパスを使ってください): |
|||
$ cgexec -g memory,cpuset:matlab /opt/MATLAB/2012b/bin/matlab -desktop |
$ cgexec -g memory,cpuset:matlab /opt/MATLAB/2012b/bin/matlab -desktop |
||
正しい実行可能ファイルのパスを使って下さい。 |
|||
== ドキュメント == |
== ドキュメント == |
||
* コントローラーや特定のスイッチ・オプションに関する情報はカーネルのドキュメント ([https://www.kernel.org/doc/Documentation/cgroup-v1/ v1] と [https://www.kernel.org/doc/Documentation/cgroup-v2.txt v2]) を参照してください (または {{pkg|linux-docs}} をインストールして {{ic|/usr/src/linux/Documentation/cgroup}} を見て下さい)。 |
|||
* コントローラや特定のスイッチや調整可能項目の意味については、カーネルのドキュメント [https://docs.kernel.org/admin-guide/cgroup-v1/index.html v1] または [https://docs.kernel.org/admin-guide/cgroup-v2.html v2] を参照してください(または {{Pkg|linux-docs}} をインストールして、{{ic|/usr/src/linux/Documentation/cgroup}} を参照してください) |
|||
* 詳細かつ完全なリソース管理ガイドが [http://docs.fedoraproject.org/en-US/Fedora/17/html-single/Resource_Management_Guide/index.html#sec-How_Control_Groups_Are_Organized fedora プロジェクトのドキュメント] にあります。 |
|||
* Linuxマニュアルページ: {{man|7|cgroups}} |
|||
コマンドや設定ファイルについては、{{ic|man cgcreate}} や {{ic|man cgrules.conf}} などの該当する man ページを見て下さい。 |
|||
* 詳細で完全なリソース管理ガイドは、[https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/ch01#sec-How_Control_Groups_Are_Organized Red Hat Enterprise Linux のドキュメント] にあります。 |
|||
コマンドと設定ファイルについては、該当するmanページを参照してください。例: {{man|1|cgcreate|url=https://github.com/libcgroup/libcgroup/blob/main/doc/man/cgcreate.1}} または {{man|5|cgrules.conf|url=https://github.com/libcgroup/libcgroup/blob/main/doc/man/cgrules.conf.5}} |
|||
== ヒントとテクニック == |
|||
=== cgroup v1 を有効にする === |
|||
現在、cgroup v2 がデフォルトで有効になっており、cgroup v1 は廃止と見なされ、systemd v256 以降ではシステムが起動を拒否します。[https://github.com/systemd/systemd/issues/30852] 代わりに cgroup v1 に切り替えたい場合は、以下の[[カーネルパラメータ]]を設定する必要があります: |
|||
SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1 systemd.unified_cgroup_hierarchy=0 |
|||
== 参照 == |
|||
* [https://systemd.io/CGROUP_DELEGATION/ systemd cgroups ハッカーガイド] |
|||
* [https://chrisdown.name/talks/cgroupv2/cgroupv2-fosdem.pdf cgroupv2: Linux's new unified control group system] |
|||
{{TranslationStatus|cgroups|2024-07-10|811071}} |
|||
2024年7月10日 (水) 19:45時点における最新版
Control groups (一般的には cgroup と知られています) とは、プロセスのグループを管理、制限、監査するための、Linux カーネルによって提供されている機能です。cgroup はプロセスの集合 (およびその部分集合) に対して操作することができる (また、異なるシステムユーザを用いることもできる) ので 、nice(1) コマンドや /etc/security/limits.conf のような他のアプローチと比べて、cgroup はより柔軟です。
コントロールグループは様々なツールによってアクセスできます:
- systemd ユニットファイルでディレクティブを使ってサービスやスライスに対する制限を指定する。
cgroupファイルシステムに直接アクセスする。cgcreate、cgexec、cgclassify(libcgroupAUR と libcgroup-gitAUR の一部です) のようなツールを使う。- "Rules Engine Daemon" を使って、特定のユーザ/グループ/コマンドをグループに自動的に移動する (
/etc/cgrules.confとcgconfig.service) (libcgroupAUR と libcgroup-gitAUR の一部です)。 - Linux コンテナ (LXC) 仮想化などのような他のソフトウェアを使う。
Arch Linux の場合は、systemd がデフォルトのインストールの一部なので、cgroup を起動・管理する方法として systemd が最も簡単で推奨されます。
インストール
cgroup を自動的に管理するために、以下のパッケージのうち1つをインストールしていることを確認してください:
- systemd - systemd サービスのリソースを管理するために必要です。
- libcgroupAUR、libcgroup-gitAUR - スタンドアロンツールのセット (
cgcreate、cgclassify、永続的な設定はcgconfig.conf)。
systemd を使う
階層
現在の cgroup 階層は systemctl status コマンドか systemd-cgls コマンドを使って見ることができます。
$ systemctl status
● myarchlinux
State: running
Jobs: 0 queued
Failed: 0 units
Since: Wed 2019-12-04 22:16:28 UTC; 1 day 4h ago
CGroup: /
├─user.slice
│ └─user-1000.slice
│ ├─user@1000.service
│ │ ├─gnome-shell-wayland.service
│ │ │ ├─ 1129 /usr/bin/gnome-shell
│ │ ├─gnome-terminal-server.service
│ │ │ ├─33519 /usr/lib/gnome-terminal-server
│ │ │ ├─37298 fish
│ │ │ └─39239 systemctl status
│ │ ├─init.scope
│ │ │ ├─1066 /usr/lib/systemd/systemd --user
│ │ │ └─1067 (sd-pam)
│ └─session-2.scope
│ ├─1053 gdm-session-worker [pam/gdm-password]
│ ├─1078 /usr/bin/gnome-keyring-daemon --daemonize --login
│ ├─1082 /usr/lib/gdm-wayland-session /usr/bin/gnome-session
│ ├─1086 /usr/lib/gnome-session-binary
│ └─3514 /usr/bin/ssh-agent -D -a /run/user/1000/keyring/.ssh
├─init.scope
│ └─1 /sbin/init
└─system.slice
├─systemd-udevd.service
│ └─285 /usr/lib/systemd/systemd-udevd
├─systemd-journald.service
│ └─272 /usr/lib/systemd/systemd-journald
├─NetworkManager.service
│ └─656 /usr/bin/NetworkManager --no-daemon
├─gdm.service
│ └─668 /usr/bin/gdm
└─systemd-logind.service
└─654 /usr/lib/systemd/systemd-logind
プロセスの cgroup を見つける
あるプロセスの cgroup 名は、/proc/PID/cgroup で見ることができます。
例えば、現在のシェルの cgroup は:
$ cat /proc/self/cgroup
0::/user.slice/user-1000.slice/session-3.scope
cgroup のリソース使用量
systemd-cgtop コマンドを使用して、cgroup のリソース使用量を見ることができます:
$ systemd-cgtop
Control Group Tasks %CPU Memory Input/s Output/s user.slice 540 152,8 3.3G - - user.slice/user-1000.slice 540 152,8 3.3G - - user.slice/u…000.slice/session-1.scope 425 149,5 3.1G - - system.slice 37 - 215.6M - -
カスタム cgroup
systemd.slice(5) systemd ユニットファイルを使うことで、カスタム cgroup 設定を定義できます。このユニットファイルは、systemd のディレクトリ内 (/etc/systemd/system/ など) に配置しなければなりません。リソースの割り当て可能な管理オプションは、systemd.resource-control(5) にてドキュメント化されています。
以下は、1 つの CPU の 30% のみの使用を許可する slice ユニットの例です:
/etc/systemd/system/my.slice
[Slice] CPUQuota=30%
サービスとして
サービスユニットファイル
リソースは、サービスの定義で、あるいはドロップインファイル として指定可能です:
[Service] MemoryMax=1G
この例では、サービスのメモリ使用量を 1 GB に制限します。
スライスでユニットをグループ化
サービスは、どのスライス内で実行するかを指定できます:
[Service] Slice=my.slice
root として
systemd-run を使うことで、指定されたスライス内でコマンドを実行することができます。
# systemd-run --slice=my.slice command
--uid=username オプションを使うことで、指定されたユーザとしてコマンドをスポーンできます。
# systemd-run --uid=username --slice=my.slice command
--shell オプションを使うことで、スライスの中でコマンドシェルをスポーンできます。
非特権ユーザとして
非特権ユーザは、いくつかの条件を満たせば、そのユーザに与えられたリソースを新しい cgroup に配分することができます。
非 root ユーザが cgroup リソースを管理できるようにするには、cgroup v2 を使用しなければなりません。
コントローラのタイプ
すべてのリソースがユーザによって制御できるわけではありません。
| コントローラ | ユーザによって制御可能か | オプション |
|---|---|---|
| cpu | 委譲する必要あり | CPUAccounting, CPUWeight, CPUQuota, AllowedCPUs, AllowedMemoryNodes |
| io | 委譲する必要あり | IOWeight, IOReadBandwidthMax, IOWriteBandwidthMax, IODeviceLatencyTargetSec |
| memory | Yes | MemoryLow, MemoryHigh, MemoryMax, MemorySwapMax |
| pids | Yes | TasksMax |
| rdma | No | ? |
| eBPF | No | IPAddressDeny, DeviceAllow, DevicePolicy |
ユーザ委譲
ユーザが cpu や io リソースを制御するには、リソースを委譲する必要があります。これはドロップインファイルを使うことで可能です。
例えば、あなたのユーザ ID が 1000 の場合:
/etc/systemd/system/user@1000.service.d/delegate.conf
[Service] Delegate=cpu cpuset io
再起動し、あなたのセッションのスライスが cpu と io コントローラを所有していることを確認してください:
$ cat /sys/fs/cgroup/user.slice/user-1000.slice/cgroup.controllers
cpuset cpu io memory pids
ユーザ定義のスライス
ユーザのスライスファイルは ~/.config/systemd/user/ に配置できます。
特定のスライス下でコマンドを実行するには:
$ systemd-run --user --slice=my.slice command
また、ログインシェルをスライス内で実行することも可能です:
$ systemd-run --user --slice=my.slice --shell
実行時の調整
cgroup のリソースは、systemctl set-property コマンドを使うことで実行時に調整可能です。オプションについては systemd.resource-control(5) と同じです。
--runtime オプションを渡さなかった場合、加えた調整は 永続化 されます。加えた調整は、システム全体のオプションは /etc/systemd/system.control/ に保存され、ユーザのオプションは .config/systemd/user.control/ に保存されますs。例えば、すべてのユーザセッションに対してインターネットアクセスを切断するには:
$ systemctl set-property user.slice IPAddressDeny=any
libcgroup を使う
systemd を使って cgconfig を有効化できます。これにより、cgconfig.conf 内のエラーをより簡単に追跡できます。
一時的なグループ
「一時的な」なグループをその場で作成できます。一般ユーザにカスタムのグループを作成する権限を与えることもできます。以下の groupname は cgroup 名です:
# cgcreate -a user -t user -g memory,cpu:groupname
これで、groupname グループで調整可能なものはすべて、あなたのユーザによって書き込み可能です:
$ ls -l /sys/fs/cgroup/memory/groupname
total 0 -rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.event_control -rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.procs -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_period_us -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_runtime_us -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.shares -rwxrwxr-x 1 user root 0 Sep 25 00:39 notify_on_release -rwxrwxr-x 1 user root 0 Sep 25 00:39 tasks
cgroup は階層的なので、好きなだけサブグループを作成できます。通常のユーザが bash シェルを新しいサブグループ foo 下で実行したい場合:
$ cgcreate -g memory,cpu:groupname/foo $ cgexec -g memory,cpu:groupname/foo bash
確認するには (レガシーな (v1) cgroup でのみ意味があります):
$ cat /proc/self/cgroup
11:memory:/groupname/foo 6:cpu:/groupname/foo
新しいサブディレクトリがこのグループ用に作成されました。このグループ内のすべてのプロセスのメモリ使用量を 10 MBに制限するには、以下を実行してください:
$ echo 10000000 > /sys/fs/cgroup/memory/groupname/foo/memory.limit_in_bytes
メモリ制限は RAM の使用に対してのみ適用されることに注意してください。一度タスクがこの制限に到達すると、タスクはスワップし始めます。しかし、他のプロセスのパフォーマンスに大きな影響を及ぼすことはありません。
同じように、このグループの CPU の優先度 ("shares") も変更できます。デフォルトでは、すべてのグループは 1024 shares となっています。100 shares のグループは CPU 時間の約 10 % を獲得します:
$ echo 100 > /sys/fs/cgroup/cpu/groupname/foo/cpu.shares
cgroup のディレクトリを一覧表示することで、より多くのパラメータや統計を見ることができます。
また、すでに実行中のプロセスの cgroup を変更することもできます。すべての 'bash' コマンドをこのグループに移動するには:
$ pidof bash 13244 13266 $ cgclassify -g memory,cpu:groupname/foo `pidof bash` $ cat /proc/13244/cgroup 11:memory:/groupname/foo 6:cpu:/groupname/foo
グループの設定を永続化する
起動時に cgroup が作成されるようにしたい場合、代わりに /etc/cgconfig.conf でグループを定義することができます。例えば、"groupname" に制限を管理しタスクを追加する $USER のパーミッションとグループ $GROUP の users を定義します。サブグループの "groupname/foo" グループの定義は以下のようになります:
/etc/cgconfig.conf
group groupname {
perm {
# who can manage limits
admin {
uid = $USER;
gid = $GROUP;
}
# who can add tasks to this group
task {
uid = $USER;
gid = $GROUP;
}
}
# create this group in cpu and memory controllers
cpu { }
memory { }
}
group groupname/foo {
cpu {
cpu.shares = 100;
}
memory {
memory.limit_in_bytes = 10000000;
}
}
- コメントは行の先頭から始めてください! コメントを表す # 文字は行の始めの文字として現れなければなりません。そうしないと、cgconfigparser が解析するときに問題が発生しますが、cgconfig を Systemd で起動しない限り、エラーとしては
cgroup change of group failedしか報告されません。 - permissions セクションは任意です。
/sys/fs/cgroup/ディレクトリ階層には controllers サブディレクトリが全て含まれ、起動時に仮想ファイルシステムとして作成・マウントされます。$CONTROLLER-NAME { }コマンドを使って新しいグループエントリを作成することが可能です。何らかの理由で他の場所に階層を作成・マウントしたいときは、/etc/cgconfig.confに以下のようにふたつ目のエントリを書く必要があります:
mount {
cpuset = /your/path/groupname;
}
これは以下のシェルコマンドと同等です:
# mkdir /your/path/groupname # mount -t /your/path -o cpuset groupname /your/path/groupname
cgroup の仮想ファイルシステムを使う
systemd 232 以降では、次のセクションで説明する cgm メソッドについて説明しますが、このセクションでは代わりにメモリ使用量を制限する手動のメソッドについて説明します。
groupname で新しい cgroup を作成してください:
# mkdir /sys/fs/cgroup/memory/groupname
例: 最大のメモリ制限を 100MB に設定するには:
# echo 100000000 > /sys/fs/cgroup/memory/groupname/memory.limit_in_bytes
プロセスを cgroup に移動してください。
# echo pid > /sys/fs/cgroup/memory/groupname/cgroup.procs
例
コマンドのメモリまたは CPU 使用を制限する
以下の例は、指定されたコマンドを 2GB のメモリに制限する cgroup を示しています。
$ systemd-run --scope -p MemoryMax=2G --user command
以下の例は、コマンドを 1 つの CPU コアの 20% に制限するものです。
$ systemd-run --scope -p CPUQuota="20%" --user command
Matlab
MATLAB にはマシンのメモリや CPU を食い尽くす事態に対する保護が存在しないため、高負荷な計算を行うとシステムがクラッシュする危険があります。以下の例は、始めの CPU コア 6 つとメモリ 5 GB に制限する cgroup です。
systemd で
~/.config/systemd/user/matlab.slice
[Slice] AllowedCPUs=0-5 MemoryHigh=6G
Matlab を以下のように実行してください (正しいパスを使ってください):
$ systemd-run --user --slice=matlab.slice /opt/MATLAB/2012b/bin/matlab -desktop
libcgroup で
/etc/cgconfig.conf
group matlab {
perm {
admin {
uid = username;
}
task {
uid = username;
}
}
cpuset {
cpuset.mems="0";
cpuset.cpus="0-5";
}
memory {
memory.limit_in_bytes = 5000000000;
}
}
username を変更することで、そのユーザとして Matlab を実行できます。
また、cpu 制限によって CPU share を制限することもできます。
以下のように Matlab を実行してください (正しいパスを使ってください):
$ cgexec -g memory,cpuset:matlab /opt/MATLAB/2012b/bin/matlab -desktop
ドキュメント
- コントローラや特定のスイッチや調整可能項目の意味については、カーネルのドキュメント v1 または v2 を参照してください(または linux-docs をインストールして、
/usr/src/linux/Documentation/cgroupを参照してください) - Linuxマニュアルページ: cgroups(7)
- 詳細で完全なリソース管理ガイドは、Red Hat Enterprise Linux のドキュメント にあります。
コマンドと設定ファイルについては、該当するmanページを参照してください。例: cgcreate(1) または cgrules.conf(5)
ヒントとテクニック
cgroup v1 を有効にする
現在、cgroup v2 がデフォルトで有効になっており、cgroup v1 は廃止と見なされ、systemd v256 以降ではシステムが起動を拒否します。[1] 代わりに cgroup v1 に切り替えたい場合は、以下のカーネルパラメータを設定する必要があります:
SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1 systemd.unified_cgroup_hierarchy=0