「コントロールグループ」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
imported>Mkawamorita
(fix typo: "$ echo >100 > /sys/fs/cgroup/cpu/groupname/foo/cpu.shares" -> "$ echo 100 > /sys/fs/cgroup/cpu/groupname/foo/cpu.shares")
 
(update TranslationStatus.)
 
(5人の利用者による、間の34版が非表示)
1行目: 1行目:
  +
{{Lowercase title}}
 
[[Category:カーネル]]
 
[[Category:カーネル]]
 
[[Category:仮想化]]
 
[[Category:仮想化]]
 
[[en:Cgroups]]
 
[[en:Cgroups]]
  +
[[pt:Cgroups]]
 
{{Related articles start}}
 
{{Related articles start}}
{{Related4|Linux Containers}}
+
{{Related|Linux コンテナ}}
{{Related|Arch systemd container}}
+
{{Related|systemd-nspawn}}
 
{{Related|Docker}}
 
{{Related|Docker}}
  +
{{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 には使い方が複数存在します:
 
* ''cgcreate'', ''cgexec'', ''cgclassify'' などのツールを使ってオンザフライでグループを作成・管理する
 
* 特定のユーザーやグループ、コマンドを自動的にグループに移動する"ルールエンジンデーモン" ({{ic|/etc/cgrules.conf}} と {{ic|/usr/lib/systemd/system/cgconfig.service}})
 
* [[Linux Containers]] (LXC) 仮想化など他のソフトウェアで使う
 
   
  +
コントロールグループは様々なツールによってアクセスできます:
残念ながら"ハウツー"方式の簡単なドキュメントが存在しないため、この機能はあまり評価を受けていません。この記事ではその穴を埋める説明を行います。
 
  +
* [[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 が最も簡単で推奨されます。
   
 
== インストール ==
 
== インストール ==
まず、cgroups を管理するためのティリティをインストールしてください。[[AUR|AUR]] から {{AUR|libcgroup}} パッケージをインストールする必要があります。
+
cgroup自動的に管理するために、以下パッケジのうち1つ[[インストール]]していることを確認してください:
  +
* {{Pkg|systemd}} - systemd サービスのリソースを管理するために必要です。
  +
* {{AUR|libcgroup}}、{{AUR|libcgroup-git}} - スタンドアロンツールのセット ({{ic|cgcreate}}、{{ic|cgclassify}}、永続的な設定は {{ic|cgconfig.conf}})。
   
  +
== systemd を使う ==
クライアントスクリプトの {{ic|cgm}} を使いたい場合は、{{ic|cgmanager}} デーモンを起動する必要があります。
 
   
  +
=== 階層 ===
{{ic|cgmanager}} デーモンは以下のような [[Systemd|systemd ユニット]]を使うことで起動できます:
 
   
  +
現在の cgroup 階層は {{ic|systemctl status}} コマンドか {{ic|systemd-cgls}} コマンドを使って見ることができます。
{{hc|/usr/lib/systemd/system/cgmanager.service|<nowiki>
 
[Unit]
 
Description=Control Group manager
 
   
  +
{{hc|$ systemctl status|<nowiki>
  +
● 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 を見つける ===
  +
  +
あるプロセスの cgroup 名は、{{ic|/proc/''PID''/cgroup}} で見ることができます。
  +
  +
例えば、現在のシェルの cgroup は:
  +
  +
{{hc|$ cat /proc/self/cgroup|
  +
0::/user.slice/user-1000.slice/session-3.scope
  +
}}
  +
  +
=== cgroup のリソース使用量 ===
  +
  +
{{ic|systemd-cgtop}} コマンドを使用して、cgroup のリソース使用量を見ることができます:
  +
  +
{{hc|$ 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 ===
  +
  +
{{man|5|systemd.slice}} systemd ユニットファイルを使うことで、カスタム cgroup 設定を定義できます。このユニットファイルは、systemd のディレクトリ内 ({{ic|/etc/systemd/system/}} など) に配置しなければなりません。リソースの割り当て可能な管理オプションは、{{man|5|systemd.resource-control}} にてドキュメント化されています。
  +
  +
以下は、1 つの CPU の 30% のみの使用を許可する slice ユニットの例です:
  +
  +
{{hc|/etc/systemd/system/my.slice|2=
  +
[Slice]
  +
CPUQuota=30%
  +
}}
  +
  +
=== サービスとして ===
  +
  +
==== サービスユニットファイル ====
  +
  +
リソースは、サービスの定義で、あるいは[[ドロップインファイル]] として指定可能です:
  +
  +
[Service]
  +
MemoryMax=1G
  +
  +
この例では、サービスのメモリ使用量を 1 GB に制限します。
  +
  +
==== スライスでユニットをグループ化 ====
  +
  +
サービスは、どのスライス内で実行するかを指定できます:
  +
  +
{{bc|1=
 
[Service]
 
[Service]
  +
Slice=my.slice
Type=simple
 
  +
}}
ExecStart=/usr/bin/cgmanager
 
   
  +
=== root として ===
[Install]
 
  +
WantedBy=sysinit.target
 
  +
{{ic|systemd-run}} を使うことで、指定されたスライス内でコマンドを実行することができます。
</nowiki>}}
 
  +
  +
# 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}} 内のエラーをより簡単に追跡できます。
== Systemd でリソースグループを管理する ==
 
systemd を使って ''cgconfig'' サービスを[[systemd#ユニットを使う|有効にする]]ことができます:
 
{{ic|# systemctl enable cgconfig.service}}
 
次のコマンドを使えば {{ic|cgconfig.conf}} ファイルにエラーがないか簡単に調べることができます:
 
{{ic|$ systemctl status cgconfig.service}}
 
   
== シンプルな使い方 ==
 
 
=== 一時的なグループ ===
 
=== 一時的なグループ ===
cgroups を使って即座に"一時的な"グループを作成することができます。実際に、通常ユーザーにカスタムグループを作成する権限を与えることも可能です。次のコマンドを root で実行してください ($USER はあなたのユーザー名に、''groupname'' は cgroup に付けたい名前に置き換えてください):
 
   
  +
「一時的な」なグループをその場で作成できます。一般ユーザにカスタムのグループを作成する権限を与えることもできます。以下の {{ic|groupname}} は cgroup 名です:
# cgcreate -a ''$USER'' -g memory,cpu:''groupname''
 
   
  +
# cgcreate -a ''user'' -t ''user'' -g memory,cpu:''groupname''
ユーザーによってグループ ''groupname'' の全ての設定を書き換えることができます:
 
   
  +
これで、{{ic|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
 
   
  +
{{hc|$ ls -l /sys/fs/cgroup/memory/''groupname''|
Cgroups は階層式なので、好きなだけサブグループを作成することができます。例えば、通常ユーザーとして、[[bash|bash]] シェルを新しいサブグループ 'foo' 下で動作させたい場合:
 
  +
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''
 
   
  +
$ cgcreate -g memory,cpu:'''groupname/foo'''
さあ、確認してみましょう:
 
  +
$ '''cgexec''' -g memory,cpu:groupname/foo '''bash'''
   
  +
確認するには (レガシーな (v1) cgroup でのみ意味があります):
$ cat /proc/self/cgroup
 
  +
11:memory:/groupname/foo
 
  +
{{hc|$ cat /proc/self/cgroup|
6:cpu:/groupname/foo
 
  +
11:memory:/groupname/foo
  +
6:cpu:/groupname/foo
  +
}}
   
このグループの新しいサブディレクトリが作成されてい。このグループ内のてのプロセスのメモリ使用量を 10 MB に制限するには、を実行します:
+
新しいサブディレクトリがこのグループ用に作成されました。このグループ内のすべてのプロセスのメモリ使用量を 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 の使用にし適用されないので注意してください -- タスクが制限に達すると、スワップ始めます。しかしながら他のプロセスのパフォーマンスにはあまり影響を与えません。
+
メモリ制限は 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|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''';
 
}
 
}
 
}
 
}
115行目: 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|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'';
}
+
}
   
 
これは以下のシェルコマンドと同等です:
 
これは以下のシェルコマンドと同等です:
{{ic|# 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'' メソッドについて説明しますが、このセクションでは代わりにメモリ使用量を制限する手動のメソッドについて説明します。
  +
  +
''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 = ''$USER'';
+
uid = ''username'';
 
}
 
}
 
task {
 
task {
uid = ''$USER'';
+
uid = ''username'';
 
}
 
}
 
}
 
}
161行目: 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/cgroups/ カーネルの Documentation/cgroup] を参照してください (または {{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 ファイルシステムに直接アクセスする。
  • cgcreatecgexeccgclassify (libcgroupAURlibcgroup-gitAUR の一部です) のようなツールを使う。
  • "Rules Engine Daemon" を使って、特定のユーザ/グループ/コマンドをグループに自動的に移動する (/etc/cgrules.confcgconfig.service) (libcgroupAURlibcgroup-gitAUR の一部です)。
  • Linux コンテナ (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 メソッドについて説明しますが、このセクションでは代わりにメモリ使用量を制限する手動のメソッドについて説明します。

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
ノート: この最後のコマンドでは、一度に一つの 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 にはマシンのメモリや 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

参照

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