docker(六)--docker系統資源限制


 

 默認情況下容器是沒有資源限制的,所以它可以幾乎消耗完docker主機上所分配的所有資源
 docker提供了限制一個容器可使用的內存、cpu、block io的方法。
 當一個容器內的進程消耗完它的內存后,可能會因為OOM被kill掉,而CPU是可壓縮性資源,kernel可以壓縮它不受影響

內存OOME

linux主機上kernel探測到主機內存不足使用,就會發出一個異常,並且開始殺死一些進程一旦發生OOME,任何進程都有可能被殺死,包括docker daemon在內,為此,Docker特地的調整了docker daemon的OOM優先級,以免它被殺掉,但容器的優先級並未被調整

工作邏輯:在宿主機上,運行了很多的容器,系統級也有很多的進程,包括docker daemon自身的進程,如果內核要執行一些系統管理級的操作,發現內存沒有了,啟動評估,一般認為哪個耗內存更多,就會kill掉那個進程,比較快釋放內存,但是這個進程不一定應該被殺,如A可以消耗內存10G,B可消耗內存1G,A只消耗10分之一,B已經消耗完了,不一定要Kill A。

  內核會對進程排優先級,自從到下逆序,一個個的殺掉,直接內存足夠使用為止。

  每個進程可以分配OOM obj, 每個進程計算好后可以有一個OOM score,得分越高就應該被殺掉的,得分是對它的申請和占用的空間使用一系列復雜的計算來做的,如果計算出后,某個進程是最高的,但是不應該被殺掉,如docker daemon這個進程可以調整優先級處理。每個進程有一個oom adj,也就是權重,優先級越低,得分就變得越少,可以把docker daemon的優先級調低,得分就少,就不會被殺。如果一個容器在生產提供重要的服務,它卻被殺掉,就很嚴重,應該開啟就要調整它的優先級。而且也可以定義容器的策略,一旦被kill掉,可以restart。

 

控制容器的內存資源

# docker run --help

-m, --memory bytes Memory limit
--memory-reservation bytes Memory soft limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--memory-swappiness int Tune container memory swappiness (0 to 100) (default -1)

ram物理內存,swap交換內存

  • -m (-memory) 限制ram內存空間,接收k,b,m,g作為單位
  • --memory-swap * 限制交換內存空間使用,使用它的前提必須先設定-m,沒有設置物理內存,就不能設置交換分區
  • --memory-swappiness 使用memory的傾向性(0-100),0表示能不用交換內存就不用
  • --memory-reservation 預留的內存空間
  • --oom-kill-disable 禁止OOM被KILL掉,如容器很消耗內存,但是又很重要不能被kill

 

 

CPU

跟內存不同,默認情況下,每個容器是不限制使用宿主機上CPU資源,可以自行限制,不過大多數用戶使用默認的CFS調度,CPU的核心數量是小於進程數的,一個系統上可能運行很多進程,需要運行進程數量大於核心數量時,那個應該優先運行?所以需要調度器來操作,因此內核中進程管理最重要的一個組件是進程調度器,調度進程運行在本地CPU核心上的,那個進程應該被優先運行,非實時的優先級是100-139,實時是0-99,使用nice值來調整[-20,19]非實時的,使用CFS(完全公平調度器),是分配每個進程使用的CPU的,進程還分為兩類批處理的和交互式的,交互式的優先級比較高,用戶點擊mouse就要執行,不然就感覺很慢,但是交互界面使用的CPU的時間都比較短的,但是批處理進程比較消耗CPU,但是通常不需要立刻做出響應,優先級比較低。
  CPU密集型表示對資源占用很大,I/O密集型的是對於I/O資源占用比較大的,對於CPU資源應該盡可能調低它的優先級,因為給它它就會盡可能的使用,內核有算法對這些進程做計算和懲罰,動態調低調高。

選項:

-c, --cpu-shares int CPU shares (relative weight)
--cpus decimal Number of CPUs
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)


--cpu-shares CPU資源共享,按比例切分系統上所有可用的CPU資源, 如當前系統上一共運行了兩個容器,權重比是1024:512的值,假設兩個容器不需要盡可能多的使用CPU,CPU資源假設有100份,兩個容器的比例是2:1, 如果第二個容器啟動幾乎都不需要CPU資源,這時第一個容器可以占用所有的CPU資源,就是需要就按比例分,不需要就給需要用的。CPU是可壓縮資源,隨時按比例運行。
--cpus=<value>  一個容器可以使用幾核心,可以使用小數,如1.5核(限制數量)
--cpuset-cpus   進程只能運行在指定那個核上(限制范圍)

 

CPU密集型 vs IO密集型

CPU密集型又稱計算密集型,特點是要進行大量的計算,主要消耗CPU資源,一些大量循環的代碼(例如:圖片處理、視頻編碼、人工智能等),全靠CPU的運算能力。這種計算密集型任務雖然也可以用多任務完成,但是任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低,所以,要最高效地利用CPU,計算密集型任務同時進行的數量應當等於CPU的核心數。對於計算密集型任務,最好用C語言編寫。

IO密集型,涉及到網絡、磁盤IO的任務都是IO密集型任務,這類任務的特點是CPU消耗很少,任務的大部分時間都在等待IO操作完成(因為IO的速度遠遠低於CPU和內存的速度)。對於IO密集型任務,任務越多,CPU效率越高,但也有一個限度。常見的大部分任務都是IO密集型任務,比如Web應用。對於IO密集型任務,最合適的語言就是開發效率最高(代碼量最少)的語言,腳本語言是首選,C語言最差。

 

docker壓測工具
# docker pull lorel/docker-stress-ng
# docker run --name stress -it --rm lorel/docker-stress-ng:latest

測試內存

# docker run --name stress -it --rm -m 256m lorel/docker-stress-ng:latest stress --vm 2
#-m指定可使用的內存大小,--vm啟動的子進程,每個進程默認是256MB,所以兩個進程需要512M,會超出

# docker top stress #顯示容器占了多少資源
可以看到內存最多跑到256M,不會達到512M

測試cpu

# lscpu

# docker run --name stress -it --rm --cpus 1 lorel/docker-stress-ng:latest stress --cpu 4
#限制使用1顆核心,啟動4個進程來操作
# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
5a006d928b2c stress 99.97% 7.938MiB / 3.686GiB 0.21% 508B / 0B 0B / 0B 5
如果不限制,它會使用完,因為是兩核,差不多200%
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
abb5cf0e98f9 stress 199.06% 7.934MiB / 3.686GiB 0.21% 578B / 0B 0B / 0B 5

指定使用哪個核cpu
# docker run --name stress -it --rm --cpuset-cpus 1 lorel/docker-stress-ng:latest stress --cpu 4

盡可能使用
# docker run --name stress -it --rm --cpu-shares 1024 lorel/docker-stress-ng:latest stress --cpu 4

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM