ぐるっとぐりっど

日曜プログラマがいろいろ試してみたことを、後の自分のためにまとめておく場所

Dockerのコンテナから見えるメモリ使用量の不思議

概要

CentOSもしばらく前に7が出て、Dockerが使えるようになった(正確には、6.5からDockerを正式サポートしてるはずだけど)。
コンテナとかその辺これまで使ったことなかったので、仮想化に慣れた身からは、コンテナからのメモリの見え方が奇妙に思えたのでメモ。

メモリを制限する

Dockerは、runするときに、-mオプションをつけると、メモリを制限することができる

# docker run -m 512m -i -t centos:centos7 /bin/bash

でもこの状態で、freeコマンドを実行してみると、1GB割り当てられてるように見える。

bash-4.2# free
             total       used       free     shared    buffers     cached
Mem:       1010864     204616     806248       8744         64      49248
-/+ buffers/cache:     155304     855560
Swap:      2097148      92700    2004448


どうやら、実行時にメモリを制限しても、コンテナから見えるメモリはホストと同一らしい。ホストでのfreeコマンドの実行結果も一緒だ。

  • ホストで実行した場合
[root@komachi ~]# free
             total       used       free     shared    buffers     cached
Mem:       1010864     204616     806248       8744         64      49248
-/+ buffers/cache:     155304     855560
Swap:      2097148      92700    2004448

制限してるはずなのに、違いが見れないのは仮想化に慣れてる身からは奇妙に思える。dockerは仮想化じゃないけどね。そこで、次のコマンドをコンテナとホストで実行して挙動の違いを見てみた。このコマンドを実行すると、bashのメモリ使用量がどんどん上がっていく(OOM Killerに殺されるまで)。

/dev/null < `yes` &

コンテナ上で実行した場合

topコマンドで、プロセスごとのメモリ使用率を見ていくと、/bin/bashプロセスのメモリ使用率がどんどん上昇していくが、50%程度しか上昇しない様子が見れた。ホストの物理メモリが1GBなのに対し、コンテナには512MB割り当ててるので、50%しか使わないことは想定どおりの動作だ。
50%まで伸びた後はその後はどんどんSwap outの量が増えていく様子が見え、あくまでも制限しているのは物理メモリであることがわかる。

top - 06:10:13 up 1 day,  7:18,  2 users,  load average: 0.31, 0.12, 0.09
Tasks: 234 total,   3 running, 231 sleeping,   0 stopped,   0 zombie
%Cpu(s): 40.2 us, 59.8 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:   1010864 total,   728828 used,   282036 free,       64 buffers
KiB Swap:  2097148 total,   101904 used,  1995244 free.    47272 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
15163 root      20   0    4316     24      0 D 54.1  0.0   0:05.23 yes
15162 root      20   0  535292 514696     20 R 45.2 50.9   0:04.36 bash

ちなみに、複数実行してみると、合計で50%超えないように制限されていることも確認でき、コンテナレベルで50%に制限してることもわかった。

ホストで実行した場合

コンテナで実行した場合と異なり、/bin/bashのメモリ使用率が際限なく上昇していく。ホストとコンテナとで結果が違うので、コンテナで50%しか上昇しないのは、コンテナのメモリを512MBと制限したおかげであると判断できる。

top - 06:24:15 up 1 day,  7:32,  2 users,  load average: 0.46, 0.23, 0.16
Tasks: 236 total,   3 running, 233 sleeping,   0 stopped,   0 zombie
%Cpu(s): 61.1 us, 38.3 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.6 si,  0.0 st
KiB Mem:   1010864 total,   948604 used,    62260 free,       48 buffers
KiB Swap:  2097148 total,   198756 used,  1898392 free.     2288 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
15220 root      20   0  107896     16      0 R 53.7  0.0   0:08.74 yes
15219 root      20   0  981644 764460     28 S 44.7 75.6   0:07.41 bash

まとめ

リソースを制限したコンテナからもホストの資源が同じように見える。ただし、実行時には制限したリソース以上には使用することができない。

備考

よくよくドキュメント読んだら、ばっちりphysical RAMって書いてあった。仮想化みたいに、そもそも割り当てられてるメモリの量が違って見えると思い込んでいたので完全にスルーしてた。

Run Reference - Docker Documentation