docker安全

48 篇文章 1 订阅

前言:

docker内部的隔离机制是通过namespace来做的,但是在Linux系统里面很多东西是不能通过namespace来隔离的,比如:时间。
容器的资源控制,而namespace把容器在我们的linux系统网络成为独立个体,并不能做资源限制,很可能一个容器上面跑了一个java程序,但是这个容器把我们的内存占用完了,那么这是不合理的。

所以一定要对docker容器的配额进行限额,资源限制。

docker内部通过Cgroup直接进行资源限制,我们可以在run建立容器时加参数进行控制。

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

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

命名空间隔离的安全

  • 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间。命名空间提供了最基础也最直接的隔离。
  • 与虚拟机方式相比,通过Linux namespace来实现的隔离不是那么彻底。
  • 容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核。
  • 在 Linux 内核中,有很多资源和对象是不能被 Namespace 化的,比如:时

控制组资源控制的安全

  • 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。
  • Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等资源。
  • 确保当发生在容器内的资源压力不会影响到本地主机系统和其他
  • 容器,它在防止拒绝服务攻击(DDoS)方面必不可少。

今天我们主要讲一下cgroup机制对容器资源的控制能力。

首先了解一下几个控制器:

  • blkio: 这个subsystem可以为块设备设定输入/输出限制,比如物理驱动设备(包括磁盘、固态硬盘、USB等)。
  • cpu: 这个subsystem使用调度程序控制task对CPU的使用。
  • cpuacct: 这个subsystem自动生成cgroup中task对CPU资源使用情况的报告。
  • cpuset: 这个subsystem可以为cgroup中的task分配独立的CPU(此处针对多处理器系统)和内存。
  • devices: 这个subsystem可以开启或关闭cgroup中task对设备的访问。
  • freezer: 这个subsystem可以挂起或恢复cgroup中的task。
  • memory: 这个subsystem可以设定cgroup中task对内存使用量的限定,并且自动生成这些task对内存资源使用情况的报告。
  • perf_event: 这个subsystem使用后使得cgroup中的task可以进行统一的性能测试。
  • net_cls: 这个subsystem Docker没有直接使用,它通过使用等级识别符(classid)标记网络数据包,从而允许 Linux 流量。

一、实验环境(rhel7.3)

  • 1、selinux和firewalld为disabled
  • 2 各主机信息
主机IP
server1172.25.1.1

二、设定 内存+交换分区 <=200M

1、针对系统中的某个进程

<1> 安装cgroup服务,可以提供cgexec命令

[root@server1 ~]# yum install libcgroup-tools.x86_64 -y
[root@server1 ~]# mount -t cgroup
[root@server1 ~]# cd /sys/fs/cgroup/memory/
[root@server1 memory]# cat memory.limit_in_bytes   #由文件内容,可以知道,内存未做限制。
9223372036854771712
[root@server1 memory]# cat memory.memsw.limit_in_bytes
9223372036854771712

在这里插入图片描述

<2>设定资源限制参数:内存+交换分区<=200M

[root@server1 ~]# cd /sys/fs/cgroup/memory/
[root@server1 memory]# mkdir xin/   #创建目录xin,该目录的名字随意给。在/sys/fs/cgroup/memory目录中创建的目录,自动继承/sys/fs/cgroup/memory目录中的内容。
#创建该目录的目的是(1)为了演示容器的运行过程。因为一旦运行容器,就会在该目录下,生成一个docker目录,docker目录中会生成容器ID对应的目录,目录中memory目录下的内容继承于/sys/fs/cgroup/memeory目录下的内容。(2)直接修改/sys/fs/cgroup/memory中的文件的内容,会报错。
[root@server1 xin]# echo 209715200 > memory.limit_in_bytes   #设定最大占用内存为200M(209715200=200*1024*1024。209715200的单位为BB)
[root@server1 xin]# echo 209715200 > memory.memsw.limit_in_bytes   #因为最大占用内存数和最大占用swap分区的内存数一样。表明最大可用内存为200M,可用swap为0M。即限制了内存+交换分区<=200M
[root@server1 xin]# cat memory.limit_in_bytes   
209715200
[root@server1 xin]# cat memory.memsw.limit_in_bytes   
209715200
 
