docker 除了可以透過參數限制 container 的 memory 使用量,也能限制每個 container 能取得的 CPU 資源,讓系統的 CPU 可以最大化使用,又不讓高優先度的 container 損失效能,一起來研究如何設定吧!
Cpuset 限制
設定 cpuset 指定 container 只能跑在特定的 CPU 核心上。比如在 arm CPU 會有 big.LITTLE 的設計,此時可以指定 container 跑在大核或小核上。
參數
# command line
--cpuset-cpus
# docker-compose (v2)
cpuset
範例
假設我們在一個六核 CPU 上面,設定 container 只能跑在 CPU 0, CPU 1,指令可以這麼下
docker run -it --rm --cpuset-cpus="0,1" alexeiled/stress-ng stress --cpu 2
因為我們開兩條 thread 去 stress,可以看到指定的兩顆 CPU 已經滿載
除了給定 CPU 編號,也能用範圍的方式表示,比如以下指令將會使用 CPU 0, CPU 1, CPU 2
docker run -it --rm --cpuset-cpus="0-2" alexeiled/stress-ng stress --cpu 2
如果在 docker-compose v2 ,則是這樣寫
version: '2.3'
services:
app:
cpuset: "0,1,2" # or "0-2"
CPU period 限制
設定 CPU period 指定 container 最多能使用的 CPU 時間,可簡單看成最大能使用的 CPU 數。
參數
# command line
--cpus
# docker-compose (v2)
cpus
範例
假設我們在二核 CPU 上測試,指定 container 最多只能使用 1 CPU ,但壓測時故意開 4 thread,指令如下
docker run -it --rm --cpus="1" alexeiled/stress-ng stress --cpu 4
可以看到 container 最多只能跑到 100% CPU,符合預期
df0a3a768016 test-cpus-1 100.12% 15.86MiB / 3.773GiB 0.41% 3.55kB / 0B 0B / 0B 5
如果看實體 CPU 狀況,發現 docker 會將 thread 平均分散到兩個 CPU 上面,但是各佔 50%,加起來剛好是 100% CPU = 1 CPU
當然也可以給予「小數」,比如設定「3.5」,表示最多可以使用 350% (3.5 顆)CPU。
如果在 docker-compose v2 中,則是這樣寫
version: '2.3'
services:
app:
cpus: 1
設定 CPU shares 可以指定當 CPU 滿載時,container 能取得多少 CPU 份額。亦可理解成當 CPU 資源不夠(滿載)的時候,container 搶奪 CPU 的能力。因此這是相對比較用的值。沒有設定時,docker 預設為 1024。
看完可能還是不太清楚,直接上範例!
參數
# command line
--cpu-shares
# docker-compose (v2)
cpu_shares
範例
假設我們在一核 CPU 上測試,其中一個 container 設定 512,另一個設定 1024,兩個 container 都嘗試用滿 CPU,此時 CPU shares 設定介入資源分配
docker run -it --rm --cpu-shares=512 --name="share-512" alexeiled/stress-ng stress --cpu 1
docker run -it --rm --cpu-shares=1024 --name="share-1024" alexeiled/stress-ng stress --cpu 1
觀察目前 container 的 CPU 使用率,發現 share-512 用約 34%,share-1024 用約 67%。
11eabb0720a7 share-512 33.83% 5.805MiB / 3.773GiB 0.15% 3.67kB / 0B 0B / 0B 2
7114a7965357 share-1024 66.81% 5.797MiB / 3.773GiB 0.15% 2.73kB / 0B 0B / 0B 2
快速算法是將 CPU 總資源除以所有的 container cpu-shares,再分別乘上各自的佔比,即可求得最終能搶奪的 CPU 資源,算式如下:
同理,如果一核 CPU 下有四個 container ,分別設定 cpu-shares:
container 1: 512
container 2: 512
container 3: 1024
container 4: 1024
可以透過上面算式預期最滿載時的資源分配如下:
container 1: 16.5%
container 2: 16.5%
container 3: 33%
container 4: 33%
但如果今天是四核 CPU,則四個 container 會分散到不同的核心上,這樣每個 container 都得吃到 100%。
如果在 docker-compose v2 中,則是這樣寫
version: '2.3'
services:
app:
cpu_shares: 512
綜合應用
這些參數可以綜合起來使用,比如,我想讓 container 跑在 CPU 0, 1, 2 上,但最多只能用到 1.5 核 CPU,同時 shares 為 512,我可以這麼設定:
--cpuset-cpus="0-2"
--cpus="1.5"
--cpu-shares=512
屆時可以觀察到,CPU 資源足夠時,container 整體最多可以吃到 150% CPU。如果是多執行緒,會分散在 CPU 0, 1, 2 上。單執行緒則會在 CPU 0, 1, 2 其中一核上跑。
如果覺得我文章內容對你有幫助的話,請在文章後面幫我按 5 個讚!讓我知道大家都喜歡什麼內容哦!
參考資料:
Runtime options with Memory, CPUs, and GPUs
Docker CPU资源限制