一、理解Docker安全
Docker容器的安全性,很大程度上依赖于Linux系统自身,评估Docker的安全性时,主要考虑以下几个方面:
1、Linux内核的命名空间机制提供的容器隔离安全
2、Linux控制组机制对容器资源的控制能力安全。
3、Linux内核的能力机制所带来的操作权限安全
4、Docker程序(特别是服务端)本身的抗攻击性。
5、其他安全增强机制对容器安全性的影响。

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

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

3、内核的能力机制
(1)内核能力机制(capability)是linux内核的一个强大特性,可以提供细粒度的权限访问控制。
(2)大部分情况下,容器并不需要“真正的”root权限,容器只需要少数的能力即可,容器内的超户并不是真正的超户。
(3)默认情况下,Docker采用“白名单”机制,禁用“必需”功能之外的其他权限

4、Docker服务端防护
(1)使用Docker容器的核心是Docker服务端,确保只有可信的用户才能访问Docker服务(对服务端进行证书加密)。
(2)将容器的root用户映射到本地主机上的非root用户,减轻容器和主机之间因权限提升而引起的安全问题。
(3)允许Docker服务端在非root权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作,这些子进程只允许在特定范围内进行操作。

5、其他安全特性
(1)在linux内核中启用GRSEC和PAX,这将增加更多的编译和运行时的安全检查,并且通过地址随机化机制来避免恶意探测等,启用该特性不需要Docker进行任何配置。
(2)使用一些增强安全特性的模板。
(3)用户可以自定义更加严格的访问控制机制来定制安全策略。
(4)在文件系统挂载到容器内部时,可以通过配置只读模式来避免容器内的应用通过文件系统破坏外部环境,特别是一些系统运行状态相关的目录。

二、容器资源控制
对容器实现资源控制我们使用的时由Linux提供cgroups机制

cgroups定义

cgroups,其名称源自控制组群(control groups)的简写,是Linux内核的一个功能,用来限制、控制与分离一个进程组的资源上限(如CPU、内存、磁盘输入输出等)。
cgroups给用户暴露出来的操作接口是文件系统,他以文件和目录的方式在/sys/fs/cgroup
执行mount -t cgroup查看

cgroups作用

Cgroups最初的目标是为资源管理提供的一个统一的框架,既整合现有的cpuset等子系统,也为未来开发新的子系统提供接口。现在的cgroups适用于多种应用场景,从单个进程的资源控制,到实现操作系统层次的虚拟化(OS Level Virtualization)。Cgroups提供了以下功能:
1.限制进程组可以使用的资源数量(Resource limiting )。比如:memory子系统可以为进程组设定一个memory使用上限,一旦进程组使用的内存达到限额再申请内存,就会触发OOM(out of memory)。
2.进程组的优先级控制(Prioritization )。比如:可以使用cpu子系统为某个进程组分配特定cpu share。
3.记录进程组使用的资源数量(Accounting )。比如:可以使用cpuacct子系统记录某个进程组使用的cpu时间
4.进程组隔离(Isolation)。比如:使用ns子系统可以使不同的进程组使用不同的namespace,以达到隔离的目的,不同的进程组有各自的进程、网络、文件系统挂载空间。
5.进程组控制(Control)。比如:使用freezer子系统可以将进程组挂起和恢复。

<一>、CPU和内存的控制
1、命令设置限制CPU

docker run --cpu-period 100000 --cpu-quota 20000 -it --name demo busybox
#设置--cpu-period和--cpu-quota,两个参数需组合使用,限制进度在--cpu-period的时间内只能被分到总量为--cpu-quota的CPU时间。20%

docker安全审计 docker 安全_docker安全审计


2、命令设置限制内存使用

[root@server2 shm]# docker run --memory 200M --memory-swap 200M -it busybox
#但是隔离不彻底,显示仍为宿主及内存,但是实际内存限制是生效的。和手动一样也是通过该文件生效的
cd /sys/fs/cgroup/memory/docker/
[root@server2 docker]# cd 9fba95adc0a5087841149c447acaaa1a7467142635ed9175363a5a820963a744
[root@server2 9fba95adc0a5087841149c447acaaa1a7467142635ed9175363a5a820963a744]# cat memory.memsw.limit_in_bytes 
209715200

3、安装cgroup,可提供cgexec命令