值的注意的是:/sys/fs/cgroup/memory目录中的文件,不能用vim进行编辑,利用vim进行编辑,无法进行保存退出(即使使用"wq!",也不能保存退出。)

在这里插入图片描述
现在的内存可用available:1651M
在这里插入图片描述

3、<测试>

[root@server1 ~]# cd /dev/shm/		#值的注意的是:在该目录下进行操作,相当于直接占用内存。
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.0467416 s, 2.2 GB/s
[root@server1 shm]# free -m		#内存可用少了100M
              total        used        free      shared  buff/cache   available
Mem:           2000         136         177         116        1687        1550
Swap:          2047           0        2047
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300	#因为指定的文件的大小为300M超过了限制,所以显示Killed
Killed
[root@server1 shm]# free -m		#dd命令最多只能占用内存200M
              total        used        free      shared  buff/cache   available
Mem:           2000         136          78         215        1786        1451
Swap:          2047           0        2047
  • available=1651-200=1451
    在这里插入图片描述

补充内容:

  • 如果不对内存和swap分区进行限制,即不修改/sys/fs/cgroup/memory/memory.limit_in_bytes和/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes文件中的内容。那么不管要生成的bigfile文件的大小为多少,dd命令永远会成功。
    在这里插入图片描述
  • 如果只是对内存进行限制(限制为200M),而没有对交换f分区进行限制,即只修改/sys/fs/cgroup/memory/memory.limit_in_bytes文件中的内容,而并没有修改/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes文件中的内容。那么如果要生成的bigfile文件的大小大于200M,dd命令会成功,但是只有200M是取自内存,剩余的取自交换分区。
    在这里插入图片描述
  • 可以看到不限制交换分区的话,如果只限制内存,内存使用到额度后,会占用交换分区!!!

2、针对docker容器

<1>指定内存和交换分区的大小,运行容器

[root@server1 ~]# docker run -it --name vm1 --memory 209715200 --memory-swap 209715200 ubuntu   #利用ubuntu镜像运行容器vm1,指定内存+交换分区<200M。并使用Ctrl+p+q退出,即不要让容器停掉。

<2>查看设置是否生效

[root@server1 ~]# cd /sys/fs/cgroup/memory/docker/b58c1d873ed7efb5b7ee6be1552f79c6679ba452713c91c467055d9d4d5aab78/   #b58c1d873ed7efb5b7ee6be1552f79c6679ba452713c91c467055d9d4d5aab78为容器vm1的容器ID号
[root@server1 b58c1d873ed7efb5b7ee6be1552f79c6679ba452713c91c467055d9d4d5aab78]# cat memory.limit_in_bytes 
209715200
[root@server1 b58c1d873ed7efb5b7ee6be1552f79c6679ba452713c91c467055d9d4d5aab78]# cat memory.memsw.limit_in_bytes 
209715200
[root@server1 b58c1d873ed7efb5b7ee6be1552f79c6679ba452713c91c467055d9d4d5aab78]# ls
cgroup.clone_children           memory.kmem.tcp.max_usage_in_bytes  memory.oom_control
cgroup.event_control            memory.kmem.tcp.usage_in_bytes      memory.pressure_level
cgroup.procs                    memory.kmem.usage_in_bytes          memory.soft_limit_in_bytes
memory.failcnt                  memory.limit_in_bytes               memory.stat
memory.force_empty              memory.max_usage_in_bytes           memory.swappiness
memory.kmem.failcnt             memory.memsw.failcnt                memory.usage_in_bytes
memory.kmem.limit_in_bytes      memory.memsw.limit_in_bytes         memory.use_hierarchy
memory.kmem.max_usage_in_bytes  memory.memsw.max_usage_in_bytes     notify_on_release
memory.kmem.slabinfo            memory.memsw.usage_in_bytes         tasks
memory.kmem.tcp.failcnt         memory.move_charge_at_immigrate
memory.kmem.tcp.limit_in_bytes  memory.numa_stat
[root@server1 b58c1d873ed7efb5b7ee6be1552f79c6679ba452713c91c467055d9d4d5aab78]# cat tasks 	#看到的任务号,正是容器vm1对应的Pid
13498
  • 查看容器vm1的容器ID号
    在这里插入图片描述
  • 查看容器vm1的Pid号
    在这里插入图片描述
    值的注意的是:因为容器的隔离性并不是很好,所以在容器内使用命令"free -m"看到的内容与宿主机上使用命令"free -m"看到的内容相同。所以如果要看是否限制成功,需要进入容器对应的目录中进行查看。

