某所で話題になってたので。3.17.1 kernel で試してます (Plamo Linux 5.2)
docker でも何でもなくて単に Linux kernel の cgroup がちゃんと動いてるかって話なんですが。:-)
(2014-10-29 追記) なんか docker ってキーワード入ってるからかわかりませんが、多数アクセスいただいていますね。CFS Throttle の機能自体はもう 3 年近く前に試してちゃんと動いていたテストそのままです。dockerを使って試してるか、直接 cgroup と普通のプロセスで試してるかの違い。gihyo.jp での連載でもそのまま載ってます :-)
- Linux 3.2 の CFS bandwidth control (2) - TenForwardの日記
- 第4回 Linuxカーネルのコンテナ機能[3] ─cgroupとは?(その2):LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術|gihyo.jp … 技術評論社
cpu.shares
Linux cgroup の cpu サブシステムで cgroup 内のタスクが使用できる CPU 時間の相対比率が指定できます。これをそのまま使う形で "docker run" コマンドに "-c/--cpu-shares" というオプションがあります。cpu.shares にはデフォルトでは 1024 が入っています。
実験したのですが、なぜか CPU 使いまくるコンテナを 2 つ起動すると cpuset を使ってコア指定していても別のコアに逃げてしまうので (Why?? 後述のようにコンテナ起動しても、別のコアを使ってCPU 100%いきます)、とりあえずコア 1 個だけにして実験しました。(何か見落としてる?? 誰か教えて)
# echo 0 > /sys/devices/system/cpu/cpu0/online # echo 0 > /sys/devices/system/cpu/cpu1/online # echo 0 > /sys/devices/system/cpu/cpu3/online
コンテナを 2 つ起動します。1024:100 としています。(2 以外の CPU は無効にしてるので --cpuset=2 の指定は意味ないですが)
$ docker run -d --cpu-shares=1024 --cpuset=2 -d ubuntu sh -c "while :; do true; done" 896d40f8c9996ccf44f80431ef1f23cfde8479c5852437126338ef75abfd104f $ docker run -d --cpu-shares=100 --cpuset=2 -d ubuntu sh -c "while :; do true; done" e6f843b52a607eb66dbe3c65236327ce98c7149cfd3e73284394d98141b06193
top コマンドで見ると、まあ大体そんな感じの比率になってますね。
top - 17:01:51 up 23 min, 5 users, load average: 1.80, 1.40, 1.08 Tasks: 252 total, 9 running, 243 sleeping, 0 stopped, 0 zombie %Cpu2 : 99.7 us, 0.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 7975984 total, 1601860 used, 6374124 free, 91860 buffers KiB Swap: 7823648 total, 0 used, 7823648 free, 626368 cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 5953 root 20 0 4452 692 608 R 89.80 0.009 0:46.53 sh 5980 root 20 0 4452 840 756 R 8.980 0.011 0:03.98 sh
CFS throttling
3.2 カーネルからサポートされている、単位時間あたりの CPU 割り当て時間を指定できます。これは docker run コマンドからは直接は指定できないので、cgroupfs のファイルに直接書き込む必要があります。
- まずは 2 つコンテナを起動します。CPU を無駄に消費するようにします。
$ docker run -d ubuntu sh -c "while :; do true; done"
6c6e705f632b7030e9ab2b3414cc3ec7e9654a74d4deaadc42e3777ae22413b1
$ docker run -d ubuntu sh -c "while :; do true; done"
0add197884a6aee7132ce6647982bfa019b4cf6b85017a10173180a50547293a- top コマンドで確認します。それぞれ 100% 使っています。
top - 15:16:59 up 1:19, 7 users, load average: 1.17, 0.84, 0.67
Tasks: 254 total, 3 running, 251 sleeping, 0 stopped, 0 zombie
%Cpu(s): 52.4 us, 0.2 sy, 0.0 ni, 47.1 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 7975980 total, 3295148 used, 4680832 free, 370868 buffers
KiB Swap: 7823648 total, 0 used, 7823648 free, 1047416 cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
10064 root 20 0 4452 688 604 R 99.99 0.009 0:34.85 sh
10089 root 20 0 4452 768 688 R 99.99 0.010 0:33.61 sh
- top コマンドで確認します。それぞれ 100% 使っています。
- CFS throttling の単位時間は 100ms です。それぞれのコンテナに 10ms、5ms を割り当てます。
$ cat /sys/fs/cgroup/cpu/docker/cpu.cfs_period_us (単位時間を確認)
100000
$ echo 10000 | sudo tee /sys/fs/cgroup/cpu/docker/0add197884a6aee7132ce6647982bfa019b4cf6b85017a10173180a50547293a/cpu.cfs_quota_us (10msを設定)
10000
$ echo 5000 | sudo tee /sys/fs/cgroup/cpu/docker/6c6e705f632b7030e9ab2b3414cc3ec7e9654a74d4deaadc42e3777ae22413b1/cpu.cfs_quota_us (5msを設定)
5000- top コマンドで確認します。それぞれ大体 10% と 5% になってます。
top - 15:23:03 up 1:25, 7 users, load average: 1.51, 1.63, 1.12
Tasks: 252 total, 3 running, 249 sleeping, 0 stopped, 0 zombie
%Cpu(s): 8.1 us, 1.1 sy, 0.0 ni, 90.7 id, 0.0 wa, 0.0 hi, 0.1 si, 0.0 st
KiB Mem: 7975980 total, 3344872 used, 4631108 free, 372016 buffers
KiB Swap: 7823648 total, 0 used, 7823648 free, 1054536 cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4705 karma 20 0 1852500 733552 111680 S 16.62 9.197 14:06.92 firefox
10089 root 20 0 4452 768 688 R 9.974 0.010 5:11.81 sh
10064 root 20 0 4452 688 604 R 4.987 0.009 6:10.79 sh
- top コマンドで確認します。それぞれ大体 10% と 5% になってます。