Docker默認沒有對容器進行硬件資源的限制,當容器負載太高時會盡量佔用宿主機資源。Docker基於Linux內核提供的cgroups功能,能夠限制容器在運行時使用的資源,好比內存、CPU、IO、網絡等。
在Linux系統上,若是Linux內核探測到當前宿主機已經沒有可用內存使用,會拋出一個OOME(Out Of Memory Exception:內存異常 ),而且會開啓killing去殺掉一些進程。
一旦發生OOME,任何進程都有可能被殺死,包括Docker daemon,所以,Docker特意調整了Docker daemon的OOM_Odj優先級,以避免被殺掉,但容器的優先級並未被調整。
通過Linux系統內部複雜計算後,每一個系統進程都會有一個OOM_Score得分,OOM_Odj越高,得分越高,得分最高的進程優先被kill掉。
Docker在啓動容器時能夠調整OOM_Odj,也能夠指定重要容器禁止被OMM殺掉,在啓動容器時使用–oom-kill-disable=true指定。docker
Control Groups是Linux內核提供的一種能夠限制、記錄、隔離進程組所使用物理資源(如CPU、Memory、磁盤IO等等) 的機制,被LXC、Docker等項目用於實現進程資源控制。cgroup是提供將進程進行分組化管理的功能和接口的基礎結構,用於實現IO或內存配控制等具體的資源管理功能。cgroup實現的資源管理功能稱爲cgroup子系統,以下:
(1)blkio,設置限制每一個塊設備的輸入輸出控制,如磁盤、光盤、USB等。
(2)cpu,使用調度程序爲cgroup任務提供CPU訪問。
(3)cpuacct,產生cgroup任務的CPU資源報告。
(4)cpuset,對於多核心CPU,會爲cgroup任務分配單獨CPU和內存。
(5)devices,容許或拒絕cgroup任務對設備的訪問。
(6)freezer,暫停和恢復cgroup任務。
(7)memory,設置每一個cgroup的內存限制以及產生內存資源報告。
(8)net_cls,標記每一個網絡包以供cgroup方便使用。
(9)ns,命名空間子系統。
(10)perf_event,增長對每一個group的監測跟蹤的能力,便可以監測屬於某個特定的group的全部線程以及運行在特定CPU上的線程。ubuntu
Docker提供的內存限制功能以下:
(1)容器能使用的內存和交換分區大小。
(2)容器的核心內存大小。
(3)容器虛擬內存的交換行爲。
(4)容器內存的軟性限制。
(5)是否殺死佔用過多內存的容器。
(6)容器被殺死的優先級。bash
(1)memory
-m,--memory,內存限制,格式爲數字加單位,單位能夠爲b,k,m,g,最小爲4M。
--memory-swap,內存+交換分區大小總限制,必須比memory設置的大。
若是不設置memory和memory-swap,Docker容器默承認以用完宿主機的全部內存和swap分區。Docker容器用盡宿主機的全部內存和swap分區超過一段時間後,會被宿主機系統殺死。
若是memory設置一個不小於4M的值n,不設置memory-swap或將memory-swap設置爲 0,則Docker容器能使用的內存大小爲 n,能使用的交換分區大小也爲 n,Docker默認容器交換分區的大小和內存相同;若是在Docker容器中運行一個一直不停申請內存的程序,Docker容器最終能佔用的內存大小爲2n;若是memory設置爲a,memory-swap設置爲b,則Docker容器能使用的內存大小爲a,Docker容器能使用的swap分區大小爲b-a;若是memory設置a,memory-swap設置爲-1,則Docker容器能使用的內存大小爲a,不限制Docker容器使用swap分區大小。
--memory-reservation,內存的軟性限制。
Memory reservation 是一種軟性機制,不保證任什麼時候刻容器使用的內存不會超過memory-reservation限定值,只確保容器不會長時間佔用超過memory-reservation限制的內存大小。雖然Docker容器最多可使用memory的內存大小,但在宿主機內存資源緊張時,在系統的下次內存回收時,系統會回收容器的部份內存頁,強迫容器的內存佔用回到memory-reservation的大小。
默認狀況下,未設置memory-reservation值,其值與memory限定值相同。若是memory-reservation設置爲0,則等同於沒有設置。
(2)OOM killer
--oom-kill-disable,是否阻止OOM killer殺死容器,默認未設置。
默認狀況下,在出現out-of-memory(OOM)錯誤時,OOM killer進程會殺死Docker容器內的進程來釋放內存。經過設置--oom-kill-disable選項來禁止OOM killer殺死容器內進程。確保只有在使用memory選項時才使用oom-kill-disable選項禁用OOM killer。若是沒有設置memory選項,但禁用OOM-killer,可能會形成出現OOM錯誤時,經過殺死宿主機進程獲取更多內存。
--oom-score-adj,容器被OOM killer殺死的優先級,範圍是[-1000, 1000],默認爲0,值越大越容易被kill。
--memory-swappiness,用於設置容器的虛擬內存控制行爲。值爲0~100之間的整數。
(3)kernel memory
--kernel-memory,核心內存限制,最小爲4M。
核心內存和用戶內存不一樣的地方在於核心內存不能被交換出,所以Docker容器能夠經過消耗太多內存來堵塞一些系統服務。核心內存包括:stack pages(棧頁面)、slab pages、socket memory pressure、tcp memory pressure。
能夠經過設置核心內存限制來約束核心內存。例如,每一個進程都要消耗一些棧頁面,經過限制核心內存,能夠在覈心內存使用過多時阻止新進程被建立。
核心內存和用戶內存並非獨立的,必須在用戶內存限制的上下文中限制核心內存。
假設用戶內存的限制值爲U,核心內存的限制值爲K。有三種可能地限制核心內存的方式:
U != 0,不限制核心內存,是默認的標準設置方式
K < U,核心內存是用戶內存的子集,每一個cgroup的內存總量被過分使用,能夠設置K,groups總數就不會超過總內存。
K > U,核心內存的變化也會致使用戶計數器的變化,容器核心內存和用戶內存都會觸發回收行爲。
docker run -it -m 500M --kernel-memory 50M ubuntu:16.04 /bin/bash
啓動容器,Docker容器的進程最多能使用500M內存、50M核心內存。
docker run -it --kernel-memory 50M ubuntu:16.04 /bin/bash
沒用設置用戶內存限制,Docker容器中的進程可使用盡量多的內存,但最多能使用50M核心內存。
(4)Swappiness
默認狀況下,Docker容器的內核能夠交換出必定比例的匿名頁,使用memory-swappiness參數進行設置。--memory-swappiness能夠設置爲從 0到100。0表示關閉匿名頁面交換。100表示全部的匿名頁均可以交換。默認狀況下,若是設置--memory-swappiness,則從父進程繼承而來。
docker run -it --memory-swappiness=0 ubuntu:16.04 /bin/bash
memory-swappiness設置爲0能夠保持容器的工做集,避免交換代理的性能損失。網絡
默認狀況,全部Docker容器能夠平等地使用宿主機CPU資源而且沒有限制。
Docker提供的CPU資源限制選項能夠在多核系統上限制容器能利用哪些 CPU。而Docker容器最多能使用CPU時間有兩種限制方式:一是有多個CPU 密集型的容器競爭CPU時,設置各個容器能使用CPU時間相對比例;二是以絕對的方式設置容器在每一個調度週期內最多能使用的CPU時間。
Docker能夠經過-c或--cpu-shares設置容器使用CPU的權重。若是不指定,默認值爲1024。app
docker run與CPU限制相關選項以下:
--cpuset-cpus="" 容許使用的CPU集,值能夠爲0-3,0,1
-c,--cpu-shares=0 CPU權重
--cpu-period=0 限制CPU CFS週期,範圍從100ms~1s,即[1000, 1000000]
--cpu-quota=0 限制CPU CFS配額,必須不小於1ms,即大於等於1000
--cpuset-mems="" 容許在上執行的內存節點(MEMs),只對NUMA系統有效
--cpus=value 指定容器可使用的CPU資源量。若是主機有兩個CPU而且設置 --cpus="1.5",則容器最多可使用1.5個CPU,
--cap-add=sys_nice 開啓Docker容器CAP_SYS_NICE功能,容許容器引起進程良好值,設置實時調度策略,設置CPU親和性以及其餘操做。
--cpu-rt-runtime=value 容器能夠在Docker守護程序的實時調度程序週期內以實時優先級運行的最大微秒數,須要開啓CAP_SYS_NICE功能 。
--ulimit rtprio=value 容器容許的最大實時優先級,須要開啓CAP_SYS_NICE功能。docker run --it --cpu-rt-runtime=950000 --ulimit rtprio=99 --cap-add=sys_nice ubuntu
實時調度程序運行容器,須要運行docker daemon,並將--cpu-rt-runtime設置爲每一個運行時間段爲實時任務保留的最大微秒數。默認週期爲1000000微秒(1秒),設置--cpu-rt-runtime=950000可確保使用實時調度程序的容器每1000000微秒可運行950000微秒,並保留至少50000微秒用於非實時任務。
其中--cpuset-cpus用於設置容器可使用的 CPU核。
-c,--cpu-shares用於設置多個容器競爭CPU時,各個容器能分配到的CPU權重。
--cpu-period和--cpu-quata用於絕對設置容器能使用 CPU 時間。docker run -it --cpuset-cpus="1,3" ubuntu:14.04 /bin/bash
容器中的進程能夠在cpu 1和cpu 3上執行。docker run -it --cpuset-cpus="0-2" ubuntu:14.04 /bin/bash
容器中的進程能夠在 cpu 0、cpu 1 及 cpu 2上執行。docker run -it --cpuset-mems="1,3" ubuntu:14.04 /bin/bash
容器中的進程只能使用內存節點1和3上的內存
在多核系統上,CPU時間權值是在全部CPU核上計算的。即便某個容器的 CPU 時間限制少於100%,也能使用各個CPU核的100%時間。socket
Docker對磁盤IO的控制須要依賴宿主機設備,主要參數以下:
--device-read-bps 限制設備上的讀速度(bytes per second),單位能夠是kb、mb或者gb。
--device-read-iops 經過每秒讀IO次數來限制指定設備的讀速度。
--device-write-bps 限制設備的寫速度(bytes per second),單位能夠是kb、mb或者gb。
--device-write-iops 經過每秒寫IO次數來限制指定設備的寫速度。
--blkio-weight 容器默認磁盤IO的加權值,有效值範圍爲10-100。
--blkio-weight-device 針對特定設備的IO加權控制,其格式爲DEVICE_NAME:WEIGHTdocker run -tid –name disk1 –device-write-bps /dev/sda:1mb ubuntu:stress
tcp
docker使用devicemapper做爲存儲驅動時,默認每一個容器和鏡像的最大大小爲10G。在docker daemon啓動時可使用dm.basesize來指定,但會致使Docker Host上的全部本地鏡像和容器都被清理掉,使用aufs或者overlay等其它存儲驅動時,沒有限制。ide