目的
cgroupによって、特定プロセスのメモリをどのように制御できるのかをご紹介します。
今回はcgroup v1を使います。
OSはCentOS7です。
cgroupとは
システムのプロセスをグループ化したり、そのグループ化したプロセスにどれくらいCPUやメモリなどのリソースを割り当てるかを制御するLinuxカーネルの機能です。
cgroupを使うことで、あるプロセスだけがシステムのリソースを使い切ってしまうのを防げます。
cgroupについてより詳しく知りたい方は以下を参照ください。
https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/6/html/resource_management_guide/ch01
cgroupによるメモリ制御を試す
以下の流れで進めていきます。
- テスト用のグループ作成
- 使用できるメモリの最大値を設定
- メモリに負荷をかけるプログラムを実行
- テストグループに3で実行したプロセスを追加
1. テスト用のグループ作成
cgroupではプロセスをグループ化してリソースを制御できます。
デフォルトでは/sys/fs/cgroup/memoryにメモリを制御するプログラム(サブシステム)がマウントされていて、その配下にディレクトリを作成することでグループを新たに作成できます。
今回はtestというグループを作成します。
# mkdir /sys/fs/cgroup/memory/test
ディレクトリを作成すると、そのグループを制御するために必要なファイルが自動で作成されます。
# cd /sys/fs/cgroup/memory/test
# ls
cgroup.clone_children memory.kmem.max_usage_in_bytes memory.limit_in_bytes memory.numa_stat memory.use_hierarchy
cgroup.event_control memory.kmem.slabinfo memory.max_usage_in_bytes memory.oom_control notify_on_release
cgroup.procs memory.kmem.tcp.failcnt memory.memsw.failcnt memory.pressure_level tasks
memory.failcnt memory.kmem.tcp.limit_in_bytes memory.memsw.limit_in_bytes memory.soft_limit_in_bytes
memory.force_empty memory.kmem.tcp.max_usage_in_bytes memory.memsw.max_usage_in_bytes memory.stat
memory.kmem.failcnt memory.kmem.tcp.usage_in_bytes memory.memsw.usage_in_bytes memory.swappiness
memory.kmem.limit_in_bytes memory.kmem.usage_in_bytes memory.move_charge_at_immigrate memory.usage_in_bytes
各ファイルの用途を知りたい方は以下を参照ください。
https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/6/html/resource_management_guide/sec-memory
2. 使用できるメモリの最大値を設定
testグループで使用できるメモリの最大値を設定するには、「memory.limit_in_bytes」ファイルに値を書き込みます。
今回は10Mを設定してみます。
# echo 10M > memory.limit_in_bytes
# cat memory.limit_in_bytes
10485760
3. メモリに負荷をかけるプログラムを実行
メモリを10M以上使うプログラムを実行したかったので、stressコマンドを使いました。
オプションの意味は以下の通りです。
オプション | 意味 |
---|---|
-m N | メモリを消費するN個のVMを生成する |
--vm-bytes | 1VMごとのサイズを指定する |
stressコマンド実行後、topコマンドでPIDとメモリ使用量を確認します。
# stress -m 1 --vm-bytes 512M &
[1] 10853
# top | egrep 'COMMAND|stress'
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
10854 root 20 0 531604 40956 128 R 100.0 2.0 1:50.60 stress
10854 root 20 0 531604 456700 128 R 99.4 22.3 1:54.14 stress
10854 root 20 0 531604 227324 128 R 100.0 11.1 1:58.14 stress
10854 root 20 0 531604 108540 128 R 99.8 5.3 2:02.13 stress
10854 root 20 0 531604 38908 128 R 99.7 1.9 2:05.14 stress
PIDは10854、メモリの使用量は、最低でも10M以上は使っているようです。
4. テストグループに3で実行したプロセスを追加
グループにプロセスを追加するには、/sys/fs/cgroup/memory/test配下の「tasks」ファイルにPIDを追加します。グループにプロセスを追加するとそのグループに設定されているメモリの最大値などが適用されることになります。
では、実際にPIDを追加して、当該プロセスがどうなるか確認してみます。
# echo 10854 > tasks
# stress: FAIL: [10853] (415) <-- worker 10854 got signal 9
stress: WARN: [10853] (417) now reaping child worker processes
stress: FAIL: [10853] (451) failed run completed in 30s
[1]+ 終了 1 stress -m 1 --vm-bytes 512M
testグループに設定していた最大値10Mよりも多く使用していたため、
OOM Killerによって強制終了されました。
まとめ
今回はcgroup v1でメモリの制御を試してみました。
メモリを制御するには、メモリ制御用のプログラム(サブシステム)がマウントされているディレクトリ配下に新たにグループを作成し、その配下に作成されたファイルに最大値を設定したり、プロセスを追加することで制御できることがわかりました。
参照