[root@server1 ~]# yum install libcgroup-tools.x86_64 -y
[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 		#swap内存
9223372036854771712

docker安全审计 docker 安全_docker_02


4、手动配置-CPU控制优先级

cpu.shares #优先级

(1)创建一个cpu控制器目录

cgcreate -g cpu:x1		#创建一个cpu控制器目录
[root@server2 x1]# pwd
/sys/fs/cgroup/cpu/x1
[root@server2 x1]# cat cpu.shares 
1024

docker安全审计 docker 安全_Docker_03

[root@server2 x1]# cd /sys/devices/system/cpu/
[root@server2 cpu]# ls		#除CPU0外其他都可以删掉
cpu0  cpu1  cpuidle  isolated  kernel_max  modalias  nohz_full  offline  online  possible  power  present  smt  uevent  vulnerabilities
[root@server2 cpu1]# echo 0 > online 	#0放在online,1为offline,禁用一个cpu

docker安全审计 docker 安全_运维_04


docker安全审计 docker 安全_进程组_05


(2)进程优先级控制cpu占用百分比

dd if=/dev/zero of=/dev/null &		#只跑一个cpu会占满,跑两个会平分,因为优先级相同。
fg+ctrlC				#删除一个后只剩一个占满cpu

docker安全审计 docker 安全_docker_06


docker安全审计 docker 安全_运维_07

[root@server2 cpu1]# cd /sys/fs/cgroup/cpu/x1/
[root@server2 x1]# echo 100 > cpu.shares
[root@server2 x1]# cat cpu.shares 
100
#使用新建的x1控制器的优先级
cgexec -g cpu:x1 dd if=/dev/zero of=/dev/null &		#dd指令运行在x1控制器下

docker安全审计 docker 安全_Docker_08


docker安全审计 docker 安全_docker安全审计_09

[root@server2 x1]# cat tasks 	#进程pid,删掉进程后为空
4580

docker安全审计 docker 安全_docker_10


(3)分到总量为–cpu-quota的CPU控制cpu占用百分比

[root@server2 x1]# echo 20000 > cpu.cfs_quota_us
[root@server2 x1]# cgexec -g cpu:x1 dd if=/dev/zero of=/dev/null &
[1] 4608
[root@server2 x1]# cgexec -g cpu:x1 dd if=/dev/zero of=/dev/null &
[2] 4610
#在来一个两个进程共占20%
[root@server2 x1]# cat tasks 
4608
4610

docker安全审计 docker 安全_Docker_11


docker安全审计 docker 安全_docker_12


docker安全审计 docker 安全_运维_13


docker安全审计 docker 安全_Docker_14


(4)删除一个cpu控制器目录

[root@server2 cpu]# cgdelete -g cpu:x1

5、手动配置-设置指定限制内存memory

[root@server2 memory]# pwd
/sys/fs/cgroup/memory

(1)创建一个cpu控制器目录

[root@server2 memory]# cgcreate -g memory:x2

docker安全审计 docker 安全_运维_15


(2)通过内存资源限制限制cpu

[root@server2 x2]# echo 209715200 > memory.limit_in_bytes
[root@server2 x2]# cat memory.limit_in_bytes
209715200
[root@server2 shm]# cd /dev/shm		#写入数据会受限制为200M,但是root用户不会。
[root@server2 shm]# cgexec -g memory:x2 dd if=/dev/zero of=bigfile bs=1M count=100
[root@server2 shm]# free -m
              total        used        free      shared  buff/cache   available
Mem:            991         160         268         112         561         564
Swap:          2047           0        2047

[root@server2 shm]# cgexec -g memory:x2 dd if=/dev/zero of=bigfile bs=1M count=300
[root@server2 shm]# free -m		#300虽然可以但是是物理内存只允许损耗200M,swap分区代替损耗100M
              total        used        free      shared  buff/cache   available
Mem:            991         161         169         210         660         465
Swap:          2047         102        1945

docker安全审计 docker 安全_docker_16


docker安全审计 docker 安全_Docker_17


(3)swap分区占用也进行限制

[root@server2 x2]# echo 209715200 > memory.memsw.limit_in_bytes 
[root@server2 x2]# cat memory.memsw.limit_in_bytes 
209715200
[root@server2 shm]# cgexec -g memory:x2 dd if=/dev/zero of=bigfile bs=1M count=300	#内存溢出,只允许用200M
Killed

docker安全审计 docker 安全_运维_18


docker安全审计 docker 安全_docker_19


(4)删除一个cpu控制器目录

[root@server2 ~]# cgdelete -g memory:x2

<二>、Block IO限制
限制写入速度

docker run -it --device-write-bps /dev/sda:10MB ubuntu
#–device-write-bps限制写设备的bps

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

dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct