リソースの割り当てを柔軟に管理するための、Linuxカーネルの機能のこと(プロセスをグループ化したものに対してもリソースを割り当てることができる)。省略して cgroup と呼ばれる。
RedHatのマニュアル:リソース管理ガイド に細かく書いてあるので、手元にある CentOS-6.0 でざっと試してみた。
- 1. インストール
- CentOSならあらかじめインストールされているらしい。無ければ
yum install libcgroup
を実行。そうすると/etc/cgconfig.conf, /etc/init.d/cgconfig
などができる。 - 2. /etc/cgconfig.conf を編集
- とりあえずメモリの使用量を制限するため、
/etc/cgconfig.conf
に数行追加。 group test { memory { memory.limit_in_bytes = 50K; } }
- これでハードリミット50KBの制限を与えたことになる。ソフトリミット "memory.soft_limit_n_bytes" もあるらしい。
- 3.
cgconfig
サービスを起動 # service cgconfig start
- 起動すると
/cgroup/memory/test
というディレクトリが生成される。その中にある疑似ファイルを利用して cgroup を制御したり、情報を読み取ったりすることができる。たとえばmemory.limits_in_bytes
を開いてみると、上記の cgconfig.conf に記載した50KBの制限がバイト単位で指定されているのがわかる(設定ファイルで指定した値と正確には一致しない)。# cat /cgroup/memory/test/memory.limits_in_bytes 53248
- 起動すると
- 4.
/etc/cgrules.conf
を編集 メモリの使用量を制限したいユーザー、プロセス名(またはコマンドパス)等を指定する。ここではとりあえず /rootディレクトリに置いてある a.out と b.out というコマンドを対象にすることにして、次の2行を追加。
root:/root/a.out memory test/ root:/root/b.out memory test/
- 5.
cgred
サービスを起動 # service cgred start
- 6. テスト
- これで準備ができたので、とりあえず "hello, world"を出力して無限ループするプログラム(hello_and_stop.c)を書く。
/* hello_and_stop.c */ #include <stdio.h> int main(void){ printf("hello, world\n"); while(1){} return 0; }
- コンパイルしたあと、cgroup の制限を超えるまで地道に a.out と b.out をバックグラウンド実行する。
-
# gcc hello_and_stop.c # cp a.out b.out # ./a.out & [1] 5690 hello, world # ./b.out & [2] 5691 hello, world # ./a.out & [3] 5692 hello, world # ./b.out & [4] 5693 Memory cgroup out of memory: kill process 5690 (a.out) score 59 or a child Killed process 5690 (a.out) vsz:3832kB, anon-rss:16kB, file-rss:300kB hello, world [1] Killed ./a.out #
4回目の実行で制限を超えて、一番最初に実行したプロセス(PID=5690)が kill された。b.out を実行したにもかかわらず a.out が kill されたので、グループ化してリソース管理が行われているに違いない。
- 7. ログを確認
- 制限を超えたときのログは、とりあえず
/var/log/messages
に記録されていた。意外と親切でたくさんの情報が残っている。 Nov 23 20:05:58 localhost kernel: b.out invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0 Nov 23 20:05:58 localhost kernel: b.out cpuset=/ mems_allowed=0 Nov 23 20:05:58 localhost kernel: Pid: 5693, comm: b.out Not tainted 2.6.32-71.29.1.el6.x86_64 #1 Nov 23 20:05:58 localhost kernel: Call Trace: Nov 23 20:05:58 localhost kernel: [
] ? cpuset_print_task_mems_allowed+0x91/0xb0 Nov 23 20:05:58 localhost kernel: [ ] oom_kill_process+0xcb/0x2e0 Nov 23 20:05:58 localhost kernel: [ ] ? select_bad_process+0xd0/0x110 Nov 23 20:05:58 localhost kernel: [ ] mem_cgroup_out_of_memory+0x73/0x90 Nov 23 20:05:58 localhost kernel: [ ] mem_cgroup_handle_oom+0x147/0x170 Nov 23 20:05:58 localhost kernel: [ ] ? autoremove_wake_function+0x0/0x40 Nov 23 20:05:58 localhost kernel: [ ] __mem_cgroup_try_charge+0x20d/0x240 Nov 23 20:05:58 localhost kernel: [ ] mem_cgroup_charge_common+0x7b/0xc0 Nov 23 20:05:58 localhost kernel: [ ] mem_cgroup_newpage_charge+0x48/0x50 Nov 23 20:05:58 localhost kernel: [ ] handle_pte_fault+0x7a0/0xad0 Nov 23 20:05:58 localhost kernel: [ ] ? tty_ioctl+0xf7/0x950 Nov 23 20:05:58 localhost kernel: [ ] handle_mm_fault+0x1ed/0x2b0 Nov 23 20:05:58 localhost kernel: [ ] do_page_fault+0x123/0x3a0 Nov 23 20:05:58 localhost kernel: [ ] page_fault+0x25/0x30 Nov 23 20:05:58 localhost kernel: Task in /test killed as a result of limit of /test Nov 23 20:05:58 localhost kernel: memory: usage 52kB, limit 52kB, failcnt 48 Nov 23 20:05:58 localhost kernel: memory+swap: usage 264kB, limit 9007199254740991kB, failcnt 0 Nov 23 20:05:58 localhost kernel: Mem-Info: Nov 23 20:05:58 localhost kernel: Node 0 DMA per-cpu: Nov 23 20:05:58 localhost kernel: CPU 0: hi: 0, btch: 1 usd: 0 Nov 23 20:05:58 localhost kernel: CPU 1: hi: 0, btch: 1 usd: 0 Nov 23 20:05:58 localhost kernel: Node 0 DMA32 per-cpu: Nov 23 20:05:58 localhost kernel: CPU 0: hi: 186, btch: 31 usd: 75 Nov 23 20:05:58 localhost kernel: CPU 1: hi: 186, btch: 31 usd: 127 Nov 23 20:05:58 localhost kernel: active_anon:88921 inactive_anon:97754 isolated_anon:0 Nov 23 20:05:58 localhost kernel: active_file:11086 inactive_file:12590 isolated_file:0 Nov 23 20:05:58 localhost kernel: unevictable:0 dirty:0 writeback:0 unstable:0 Nov 23 20:05:58 localhost kernel: free:21668 slab_reclaimable:5484 slab_unreclaimable:10278 Nov 23 20:05:58 localhost kernel: mapped:2668 shmem:0 pagetables:1732 bounce:0 Nov 23 20:05:58 localhost kernel: Node 0 DMA free:4776kB min:664kB low:828kB high:996kB active_anon:3944kB inactive_anon:6172kB active_file:132kB inactive_file:596kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15308kB mlocked:0kB dirty:0kB writeback:0kB mapped:36kB shmem:0kB slab_reclaimable:16kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:64kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no Nov 23 20:05:58 localhost kernel: lowmem_reserve[]: 0 994 994 994 Nov 23 20:05:58 localhost kernel: Node 0 DMA32 free:81896kB min:44388kB low:55484kB high:66580kB active_anon:351740kB inactive_anon:384844kB active_file:44212kB inactive_file:49764kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:1017952kB mlocked:0kB dirty:0kB writeback:0kB mapped:10636kB shmem:0kB slab_reclaimable:21920kB slab_unreclaimable:41112kB kernel_stack:1576kB pagetables:6864kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no Nov 23 20:05:58 localhost kernel: lowmem_reserve[]: 0 0 0 0 Nov 23 20:05:58 localhost kernel: Node 0 DMA: 24*4kB 13*8kB 6*16kB 4*32kB 2*64kB 3*128kB 1*256kB 1*512kB 1*1024kB 1*2048kB 0*4096kB = 4776kB Nov 23 20:05:58 localhost kernel: Node 0 DMA32: 210*4kB 419*8kB 474*16kB 365*32kB 163*64kB 41*128kB 23*256kB 24*512kB 6*1024kB 1*2048kB 4*4096kB = 81888kB Nov 23 20:05:58 localhost kernel: 25202 total pagecache pages Nov 23 20:05:58 localhost kernel: 1523 pages in swap cache Nov 23 20:05:58 localhost kernel: Swap cache stats: add 238961, delete 237438, find 53952/75027 Nov 23 20:05:58 localhost kernel: Free swap = 1904848kB Nov 23 20:05:58 localhost kernel: Total swap = 2064376kB Nov 23 20:05:58 localhost kernel: 262128 pages RAM Nov 23 20:05:58 localhost kernel: 7828 pages reserved Nov 23 20:05:58 localhost kernel: 19543 pages shared Nov 23 20:05:58 localhost kernel: 211774 pages non-shared Nov 23 20:05:58 localhost kernel: Memory cgroup out of memory: kill process 5690 (a.out) score 59 or a child Nov 23 20:05:58 localhost kernel: Killed process 5690 (a.out) vsz:3832kB, anon-rss:16kB, file-rss:300kB
ちなみに /etc/cgconfig.conf
, /etc/cgrules.conf
を変更したときには、それぞれ # service cgconfig restart
, # service cgred restart
を行うと変更が反映される。