Help us understand the problem. What is going on with this article?

Dockerのリソースの制限(CPU/メモリ)とCPUの動きについてまとめ

More than 3 years have passed since last update.

Dockerリソースの制限について

環境情報

  • Red Hat Enterprise Linux 7.1
  • Docker 1.6.2.el7

リソース管理を実現する機能

cgroups


Linuxの標準機能cgroupsを使用して、リソース管理を実現しています。詳しくは以下のリンクなどをご覧ください。

CPU

--cpuset-cpus


CPUの割り当てを決定するオプションです

  • --cpuset-cpus 0  #CPUコア0を使用
  • --cpuset-cpus 0-2 #CPUコア0~2を使用
  • --cpuset-cpus 1,2 #CPUコア1と2を使用

/sys/fs/cgroup/cpuset/system.slice/docker-xxx.scope/cpuset.cpus に割り当てられたCPU情報が管理されています。

 

CPUの割当数
[root@master]# cat /sys/fs/cgroup/cpuset/system.slice/docker-xxx.scope/cpuset.cpus
0-1

 

CPUが故障した場合の動作を確認してみる


CPUを2ソケット搭載した仮想サーバを用意し、--cpuset-cpus 1で2つ目のCPUにアサイン。
ログインもcurlも可能。

[root@master ~]# docker run -d -p 80 --cpuset-cpus 1 apache-plugin:2.2.9

[root@master ~]# cat /sys/fs/cgroup/cpuset/system.slice/docker-xxx.scope/cpuset.cpus
1

[root@master ~]# docker exec -it xxx /bin/bash
root@xxx:/usr/local/apache2# exit

[root@master ~]# curl 0.0.0.0:32768
<HTML><HEAD><TITLE>Weblogic Bridge Message</TITLE></HEAD> <BODY><H2>Failure of Web Server bridge:</H2><P><hr><PRE>Invalid configuration details. Cannot continue.</PRE><P>
<hr> </BODY></HTML>

 

  • cpu1を停止
[root@master ~]# echo 0 > /sys/devices/system/cpu/cpu1/online

すると、cpuset.cpusの表示が消え、curlは帰ってくるのに、docker execは失敗する

[root@master ~]# cat /sys/fs/cgroup/cpuset/system.slice/docker-57a0bbf56f71a022c2b8a2b4bac5d381cb3115ea87fcae1cb8b2b3f2f1402e5e.scope/cpuset.cpus


[root@master ~]# docker exec -it xxx /bin/bash
Cannot run exec command xxx in container xxx: [8] System error: write /sys/fs/cgroup/cpuset/system.slice/docker-xxx.scope/cgroup.procs: no space left on device
                        Error starting exec command in container xxx: Cannot run exec command xxx in container xxx: [8] System error: write /sys/fs/cgroup/cpuset/system.slice/docker-xxx.scope/cgroup.procs: no space left on device

#なぜかcurlは成功する
[root@master ~]# curl 0.0.0.0:32768
<HTML><HEAD><TITLE>Weblogic Bridge Message</TITLE></HEAD> <BODY><H2>Failure of Web Server bridge:</H2><P><hr><PRE>Invalid configuration details. Cannot continue.</PRE><P>
<hr> </BODY></HTML>

 

  • どういうことか検証してみる

起動したdockerコンテナ上でyesを実行します。topで確認するとこんな感じ。Pが使用しているCPU番号です、1番になってますね。

PID  USER  PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+   COMMAND  P
7221 root  20   0    4220    348    272 R 100.0  0.0     6:18.70 yes      1

 

  • CPU1番を停止
[root@master ~]# echo 0 > /sys/devices/system/cpu/cpu1/online

 
なんと、Pが0になりました。つまり、yesプロセスはCPU0番で通信します。

PID  USER  PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+   COMMAND  P
7221 root  20   0    4220    348    272 R 100.0  0.0     6:18.70 yes      0

先ほどcurlが成功したのはこれが理由ですね。

