我们在启动Docker容器时,默认情况下容器所使用的资源是没有限制的,这样就会存在部分特别耗资源的容器会占用大量系统资源,从而导致其他容器甚至整个服务器性能降低,为此,Docker提供了一系列参数方便我们对容器的CPU、内存、IO等进行限制。为了方便演示,我们这里使用progrium/stress镜像,这个镜像内置一个压力测试工具,通过它我们可以很方便进行实验。首先我们拉取此镜像:

$ sudo docker pull progrium/stress
Using default tag: latest
latest: Pulling from progrium/stress
Image docker.io/progrium/stress:latest uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
a3ed95caeb02: Pull complete
871c32dbbb53: Pull complete
dbe7819a64dd: Pull complete
d14088925c6e: Pull complete
58026d51efe4: Pull complete
7d04a4fe1405: Pull complete
1775fca35fb6: Pull complete
5c319e267908: Pull complete
Digest: sha256:e34d56d60f5caae79333cee395aae93b74791d50e3841986420d23c2ee4697bf
Status: Downloaded newer image for progrium/stress:latest
docker.io/progrium/stress:latest

一、容器内存限制

与操作系统类似,容器可使用的内存包括两部分:物理内存,Swap交换空间,因此Docker通过以下两个参数对内存资源进行限制:

  • -m或--memroy:设置内存使用限额

  • --memory-swap:设置内存和交换空间总大小,如果只设置-m而不设置此参数,则默认内存和交换空间总大小是-m的两倍

例如我们按如下配置启动容器:我们设置内存为200M,内存与Swap总共300M,那么Swap就是100M。

sudo docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M

这里我们对stress进行设置:

--vm 1:启动一个工作线程

--vm-bytes:每个工作线程分配280M内存

$ sudo docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [7] forked
stress: dbug: [7] allocating 293601280 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: dbug: [7] freed 293601280 bytes
stress: dbug: [7] allocating 293601280 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: dbug: [7] freed 293601280 bytes
stress: dbug: [7] allocating 293601280 bytes ...

我们可以看到stress容器启动后不断在申请内存,释放内存,由于我们设置--vm-bytes 280M,所以它每次会申请280M内存空间,大家可能会注意到,容器启动后有一段告警信息:

WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.

这是因为我这边宿主机使用Ubuntu,在Ubuntu上默认是没有开启Swap限制的,这样就会导致容器的swap限制不生效,为了解决这个问题,我们需要先修改/etc/default/grub file 文件:

$ sudo vim /etc/default/grub file

添加如下内容:

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"

使用 sudo update-grub 更新系统的GRUB,并重启系统。

$ sudo update-grub
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/50-curtin-settings.cfg'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.15.0-159-generic
Found initrd image: /boot/initrd.img-4.15.0-159-generic
Found linux image: /boot/vmlinuz-4.15.0-158-generic
Found initrd image: /boot/initrd.img-4.15.0-158-generic
Found linux image: /boot/vmlinuz-4.15.0-156-generic
Found initrd image: /boot/initrd.img-4.15.0-156-generic
Found linux image: /boot/vmlinuz-4.15.0-154-generic
Found initrd image: /boot/initrd.img-4.15.0-154-generic
done

OK,解决了这个问题后我们继续内存限额的实现,我们这次将vm-bytes设置为310M,看看会有什么样的效果:

$ sudo docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [7] forked
stress: dbug: [7] allocating 325058560 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: FAIL: [1] (416) <-- worker 7 got signal 9
stress: WARN: [1] (418) now reaping child worker processes
stress: FAIL: [1] (422) kill error: No such process
stress: FAIL: [1] (452) failed run completed in 0s

我们可以看到,当线程每次申请的内存大于300M的时候会stress线程报错,容器退出。

二、容器的CPU限制

默认情况下,所有容器都可以平等使用宿主机的CPU而没有限制,Docker提供-c或--cpu-share参数用于设置容器的CPU权重,如果不指定则默认为1024。与内存限制不同,-c设置的并不是容器使用CPU的核的数量,而是相对的权重值,某个容器最终能分配到的CPU资源取决于它的cpu share占所有容器cpu share总和的比例,也就是说-c可以决定容器CPU优先级。

我们首先启动containerA,cpu share为1024:

$ sudo docker run --name containerA -it -c 1024 progrium/stress --cpu 2
stress: info: [1] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [8] forked
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [9] forked

接着启动containerB,cpu share为512:

$ sudo docker run --name containerB -it -c 512 progrium/stress --cpu 2
stress: info: [1] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [8] forked
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [9] forked

PS:注意我们要确保stress容器能够将host的cpu拉满这样才能确保实验效果,所以大家在实验时要注意看自己的宿主机CPU有多少个,例如我的机器cpu为2,所以在启动stress容器时--cpu也设置为2。

我们在宿主机上通过top命令能够明显看出效果:containerA消耗的CPU是containerB的两倍:

