Docker限制容器的Block IO

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker限制容器的Block IO相关的知识,希望对你有一定的参考价值。

参考技术A Block IO指的是磁盘的读写,docker可以通过设置权重以及限制bps和iops的方式控制容器读写磁盘的带宽。
通过命令

docker help run | grep -E ‘bps|IO’

可以查询block IO的选项参数。

主要参数有:
–blkio-weight:容器默认磁盘IO的加权值,有效值范围为10-1000。
–blkio-weight-device: 针对特定设备的IO加权控制。其格式为DEVICE_NAME:WEIGHT
–device-read-bps:限制此设备上的读速度(bytes per second),单位可以是KB、MB或者GB。
–device-read-iops:通过每秒读IO次数来限制指定设备的读速度。
–device-write-bps :限制此设备上的写速度(bytes per second),单位可以是KB、MB或者GB。
–device-write-iops:通过每秒写IO次数来限制指定设备的写速度。

接下来将介绍每一个命令的具体使用方法。

1、–blkio-weight、–blkio-weight-device
使用以下命令创建容器

docker run -it --rm --blkio-weight 100 centos /bin/bash

采用docker inspect 命令查看生成的容器的元数据。

2、–device-write-bps、–device-read-bps
2.1 --device-write-bps
使用以下命令创建容器,并限制容器的写入速度是上限30MB/s

docker run -it --rm --device-write-bps /dev/sda:30MB centos

采用docker inspect命令对容器数据进行查看,发现设置成功。

在容器内采用dd命令对容器的写入速度进行测试,验证其读写速度在30M左右,其中oflag=direct 指定用 direct IO 方式写文件,这样 --device-write-bps 才能生效。

如果不采用oflag=direct方式,进行测试,发现速度为2.0GB/s,也间接说明成功限制容器写入速度。

2.2 --device-read-bps
使用以下命令创建容器,并限制容器的读出数据速度是上限30MB/s

docker run -it --rm --device-read-bps /dev/sda:30MB centos

同样,采用docker inspect命令对容器数据进行查看,发现设置成功。

在容器内采用dd命令对容器的写入速度进行测试,验证其读写速度在30M左右。首先需要生成读取数据文件test.out。

time dd if=/dev/zero of=test.out bs=1M count=256

然后再运行dd命令,对容器读取数据速度进行测试,和–device-write-bps类似,iflag=direct是对–device-read-bps的读取速度进行限制。

time dd if=test.out of=/dev/zero bs=1M iflag=direct

在不加iflag=direct的情况下进行测试,发现速度为7.9GB/s,远远大于30MB/s,从而可以看出成功限制容器读取数据的速度。

3、–device-write-iops,–device-read-iops
–device-write-iops,–device-read-iops是通过限制容器每秒读取IO的次数来限制容器的读写速度。

3.1 --device-write-iops
使用以下命令创建容器,并限制容器的每秒写入数据次数不超过30次。

docker run -it --rm --device-write-iops /dev/sda:30 centos

同样,采用docker inspect命令对容器数据进行查看,发现设置成功。

在容器内采用dd命令对容器的写入速度进行测试,写入速度限制到了15.8MB/s。

time dd if=/dev/zero of=test.out bs=1M count=256 oflag=direct

在不加oflag-direct的时候进行测试,速度为2.4GB/s,说明限制容器写入次数成功。

3.2 --device-read-iops
使用以下命令创建容器,并限制容器的每秒读取数据次数不超过30次。

docker run -it --rm --device-read-iops /dev/sda:30 centos

同样,采用docker inspect命令对容器数据进行查看,发现设置成功。

然后在运行dd命令对容器每秒读取io次数进行查看,命令格式通–device-read-bps,接下来将不再进行赘述,直接上图,读取速度为15.8MB/s。

在不加iflag=direct的情况下进行测试,发现读取速度为9.0GB/s远大于15.8MB/s,说明限制容器读取次数成功。

————————————————
原文链接: https://blog.csdn.net/weixin_44713619/article/details/105728147

Docker-安全CPU限额内存限制IO限制安全加固

一、Docker安全介绍

Docker容器的安全性,很大程度上依赖于Linux系统自身,评估Docker的安全性时,主要考虑以下几个方面

