既に類似記事がありましたが、確認のためにメモ。
もし、間違っている部分などあればご指摘ください。
検証環境
$docker info
Containers: 5
Running: 5
Paused: 0
Stopped: 0
Images: 13
Server Version: 17.12.1-ce
Storage Driver: devicemapper
Pool Name: docker-docker--pool
Pool Blocksize: 524.3kB
Base Device Size: 10.74GB
Backing Filesystem: ext4
Udev Sync Supported: true
Data Space Used: 2.259GB
Data Space Total: 23.33GB
Data Space Available: 21.07GB
Metadata Space Used: 1.507MB
Metadata Space Total: 25.17MB
Metadata Space Available: 23.66MB
Thin Pool Minimum Free Space: 2.333GB
Deferred Removal Enabled: true
Deferred Deletion Enabled: true
Deferred Deleted Device Count: 0
Library Version: 1.02.135-RHEL7 (2016-11-16)
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 9b55aab90508bd389d7654c4baf173a981477d55
runc version: 9f9c96235cc97674e935002fc3d78361b696a69e
init version: 949e6fa
Security Options:
seccomp
Profile: default
Kernel Version: 4.9.85-38.58.amzn1.x86_64
Operating System: Amazon Linux AMI 2017.09
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 3.86GiB
Name: ip-172-31-16-119
ID: 7BRW:LUN6:5ZPM:CNL7:YVW3:MV6V:MGJ7:WY6X:CCVF:7PIT:F73P:LHEH
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
--memory オプションの概要について
以下に記載のように --memory
オプションによってコンテナのメモリのハードリミットを設定できます。
また、こちらは cgroup を利用しており、 memory.limit_in_bytes として確認が出来る点が記載されております。
Specify hard limits on memory available to containers (-m, --memory)
These parameters always set an upper limit on the memory available to the container. On Linux, this is set on the cgroup and applications in a container can query it at /sys/fs/cgroup/memory/memory.limit_in_bytes
実際に検証環境でも上記動作となっている事が確認出来ました。
# 20M をハードリミットとして指定
$docker run -d -m "20M" --name wp20m wordpress
822a4003bb46009215c0013a7031b81b8af491c76eff65b303f00161d78e3a45
# 対象コンテナの memory.limit_in_bytes を確認
$cat /cgroup/memory/docker/822a4003bb46009215c0013a7031b81b8af491c76eff65b303f00161d78e3a45/memory.limit_in_bytes
20971520
# docker inspect コマンドでも設定値は確認できる
$ docker inspect --format='{{.HostConfig.Memory}}' wp20m
20971520
--memory に指定した値を超過した場合どうなるのか
docker run
には --oom-kill-disable
オプションがあります。
こちらの説明に書いてあるようにデフォルトでは out-of-memory の場合には OOM が発生してカーネルがコンテナ内のプロセスを kill する旨が書いてあります。
--oom-kill-disable By default, if an out-of-memory (OOM) error occurs, the kernel kills processes in a container. To change this behavior, use the --oom-kill-disable option. Only disable the OOM killer on containers where you have also set the -m/--memory option. If the -m flag is not set, the host can run out of memory and the kernel may need to kill the host system’s processes to free memory.
上記より、デフォルトでは OOM が発生し、コンテナが停止となると考えられますが、試しにやってみます。
# メモリは 10M を指定
$docker run -d -m "10m" --name wp10m wordpress
b5f60e8379207df79fa9fbe3ea09ec003380192d40c7fc79227b142b830bd570
# --oom-kill-disable オプションを指定しない場合、デフォルトで disable が false な事を確認
$docker inspect --format='{{.HostConfig.OomKillDisable}}' wp10m
false
# 起動している
$docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5f60e837920 wordpress "docker-entrypoint.s…" About a minute ago Up About a minute 80/tcp wp10m
# 10分ほど経過後終了ステータスコード 137 によって終了
$docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5f60e837920 wordpress "docker-entrypoint.s…" 5 minutes ago Exited (137) About a minute ago wp10m
# docker inspect 一部抜粋。OOMkilled されたのが分かる
$docker inspect wp10m
"State": {
"Status": "exited",
"Running": false,
"Paused": false,
"Restarting": false,
"OOMKilled": true,
"Dead": false,
"Pid": 0,
"ExitCode": 137,
"Error": "",
"StartedAt": "2018-05-26T21:26:23.199697785Z",
"FinishedAt": "2018-05-26T21:30:20.351086551Z"
},
# /var/log/messages からも OOM によって kill されたことが分かる。コンテナIDも記載されているので特定も出来そう
$cat /var/log/messages |grep -i kill
May 26 21:30:20 ip-172-31-16-119 kernel: [247319.777361] [<ffffffff81187f5b>] oom_kill_process+0x20b/0x3e0
May 26 21:30:20 ip-172-31-16-119 kernel: [247319.853629] Task in /docker/b5f60e8379207df79fa9fbe3ea09ec003380192d40c7fc79227b142b830bd570 killed as a result of limit of /docker/b5f60e8379207df79fa9fbe3ea09ec003380192d40c7fc79227b142b830bd570
May 26 21:30:20 ip-172-31-16-119 kernel: [247319.909426] Memory cgroup out of memory: Kill process 19299 (apache2) score 831 or sacrifice child
May 26 21:30:20 ip-172-31-16-119 kernel: [247319.914894] Killed process 19299 (apache2) total-vm:389804kB, anon-rss:7656kB, file-rss:0kB, shmem-rss:376kB
終了スタータスコードが137で終了する点についてはいくつかの Github issue に記載がありました。
後者のGtihub issueのコメントにあるようにこの終了コードはコンテナのプロセスが返したコードと考えると分かりやすい気がします。
流れとしては以下と考えています。
- OOM がシグナルSIGKILL(9)を対象のコンテナ内のプロセスに送信
- 上記シグナルを受けてコンテナのプロセスが終了。SIGKILL(9)のため、128+9で137 を返却。参考記事。Appendix E. Exit Codes With Special Meanings
cgroup の memory.limit_in_bytes
を超過した場合に OOM が終了させるテストについては Redhat のページにも記載がありました。
5.ステップ 2 で設定した上限を超える大容量のメモリーを割り当てようとするテストプログラムを起動します。blue cgroup の空きメモリーがなくなるとすぐに OOM Killer がテストプログラムを強制終了し、標準出力に Killed をレポートします。