Docker 资源限制之内存

一、压测工具

  • stress

通过如下 Dockerfile 构建简单的测试镜像

➜  cat Dockerfile
FROM ubuntu:latestRUN apt-get update && \apt-get install stress
➜   docker build -t ubuntu-stress:latest .

二、内存测试

  • Runtime constraints on resources

  • 目前 Docker 支持内存资源限制选项

    • -m--memory=""

      • Memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of bkm, or g. Minimum is 4M.
    • --memory-swap=""
      • Total memory limit (memory + swap, format: <number>[<unit>]). Number is a positive integer. Unit can be one of bkm, or g.
    • --memory-swappiness=""
      • Tune a container’s memory swappiness behavior. Accepts an integer between 0 and 100.
    • --shm-size=""
      • Size of /dev/shm. The format is <number><unit>. number must be greater than 0. Unit is optional and can be b (bytes), k (kilobytes), m (megabytes), or g(gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses 64m.
      • 根据实际需求设置,这里不作过多的介绍
    • --memory-reservation=""
      • Memory soft limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of bkm, or g.
    • --kernel-memory=""
      • Kernel memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of bkm, or g. Minimum is 4M.
      • kernel memory 没有特殊需求,则无需额外设置
    • --oom-kill-disable=false
      • Whether to disable OOM Killer for the container or not.

默认启动一个 container,对于容器的内存是没有任何限制的。

➜  ~ docker help run | grep memory  # 测试 docker 版本 1.10.2,宿主系统 Ubuntu 14.04.1--kernel-memory                 Kernel memory limit-m, --memory                    Memory limit--memory-reservation            Memory soft limit--memory-swap                   Swap limit equal to memory plus swap: '-1' to enable unlimited swap--memory-swappiness=-1          Tune container memory swappiness (0 to 100)
➜  ~

2.1 -m ... --memory-swap ...

  • docker run -it --rm -m 100M --memory-swap -1 ubuntu-stress:latest /bin/bash

指定限制内存大小并且设置 memory-swap 值为 -1,表示容器程序使用内存受限,而 swap 空间使用不受限制(宿主 swap 支持使用多少则容器即可使用多少。如果 --memory-swap 设置小于 --memory则设置不生效,使用默认设置)。

➜  ~ docker run -it --rm -m 100M --memory-swap -1 ubuntu-stress:latest /bin/bash
root@4b61f98e787d:/# stress --vm 1 --vm-bytes 1000M  # 通过 stress 工具对容器内存做压测
stress: info: [14] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd

使用 docker stats 查看当前容器内存资源使用:

➜  ~ docker stats 4b61f98e787d
CONTAINER           CPU %               MEM USAGE/LIMIT     MEM %               NET I/O
4b61f98e787d        6.74%               104.8 MB/104.9 MB   99.94%              4.625 kB/648 B

通过 top 实时监控 stress 进程内存占用:

➜  ~ pgrep stress
8209
8210    # 需查看 stress 子进程占用,
➜  ~ top -p 8210    # 显示可以得知 stress 的 RES 占用为 100m,而 VIRT 占用为 1007m
top - 17:51:31 up 35 min,  2 users,  load average: 1.14, 1.11, 1.06
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.2 us,  3.1 sy,  0.0 ni, 74.8 id, 21.9 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:   8102564 total,  6397064 used,  1705500 free,   182864 buffers
KiB Swap: 15625212 total,  1030028 used, 14595184 free.  4113952 cached MemPID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND8210 root      20   0 1007.1m 100.3m   0.6m D  13.1  1.3   0:22.59 stress

也可以通过如下命令获取 stress 进程的 swap 占用:

➜  ~ for file in /proc/*/status ; do awk '/VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 2 -n -r | grep stress
stress 921716 kB
stress 96 kB
➜  ~ docker run -it --rm -m 100M ubuntu-stress:latest /bin/bash

按照官方文档的理解,如果指定 -m 内存限制时不添加 --memory-swap 选项,则表示容器中程序可以使用 100M 内存和 100M swap 内存。默认情况下,--memory-swap 会被设置成 memory 的 2倍。

We set memory limit(300M) only, this means the processes in the container can use 300M memory and 300M swap memory, by default, the total virtual memory size --memory-swap will be set as double of memory, in this case, memory + swap would be 2*300M, so processes can use 300M swap memory as well.

如果按照以上方式运行容器提示如下信息:

WARNING: Your kernel does not support swap limit capabilities, memory limited without swap.

可参考 Adjust memory and swap accounting 获取解决方案:

  • To enable memory and swap on system using GNU GRUB (GNU GRand Unified Bootloader), do the following:

    • Log into Ubuntu as a user with sudo privileges.
    • Edit the /etc/default/grub file.
    • Set the GRUB_CMDLINE_LINUX value as follows:
      • GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
    • Save and close the file.
    • Update GRUB.
      • $ sudo update-grub
    • Reboot your system.
➜  ~ docker run -it --rm -m 100M ubuntu-stress:latest /bin/bash
root@ed670cdcb472:/# stress --vm 1 --vm-bytes 200M # 压测 200M,stress 进程会被立即 kill 掉
stress: info: [17] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: FAIL: [17] (416) <-- worker 18 got signal 9
stress: WARN: [17] (418) now reaping child worker processes
stress: FAIL: [17] (452) failed run completed in 2s
root@ed670cdcb472:/# stress --vm 1 --vm-bytes 199M

docker stats 和 top 获取资源占用情况:

➜  ~ docker stats ed670cdcb472
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O
ed670cdcb472        13.35%              104.3 MB / 104.9 MB   99.48%              6.163 kB / 648 B    26.23 GB / 29.21 GB
➜  ~ pgrep stress
16322
16323
➜  ~ top -p 16323
top - 18:12:31 up 56 min,  2 users,  load average: 1.07, 1.07, 1.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.8 us,  4.0 sy,  0.0 ni, 69.6 id, 21.4 wa,  0.0 hi,  0.2 si,  0.0 st
KiB Mem:   8102564 total,  6403040 used,  1699524 free,   184124 buffers
KiB Swap: 15625212 total,   149996 used, 15475216 free.  4110440 cached MemPID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
16323 root      20   0  206.1m  91.5m   0.6m D   9.9  1.2   0:52.58 stress
  • docker run -it -m 100M --memory-swap 400M ubuntu-stress:latest /bin/bash
➜  ~ docker stats ed670cdcb472
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O
ed670cdcb472        13.35%              104.3 MB / 104.9 MB   99.48%              6.163 kB / 648 B    26.23 GB / 29.21 GB
➜  ~ pgrep stress
16322
16323
➜  ~ top -p 16323
top - 18:12:31 up 56 min,  2 users,  load average: 1.07, 1.07, 1.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.8 us,  4.0 sy,  0.0 ni, 69.6 id, 21.4 wa,  0.0 hi,  0.2 si,  0.0 st
KiB Mem:   8102564 total,  6403040 used,  1699524 free,   184124 buffers
KiB Swap: 15625212 total,   149996 used, 15475216 free.  4110440 cached MemPID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
16323 root      20   0  206.1m  91.5m   0.6m D   9.9  1.2   0:52.58 stress

docker stats 和 top 获取资源占用情况:

➜  ~ docker stats 5ed1fd88a1aa
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O
5ed                 12.44%              104.8 MB / 104.9 MB   99.92%              4.861 kB / 648 B    9.138 GB / 10.16 GB
➜  ~ pgrep stress
22721
22722
➜  ~ top -p 22722
top - 18:18:58 up  1:02,  2 users,  load average: 1.04, 1.04, 1.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.4 us,  3.3 sy,  0.0 ni, 73.7 id, 21.6 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem:   8102564 total,  6397416 used,  1705148 free,   184608 buffers
KiB Swap: 15625212 total,   366160 used, 15259052 free.  4102076 cached MemPID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
22722 root      20   0  406.1m  84.1m   0.7m D  11.7  1.1   0:08.82 stress

根据实际测试可以理解,-m 为物理内存上限,而 --memory-swap 则是 memory + swap 之和,当压测值是 --memory-swap 上限时,则容器中的进程会被直接 OOM kill。

2.2 -m ... --memory-swappiness ...

swappiness 可以认为是宿主 /proc/sys/vm/swappiness 设定:

Swappiness is a Linux kernel parameter that controls the relative weight given to swapping out runtime memory, as opposed to dropping pages from the system page cache. Swappiness can be set to values between 0 and 100 inclusive. A low value causes the kernel to avoid swapping, a higher value causes the kernel to try to use swap space. Swappiness

--memory-swappiness=0 表示禁用容器 swap 功能(这点不同于宿主机,宿主机 swappiness 设置为 0 也不保证 swap 不会被使用):

  • docker run -it --rm -m 100M --memory-swappiness=0 ubuntu-stress:latest /bin/bash
➜ ~ docker run -it --rm -m 100M --memory-swappiness=0 ubuntu-stress:latest /bin/bash
root@e3fd6cc73849:/# stress --vm 1 --vm-bytes 100M # 没有任何商量的余地,到达 100M 直接被 kill
stress: info: [18] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: FAIL: [18] (416) <-- worker 19 got signal 9
stress: WARN: [18] (418) now reaping child worker processes
stress: FAIL: [18] (452) failed run completed in 0sroot@e3fd6cc73849:/#

2.3 --memory-reservation ...

--memory-reservation ... 选项可以理解为内存的软限制。如果不设置 -m 选项,那么容器使用内存可以理解为是不受限的。按照官方的说法,memory reservation 设置可以确保容器不会长时间占用大量内存。

2.4 --oom-kill-disable

➜ ~ docker run -it --rm -m 100M --memory-swappiness=0 --oom-kill-disable ubuntu-stress:latest /bin/bash
root@f54f93440a04:/# stress --vm 1 --vm-bytes 200M # 正常情况不添加 --oom-kill-disable 则会直接 OOM kill,加上之后则达到限制内存之后也不会被 killstress: info: [17] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd

但是如果是以下的这种没有对容器作任何资源限制的情况,添加 --oom-kill-disable 选项就比较 危险 了:

$ docker run -it --oom-kill-disable ubuntu:14.04 /bin/bash

因为此时容器内存没有限制,并且不会被 oom kill,此时系统则会 kill 系统进程用于释放内存。

2.5 --kernel-memory

Kernel memory is fundamentally different than user memory as kernel memory can’t be swapped out. The inability to swap makes it possible for the container to block system services by consuming too much kernel memory. Kernel memory includes:

  • stack pages
  • slab pages
  • sockets memory pressure
  • tcp memory pressure

这里直接引用 Docker 官方介绍,如果无特殊需求,kernel-memory 一般无需设置,这里不作过多说明。

三、内存资源限制 Docker 源码解析

关于 Docker 资源限制主要是依赖 Linux cgroups 去实现的,关于 cgroups 资源限制实现可以参考:Docker背后的内核知识——cgroups资源限制, libcontainer 配置相关的选项:

  • github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go
68 func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
69     if cgroup.Resources.Memory != 0 {
70         if err := writeFile(path, "memory.limit_in_bytes", strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil {
71             return err
72         }
73     }
74     if cgroup.Resources.MemoryReservation != 0 {
75         if err := writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil {
76             return err
77         }
78     }
79     if cgroup.Resources.MemorySwap > 0 {
80         if err := writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil {
81             return err   // 如果 MemorySwap 没有设置,则 cgroup 默认设定值是 Memory 2 倍,详见后文测试
82         }
83     }
84     if cgroup.Resources.OomKillDisable {
85         if err := writeFile(path, "memory.oom_control", "1"); err != nil {
86             return err
87         }
88     }
89     if cgroup.Resources.MemorySwappiness >= 0 && cgroup.Resources.MemorySwappiness <= 100 {
90         if err := writeFile(path, "memory.swappiness", strconv.FormatInt(cgroup.Resources.MemorySwappiness, 10)); err != nil {
91             return err
92         }
93     } else if cgroup.Resources.MemorySwappiness == -1 {
94         return nil  // 如果 MemorySwappiness 设置为 -1,则不做任何操作,经测试默认值为 60,后文附测试
95     } else {
96         return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", cgroup.Resources.MemorySwappiness)
97     }
98
99     return nil
100 }

附测试:

➜ ~ docker run -it --rm -m 100M --memory-swappiness=-1 ubuntu-stress:latest /bin/bashroot@fbe9b0abf665:/#

查看宿主对应 container cgroup 对应值:

➜ ~ cd /sys/fs/cgroup/memory/docker/fbe9b0abf665b77fff985fd04f85402eae83eb7eb7162a30070b5920d50c5356
➜ fbe9b0abf665b77fff985fd04f85402eae83eb7eb7162a30070b5920d50c5356 cat memory.swappiness # swappiness 如果设置 -1 则该值默认为 60
60
➜ fbe9b0abf665b77fff985fd04f85402eae83eb7eb7162a30070b5920d50c5356 cat memory.memsw.limit_in_bytes # 为设置的 memory 2 倍
209715200
➜ fbe9b0abf665b77fff985fd04f85402eae83eb7eb7162a30070b5920d50c5356

转自:http://blog.opskumu.com/docker-memory-limit.html

Docker 资源限制之内存相关推荐

  1. Docker资源控制与TLS加密通信

    文章目录 Docker资源控制 使用stress工作测试cpu和内存 cup周期限制 CPU Core 控制 cpu配额控制参数的混合使用 内存限额 IO限制 bps和iops的限制 Docker-T ...

  2. 你可能不知道的Docker资源限制

    本篇内容涉及Docker的内存与CPU限制,可以用于在实际开发中为指定容器设置限制最大使用的资源量,预计阅读时间为5分钟. 01 - What is 资源限制? 默认情况下,容器是没有资源限制的,它会 ...

  3. 实例解读:如何减少Docker中的Java内存消耗

    最近,我所在的团队面临着部署微服务(Java+SpringMVC in Docker on AWS)的问题.主要问题是,很多非常轻巧的应用程序消耗了太多的内存.因此,我们经过多方尝试找到了在Docke ...

  4. 【云原生】监视Docker桌面的容器内存和CPU使用情况

    目录 一.如何监视Docker桌面的容器内存和CPU使用情况 1.stats命令 2.Docker 统计命令stats是如何工作的 2.1.命令与描述 2.2.OPTIONS 2.3.例子 2.4.格 ...

  5. Docker中的Java内存消耗优化以及我们如何使用Spring Boot

    ---- / BEGIN/ ---- 如果您的Docker容器占用太多内存而无法达到最佳性能,请阅读下文以了解一个团队如何找到解决方案. 最近,我所在的团队在部署我们的微服务(AWS上Docker中的 ...

  6. 如何快速清理docker资源

    前言 如果经常使用 docker,你会发现 docker 占用的资源膨胀很快,其中最明显也最容易被察觉的应该是对磁盘空间的占用.本文将介绍如何快速的清理 docker 占用的系统资源,具体点说就是删除 ...

  7. Docker资源汇总

    Docker 资源汇总 Docker 资源 Docker 官方主页: https://www.docker.com Docker 官方博客: https://blog.docker.com/ Dock ...

  8. Android应用性能优化系列视图篇——隐藏在资源图片中的内存杀手

    图片加载性能优化永远是Android领域中一个无法绕过的话题,经过数年的发展,涌现了很多成熟的图片加载开源库,比如Fresco.Picasso.UIL等等,使得图片加载不再是一个头疼的问题,并且大幅降 ...

  9. 稳定性资源问题,内存上涨

    稳定性资源问题,内存上涨的问题 一.以容器作为服务器的内存持续上涨问题定位: 解决思路(因为可用内存=free+cached+buffers ) 查看jvm的设置 调整jvm的设置 查看缓存的情况 通 ...

最新文章

  1. hibernate之Configuration对象
  2. Python练习 | Python之图像的基本操作和处理
  3. Windows7下用VirtualBox安装Ubuntu网卡配置
  4. liferay开发文档_Liferay –简单主题开发
  5. FreeRTOS系列第19篇---FreeRTOS信号量
  6. 使用AirFlow调度MaxCompute
  7. 转网口显示未识别的网络_已有1700万用户携号转网 超99%用户1小时内办结
  8. Training and investigating Residual Nets 自己分析
  9. Linux下如何查看定位当前正在运行的Nginx的配置文件
  10. mysql读写分离实战
  11. Windows下GDAL3.1.2编译 (VS2015)
  12. C语言调用拼多多api,vb CommonDialog 属性
  13. linux下 使用apache2 ab 测试进行压力测试
  14. MySQL(2)----DDL语句之增、删、改、查操作
  15. Mysql使用dos命令安装
  16. 使用双显示器时其中一个屏幕出现重影的问题——缺少吸收磁环
  17. cgb2008-京淘day04
  18. 编程语言居然是魔法咒语!
  19. Tableau——预警标识
  20. 线程 守护线程 递归锁

热门文章

  1. vs2010 在svn上传东西的时候 出现一个错误 An internal occurred 值不在预期范围内 要如何解决呢?...
  2. 如何使用CSS来修改SVG原点和制作SVG动画
  3. FullCalendar 一: 日程安排FullCalendar
  4. jquery 表单验证
  5. 数据预处理-数据变换-连续属性离散化实现:pandas(0.23)+sklearn(0.19.1)+matplotlib(2.2.2)
  6. Linux——Linux下安装tree
  7. Linux远程管理工具(PuTTY和SecureCRT)
  8. Nginx学习之四-Nginx进程同步方式-自旋锁(spinlock)
  9. Win7下安装配置OpenCV2.3+Visual Studio 2008
  10. 0407 背景相关的作业