Linux内核的命名空间机制提供的容器隔离安全
Linux控制组机制对容器资源的控制能力安全。
Linux内核的能力机制所带来的操作权限安全
Docker程序(特别是服务端)本身的抗攻击性。
其他安全增强机制对容器安全性的影响。

1.命名空间隔离的安全

就是当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间。命名空间提供了最基础也最直接的隔离。
与虚拟机方式相比,通过Linux namespace来实现的隔离不是那么彻底。

[root@server1 ~]# docker run -d --name demo nginx
[root@server1 ~]# docker inspect demo | grep Pid


我们在系统进程里进入pid里查看一下信息!

cd /proc/8980/
cd ns/
ls

2.控制组资源控制的安全

当docker启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。
在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。

可以在memory内存看到运行的容器:

cd /sys/fs/cgroup/memory/docker/
ls


可以cpu中看到运行的容器:

二、容器资源控制

Linux Cgroups 的全称是 Linux Control Group。

我们只能限制一个进程使用的资源上限:包括 CPU、内存、磁盘、网络带宽等等。
Linux Cgroups 给用户暴露出来的操作接口是文件系统。
它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。

在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。
在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录)。
控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定。

1.内存限制

容器可用内存包括两个部分:物理内存和swap交换分区。
–m 设置内存使用限额

docker run -it --m 200M -d --name demo nginx
 cd /sys/fs/cgroup/memory/docker/ #可以看到打开的进程


我们进入到刚才的容器中,看到memory.limit_in_bytes内容是内存限制

cd *************
cat memory.limit_in_bytes

但是刚才的demo镜像不能够查看空间,所以我们需要换一个镜像

docker run -m 200M -it --rm busyboxplus
free -m


我们专门创建一个用来测试内存的目录x1

cd /sys/fs/cgroup/memory
mmkdir x1
cd x1/
ls

我们可以发现,创建好的目录x1里面拥有很多配置文件,因为它直接继承上级目录下的所有文件!

然后我们限制上传的内存最大为200M

echo 209715200 > memory.limit_in_bytes
cat memory.limit_in_bytes


下载libcgroup-tools工具

yum install -y libcgroup-tools.x86_64

我们创建指定大小的空间,但是我们发现前面已经设置了最大内存为200M,但是为什么能创建300M的空间呢?

cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300 


那是因为它占用了我们的swap分区的大小!
我们每次创建一定大小空间之后,用free -m查看一下内存情况就明白了!
我们的mem空间并没有使用有效空间都是1432如下图,但是swap空间使用多了100M,这下刚才的疑惑就解决了!!

删除创建的bigfile文件,那么我们是不是把swap分区关闭,创建300M空间就会失败呢?

rm -f bigfile
swapoff -a
free -m
cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300

果然没有了swap分区之后,创建300M分区直接报错!(killed)

但是在实际生产中,swap分区会使用,不能够关闭的!!
所以我们重新打开swap分区,删除bigfile文件!寻找别的方法来解决刚刚的问题:

swapon -a
swapon -s
free -m
rm -f bigfile


我们进入刚才的设置内存大小的路径下:
我们把200M的限制给内存+swap一共200M ,刚才的问题不就解决了马?

 cd /sys/fs/cgroup/memory/x1
 echo 209715200 > memory.memsw.limit_in_bytes      %内存+swap一共给200M

cd /dev/shm
cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300
cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=100
du -h *
cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=200
du -h *

我们可以看到创建300M空间直接失败!

创建100M成功,创建200M也不行,只能创建199M!

2.cpu限额

我们需要创建一个专门用于测试cpu的目录x2

cd /sys/fs/cgroup/cpu
mmkdir x2
cd x2/
ls


cpu.shares 不是限制进程能使用的绝对的 cpu 时间,而是控制各个组之间的配额!
cpu.shares,表示 CPU Cgroup 对于控制组之间的CPU 分配比例,缺省值是1024

例如:
group3 中的cpu.shares 是1024,group4 中的 cpu.shares 是 3072,那么 group3:group4 = 1:3

我们先设置cpu.shares的配额为100,应该是10/100的cpu损耗!
然后使用dd命令测试cpu的负载情况