补充内容:

–memory可以单独使用,但是–memory-swap是必须要与–memory一起使用的

正常情况下,–memory-swap的值包含容器可用内存和可用swap,所以–memory=“300m” --memory-swap="1g"的含义为:容器可以使用300M的物理内存,并且可以使用700M(1G-300M)的swap。–memory-swap 是容器可以使用的物理内存和可以使用的swap之和!
把–memory-swap设置为0和不设置是一样的,此时如果设置了–memory,则容器可以使用两倍–memory容量的swap。–memory=“300m”,–memory-swap没有设置,相当于可以使用300m内存+600m的swap
如果–memory-swap的值和–memory相同,则容器不能使用swap。
如果–memory-swap设置为-1,相当于不限制swap的容量,但是会受host主机的swap容量
在容器内部,free看到的swap是host的swap,并不是容器可用的swap容量。
–oom-kill-disable 当OOM(Out Of Memory)发生的时候,内核会kill掉容器内的进程,为了改变这种行为,可以在设置–memory的时候,同时设置–oom-kill-disable。如果没有设置–oom-kill-disable,则host可能会OOM,这时候内核会kill host的系统进程来释放memory。

三、针对cpu的限制

1、针对系统的某一个进程

<1>对cpu.cfs_quota_us写入整数值可以控制占用的cpu的大小
[root@server1 cpu]# mkdir x2
[root@server1 cpu]# cd x2/
[root@server1 x2]# echo 20000 > cpu.cfs_quota_us 		#占用"20000/100000=20%"的CPU
[root@server1 x2]# cat cpu.cfs_quota_us 
20000
[root@server1 x2]# 
值的注意的是:/sys/fs/cgroup/cpu目录中的文件,不能用vim进行编辑,利用vim进行编辑,无法进行保存退出(即使使用"wq!",也不能保存退出。)

<2>测试

[root@server1 ~]# dd if=/dev/zero of=/dev/null &
[1] 13799
[root@server1 ~]# top		#看到dd命令占用的cpu比例将近为100%,这是因为还没有在tasks文件中写入要限制的进程号
13799 root      20   0  107940    608    516 R 99.9  0.0   0:45.50 dd
[root@server1 ~]# cd /sys/fs/cgroup/cpu/x2/
[root@server1 x2]# cat tasks 
[root@server1 x2]# echo 13799 > tasks 		#写入dd命令的进程号,对该进程进行限制
[root@server1 x2]# cat tasks 
13799
[root@server1 x2]# top		#看到dd命令占用的cpu比例在20%左右。
13799 root      20   0  107940    608    516 R 20.0  0.0   2:01.65 dd
[root@server1 x2]# kill -9 13799		#当dd命令对应的进程杀掉之后,tasks文件中的进程号,也会随之消失
[root@server1 x2]# cat tasks

补充:

  • 如果不对cpu进行限制,即不修改/sys/fs/cgroup/cpu/cpu.cfs_quota_us(文件内容默认是-1,表示不限制)文件中的内容。那么执行命令"dd if=/dev/zero of=/dev/null &"时,会占用100%的cpu。
  • cpu.cfs_period_us:cpu分配的周期(微秒),默认为100000。
  • cpu.cfs_quota_us:表示该control group限制占用的时间(微秒),默认为-1,表示不限制。如果设为50000,表示占用50000/100000=50%的CPU。

2、针对docker容器

<1>指定占用的cpu的大小,运行容器

[root@server1 ~]# docker run -it --name vm2 --cpu-quota 20000 ubuntu		#利用ubuntu镜像运行容器vm2,指定占用的cpu的大小,并使用Ctrl+p+q退出,即不要让容器停掉。
root@42f539ae0a3d:/# dd if=/dev/zero of=/dev/null &		#执行dd命令
[1] 15

<2>测试

[root@server1 xin]# top
13921 root      20   0    4368    356    280 R 19.9  0.0   0:13.15 dd
[root@server1 ~]# cd /sys/fs/cgroup/cpu
[root@server1 cpu]# cd docker/
[root@server1 docker]# ls
42f539ae0a3d30e27d350356a9f50ac4ac46cc71b1bd3c465cc0b56bd5d158f0  cpu.cfs_period_us
b58c1d873ed7efb5b7ee6be1552f79c6679ba452713c91c467055d9d4d5aab78  cpu.cfs_quota_us
cgroup.clone_children                                             cpu.rt_period_us
cgroup.event_control                                              cpu.rt_runtime_us
cgroup.procs                                                      cpu.shares
cpuacct.stat                                                      cpu.stat
cpuacct.usage                                                     notify_on_release
cpuacct.usage_percpu                                              tasks
[root@server1 docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
42f539ae0a3d        ubuntu              "/bin/bash"         2 minutes ago       Up 2 minutes                            vm2
b58c1d873ed7        ubuntu              "/bin/bash"         2 hours ago         Up 2 hours                              vm1
[root@server1 docker]# cd 42f539ae0a3d30e27d350356a9f50ac4ac46cc71b1bd3c465cc0b56bd5d158f0/
[root@server1 42f539ae0a3d30e27d350356a9f50ac4ac46cc71b1bd3c465cc0b56bd5d158f0]# cat cpu.cfs_quota_us
20000
[root@server1 42f539ae0a3d30e27d350356a9f50ac4ac46cc71b1bd3c465cc0b56bd5d158f0]# cat tasks
13877
13921
  • 查看容器vm2的容器Pid
    在这里插入图片描述
  • 补充内容

如果在运行容器时,不对cpu进行限制,那么在容器内执行命令"dd if=/dev/zero of=/dev/null",cpu的占有率会接近100%
在这里插入图片描述
在这里插入图片描述

四、 针对写速率的限制

针对docker容器

<1>赋予全部的权限运行容器(因为直接运行容器的话,是以普通用户的身份进行登录的,会没有权限),查看容器内的磁盘名称

首先不做任何操作运行容器:(普通用户身份)
在这里插入图片描述
全部的权限运行容器:

[root@server1 ~]# docker run -it --rm --privileged=true ubuntu
root@3b02bf2d4f39:/# fdisk -l

Disk /dev/sda: 21.5 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders, total 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00018bf3

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     2099199     1048576   83  Linux
/dev/sda2         2099200    41943039    19921920   8e  Linux LVM

<2>限制写入的速率,运行容器,并进行测试

[root@server1 ~]# docker run -it --rm --device-write-bps /dev/sda:20MB ubuntu		#以写入速率为20M/s的限制运行容器
root@246b26416405:/# dd if=/dev/zero of=file bs=1M count=300 oflag=direct		截取300M的名为file的文件。其中参数oflag=direct表示跳过内存缓存,直接存在磁盘中。必须加该参数,否则测试会失败。
300+0 records in
300+0 records out
314572800 bytes (315 MB) copied, 14.929 s, 21.1 MB/s  #看到速率为201.1 MB/s,表示配置成功

五、Block IO限制

我们首先查看我们的memory控制器是否存在:

[root@server1 x1]# pwd
/sys/fs/cgroup/memory/x1
[root@server1 x1]# echo 314572800 > memory.limit_in_bytes 
[root@server1 x1]# cat memory.limit_in_bytes
314572800
[root@server1 x1]# echo 314572800 > memory.memsw.limit_in_bytes 
[root@server1 x1]# cat memory.memsw.limit_in_bytes
314572800

建立一个测试用户:

[root@server1 x1]# useradd zhao

编辑文件,配置

[root@server1 x1]# vim /etc/cgrules.conf
zhao    memory          x1/ 
用户	     内存        控制器

启动服务:

[root@server1 ~]# systemctl start cgred.service 
[root@server1 ~]# systemctl status cgred.service

在这里插入图片描述
测试:

[root@server1 x1]# su - zhao
Last login: Wed Jun  5 19:53:45 CST 2019 on pts/0
[zhao@server1 ~]$ cd /dev/shm/
[zhao@server1 shm]$ dd if=/dev/zero of=bigfile bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.0412313 s, 2.5 GB/s
[zhao@server1 shm]$ dd if=/dev/zero of=bigfile bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 0.072628 s, 2.9 GB/s
[zhao@server1 shm]$ dd if=/dev/zero of=bigfile bs=1M count=400
Killed
[zhao@server1 shm]$ du -h bigfile 
298M	bigfile
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值