「Cgroups」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(同期)
(→‎例: コマンドのメモリ使用を制限するを翻訳して追加)
 
(2人の利用者による、間の12版が非表示)
1行目: 1行目:
  +
{{Lowercase title}}
 
[[Category:カーネル]]
 
[[Category:カーネル]]
 
[[Category:仮想化]]
 
[[Category:仮想化]]
8行目: 9行目:
 
{{Related|limits.conf}}
 
{{Related|limits.conf}}
 
{{Related articles end}}
 
{{Related articles end}}
'''cgroups''' (別名 '''control groups''') は特定のプロセス (プロセスグループ) のリソースの使用量を制限・監視する Linux カーネルの機能です。'nice' コマンドや {{ic|/etc/security/limits.conf}} などの他の方法と比べて、cgroups は柔軟性が優れています。
 
   
  +
'''コントロールグループ''' (一般的には '''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 Containers]] (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''
  +
  +
{{ic|1=--uid=''username''}} オプションを使うことで、指定されたユーザとしてコマンドをスポーンできます。
  +
  +
# 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 の使用にし適用されないので注意してください -- タスクが制限に達すると、スワップ始めます。しかしながら他のプロセスのパフォーマンスにはあまり影響を与えません。
+
メモリ制限は RAM の使用にてのみ適用されることに注意してください。一度タスクがこの制限に達すると、タスクはスワップ始めます。しかし他のプロセスのパフォーマンスに大きな影響を及ぼすことはありません。
   
同じようにこのグループの CPU 優先度 ("shares") 変更することもできます。デフォルトではてのグループは 1024 shares なっています。100 shares のグループは CPU 時間の ~10% だけ使うようになります:
+
同じようにこのグループの 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' コマンドをこのグループに移動するには:
+
また、すでに実行中のプロセスの 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行目: 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}} しか報告されません。
+
*コメントは行の先頭から始めてください! コメントを表す '''#''' 文字は行の始めの文字として現れなければなりません。そうしないと、''cgconfigparser'' が解析するときに問題が発生しますが、''cgconfig'' を [[Systemd]] で起動しない限り、エラーとしては {{ic|cgroup change of group failed}} しか報告されません。
 
*''permissions'' セクションは任意です。
 
*''permissions'' セクションは任意です。
*{{ic|/sys/fs/cgroup/}} ディレクトリ階層には ''controllers'' サブディレクトリが全て含まれ、起動時に仮想ファイルシステムとして作成・マウントされます。{{ic|<nowiki>$CONTROLLER-NAME { }</nowiki>}} コマンドを使って新しいグループエントリを作成することが可能です。何らかの理由で他の場所に階層を作成・マウントしたいときは、{{ic|/etc/cgconfig.conf}} に以下のようにふたつ目のエントリを書く必要があります:
+
*{{ic|/sys/fs/cgroup/}} ディレクトリ階層には ''controllers'' サブディレクトリが全て含まれ、起動時に仮想ファイルシステムとして作成・マウントされます。{{ic|''$CONTROLLER-NAME { }''}} コマンドを使って新しいグループエントリを作成することが可能です。何らかの理由で他の場所に階層を作成・マウントしたいときは、{{ic|/etc/cgconfig.conf}} に以下のようにふたつ目のエントリを書く必要があります:
  +
mount {
 
  +
mount {
cpuset &#61; /your/path/''groupname'';
 
  +
cpuset = /your/path/''groupname'';
}
 
  +
}
  +
 
これは以下のシェルコマンドと同等です:
 
これは以下のシェルコマンドと同等です:
# mkdir /your/path/''groupname''
+
# mkdir /your/path/''groupname''
# mount -t /your/path -o cpuset ''groupname'' /your/path/''groupname''
+
# mount -t /your/path -o cpuset ''groupname'' /your/path/''groupname''
  +
<nowiki/>}}
}}
 
   
  +
== cgroup の仮想ファイルシステムを使う ==
== 活用例 ==
 
  +
  +
systemd 232 以降では、次のセクションで説明する ''cgm'' メソッドについて説明しますが、このセクションでは代わりにメモリ使用量を制限する手動のメソッドについて説明します。
  +
  +
新しい cgroup を作成してください (ここでは名前は ''groupname'' とします):
  +
  +
# mkdir /sys/fs/cgroup/memory/''groupname''
  +
  +
例: 最大のメモリ制限を 100MB に設定するには:
  +
  +
# echo 100000000 > /sys/fs/cgroup/memory/''groupname''/memory.limit_in_bytes
  +
  +
プロセスを cgroup に移動してください (注: 1度に1つの PID のみを書き込むことができます。移動させたいプロセスそれぞれに対してこれを繰り返してください):
  +
  +
# echo ''pid'' > /sys/fs/cgroup/memory/''groupname''/cgroup.procs
  +
  +
{{Note|この最後のコマンドでは、一度に 1 つの PID のみを書き込むことができるため、移動する必要があるプロセスごとにこれを繰り返します。}}
  +
  +
== 例 ==
  +
  +
=== コマンドのメモリ使用を制限する ===
  +
  +
次の例は、特定のコマンドを 2 GB のメモリに制限する ''cgroup'' を示しています。
  +
  +
$ systemd-run --scope -p MemoryMax=2G --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 = ''$USER'';
+
uid = ''username'';
 
}
 
}
 
task {
 
task {
uid = ''$USER'';
+
uid = ''username'';
 
}
 
}
 
}
 
}
186行目: 371行目:
 
}
 
}
 
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 プロジェクトのドキュメント] にあります。
 
  +
* 詳細かつ完全なリソース管理ガイドが [https://docs.fedoraproject.org/en-US/Fedora/17/html-single/Resource_Management_Guide/index.html#sec-How_Control_Groups_Are_Organized fedora プロジェクトのドキュメント] にあります。
 
コマンドや設定ファイルについては、{{ic|man cgcreate}} や {{ic|man cgrules.conf}} などの該当する man ページを見て下さい。
 
コマンドや設定ファイルについては、{{ic|man cgcreate}} や {{ic|man cgrules.conf}} などの該当する man ページを見て下さい。
  +
  +
== ヒントとテクニック ==
  +
  +
=== cgroup v1 を有効化する ===
  +
  +
現在、cgroup v2 がデフォルトで有効化されています。cgroup v1 に切り替えたいなら、次の[[カーネルパラメータ]]を設定する必要があります:
  +
  +
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]
  +
* {{man|7|cgroups}}
  +
  +
{{TranslationStatus|cgroups|2022-09-22|733934}}

2023年10月11日 (水) 23:04時点における最新版

関連記事

コントロールグループ (一般的には cgroup と知られています) とは、プロセスのグループを管理、制限、監査するための、Linux カーネルによって提供されている機能です。cgroup はプロセスの集合 (およびその部分集合) に対して操作することができる (また、異なるシステムユーザを用いることもできる) ので 、nice(1) コマンドや /etc/security/limits.conf のような他のアプローチと比べて、cgroup はより柔軟です。

コントロールグループは様々なツールによってアクセスできます:

  • systemd ユニットファイルでディレクティブを使ってサービスやスライスに対する制限を指定する。
  • cgroup ファイルシステムに直接アクセスする。
  • cgcreatecgexeccgclassify (libcgroupAURlibcgroup-gitAUR の一部です) のようなツールを使う。
  • "Rules Engine Daemon" を使って、特定のユーザ/グループ/コマンドをグループに自動的に移動する (/etc/cgrules.confcgconfig.service) (libcgroupAURlibcgroup-gitAUR の一部です)。
  • Linux Containers (LXC) 仮想化などのような他のソフトウェアを使う。

Arch Linux の場合は、systemd がデフォルトのインストールの一部なので、cgroup を起動・管理する方法として systemd が最も簡単で推奨されます。

インストール

cgroup を自動的に管理するために、以下のパッケージのうち1つをインストールしていることを確認してください:

  • systemd - systemd サービスのリソースを管理するために必要です。
  • libcgroupAURlibcgroup-gitAUR - スタンドアロンツールのセット (cgcreatecgclassify、永続的な設定は 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
ノート: 技術的には eBPF はコントローラではありませんが、上記の systemd オプションは eBPF を使って実装されており、root のみがそれらのオプションの設定を許可されています。

ユーザ委譲

ユーザが 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。
ノート: すべてのリソースの変更が即座に反映されるわけではありません。例えば、TaskMax を変更した場合、新しいプロセスを作成したときに変更が適用されます。

例えば、すべてのユーザセッションに対してインターネットアクセスを切断するには:

$ 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

グループの設定を永続化する

ノート: systemd ≥ 205 を使って cgroups を管理する場合、このファイルは完全に無視することができます。

起動時に cgroup が作成されるようにしたい場合、代わりに /etc/cgconfig.conf でグループを定義することができます。例えば、"groupname" に制限を管理しタスクを追加する $USER のパーミッションとグループ $GROUPusers を定義します。サブグループの "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 が解析するときに問題が発生しますが、cgconfigSystemd で起動しない限り、エラーとしては 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 メソッドについて説明しますが、このセクションでは代わりにメモリ使用量を制限する手動のメソッドについて説明します。

新しい cgroup を作成してください (ここでは名前は groupname とします):

# mkdir /sys/fs/cgroup/memory/groupname

例: 最大のメモリ制限を 100MB に設定するには:

# echo 100000000 > /sys/fs/cgroup/memory/groupname/memory.limit_in_bytes

プロセスを cgroup に移動してください (注: 1度に1つの PID のみを書き込むことができます。移動させたいプロセスそれぞれに対してこれを繰り返してください):

# echo pid > /sys/fs/cgroup/memory/groupname/cgroup.procs
ノート: この最後のコマンドでは、一度に 1 つの PID のみを書き込むことができるため、移動する必要があるプロセスごとにこれを繰り返します。

コマンドのメモリ使用を制限する

次の例は、特定のコマンドを 2 GB のメモリに制限する cgroup を示しています。

$ systemd-run --scope -p MemoryMax=2G --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

ドキュメント

  • コントローラーや特定のスイッチ・オプションに関する情報はカーネルのドキュメント (v1v2) を参照してください (または linux-docs をインストールして /usr/src/linux/Documentation/cgroup を見て下さい)。
  • 詳細かつ完全なリソース管理ガイドが fedora プロジェクトのドキュメント にあります。

コマンドや設定ファイルについては、man cgcreateman cgrules.conf などの該当する man ページを見て下さい。

ヒントとテクニック

cgroup v1 を有効化する

現在、cgroup v2 がデフォルトで有効化されています。cgroup v1 に切り替えたいなら、次のカーネルパラメータを設定する必要があります:

systemd.unified_cgroup_hierarchy=0

参照

翻訳ステータス: このページは en:cgroups の翻訳バージョンです。最後の翻訳日は 2022-09-22 です。もし英語版に 変更 があれば、翻訳の同期を手伝うことができます。