echo 100 > cpu.shares
dd if=/dev/zero of=/dev/null &


输入top进入查看cpu消耗,是100,这不合适!是因为只有一个进程所以是100,所以我们还需要再创建一个压力来测试

我们把cpu线程PID写入tasks中

cat tasks
echo 10053 > tasks


我们再测试使用一个损耗打入后台

dd if=/dev/zero of=/dev/null &

top 查看cpu消耗都是100,这还是不合适!

top


因为我们的虚拟机是双cpu的可以独立工作,所以可以关闭一个cpu

cd /sys/devices/system/cpu/cpu1
cat online
echo 0 > online


此时查看top
一个cpu稳定在10左右,另一个90左右

但是实际生产中不能关闭另一个cpu,行不通!
重新打开cpu1,恢复cpu的配额

echo 1 > online
echo 1024 > cpu.shares


cpu.cfs_period_us,它是CFS算法的一个调度周期,一般值是 100000十万,单位是微秒,就是 100ms
cpu.cfs_quota_us,它表示CFS算法中,在一个调度周期里这个控制组被允许的运行时间,比如这个值为 50000时,就是 50ms。

如果用这个值cpu.cfs_quota_us除以调度周期cpu.cfs_period_us,50ms/100ms=0.5,表示这个控制组被允许使用的CPU最大配额就是0.5个CPU

cat cpu.cfs_quota_us
cat cpu.cfs_period_us
echo 20000 > cpu.cfs_quota_us

此时我们这样设置就是允许使用的cpu为0.2个cpu!!

top
查看看到cpu使用为20和设置的效果一样!
注意:追加是>>
如果这个时候我们把另一个cpu也追加入到线程里面

echo 10066 >> tasks


那么这个时候就是两个进程去争夺20的cpu配额
所以每个进程分的10!!如下图:

3.Block IO限制(磁盘IO)

–device-write-bps限制写设备的bps

目前的block IO限制只对direct IO有效。(不使用文件缓存)

docker run -it --rm --device-write-bps /dev/vda:30MB rhel7 bash
dd if=/dev/zero of bigfile bs=1M count=200 oflag=direct
dd if=/dev/zero of bigfile bs=1M count=200

我们可以看到加上oflag=direct参数速度为30MB左右,不加参数,速度为2。6G就差别很大!!

三.docker安全加固

利用LXCFS增强docker容器隔离性和资源可见性

[root@server1 ~]# yum install lxcfs-2.0.5-3.el7.centos.x86_64.rpm -y
[root@server1 ~]#docker pull ubuntu
[root@server1 ~]# lxcfs /var/lib/lxcfs &            ##运行
[root@server1 lxcfs]# docker run  -it -m 256m \\
>       -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \\
>       -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \\
>       -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \\
>       -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \\
>       -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \\
>       -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \\
>       ubuntu

我们可以看到mem和swap的大小一致!

我们先运行一个普通的容器
发现控制网络的时候,被拒绝了!

docker run -it --rm  busyboxplus
ip link set down eth0

1.设置特权级运行的容器

–privileged=true
有的时候我们需要容器具备更多的权限,比如操作内核模块,控制swap交换分区,挂载USB磁盘,修改MAC地址等。

docker run -it --rm --privileged=true busyboxplus
ip link set down eth0

这次控制网络eth0成功了!

2.设置容器白名单

–cap-add
–privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时Docker 提供了权限白名单的机制,使用–cap-add添加必要的权限。

当我们运行容器给他一定的白名单时候,发现可以进行添加IP,删除IP操作!

docker run -it --rm --cap-add=NET_ADMIN busybox
/ # ip addr add 172.25.0.100/24 dev eth0
/ # ip addr del 172.25.0.100/24 dev eth0


进行添加IP:172.25.0.100

删除ip

以上是关于Docker限制容器的Block IO的主要内容,如果未能解决你的问题,请参考以下文章

限制容器的 Block IO - 每天5分钟玩转 Docker 容器技术(29)

centos7下安装docker(9.3容器对资源的使用限制-Block IO))

Docker设置容器CPUmemory磁盘IO资源限制

Docker-安全CPU限额内存限制IO限制安全加固

Docker 限制容器资源

docker 容器资源限制