あくまで一例です。
開発環境とかで一時的に使うのでなく、サービスとして永続的に使う場合は、ホストのリソースを食い尽くさないように制限をかけると良い。
※ ログサイズについてはこちら
CPU
制限無し
[zaki@cloud-dev ~]$ docker run --rm -it centos:7 bash [root@fb3e8ba23a4d /]#
top - 20:00:32 up 6 days, 11:09, 4 users, load average: 0.02, 0.05, 0.05 Tasks: 334 total, 1 running, 333 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 7990068 total, 334524 free, 4077584 used, 3577960 buff/cache KiB Swap: 3670012 total, 3663100 free, 6912 used. 3565080 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 32689 zaki 20 0 162256 2480 1576 R 0.7 0.0 0:00.08 top 1 root 20 0 193880 6468 3812 S 0.0 0.1 0:05.94 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.05 kthreadd 4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H 6 root 20 0 0 0 0 S 0.0 0.0 0:10.00 ksoftirqd/0
こんな感じ。
ここで負荷試験ツールである(負荷試験ツールでは無い)yes
を実行する。(/dev/null
に捨てるのを忘れずに)
[root@fb3e8ba23a4d /]# yes > /dev/null
top
はこんな感じ。(CPUは1
押下してコア毎の表示)
top - 20:08:41 up 6 days, 11:17, 4 users, load average: 0.08, 0.09, 0.07 Tasks: 336 total, 2 running, 334 sleeping, 0 stopped, 0 zombie %Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 0.3 us, 0.0 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 98.7 us, 1.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 7990068 total, 232872 free, 4103872 used, 3653324 buff/cache KiB Swap: 3670012 total, 3663100 free, 6912 used. 3538792 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 33045 root 20 0 4368 356 280 R 100.0 0.0 0:06.16 yes 32689 zaki 20 0 162256 2480 1576 R 0.3 0.0 0:01.10 top 1 root 20 0 193880 6468 3812 S 0.0 0.1 0:05.98 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.05 kthreadd 4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H 6 root 20 0 0 0 0 S 0.0 0.0 0:10.01 ksoftirqd/0 7 root rt 0 0 0 0 S 0.0 0.0 0:00.49 migration/0 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh 9 root 20 0 0 0 0 S 0.0 0.0 1:01.89 rcu_sched
この通り、100%使い切っている。
制限あり
docker run
のオプションの--cpu
を使用する。
--cpus decimal Number of CPUs
例として30%制限で実行してみる。
追加するオプションは--cpus 0.3
docker run --cpus 0.3 --rm -it centos:7 bash
[zaki@cloud-dev ~]$ docker run --cpus 0.3 --rm -it centos:7 bash [root@9d2afc703344 /]#
これで同じように負荷試験ツール(負荷試験ツールではない)を実行する。
[root@9d2afc703344 /]# yes > /dev/null
top - 20:12:57 up 6 days, 11:21, 4 users, load average: 0.01, 0.07, 0.07 Tasks: 334 total, 2 running, 332 sleeping, 0 stopped, 0 zombie %Cpu0 : 29.8 us, 0.7 sy, 0.0 ni, 69.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 7990068 total, 233236 free, 4103396 used, 3653436 buff/cache KiB Swap: 3670012 total, 3663100 free, 6912 used. 3539264 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 33182 root 20 0 4368 352 280 R 29.9 0.0 0:03.66 yes 1054 root 20 0 902308 46228 13440 S 0.3 0.6 8:48.25 containerd 22511 zaki 20 0 1248016 72048 16856 S 0.3 0.9 2:45.80 node 33054 zaki 20 0 162256 2476 1576 R 0.3 0.0 0:00.20 top 1 root 20 0 193880 6500 3844 S 0.0 0.1 0:05.99 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.05 kthreadd 4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
この通り、CPU使用率30%に制限できました。
メモリ
制限無し
[root@4f061ab0d609 /]# /dev/null < $(yes)
top - 20:32:15 up 6 days, 11:41, 5 users, load average: 0.54, 0.20, 0.10 Tasks: 341 total, 3 running, 338 sleeping, 0 stopped, 0 zombie %Cpu(s): 27.1 us, 14.5 sy, 0.0 ni, 58.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 7990068 total, 135848 free, 6148588 used, 1705632 buff/cache KiB Swap: 3670012 total, 3650556 free, 19456 used. 1494248 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 33771 root 20 0 2091740 2.0g 472 R 97.0 26.0 0:17.83 bash 33772 root 20 0 4368 352 280 R 69.1 0.0 0:12.94 yes 45 root 20 0 0 0 0 S 0.7 0.0 0:03.09 kswapd0 33416 zaki 20 0 162256 2472 1576 R 0.3 0.0 0:00.55 top 1 root 20 0 193880 6168 3512 S 0.0 0.1 0:06.07 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.05 kthreadd 4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
root 33715 0.0 0.0 107560 3240 ? Sl 20:31 0:00 \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/4f061ab0d60936997b8f90fd2155e3ca4843036f557ef6efb60967e2350a8268 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup root 33733 0.1 0.0 11828 1904 pts/0 Ss 20:31 0:00 \_ bash root 33771 98.1 17.4 1403428 1392432 pts/0 R+ 20:31 0:11 \_ bash root 33772 71.2 0.0 4368 352 pts/0 R 20:31 0:08 \_ yes
[root@4f061ab0d609 /]# /dev/null < $(yes) bash: xrealloc: cannot allocate 18446744071562067968 bytes (331776 bytes allocated) [root@4f061ab0d609 /]#
2GBの時点でメモリアロケートに失敗して停止した。(コンテナではなくyes
を実行しているプロセスが)
この制限は未調査。
ulimit
で見える範囲ではとくに制限はないんだけど。
[zaki@cloud-dev ~]$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 31118 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 4096 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
追記: 2GB仕様について
2GB制限はおそらく確認に使用した/dev/null < $(yes)
で使用されるbashの制限か仕様。
Cで「mallo(3)
をforループでぶん回す」プログラムを書いてコンテナで動かすと、特に制限なく動作した。
なんか bash のメモリリークっぽいのではという記事を見つけたんですが、まだよくわかってないです。cannot allocate 18446744071562067968 bytes の数字がちょっと大きすぎます。
— すぎむら (@sugitk) 2020年9月8日
centos:8 のイメージでも同様でした。
たしかにすごく切りのいい数値ですね💦
— z a k i 🌈 (@zaki_hmkc) 2020年9月8日
ちなみにループでmalloc()するだけのCで書いたa.outを作ってコンテナに入れて動かすと、こちらは2GBの制限は受けなかったので、カーネルとかではなくてbashの制限or仕様なのは間違いなさそうです pic.twitter.com/Yk4yohHfux
制限あり
--memory
で制限を設定できる。
-m, --memory bytes Memory limit
例として512MBで制限を掛けてみる。
[zaki@cloud-dev ~]$ docker run -m 512m --rm -it centos:7 bash [root@e9787badb7c0 /]#
[zaki@cloud-dev ~]$ top top - 20:38:04 up 6 days, 11:46, 5 users, load average: 0.61, 0.28, 0.15 Tasks: 339 total, 2 running, 337 sleeping, 0 stopped, 0 zombie %Cpu(s): 25.2 us, 15.6 sy, 0.0 ni, 58.4 id, 0.0 wa, 0.0 hi, 0.8 si, 0.0 st KiB Mem : 7990068 total, 1693808 free, 4591392 used, 1704868 buff/cache KiB Swap: 3670012 total, 3197180 free, 472832 used. 3050796 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 34133 root 20 0 985940 521512 472 R 98.3 6.5 0:08.44 bash 34134 root 20 0 4368 280 280 S 64.8 0.0 0:05.75 yes 34042 zaki 20 0 162256 2484 1576 R 0.3 0.0 0:00.09 top 57182 root 20 0 0 0 0 S 0.3 0.0 0:39.54 kworker/0:1 1 root 20 0 193880 6172 3516 S 0.0 0.1 0:06.11 systemd
この辺までは負荷がかかるが、RESの数値の通り512MBあたりで頭打ち。
そのまま停止する。
[root@18fd18524341 /]# /dev/null < $(yes) Killed
お、出力が違う。。
出力メッセージの違いはbash周りの内部処理に依存していて詳細は未確認だが、設定している512MB程度以上のリソースを使用することはできないようになる。
(制限を超えたメモリをallocateしようとしてエラーになったらクラッシュするようになっているのだろう)
その他のオプション
--oom-kill-disable
でOOMを無効にしたり、--memory-swap
でswap込みのメモリ量を設定もできる模様。
詳しくはドキュメント参照。
参考
環境
[zaki@cloud-dev ~]$ docker version Client: Docker Engine - Community Version: 19.03.12 API version: 1.40 Go version: go1.13.10 Git commit: 48a66213fe Built: Mon Jun 22 15:46:54 2020 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.12 API version: 1.40 (minimum version 1.12) Go version: go1.13.10 Git commit: 48a66213fe Built: Mon Jun 22 15:45:28 2020 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.2.13 GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429 runc: Version: 1.0.0-rc10 GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd docker-init: Version: 0.18.0 GitCommit: fec3683 [zaki@cloud-dev ~]$ uname -r 3.10.0-1127.18.2.el7.x86_64 [zaki@cloud-dev ~]$ cat /etc/redhat-release CentOS Linux release 7.8.2003 (Core)
制限という意味では、あとログファイルサイズも制限しておかないと、あふれる。(訳:あふれた)
追記: docker statsを使ったコンテナ毎のリソース使用状況
コンテナ毎のリソース使用状況はdocker stats
でも見れる。(知らなかった!)
外側から
— すぎむら (@sugitk) 2020年9月8日
docker stats
してみるとどう見えるでしょう
top
より断然見やすいです(笑)
追記: inspectで確認
docker inspect
で制限をかけているコンテナを確認すると、HostConfig
以下のMemory
とNanoCpus
に指定した数値が設定される。
docker run --cpus 0.3 -m 512m --rm -it centos:7 bash
した場合は以下の通り。
"HostConfig": { [...] "Memory": 536870912, "NanoCpus": 300000000,
制限を行っていない場合は、どちらも0
になる。