Dockerのパラメータで指定しても、障害時にはCPUがスケールするようです。ただし、docker execdocker restartなどdocker経由のコマンドについては弾かれましたので注意が必要ですね。

 

復旧方法

#CPUをOnlineにします
[root@master ~]# echo 1 > /sys/devices/system/cpu/cpu1/online

#使用可能なCPUを指定します
[root@master ~]# echo 0-1 > /sys/fs/cgroup/cpuset/system.slice/cpuset.cpus

#コンテナに割り当てるCPUをセットします
[root@master ~]# echo 1 >  /sys/fs/cgroup/cpuset/system.slice/docker-xxx.scope/cpuset.cpus

万が一割り当てているCPUが故障した場合は、対象のファイルにechoするとそちらのCPUを参照するようになります。

[root@master ~]# echo [割り当てたいCPU番号] >  /sys/fs/cgroup/cpuset/system.slice/docker-xxx.scope/cpuset.cpus

-c,--cpu-shares


CPU使用の優先度を決定するオプションです(デフォルトは1024)

  • -c 2048 (通常の2倍の優先度)
  • --cpu-shares=0

デフォルトの設定では、どのコンテナも同一の設定(1024)が付与されているためCPU割り当ての優先度は同一です。

公式のmanでは以下のように記載されていました。

コンテナが3つあり、それぞれの優先度が1024,512,512と割り当てられていた場合には、CPUの割り当てが50%,25%,25%になります。ここに優先度1024のコンテナを追加すると、33%,16.5%,16.5%,33%となります。

なお、設定したCPUの優先度情報はsystemd(RHEL7の場合)にて管理されています。

CPUの優先度
[root@master system.slice]# systemctl show docker-ad712da4d702e4f8307def0f9b160a556565c2d8dea80ecc27160c19297d06ba.scope --property=CPUShares
CPUShares=1024

もしくは、こちらで確認。

CPUの優先度
[root@master]# cat /sys/fs/cgroup/cpuset/system.slice/docker-xxx.scope/cpuset.shares
2048

メモリ

-m,--memory


メモリ使用量を決定するオプションです(b,k,m,gが使用可能)

  • -m 128b
  • -m 128k
  • -m 128m
  • -m 128G
  • --memory="128g"

-m 128mとした場合に使用できるメモリサイズは128M。このときのSwapのサイズも同じく128Mとなる。

これらの合計256Mを使い切るとLinux機能である「OOM Killer」によってコンテナ内のプロセスが強制停止させられる。

なお、設定したメモリ情報はsystemd(RHEL7の場合)にて管理されています。

メモリの使用量上限
[root@master system.slice]# systemctl show docker-ad712da4d702e4f8307def0f9b160a556565c2d8dea80ecc27160c19297d06ba.scope --property=MemoryLimit
MemoryLimit=18446744073709551615

もしくは、こちらで確認。

メモリの使用量上限
[root@master]# cat /sys/fs/cgroup/memory/system.slice/docker-xxx.scope/memory.limit_in_bytes
9223372036854775807
メモリ+Swapの使用量上限
[root@master]# cat /sys/fs/cgroup/memory/system.slice/docker-xxx.scope/memory.memsw.limit_in_bytes
9223372036854775807

--memory-swap


メモリ+Swapサイズを決定するオプションです(b,k,m,gが使用可能)

  • --memory-swap="128b"
  • --memory-swap="128k"
  • --memory-swap="128m"
  • --memory-swap="128g"
  • --memory-swap="-1"

-1を設定するとSwapを無効にすることが出来ます。このオプションは-mで指定した値よりも大きくなるため(Swapを使用する場合)、-mと組み合わせて使用しましょう。

(追記)
-1を設定するとswapを無制限で使用できるようになります。

※古いバージョンのマニュアルやmanにはswapの制限無効化とありますが、ドキュメントの誤りだったようです。
https://github.com/docker/docker/issues/18894

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした