本文收錄在容器技術學習系列文章總目錄
1、限制容器的資源
預設情況下,容器沒有資源限制,可以使用主機核心排程程式允許的儘可能多的給定資源。Docker提供了控制容器可以使用多少記憶體或CPU的方法,設定docker run命令的執行時配置標誌。本篇提供有關何時應設定此類限制的詳細資訊以及設定這些限制的可能含義。
其中許多功能都要求您的核心支援Linux功能。要檢查支援,可以使用該 docker info命令。如果核心中禁用了某項功能,您可能會在輸出結尾處看到一條警告,如下所示:WARNING: No swap limit support,請參閱作業系統的文件以啟用它們,瞭解更多。
[root@along ~]# docker info Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 43 Server Version: 17.03.2-ce Storage Driver: overlay Backing Filesystem: xfs Supports d_type: true Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: bridge host macvlan null overlay Swarm: inactive Runtimes: runc Default Runtime: runc Init Binary: docker-init containerd version: 4ab9917febca54791c5f071a9d1f404867857fcc runc version: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe init version: 949e6fa Security Options: seccomp Profile: default Kernel Version: 3.10.0-514.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 1 Total Memory: 976.5 MiB Name: along ID: KGWA:GDGT:PTK7:PAX4:A3JZ:LV6N:U5QD:UQCY:AGZV:P32E:V73T:JJHR Docker Root Dir: /var/lib/docker Debug Mode (client): false Debug Mode (server): false Username: alongedu Registry: https://index.docker.io/v1/ Experimental: false Insecure Registries: docker2:80 127.0.0.0/8 Registry Mirrors: https://registry.docker-cn.com Live Restore Enabled: false
2、記憶體
2.1 記憶體不足的風險
重要的是不要讓正在執行的容器佔用太多的主機記憶體。在Linux主機上,如果核心檢測到沒有足夠的記憶體來執行重要的系統功能,它會丟擲一個OOME 或者 Out Of Memory Exception,並開始查殺程式以釋放記憶體。任何程式都會被殺死,包括Docker和其他重要的應用程式。如果錯誤的程式被殺死,這可以有效地降低整個系統。
Docker嘗試通過調整Docker守護程式上的OOM優先順序來降低這些風險,以便它比系統上的其他程式更不可能被殺死。容器上的OOM優先順序未調整。這使得單個容器被殺死的可能性比Docker守護程式或其他系統程式被殺死的可能性更大。您不應試圖通過–oom-score-adj 在守護程式或容器上手動設定為極端負數或通過設定容器來繞過這些安全措施–oom-kill-disable。
有關Linux核心的OOM管理的更多資訊,請參閱記憶體不足管理。
您可以通過以下方式降低OOME導致系統不穩定的風險:
- 在將應用程式投入生產之前,請執行測試以瞭解應用程式的記憶體要求。
- 確保您的應用程式僅在具有足夠資源的主機上執行。
- 限制容器可以使用的記憶體量,如下所述。
- 在Docker主機上配置交換時要小心。交換比記憶體更慢且效能更低,但可以提供緩衝以防止系統記憶體耗盡。
- 考慮將容器轉換為服務,並使用服務級別約束和節點標籤來確保應用程式僅在具有足夠記憶體的主機上執行
2.2 限制容器對記憶體設有的設定
Docker可以強制執行硬記憶體限制,允許容器使用不超過給定數量的使用者或系統記憶體或軟限制,這允許容器使用盡可能多的記憶體,除非滿足某些條件,例如核心檢測到主機上的低記憶體或爭用。當單獨使用或設定了多個選項時,其中一些選項會產生不同的效果。
大部分的選項取正整數,跟著一個字尾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殺手。如果-m 未設定該標誌,則主機可能會耗盡記憶體,並且核心可能需要終止主機系統的程式才能釋放記憶體。 |
2.2.1 –memory-swap 設定
(1)介紹
–memory-swap 是一個修飾符標誌,只有在–memory 設定時才有意義。使用swap允許容器在容器耗盡可用的所有RAM時將多餘的記憶體需求寫入磁碟。對於經常將記憶體交換到磁碟的應用程式,效能會受到影響。
(2)它的設定會產生複雜的效果:
- 如果–-memory-swap 設定為正整數,那麼這兩個–memory和 –memory-swap 必須設定。–memory-swap 表示可以使用的memory and swap,並–memory 控制非交換記憶體(實體記憶體)使用的量。所以如果–memory=”300m” 和–memory-swap=”1g”,容器可以使用300米的記憶體和700米(1g – 300m)swap。
- 如果–memory-swap 設定為0,則忽略該設定,並將該值視為未設定。
- 如果–memory-swap 設定為與值相同的值–memory,並且–memory設定為正整數,則容器無權訪問swap。請參考下面阻止容器使用交換。
- 如果–memory-swap 未設定並–memory 設定,則容器可以使用兩倍於–memory設定的swap,主機容器需要配置有swap。例如,如果設定–memory=”300m” 和–memory-swap 未設定,容器可以使用300米的記憶體和600米的swap。
- 如果–memory-swap 明確設定為-1,則允許容器使用無限制swap,最多可達宿主機系統上可用的數量。
- 在容器內部,工具如free 報告主機的swap,而不是容器內真正可用的記憶體。不要依賴free 或類似工具來確定是否存在swap。
(3)防止容器使用交換
如果–memory 和–memory-swap設定為相同的值,則可以防止容器使用swap。這是因為–memory-swap 可以使用的memory and swap,而–memory只是可以使用的實體記憶體量。
2.2.2 –memory-swappiness 設定
- 值為0將關閉匿名頁面交換。
- 值100將所有匿名頁面設定為可交換。
- 預設情況下,如果未設定–memory-swappiness,則值將從主機繼承。
2.2.3 –kernel-memory 設定
(1)介紹
核心記憶體限制以分配給容器的總記憶體表示。請考慮以下方案:
- 無限記憶體,無限核心記憶體:這是預設設定。
- 無限記憶體,有限的核心記憶體:當所有cgroup所需的記憶體量大於主機上實際存在的記憶體量時,這是合適的。您可以將核心記憶體配置為永遠不會覆蓋主機上可用的內容,而需要更多記憶體的容器需要等待它。
- 有限的記憶體,無限的核心記憶體:整體記憶體有限,但核心記憶體不受限制。
- 有限的記憶體,有限的核心記憶體:限制使用者和核心記憶體對於除錯與記憶體相關的問題非常有用。如果容器使用意外數量的任一型別的記憶體,則記憶體不足而不會影響其他容器或主機。在此設定中,如果核心記憶體限制低於使用者記憶體限制,則核心記憶體不足會導致容器遇到OOM錯誤。如果核心記憶體限制高於使用者記憶體限制,則核心限制不會導致容器遇到OOM。
當您開啟任何核心記憶體限制時,主機會根據每個程式跟蹤“高水位線”統計資訊,因此您可以跟蹤哪些程式(在本例中為容器)正在使用多餘的記憶體。通過/proc/<PID>/status在主機上檢視,可以在每個過程中看到這一點。
3、CPU
- 預設情況下,每個容器對主機CPU週期的訪問許可權是不受限制的。
- 您可以設定各種約束來限制給定容器訪問主機的CPU週期。
- 大多數使用者使用和配置 預設CFS排程程式。
- 在Docker 1.13及更高版本中,您還可以配置 實時排程程式。
3.1 配置預設CFS排程程式
CFS是用於普通Linux程式的Linux核心CPU排程程式。多個執行時標誌允許您配置容器具有的CPU資源訪問量。使用這些設定時,Docker會修改主機上容器的cgroup的設定。
選項 |
描述 |
–cpus=<value> |
指定容器可以使用的可用CPU資源量。例如,如果主機有兩個CPU並且你已設定–cpus=”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訪問許可權。 |
4、操作演示
4.1 準備工作
(1)先查詢宿主機的資源:
[root@docker ~]# lscpu CPU資源 Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 1 Core(s) per socket: 1 Socket(s): 4 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 60 Model name: Intel(R) Xeon(R) CPU E3-1231 v3 @ 3.40GHz Stepping: 3 CPU MHz: 3395.854 BogoMIPS: 6792.17 Hypervisor vendor: VMware Virtualization type: full L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 8192K NUMA node0 CPU(s): 0-3 [root@docker ~]# free -h 記憶體、swap資源 total used free shared buff/cache available Mem: 7.8G 193M 7.2G 8.6M 438M 7.3G Swap: 2.0G 400K 2.0G
(2)在dockerhub 下載一個用於壓測的映象
[root@docker ~]# docker pull lorel/docker-stress-ng
(3)該壓測映象的使用方法
[root@docker ~]# docker run --name stress --rm lorel/docker-stress-ng:latest stress --help
使用–help 可以查詢此壓測映象的用法
例:
stress-ng --cpu 8 --io 4 --vm 2 --vm-bytes 128M --fork 4 --timeout 10s
語法:
- -c N, –cpu N 啟動N個子程式(cpu)
- –vm N 啟動N個程式對記憶體進行壓測
- –vm-bytes 128M 每個子程式使用多少記憶體(預設256M)
4.2 測試記憶體限制
(1)現在最大使用記憶體啟動容器
[root@docker ~]# docker run --name stress --rm -m 256m lorel/docker-stress-ng:latest stress --vm 2 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 vm [root@docker ~]# docker stats stress CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS e1fdb0520bad stress 8.22% 254MiB / 256MiB 99.22% 648B / 0B 46.9MB / 3.63GB 5
註釋:
- -m 256m 限制此容器最大隻能使用256m 記憶體;
- –vm 2 啟動壓測容器,使用256×2=512m的記憶體;
- docker stats 結果查詢,容器實際使用記憶體不能超過256m
4.3 測試CPU限制
(1)限制最大使用2核CPU
[root@docker ~]# docker run --name stress --rm --cpus 2 lorel/docker-stress-ng:latest stress --cpu 8 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 8 cpu [root@docker ~]# docker stats stress CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS ca86c0de6431 stress 199.85% 15.81MiB / 7.781GiB 0.20% 648B / 0B 0B / 0B 9
(2)不限制使用CPU核數
[root@docker ~]# docker run --name stress --rm lorel/docker-stress-ng:latest stress --cpu 8 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 8 cpu [root@docker ~]# docker stats stress CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 167afeac7c97 stress 399.44% 15.81MiB / 7.781GiB 0.20% 508B / 0B 0B / 0B 9