1、前言
通常情况下,我们一台宿主机上会同时启动多个Docker容器,而在默认情况下,Docker是没有限制其运行的容器所使用的硬件资源,比如CPU,内存,IO等。而在实际环境中,往往一个容器的负载过高,会占用宿主机的大部分资源,会导致其他容器的访问资源被抢占,而出现响应超时或无法响应等情况。
因此,我们往往会对同时启动的Docker容器做资源的分配和管理。这就是我们今天要说的容器资源管理。
2、CGroup
熟悉Linux的应该知道,Linux内核提供了一组为cgroup(Controller Group)的进程,通过这些进程可以限制应用对资源的使用,如CPU,内存等。通过cgroup可以对系统资源做精细化控制,例如实现对每个容器使用的CPU比率进行限制。
Linux CGroup主要提供了几种功能:
- Resource Limitation:限制资源的使用,如CPU,内存的上限。
- Prioritization:应用的优先级控制,如控制任务的调度。
- Accounting:应用的审计和统计,例如实现应用的计费。
- Control:实现对应用的控制,例如应用的挂起,恢复和执行等。
2.1、是否开启CGroup
代码语言:javascript复制cat /boot/config-3.10.0-1160.el7.x86_64 |grep CGROUP
如果相关参数是y,表示已经启动了Linux CGroup,默认是开启的。
2.2、Linux CGroup限制资源能使用
2.2.1、创建一个demo
创建一个high_cpu.java文件。
代码语言:javascript复制touch high_cpu.java
编写一段死循环代码。
代码语言:javascript复制class HighCpu {
public static void main(String args[]) {
int i=0;
while(true){
i ;
}
}
}
再编译执行他。
代码语言:javascript复制javac high_cpu
nohup java HighCpu &
执行完观察cpu占用情况。
代码语言:javascript复制htop
我这里启了两个,所以两个进程。但是不影响我们观测,可以看到进程3999的CPU使用率已经接近100%。
安装htop步骤:
yum -y install epel-release.noarch
yum -y install htop
2.2.2、CGroup限制CPU使用
1)首先进入系统cgroup目录下。
代码语言:javascript复制cd /sys/fs/cgroup/
ls
可以看到里面有很多熟悉的资源相关文件,如cpu,memory,blkio等。
没错,我们要限制cpu使用,当然是进入到cpu/目录。
代码语言:javascript复制cd spu/
# 创建我们自己的资源隔离脚本,
mkdir mycpu
cd mycpu
ls
可以看到在里面默认生成很多cpu相关的脚本文件。
我们着重看cpu.cfs_quota_us。
代码语言:javascript复制cat cpu.cfs_quota_us
里面的值为-1,则表示不限制cpu使用。
我们修改他的值为2000,也就是限制20%阈值。
代码语言:javascript复制echo 20000 > cpu.cfs_quota_us
#同时把我们上面的进程号(3999)写进tasks文件
echo 3999 > tasks
我们再htop观察下cpu占用,可以看到CPU使用已经成功降到了20%的上限。
2.3、Linux CGroup限制内存使用
同上面的CPU限制,内存限制也类似。
代码语言:javascript复制cd /sys/fs/cgroup/memory
mkdir mymem
cd mymem
more memory.limit_in_bytes
可以看到这个值很大,表示对内存没有进行限制。
同样我们可以通过配置进行调整。
代码语言:javascript复制echo 10m > memory.limit_in_bytes
#同时把我们上面的进程号(3999)写进tasks文件
echo 3999 > tasks
这样,内存使用就限制了10m可用。
2.4、Linux CGroup限制IO
代码语言:javascript复制cd /sys/fs/cgroup/blkio
mkdir myio
cd myio
echo '8:0 1048576' > blkio.throttle.read_bps_device
#同时把我们上面的进程号(3999)写进tasks文件
echo 3999 > tasks
上面的"8:0"是当前需要限制的设备号。如要查看/dev/sda磁盘的设备号,可以使用ls -l /dev/sda。
3、Docker对资源的管理
为什么前面说了那么多Linux CGroup对资源的管理?因为Docker是构建在Linux基础上的,因此Docker就是利用Linux CGroup来实现对资源的控制。那么有了前面CGroup的认识,我们接下来学习Docker资源管理就容易很多。
3.1、Docker对CPU的限制
Docker引擎可以通过-c或--cpu-shares来为每个容器分配一个“CPU使用的权重”。该权重与实际的处理速度无关,每个容器默认有1024个CPU配额权重。
如果启动了两个容器,并且两个都使用默认的权重值 1024,则 Docker 引擎将把 CPU使用率平均分配给这两个容器,即这两个容器各自占用 50%的 CPU使用率。
但是,如果给容器 A分配的是 1024 权重,而给容器 B分配的是 512 权重,则会发现容器A使用CPU的比例比容器B使用 CPU的比例多一倍。
3.1.1、构建一个镜像
创建一个Dockerfile文件,这里直接使用我们前面用过的例子:
代码语言:javascript复制# 指定基础镜像作为该容器的基础环境,如springboot应用最起码得有jdk环境
FROM openjdk:8
# 执行维护者的信息
MAINTAINER shamee csdn peng793049488
# 创建一个存放该工程的目录
RUN mkdir -p /data/project
ADD target/dockerfile-springboot-1.0-SNAPSHOT.jar /data/project/dockerfile-springboot-1.0-SNAPSHOT.jar
# 对外暴露一个8899端口
EXPOSE 8899
# 执行启动
ENTRYPOINT ["/bin/sh", "-c", "java -jar /data/project/dockerfile-springboot-1.0-SNAPSHOT.jar"]
使用docker build构建镜像:
代码语言:javascript复制docker build -t docker_cgroup .
构建完,便可以看到我们的镜像docker_cgroup。
3.1.2、构建两个容器
代码语言:javascript复制# 第一个容器, CPU默认(1024)
docker run -d docker_cgroup --cpu 4 --name=cpu_1024
# 第二个容器, CPU配额权重512
docker run -d -c 512 docker_cgroup --cpu 4 --name=cpu_512
3.1.3、查看CPU使用率
通过命令:
代码语言:javascript复制docker stats
可以看到CPU的占用情况,设置1024权重的CPU占用率比512的高将近一倍。
docker stats 命令可以查看容器的CPU,内存,IO等分配,使用情况。下面的内存验证和IO验证均可以使用该命令查看。
除此以外,还可以设置以下参数,直接绑定CPU核心数:
代码语言:javascript复制# 表示使用CPU0,1,2核
--cpuset-cpus=0,1,2
3.2、Docker对内存的限制
同上面CPU的管理,Docker引擎支持通过-m参数来设定容器所使用的内存。
如:
代码语言:javascript复制docker run -it xxx -m 256m
-m 256m表示限制容器使用的内存大小为256m。验证方式可以类似上面CPU管理方式,可以直接使用docker stats来查看。这里就不赘述。
3.3、Docker对IO的限制
对I/O的限制,可以使用参数:
代码语言:javascript复制# 这里是限制容器写入速度为1MB/s
docker run -it xxx --device-write-bps /dev/sda:1mb
其他参数:
参数名称 | 说明 |
---|---|
--blkio-weight | 可以通过--blkio-weight 修改容器 blkio 的权重,权重值为 10~1000 |
--blkio-weight-device weighted-device | 指定某个设备的权重 |
--device-read-bps throttled-device | 按每秒读取块设备的数据量设定上限 |
--device-read-iops throttled-device | 按照每秒读操作的次数设定上限 |
--device-write-bps throttled-device | 按每秒写入块设备的数据量设定上限 |
--device-write-iops throttled-device | 按照每秒写操作的次数设定上限 |
3.4、查看Docker的资源配置
可以使用:
代码语言:javascript复制docker inspect <容器ID或名称>
来查看容器的具体配置情况信息。