Docker 与 K8S学习笔记(六)—— 容器的资源限制的更多相关文章

  1. Docker 与 K8S学习笔记(七)—— 容器的网络

    本节我们来看看Docker网络,我们这里主要讨论单机docker上的网络.当docker安装后,会自动在服务器中创建三种网络:none.host和bridge,接下来我们分别了解下这三种网络: $ s ...

  2. Docker 与 K8S学习笔记(三)—— 镜像的使用

    前面的文章介绍过镜像的三种获取方式: 下载并使用别人创建好的镜像: 在现有镜像上创建新的镜像: 从无到有创建镜像. 本文主要介绍前两种. 一.下载镜像 在Docker Hub上有大量优质镜像可以使用, ...

  3. Docker 与 K8S学习笔记(九)—— 容器间通信

    容器之间可通过IP.Docker DNS Server或joined三种方式进行通信,今天我们来详细学习一下. 一.IP通信 IP通信很简单,前一篇中已经有所涉及了,只要容器使用相同网络,那么就可以使 ...

  4. Docker 与 K8S学习笔记(五)—— 容器的操作(下篇)

    上一篇我们学习了容器的启动和常用的进入容器的方式,今天我们来看看如何控制容器起停以及容器删除操作. 一.stop.kill.start和restart stop.kill命令都可以停止运行的容器,二者 ...

  5. Docker 与 K8S学习笔记(二)—— 容器核心知识梳理

    本篇主要对容器相关核心知识进行梳理,通过本篇的学习,我们可以对容器相关的概念有一个全面的了解,这样有利于后面的学习. 一.什么是容器? 容器是一种轻量级.可移植.自包含的软件打包技术,使应用程序可以在 ...

  6. Docker 与 K8S学习笔记(十)—— 容器的端口映射

    我们一般将应用部署在容器里面,而一个服务器上会有许许多多的容器,那么外界该如何访问我们的应用呢?答案是:端口映射. Docker可以将容器对外提供服务的端口映射到host的某个端口上,外网通过此端口访 ...

  7. Docker 与 K8S学习笔记(八)—— 自定义容器网络

    我们在上一篇中介绍了Docker中三种网络,none.host和bridge,除了这三种网络,Docker还允许我们创建自定义网络,当我们要创建自定义网络时,Docker提供了三种网络驱动供我们选择: ...

  8. Docker 与 K8S学习笔记(五)—— 容器的操作(上篇)

    上一篇我们介绍了Dockerfile的基本编写方法,这一节我们来看看Docker容器的常用操作. 一.容器的运行方式 容器有两种运行方式,即daemon形式运行与非daemon形式运行,通俗地讲就是长 ...

  9. Docker 与 K8S学习笔记(十 二)容器间数据共享

    数据共享是volume的关键特性,今天我们来看一下通过volume实现容器与host.容器与容器之间共享数据. 一.容器与host共享数据 在上一篇中介绍到的bind mount和docker man ...

随机推荐

  1. 基于《CSAPP第九章 虚拟内存》的思考和总结

    在csapp的描述中,虚拟内存的形象更加具化,虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组,内存充当了磁盘的缓存,粗呢内存的许多概念与SRAM缓存是相似的.虚拟页面有以下三种 ...

  2. 巩固javaweb的第三十天

    显示用户输入信息 1 .代码 要想输出用户在上一个页面提交的信息,可以使用下面的代码: ${param.userid} ${param.username} ${param.userpass} ${pa ...

  3. day05 连表查询与子查询

    day05 连表查询与子查询 昨日内容回顾 表关系之一对一 换位思考之后得出两边都是不可以 要么是没有关系,要么是一对一 一对一的表关系外键虽然建在哪个都可以,但是建议建在查询频率多的表上 # 外键其 ...

  4. STM32 CAN用队列缓冲接收的例子

    [1]CAN接收用队列缓冲的例子: 发单帧没有问题,多帧或者连续发两帧就有问题.

  5. int是几位;short是几位;long是几位 负数怎么表示

    其实可以直接通过stm32的仿真看到结果:(这里是我用keil进行的测试,不知道这种方法是否准确) 从上面看, char是8位  short是4*4=16位  int是8*4=32位  long是8* ...

  6. jenkins之分布式

    在jenkins的slave节点安装jdk(注:slave节点不需要安装jenkins) #:安装jdk环境 root@ubuntu:/usr/local/src# ls jdk-8u191-linu ...

  7. 【Linux】【Services】【SaaS】Docker+kubernetes(5. 安装和配置ETCD集群)

    1. 简介: 1.1. ETCD是kubernetes和openstack都用到的组件,需要首先装好 1.2. 官方网站:https://coreos.com/etcd/ 1.3. ETCD的作用: ...

  8. matplotlib画3d图

    import numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3D fig = plt.f ...

  9. pandas基础学习一

    生成对象 用值列表生成 Series 时,Pandas 默认自动生成整数索引: In [3]: s = pd.Series([1, 3, 5, np.nan, 6, 8]) In [4]: s Out ...

  10. MyEclipse配置Spring框架(基础篇)

    一.新建项目,添加spring的相关jar包等 二.创建相关类以及属性和方法 Student.java package com.yh; public class Student implements ...