預設情況下容器是沒有資源限制的,所以它可以幾乎消耗完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
ram物理記憶體,swap交換記憶體
跟記憶體不同,預設情況下,每個容器是不限制使用宿主機上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-sharescpu資源共享,按比例切分系統上所有可用的cpu資源, 如當前系統上一共執行了兩個容器,權重比是1024:512的值,假設兩個容器不需要盡可能多的使用cpu,cpu資源假設有100份,兩個容器的比例是2:1, 如果第二個容器啟動幾乎都不需要cpu資源,這時第乙個容器可以占用所有的cpu資源,就是需要就按比例分,不需要就給需要用的。cpu是可壓縮資源,隨時按比例執行。
--cpus=乙個容器可以使用幾核心,可以使用小數,如1.5核(限制數量)
--cpuset-cpus程序只能執行在指定那個核上(限制範圍)
cpu密集型 vs io密集型
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
Docker實戰(六) Docker安裝Redis
初次使用docker安裝各種環境,果然是一堆坑啊,坑,坑,坑,坑死我了。大概步驟 編寫dockerfile構建映象 編寫supervisor配置檔案 build和run redis安裝 wget io releases redis 3.0 5.tar gz tar xzf redis 3.0 5.t...
Docker實戰(六) Docker安裝Redis
初次使用docker安裝各種環境,果然是一堆坑啊,坑,坑,坑,坑死我了。大概步驟 編寫dockerfile構建映象 編寫supervisor配置檔案 build和run redis安裝 wget io releases redis 3.0 5.tar gz tar xzf redis 3.0 5.t...
docker學習筆記(六) docker網路
docker網路主要分為兩塊 容器對外服務和容器內部服務 對外服務很好理解,比如我啟動了乙個mysql的容器,然後讓別的機器可以連線到這個mysql,就是對外服務 容器內部服務很好理解,就是幾個容器之間的互相通訊。當容器內執行一些網路應用,要讓外部訪問這些應用時,可以通過 p或 p引數來指定埠對映。...