パラボラアンテナと星の日記

あることないこと

Dockerコンテナが消費するメモリの最大値を知りたいのだが

ECSで、この画面で悩むんですが、皆さんどうされてるんでしょうか。。

「Maximum Memory」にメモリの上限値を入力する。

docker runの-mオプションに相当する。

f:id:hoppie:20160628065828p:plain

memory.max_usage_in_bytesを見て調べるということでどうか。

以下はAmazon Linuxの例。

$ # 調べたいコンテナを起動(-dでデタッチ)、コンテナIDを取得する
$ CID=$(docker run -d alpine sleep 100)
$
$ # 取得したコンテナIDからmax_usage_in_bytes(使用したメモリの最大値)
$ cat /cgroup/memory/docker/$CID/memory.max_usage_in_bytes
6422528

手元のubuntuだと、「/cgroup/memory/docker」の部分は「/sys/fs/cgroup/memory/docker」でした。

ちなみに以下はcgroupで取れるmemory関連の値。抜粋。

3.7. memory

memory.max_usage_in_bytes

cgroup 内のプロセスによるメモリー最大使用量をレポートします (バイト単位)。

memory.usage_in_bytes

cgroup 内のプロセスによる現在のメモリー総使用量をレポートします (バイト単位)。

memory.limit_in_bytes

ユーザーメモリーの最大値 (ファイルキャッシュを含む) を設定します。単位が指定されていない場合、その値はバイト単位と解釈されますが、より大きな単位を示すサフィックスを使用することが可能です (キロバイトには k または K、メガバイトには m または M、ギガバイトには g または G)。 root cgroup を制限するのには、memory.limit_in_bytes は使用できません。値を適用できるのは、下位階層のグループに対してのみです。 memory.limit_in_bytes に -1 と書き込み、現行の制限値を削除します。

おまけ

Dockerコンテナ内からDockerコンテナが消費したメモリの最大値を知るにはどうすればよいかを考えてみました。

(良い方法は思いつきませんでした、、、、)

-vオプションで/cgroupをマウントする。。。という方法でどうでしょうか。

$ docker run -v /cgroup/memory/docker:/docker:ro ...

rubyコンテナを走らせ、マウントされた/dockerディレクトリを見てmemory.max_usage_in_bytesをチェックする例です。

$ docker run \
  -v /cgroup/memory/docker:/docker:ro \
  -it \
  ruby:2.3.1-alpine irb
# memory.max_usage_in_bytesを取得するヘルパ定義
irb(main):001:0> def memory_max_usage_in_bytes
irb(main):002:1>   File.read(Dir["/docker/#{ENV.fetch('HOSTNAME')}*/memory.max_usage_in_bytes"].first).to_i/1024.0/1024.0
irb(main):003:1> end
=> :memory_max_usage_in_bytes
irb(main):004:0> memory_max_usage_in_bytes
=> 11.27734375

# サイズが1万、String配列を作る
irb(main):007:0> (1..10_000).map(&:to_s); nil
=> nil
irb(main):008:0> memory_max_usage_in_bytes
=> 11.80859375

# サイズが10万、String配列を作る
irb(main):009:0> (1..100_000).map(&:to_s); nil #ai
=> nil
irb(main):010:0> memory_max_usage_in_bytes
=> 17.55859375

# サイズが100万、String配列を作る
irb(main):011:0> (1..1_000_000).map(&:to_s); nil #ai
=> nil
irb(main):012:0> memory_max_usage_in_bytes
=> 77.29296875

# サイズが300万、String配列を作る
irb(main):013:0> (1..3_000_000).map(&:to_s); nil #ai
=> nil
irb(main):014:0> memory_max_usage_in_bytes
=> 278.29296875

まわりくどいですが、これはこれで便利な気がします。