「コントロールグループ」の版間の差分
(→systemd を使う: 同期) |
(→libcgroup を使う: 追加) |
||
206行目: | 206行目: | ||
$ systemctl set-property user.slice IPAddressDeny=any |
$ systemctl set-property user.slice IPAddressDeny=any |
||
− | == |
+ | == libcgroup を使う == |
− | === 手動で使用する === |
||
− | 次のセクションで説明している ''cgm'' を使う方法の代わりに、このセクションでは手動でメモリ使用量を制限する方法を説明します。 |
||
+ | systemd を使って {{ic|cgconfig}} を[[有効化]]できます。これにより、{{ic|cgconfig.conf}} 内のエラーをより簡単に追跡できます。 |
||
− | ''groupname'' という名前の新しい cgroup を作成: |
||
+ | === 一時的なグループ === |
||
− | # mkdir /sys/fs/cgroup/memory/''groupname'' |
||
+ | 「一時的な」なグループをその場で作成できます。一般ユーザにカスタムのグループを作成する権限を与えることもできます。以下の {{ic|groupname}} は cgroup 名です: |
||
− | 最大メモリ使用制限を 100MB に設定: |
||
− | |||
− | # echo 100000000 > /sys/fs/cgroup/memory/''groupname''/memory.limit_in_bytes |
||
− | |||
− | プロセスを cgroup に移動 (一度に指定できる PID はひとつだけで、複数指定することはできません): |
||
− | |||
− | # echo ''pid'' > /sys/fs/cgroup/memory/''groupname''/cgroup.procs |
||
− | |||
− | === 一時的なグループ === |
||
− | cgroups を使って即座に"一時的な"グループを作成することができます。実際に、通常ユーザーにカスタムグループを作成する権限を与えることも可能です。次のコマンドを root で実行してください (''user'' はあなたのユーザー名に、''groupname'' は cgroup に付けたい名前に置き換えてください): |
||
# cgcreate -a ''user'' -t ''user'' -g memory,cpu:''groupname'' |
# cgcreate -a ''user'' -t ''user'' -g memory,cpu:''groupname'' |
||
+ | これで、{{ic|groupname}} グループで調整可能なものはすべて、あなたのユーザによって書き込み可能です: |
||
− | もしくは {{ic|cgmanager}} を使用 (ユーザー ID `1000` とシステムグループ ''root'' (GID 0) は適当な値に置き換えてください): |
||
− | + | {{hc|$ ls -l /sys/fs/cgroup/memory/''groupname''| |
|
+ | total 0 |
||
− | # cgm chown memory ''groupname'' ''1000'' 0 |
||
+ | -rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.event_control |
||
− | # cgm create cpu ''groupname'' |
||
+ | -rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.procs |
||
− | # cgm chown cpu ''groupname'' ''1000'' 0 |
||
+ | -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_period_us |
||
− | # chown ''user'' /sys/fs/cgroup/{memory,cpu}/''groupname''/* |
||
+ | -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}} 下で実行したい場合: |
||
− | ユーザーによってグループ ''groupname'' の全ての設定を書き換えることができます: |
||
− | $ |
+ | $ cgcreate -g memory,cpu:'''groupname/foo''' |
+ | $ '''cgexec''' -g memory,cpu:groupname/foo '''bash''' |
||
− | 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 |
||
+ | 確認するには (レガシーな (v1) cgroup でのみ意味があります): |
||
− | Cgroups は階層式なので、好きなだけサブグループを作成することができます。例えば、通常ユーザーとして、[[bash]] シェルを新しいサブグループ 'foo' 下で動作させたい場合: |
||
+ | {{hc|$ cat /proc/self/cgroup| |
||
− | $ cgcreate -g memory,cpu:''groupname/foo'' |
||
− | + | 11:memory:/groupname/foo |
|
+ | 6:cpu:/groupname/foo |
||
− | |||
+ | }} |
||
− | 同じことを {{ic|cgmanager}} で設定するには: |
||
− | |||
− | $ cgm create memory ''groupname/foo'' |
||
− | $ cgm create cpu ''groupname/foo'' |
||
− | $ bash |
||
− | $ cgm movepid memory groupname/foo $pid_of_bash |
||
− | $ cgm movepid cpu groupname/foo $pid_of_bash |
||
− | |||
− | さあ、確認してみましょう: |
||
− | |||
− | $ 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 |
$ echo 10000000 > /sys/fs/cgroup/memory/groupname/foo/memory.limit_in_bytes |
||
+ | メモリ制限は RAM の使用に対してのみ適用されることに注意してください。一度タスクがこの制限に到達すると、タスクはスワップし始めます。しかし、他のプロセスのパフォーマンスに大きな影響を及ぼすことはありません。 |
||
− | {{ic|cgmanager}} を使用する場合: |
||
+ | 同じように、このグループの CPU の優先度 ("shares") も変更できます。デフォルトでは、すべてのグループは 1024 shares となっています。100 shares のグループは CPU 時間の約 10 % を獲得します: |
||
− | $ cgm setvalue memory groupname/foo memory.limit_in_bytes 10000000 |
||
− | |||
− | メモリ制限は 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'''; |
} |
} |
||
} |
} |
||
315行目: | 287行目: | ||
} |
} |
||
− | 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/>}} |
||
− | }} |
||
== 活用例 == |
== 活用例 == |
2022年9月22日 (木) 17:09時点における版
コントロールグループ (一般的には 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 Containers (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) と同じです。
例えば、すべてのユーザセッションに対してインターネットアクセスを切断するには:
$ 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; } }
活用例
Matlab
Matlab にはマシンのメモリや CPU が全て使われるのに対するプロテクトがありません。膨大な計算を始めてしまうとシステムが使えなくなる可能性があります。以下はそれを防止するために /etc/cgconfig.conf
に配置するファイルです ($USER はあなたのユーザー名に置き換えてください):
/etc/cgconfig.conf
# Prevent Matlab from taking all memory group matlab { perm { admin { uid = $USER; } task { uid = $USER; } } cpuset { cpuset.mems="0"; cpuset.cpus="0-5"; } memory { # 5 GiB limit memory.limit_in_bytes = 5368709120; } }
この cgroup は Matlab が使えるコアをコア0から5までに (Matlab には6つのコアだけが認識されます) そしてメモリの使用量を 5 GiB に制限します。"cpu" リソースの強制を使って CPU 使用量の制限も定義することが可能ですが、"cpuset" で十分だと思われます。
matlab を次のようにして起動します:
$ cgexec -g memory,cpuset:matlab /opt/MATLAB/2012b/bin/matlab -desktop
正しい実行可能ファイルのパスを使って下さい。
ドキュメント
- コントローラーや特定のスイッチ・オプションに関する情報はカーネルのドキュメント (v1 と v2) を参照してください (または linux-docs をインストールして
/usr/src/linux/Documentation/cgroup
を見て下さい)。 - 詳細かつ完全なリソース管理ガイドが fedora プロジェクトのドキュメント にあります。
コマンドや設定ファイルについては、man cgcreate
や man cgrules.conf
などの該当する man ページを見て下さい。