默認狀況下,容器沒有資源限制,可使用主機內核調度程序容許的儘量多的給定資源。Docker提供了控制容器可使用多少內存或CPU的方法,設置docker run命令的運行時配置標誌。本節提供有關什麼時候應設置此類限制以及設置這些限制的可能含義的詳細信息。 其中許多功能都要求您的內核支持Linux功能。要檢查支持,可使用該 docker info命令。若是內核中禁用了某項功能,您可能會在輸出結尾處看到警告,以下所示: WARNING: No swap limit support
重要的是不要讓正在運行的容器佔用過多的主機內存。在Linux主機上,若是內核檢測到沒有足夠的內存來執行重要的系統功能,它會拋出一個OOME或者 Out Of Memory Exception,並開始查殺進程以釋放內存。任何進程都會被殺死,包括Docker和其餘重要的應用程序。若是錯誤的進程被殺死,這能夠有效地下降整個系統。 Docker嘗試經過調整Docker守護程序上的OOM優先級來減輕這些風險,以便它比系統上的其餘進程更不可能被殺死。容器上的OOM優先級未調整。這使得單個容器被殺死的可能性比Docker守護程序或其餘系統進程被殺死的可能性更大。您不該試圖經過--oom-score-adj在守護程序或容器上手動設置爲極端負數或經過設置容器來繞過這些安全措施--oom-kill-disable。
* docker 經過cgroup 工具來限制容器的資源使用,對於資源最重要的就是cpu 和memory 的使用node
groups(縮寫爲控制組)是Linux內核功能,用於限制,計算和隔離進程集合的資源使用狀況(CPU,內存,磁盤I / O,網絡等)。 Google的工程師(主要是Paul Menage和Rohit Seth)於2006年以「流程容器」的名義開始了這項功能的工做。[1] 在2007年底,命名法改成「控制組」,以免由Linux內核上下文中「 容器 」 一詞的多重含義引發的混淆,而且控制組功能在內核版本2.6中合併到Linux內核主線中.24,於2008年1月發佈。[2]從那時起,開發人員增長了許多新功能和控制器,例如2014年對kernfs的支持,[3] 防火牆,[4]統一的層次結構。[5]
Cgroups提供: 資源限制 組能夠設置爲不超過配置的內存限制,其中還包括文件系統緩存[8] [9] 優先級 某些組可能得到更大的CPU利用率[10]或磁盤I / O吞吐量[11] 計費 測量組的資源使用狀況,例如,可用於計費目的[12] 控制 凍結進程組,檢查點和從新啓動[12]
這些具體的資源管理功能稱爲cgroup子系統,有如下幾大子系統實現: blkio:設置限制每一個塊設備的輸入輸出控制。例如:磁盤,光盤以及usb等等。 cpu:使用調度程序爲cgroup任務提供cpu的訪問。 cpuacct:產生cgroup任務的cpu資源報告。 cpuset:若是是多核心的cpu,這個子系統會爲cgroup任務分配單獨的cpu和內存。 devices:容許或拒絕cgroup任務對設備的訪問。 freezer:暫停和恢復cgroup任務。 memory:設置每一個cgroup的內存限制以及產生內存資源報告。 net_cls:標記每一個網絡包以供cgroup方便使用。 ns:命名空間子系統。 perf_event:增長了對每group的監測跟蹤的能力,便可以監測屬於某個特定的group的全部線程以及運行在特定CPU上的線程。
在linux系統中一皆文件,固然對CGroup的接口操做也是經過文件來實現的,咱們能夠經過mount命令查看其掛載目錄:linux
[root@localhost ~]# mount -t cgroup cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd) cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event) cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids) cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_prio,net_cls) cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu) cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset) cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices) cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio) cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb) cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer) cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory) [root@localhost ~]#
以上目錄都是能夠限制的對象,docker
[root@localhost ~]# ls /sys/fs/cgroup/memory/docker/ 2bf7818020607cd2cded3006c8bf6e76a4424175ddca76ca9bb372913b43bf24 memory.max_usage_in_bytes aa843c370defc11c303473302caad3367600ad87127bbcd65989ef7cbe4eabad memory.memsw.failcnt cgroup.clone_children memory.memsw.limit_in_bytes cgroup.event_control memory.memsw.max_usage_in_bytes cgroup.procs memory.memsw.usage_in_bytes memory.failcnt memory.move_charge_at_immigrate memory.force_empty memory.numa_stat memory.kmem.failcnt memory.oom_control memory.kmem.limit_in_bytes memory.pressure_level memory.kmem.max_usage_in_bytes memory.soft_limit_in_bytes memory.kmem.slabinfo memory.stat memory.kmem.tcp.failcnt memory.swappiness memory.kmem.tcp.limit_in_bytes memory.usage_in_bytes memory.kmem.tcp.max_usage_in_bytes memory.use_hierarchy memory.kmem.tcp.usage_in_bytes notify_on_release memory.kmem.usage_in_bytes tasks memory.limit_in_bytes [root@localhost ~]#
#標紅的爲容器ID 能夠被限制的對象
測試ubuntu
[root@localhost ~]# cd /sys/fs/cgroup/cpu [root@localhost cpu]# ls cgroup.clone_children cpuacct.stat cpu.cfs_quota_us cpu.stat system.slice cgroup.event_control cpuacct.usage cpu.rt_period_us docker tasks cgroup.procs cpuacct.usage_percpu cpu.rt_runtime_us notify_on_release user.slice cgroup.sane_behavior cpu.cfs_period_us cpu.shares release_agent [root@localhost cpu]# mkdir limit_cpu_demo 在 /sys/fs/cgroup/cpu 目錄下建立文件默認會在文件下生成限制的配置文件 [root@localhost cpu]# ls cgroup.clone_children cpuacct.stat cpu.cfs_quota_us cpu.stat release_agent cgroup.event_control cpuacct.usage cpu.rt_period_us docker system.slice cgroup.procs cpuacct.usage_percpu cpu.rt_runtime_us limit_cpu_demo tasks cgroup.sane_behavior cpu.cfs_period_us cpu.shares notify_on_release user.slice [root@localhost cpu]# cd limit_cpu_demo/ [root@localhost limit_cpu_demo]# ls cgroup.clone_children cpuacct.stat cpu.cfs_period_us cpu.rt_runtime_us notify_on_release cgroup.event_control cpuacct.usage cpu.cfs_quota_us cpu.shares tasks cgroup.procs cpuacct.usage_percpu cpu.rt_period_us cpu.stat [root@localhost limit_cpu_demo]# [root@localhost limit_cpu_demo]# while :; do :; done & #執行一個循環 [1] 17392 #top top - 22:47:15 up 1:21, 1 user, load average: 0.67, 0.21, 0.11 Tasks: 101 total, 2 running, 99 sleeping, 0 stopped, 0 zombie %Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 1863224 total, 81028 free, 1496044 used, 286152 buff/cache KiB Swap: 4194300 total, 4185844 free, 8456 used. 157824 avail Mem
如上可見,此時該進程使用的CPU1已是100%,即%Cpu :100.0 us,咱們先來查看咱們剛纔建立的cpu_limit_demo目錄下這兩個參數默認值是多少: centos
[root@localhost limit_cpu_demo]# cat cpu.cfs_quota_us
-1
[root@localhost limit_cpu_demo]# cat cpu.cfs_period_us
100000
cpu.cfs_quota_us值爲-1表明沒有任何限制,cpu.cfs_period_us 則是默認的 100 ms,即100000us,下面將向cpu_limit_demo控制組的cpu.cfs_quota_us文件寫入50ms即50000us,這表示在100ms週期內,cpu最多使用%50,同時將該進程的pid號爲17406寫入對應的tasks文件,表示對那個進程限制: 緩存
[root@localhost limit_cpu_demo]# echo 50000 > cpu.cfs_quota_us [root@localhost limit_cpu_demo]# echo 17406 > tasks
能夠看到cpu 使用率爲50% 左右,說明限制生效了。一樣的道理,在/sys/fs/cgroup下的子系統均可以限制不通的資源使用如Block IO、Memory等。安全
Docker能夠強制執行硬內存限制,容許容器使用不超過給定數量的用戶或系統內存或軟限制,這容許容器使用盡量多的內存,除非知足某些條件,例如內核檢測到主機上的低內存或爭用。當單獨使用或設置了多個選項時,其中一些選項會產生不一樣的效果。
大部分的選項取正整數,跟着一個後綴b,k, m,g,,表示字節,千字節,兆字節或千兆字節。
選項 | 描述 |
---|---|
-m OR --memory= |
容器可使用的最大內存量。若是設置此選項,則容許的最小值爲4m (4兆字節)。 |
--memory-swap * |
容許此容器交換到磁盤的內存量。查看--memory-swap 詳情。 |
--memory-swappiness |
默認狀況下,主機內核能夠交換容器使用的必定百分比的匿名頁面。您能夠設置--memory-swappiness 0到100之間的值,以調整此百分比。查看--memory-swappiness 詳情。 |
--memory-reservation |
容許您指定小於軟盤限制--memory 時軟盤限制,當Docker檢測到主機上的爭用或內存不足時。若是使用--memory-reservation ,則必須將其設置爲低於--memory 優先級。由於它是軟限制,因此不能保證容器不超過限制。 |
--kernel-memory |
容器可使用的最大內核內存量。容許的最小值是4m 。因爲內核內存沒法換出,所以內核內存不足的容器可能會阻塞主機資源,這會對主機和其餘容器產生反作用。查看--kernel-memory 詳情。 |
--oom-kill-disable |
默認狀況下,若是發生內存不足(OOM)錯誤,內核會終止容器中的進程。若要更改此行爲,請使用該--oom-kill-disable 選項。僅在已設置-m/--memory 選項的容器上禁用OOM殺手。若是-m 未設置標誌,則主機可能會耗盡內存,內核可能須要終止主機系統的進程才能釋放內存。 |
有關cgroup和內存的更多信息,請參閱內存資源控制器的文檔。bash
--memory-swap
--memory-swap是一個修飾符標誌,只有在--memory設置時纔有意義。使用swap容許容器在容器耗盡可用的全部RAM時向磁盤寫入多餘的內存需求。常常將內存交換到磁盤的應用程序會下降性能。
默認--memory 和 --memory-swap 的值相同,而且 swap 的值爲(--memory-swap - [--memory]) 的值。
假如 --m 爲 300m ,--memory-swap 爲 1G ,那麼 可用memory 爲300m ,swap 爲 (1g-300M = 700M ),在實際配置中建議配合使用
若是隻設置-m 那麼默認 swap 和memory 相同,也不會進行計算,好比 -m 200M 那麼 swap 默認200M 加起來 400M
官方說明copy網絡
--memory-swap是一個修飾符標誌,只有在--memory設置時纔有意義。使用swap容許容器在容器耗盡可用的全部RAM時向磁盤寫入多餘的內存需求。常常將內存交換到磁盤的應用程序會下降性能。 它的設置會產生複雜的影響: 若是--memory-swap設置爲正整數,那麼這兩個--memory和 --memory-swap必須設置。--memory-swap表示可使用的內存和交換總量,並--memory控制非交換內存使用的數量。所以,若是--memory="300m"和--memory-swap="1g",容器可使用300米的內存和700米(1g - 300m)交換。 若是--memory-swap設置爲0,則忽略該設置,並將該值視爲未設置。 若是--memory-swap設置爲與值相同的值--memory,而且--memory設置爲正整數,則容器無權訪問swap。請參見 阻止容器使用交換。 若是--memory-swap未設置而且--memory已--memory設置,則若是主機容器配置了交換內存,則容器可使用兩倍於設置的交換。例如,若是--memory="300m"和--memory-swap未設置,容器可使用300米的內存和600米的交換。 若是--memory-swap明確設置爲-1,則容許容器使用無限制交換,最多可達主機系統上可用的數量。 在容器內部,工具如free報告主機的可用交換,而不是容器內可用的內容。不要依賴輸出free或相似工具來肯定是否存在交換。 防止容器使用交換 若是--memory和--memory-swap設置爲相同的值,則能夠防止容器使用任何交換。這是由於--memory-swap可使用的組合內存和交換量,而--memory只是可使用的物理內存量。
[root@localhost ~]# docker run -it --name c2 -m 100M --memory-swap 200M centos:latest
--memory-swappiness
值爲0將關閉匿名頁面交換。 值100將全部匿名頁面設置爲可交換。 默認狀況下,若是未設置--memory-swappiness,則值將從父進程繼承。
[root@localhost ~]# docker run -it --name c2 --memory-swappiness=0 centos:latest [root@e9fac4e4aa4d /]#
默認狀況下,若是發生內存不足(OOM)錯誤,內核會終止容器中的進程。若要更改此行爲,請使用該--oom-kill-disable選項。僅在已設置-m/--memory選項的容器上禁用OOM殺手。若是-m未設置標誌,則主機可能會耗盡內存,內核可能須要終止主機系統的進程才能釋放內存。
[root@localhost ~]# docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable centos:latest [root@2d440f001a3f /]# [root@localhost ~]# cat /sys/fs/cgroup/memory/docker/e9fac4e4aa4d1c5deb73881f612f3aa2f0bbbc42c020ce8e184f6e9601dc5d6b/memory.oom_control oom_kill_disable 0 #功能默認關閉,會kill 掉超過限制的容器 under_oom 0 [root@localhost ~]# cat /sys/fs/cgroup/memory/docker/2d440f001a3f04d69acb66c459d9a565fffc329d5e3ee9822c9480ccf58b476b/memory.oom_control oom_kill_disable 1 #功能開啓,防止kill 掉容器 under_oom 0 [root@localhost ~]#
默認狀況下,每一個容器對主機CPU週期的訪問權限是不受限制的。您能夠設置各類約束來限制給定容器訪問主機的CPU週期。大多數用戶使用和配置 默認CFS調度程序。在Docker 1.13及更高版本中,您還能夠配置 實時調度程序。 配置默認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訪問權限。 |
測試app
若是您有1個CPU,則如下每一個命令都會保證容器每秒最多佔CPU的50%。
Docker 1.13及更高版本:
docker run -it --cpus=".5" ubuntu /bin/bash
[root@829f06a8eba2 /]# while :; do :; done & [1] 14 [root@829f06a8eba2 /]# top top - 07:49:43 up 6:24, 0 users, load average: 0.36, 0.11, 0.12 Tasks: 3 total, 2 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 95.0 us, 5.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 1863224 total, 128896 free, 1400608 used, 333720 buff/cache KiB Swap: 4194300 total, 4167420 free, 26880 used. 248504 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 14 root 20 0 11820 576 200 R 94.7 0.0 0:21.47 bash 1 root 20 0 11820 1888 1512 S 0.0 0.1 0:00.08 bash 15 root 20 0 56192 2004 1468 R 0.0 0.1 0:00.06 top [root@localhost ~]# docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=".5" centos:latest [root@12959b971167 /]# [root@12959b971167 /]# while :; do :; done & [1] 14 [root@12959b971167 /]# top top - 07:51:43 up 6:26, 0 users, load average: 0.42, 0.24, 0.17 Tasks: 3 total, 2 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 51.2 us, 0.3 sy, 0.0 ni, 48.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 1863224 total, 127564 free, 1402052 used, 333608 buff/cache KiB Swap: 4194300 total, 4167420 free, 26880 used. 247084 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 14 root 20 0 11820 604 208 R 50.2 0.0 0:07.50 bash 15 root 20 0 56192 2004 1468 R 0.3 0.1 0:00.01 top 1 root 20 0 11820 1928 1540 S 0.0 0.1 0:00.08 bash
限制容器可使用的特定CPU或核心。若是您有多個CPU,則容器可使用的以逗號分隔的列表或連字符分隔的CPU範圍。第一個CPU編號爲0.有效值多是0-3(使用第一個,第二個,第三個和第四個CPU)或1,3(使用第二個和第四個CPU)。
[root@localhost ~]# docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=".5" --cpuset-cpus=0 centos:latest
[root@ad48f90b38fa /]#
使用啓動容器時,能夠傳遞多個標誌來控制容器的CPU優先級docker run
。有關ulimit
適當值的信息,請參閱操做系統的文檔或命令。
nice 值
Nice值是類UNIX操做系統中表示靜態優先級的數值。每一個進程都有本身的靜態優先級,優先級高的進程得以優先運行。 Nice值的範圍是-20~+19,擁有Nice值越大的進程的實際優先級越小(即Nice值爲+19的進程優先級最小,爲-20的進程優先級最大),默認的Nice值是0。因爲Nice值是靜態優先級,因此一經設定,就不會再被內核修改,直到被從新設定。Nice值只起干預CPU時間分配的做用,實際中的細節,由動態優先級決定。 「Nice值」這個名稱來自英文單詞nice,意思爲友好。Nice值越高,這個進程越「友好」,就會讓給其餘進程越多的時間。
選項 | 描述 |
---|---|
--cap-add=sys_nice |
授予容器CAP_SYS_NICE 容量,容許容器提高過程nice 值,設置實時調度策略,設置CPU關聯性和其餘操做。 |
--cpu-rt-runtime=<value> |
容器能夠在Docker守護程序的實時調度程序週期內以實時優先級運行的最大微秒數。你還須要--cap-add=sys_nice 旗幟。 |
--ulimit rtprio=<value> |
容器容許的最大實時優先級。你還須要--cap-add=sys_nice值 。 |
[root@localhost ~]# docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=".5" --cpuset-cpus=0 centos:latest #沒有給nice 值
[root@ae4bdc3fb9f9 /]#
[root@localhost ~]# ps -ef |grep docker root 19782 1 0 03:08 ? 00:00:17 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock root 20085 19782 0 03:09 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8081 -container-ip 172.17.0.2 -container-port 8081 root 20098 6505 0 03:09 ? 00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/2bf7818020607cd2cded3006c8bf6e76a4424175ddca76ca9bb372913b43bf24 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc root 24464 19426 0 04:06 pts/3 00:00:00 docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=.5 --cpuset-cpus=0 centos:latest root 24490 6505 0 04:06 ? 00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/ae4bdc3fb9f941fa7824916ef62ec0d2eacf76d5b53120a52392a9d37a9a2c53 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc root 24564 21769 0 04:06 pts/0 00:00:00 grep --color=auto docker [root@localhost ~]# top -p 24490 top - 04:07:08 up 6:41, 3 users, load average: 0.02, 0.10, 0.17 Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 1863224 total, 140776 free, 1402892 used, 319556 buff/cache KiB Swap: 4194300 total, 4167164 free, 27136 used. 246256 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 24490 root 20 0 10656 3352 2492 S 0.0 0.2 0:00.01 containerd-shim
root@localhost ~]# docker run -it --name c3 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=".5" --cpuset-cpus=0 --cap-add=sys_nice centos:latest [root@cb39dcbc9606 /]#