默認情況下,容器沒有資源限制,可以使用主機內核調度程序允許的儘可能多的給定資源。
Memory
內存風險
不允許容器消耗宿主機太多的內存是非常重要的。在 Linux 主機上,如果內核檢測到沒有足夠的內存來執行重要的系統功能,它會拋出 OOME
或 Out of Memory
異常,並開始終止進程以釋放內存。任何進程都會被殺死,包括 Docker 和其他重要的應用程序。如果殺錯進程,可能導致整個系統癱瘓。
Docker 通過調整 Docker daemon 上的 OOM 優先級來降低這些風險,以便它比系統上的其他進程更不可能被殺死。容器上的 OOM 優先級未調整,這使得單個容器被殺死的可能性比 Docker daemon 或其他系統進程被殺死的可能性更大。你不應試圖通過在 daemon 或容器上手動設置 --oom-score-adj
到極端負數,或通過在容器上設置 --oom-kill-disable
來繞過這些安全措施。
有關Linux內核的OOM管理的更多信息,查看 Out of Memory Management
可以通過以下方式降低 OOME 導致系統不穩定的風險:
- 在應用程序發佈到生產之前,執行相關測試以便了解應用程序的內存要求;
- 確保應用程序僅在具有足夠資源的主機上運行;
- 限制容器可以使用的內存,如下所述;
- 在 Docker 主機上配置 Swap 時要小心,Swap 比內存更慢且性能更低,但可以提供緩衝以防止系統內存耗盡;
- 考慮將 Container 轉換部署爲 Service,並使用服務級別約束和節點標籤來確保應用程序僅在具有足夠內存的主機上運行。
限制容器內存
下述選項中的大多數採用正整數,後跟 b
/ k
/ m
/ g
的後綴,代表單位:字節 / 千字節 / 兆字節 / 千兆字節。
選項 | 描述 |
---|---|
-m or --memory= | 容器可使用的最大內存, 最小值是 4m |
--memory-swap* | 允許此容器交換到磁盤的內存量 |
--memory-swappiness | 默認情況下,主機內核可以交換容器使用的匿名頁面的百分比,可以設置 --memory-swappiness 的值區間爲 0 - 100 |
--memory-reservation | 指定小於 --memory 的軟限制,當 Docker 檢測到主機上的爭用或內存不足時會激活該限制. 如果使用 --memory-reservation,則必須將其設置爲低於 --memory 才能使其優先。因爲它是軟限制,所以不保證容器不超過限制。 |
--kernel-memory | 容器可以使用的最大內核內存量, 最小值是 4m,因爲內核內存無法換出,缺乏內核內存的容器可能會阻塞主機資源,這會對主機和其他容器產生副作用 |
--oom-kill-disable | 默認情況, 如果發生內存不足(OOM)錯誤,內核會終止容器中的進程。 要改變這種行爲,使用 --oom-kill-disable 選項。 僅在已設置 -m / -memory 選項的容器上禁用 OOM killer,如果未設置 -m 標誌,則主機可能會耗盡內存,內核可能需要終止主機系統的進程才能釋放內存 |
有關 cgroup 和內存的更多信息,查看 Memory Resource Controller
關於 --memory-swap
--memory-swap
是一個修飾符標誌,只有在設置了 --memory
時纔有意義。使用 swap 允許容器在容器耗盡所有可用的 RAM 時,將多餘的內存需求寫入磁盤。對於經常將內存交換到磁盤的應用程序,性能會受到影響。
它的設置會產生複雜的影響:
- 如果
--memory-swap
設置爲正整數,則必須設置--memory
和--memory-swap
。--memory-swap
表示可以使用的 memory 和 swap 總量,--memory
控制 no-swap 的用量。 所以,如果設置--memory="300m"
和--memory-swap="1g"
, 容器可以使用 300m memory 和 700m (1g - 300m
) swap。 - 如果
--memory-swap
設置爲0
, 該設置被忽略,該值被視爲未設置。 - 如果
--memory-swap
的值等於--memory
的值, 並且--memory
設置爲正整數, 則容器無權訪問 swap。這是因爲--memory-swap
是可以使用組合的 Memory 和 Swap,而--memory
只是可以使用的 Memory。 - 如果
--memory-swap
不設置, 並且--memory
設置了值, 容器可以使用--memory
兩倍的 Swap(如果主機容器配置了 Swap)。示例: 設置--memory="300m"
並且不設置--memory-swap
,容器可以使用 300m memory 和 600m swap。 - 如果
--memory-swap
設置爲-1
,允許容器無限制使用 Swap。 - 在容器內部,像
free
等工具報告的是主機的可用 Swap,而不是容器內可用的。不要依賴於free
或類似工具的輸出來確定是否存在 Swap。
關於 --memory-swappiness
- 值爲 0 時,關閉匿名頁交換。
- 值爲 100 時,將所有匿名頁設置爲可交換。
- 默認情況下,如果不設置
--memory-swappiness
, 該值從主機繼承。
關於 --kernel-memory
內核內存限制是就分配給容器的總內存而言的,考慮一下方案:
- 無限內存,無限內核內存:這是默認行爲。
- 無限內存,有限內核內存:當所有 cgroup 所需的內存量大於主機上實際存在的內存量時,它是合適的。可以將內核內存配置爲永遠不會超過主機上可用的內存,而需求更多內存的容器需要等待它。
- 有限內存,無限內核內存:整體內存有限,但內核內存不是。
- 有限內存,有限內核內存:限制用戶和內核內存對於調試與內存相關的問題非常有用,如果容器使用意外數量的任意類型的內存,則內存不足不會影響其他容器或主機。在此設置中,如果內核內存限制低於用戶內存限制,則內核內存不足會導致容器遇到 OOM 錯誤。如果內核內存限制高於用戶內存限制,則內核限制不會導致容器遇到 OOM。
當你打開任何內核內存限制時,主機會根據每個進程跟蹤 “高水位線” 統計信息,因此您可以跟蹤哪些進程(在本例中爲容器)正在使用多餘的內存。通過查看主機上的 /proc/<PID>/status
,可以在每個進程中看到這一點。
CPU
默認情況下,每個容器對主機 CPU 週期的訪問權限是不受限制的,您可以設置各種約束來限制給定容器訪問主機的 CPU 週期。大多數用戶使用和配置 默認 CFS 調度程序。在 Docker 1.13 及更高版本中,還可以配置實時調度程序。
配置默認 CFS 調度程序
CFS 是用於普通 Linux 進程的 Linux 內核 CPU 調度程序。通過以下設置,可以控制容器的 CPU 資源訪問量,使用這些設置時,Docker 會修改主機上容器的 cgroup 的設置。
選項 | 描述 |
---|---|
--cpus=<value> | 指定容器可以使用的 CPU 資源量。例如,如果主機有兩個CPU並且,設置 --cpus="1.5",則容器最多可以使用 1.5 個 CPU,這相當於設置 --cpu-period="100000" 和 --cpu-quota="150000"。可在Docker 1.13及更高版本中使用。 |
--cpu-period=<value> | 指定 CPU CFS 調度程序週期,該週期與 --cpu-quota 一起使用,默認爲100微秒。大多數用戶不會更改默認設置,如果使用Docker 1.13 或更高版本,請改用 --cpus。 |
--cpu-quota=<value> | 對容器施加 CPU CFS 配額,在受限制之前容器限制爲每個 --cpu-period 的微秒數,作爲有效上限。如果使用Docker 1.13 或更高版本,請改用 --cpus。 |
--cpuset-cpus | 限制容器可以使用的特定 CPU 或核心。如果主機有多個CPU,則容器可以使用的以, 分 隔的列表或 - 分隔的 CPU 範圍。第一個CPU 編號爲 0,有效值可能是 0-3(使用第一個、第二個、第三個和第四個CPU)或 1,3(使用第二個和第四個CPU)。 |
--cpu-shares | 將此值設置爲大於或小於默認值 1024,以增加或減少容器的權重,並使其可以訪問主機的 CPU 週期的佔較大或較小比例。僅在 CPU 週期受限時纔會強制執行此操作。當有足夠的 CPU 週期時,所有容器都會根據需要使用儘可能多的 CPU。這是一個軟限制,--cpu-shares 不會阻止在羣集模式下的容器調度。它爲可用的 CPU 週期優先考慮容器 CPU 資源。它不保證或保留任何特定的 CPU 訪問權限。 |
示例:如果你有 1 個 CPU,則以下每個命令都會保證容器每秒最多佔 CPU 的 50%。
Docker 1.13 或更高版本:
docker run -it --cpus=".5" ubuntu /bin/bash
Docker 1.12 或更低版本:
docker run -it --cpu-period=100000 --cpu-quota=50000 ubuntu /bin/bash
配置實時調度程序
In Docker 1.13 and higher, you can configure your container to use the realtime scheduler,
在 Docker 1.13 或更高版本,你可以配置容器使用實時調度程序。在配置 Docker daemon 或配置容器之前,需要確保正確配置主機的內核。
警告:CPU 調度和優先級是高級內核級功能,大多數用戶不需要從默認值更改這些值,錯誤地設置這些值可能會導致主機系統變得不穩定或無法使用。
配置主機機器的內核
通過運行 zcat /proc/config.gz | grep CONFIG_RT_GROUP_SCHED
驗證是否在 Linux 內核中啓用了 CONFIG_RT_GROUP_SCHED
,或者檢查是否存在文件 /sys/fs/cgroup/cpu.rt_runtime_us
。有關配置內核實時調度程序的教程,請參閱操作系統的文檔。
配置DOCKER DAEMON
要使用實時調度程序運行容器,請運行 Docker daemon,並將 --cpu-rt-runtime
設置爲每個運行時間段爲實時任務保留的最大微秒數。例如,默認週期爲 1000000 微秒(1秒),設置 --cpu-rt-runtime=950000
可確保使用實時調度程序的容器每 1000000 微秒可運行 950000 微秒,並保留至少 50000 微秒用於非實時任務。要在使用 systemd 的系統上永久保留此配置,請參閱 Control and configure Docker with systemd。
配置個別容器
使用 docker run
啓動容器時,可以傳遞多個參數來控制容器的 CPU 優先級。有關適當值的信息,請參閱操作系統的文檔或 ulimit
命令。
選項 | 描述 |
---|---|
--cap-add=sys_nice | 授予容器 CAP_SYS_NICE 功能,該功能允許容器引發進程良好值,設置實時調度策略,設置 CPU 親和性以及其他操作。 |
--cpu-rt-runtime=<value> | 容器可以在 Docker 守護程序的實時調度程序週期內以實時優先級運行的最大微秒數,需要設置 --cap-add=sys_nice 。 |
--ulimit rtprio=<value> | 容器允許的最大實時優先級,需要 --cap-add=sys_nice 標誌。 |
示例:
docker run --it --cpu-rt-runtime=950000 \ --ulimit rtprio=99 \ --cap-add=sys_nice \ debian:jessie
如果未正確配置內核或 Docker Daemon,則會發生錯誤。
相關文章
Limit a container's resources Linux 使用 free 查看系統內存信息 CentOS 查看系統 CPU 信息