一    相关说明

Docker容器的安全性,很大程度上依赖于Linux系统自身!

生产环境中评估Docker的安全性时,主要考虑以下几个方面:

#(1)Linux内核的命名空间机制提供的容器隔离安全 

#(2)Linux控制组机制对容器资源的控制能力安全

#(3)Linux内核的能力机制所带来的操作权限安全,Docker程序(特别是服务端)本身的抗攻击性。

二    相关概念的理解

什么是(what)cgroup

      Cgroups 是 control groups(控制组) 的缩写,是Linux内核提供(主体)的一种可以限制、记录、隔离进程组(process groups)所使用物理资源(cpu、memory、IO等)的机制。最初由 google 的工程师提出,后来被整合进 Linux 内核。Cgroups 也是 LXC 为实现虚拟化所使用的资源管理手段,可以说没有cgroups就没有LXC!

干什么(do)

    限制进程组可以使用的资源数量(Resource limiting )

# memory子系统可以为进程组设定一个memory使用上限,一旦进程组使用的内存达到限额再申请内存,就会出发OOM(out of memory)

优先级控制(Prioritization )

#  比如可以使用cpu子系统为某个进程组分配特定cpu share

资源数量(Accounting )

#  比如可以使用cpuacct子系统记录某个进程组使用的cpu时间

进程组隔离(Isolation)

# 比如使用ns子系统可以使不同的进程组使用不同的namespace,以达到隔离的目的,不同的进程组有各自的进程、网络、文件系统挂载空间

控制(Control)

#  比如使用freezer子系统可以将进程组挂起和恢复

四个概念

# (1)Subsystems: 称之为子系统,一个子系统就是一个资源控制器,比如 cpu子系统就是控制cpu时间分配的一个控制器
# (2)Hierarchies: 可以称之为层次体系也可以称之为继承体系,指的是Control Groups是按照层次体系的关系进行组织的
# (3)Control Groups: 一组按照某种标准划分的进程。进程可以从一个Control Groups迁移到另外一个Control Groups中,同时Control Groups中的进程也会受到这个组的资源限制
# (4)Tasks: 在cgroups中,Tasks就是系统的一个进程

三   命名空间隔离的安全

  (1)当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间

docker容器密码_docker容器密码

结论1:命名空间提供了最基础也最直接的隔离,但是与虚拟机方式相比,通过Linux namespace来实现的隔离不是那么彻底

结论2:容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用(共享)一个宿主机的操作系统内核

补充:在 Linux 内核中,有很多资源和对象是不能被 Namespace 化的,比如:时间

核心:我们无法控制资源的共享,但是可以控制资源的上限!

  内核的命名空间起到隔离的作用,但是内核是共享的,所以无法做隔离!可以操作操作系统上所有挂接的group!

明确:默认对容器是没有控制的,但是每个控制器(控制项)都有一个docker目录,直接复制上级得来的!

小知识:Linux中其它的限制模块:limits security、pam 等其他控制模块!

四    控制组资源控制的安全

(1)当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合

docker容器密码_Docker_02

  • 通过新建文件夹创建一个cpu控制族群:mkdir x1,即新建了一个cpu控制族群:x1
  • 新建x1之后,可以看到目录下自动建立了相关的文件,这些文件是伪文件

docker容器密码_安全_03

补充一个实验:通过容器的创建删除看对应目录下docker的变化!

回顾

docker容器密码_安全_04

docker容器密码_docker容器密码_05

1)CPU的限制

(1)聊一聊系统层面CPU的限制

docker容器密码_进程组_06

说明:双核不会争抢,可以做CPU的绑定,默认三个才会争抢

docker容器密码_Docker_07

相关参数的说明

# pu.cfs_period_us:cpu分配的周期(微秒),默认为100000。

# cpu.cfs_quota_us:表示该control group限制占用的时间(微秒),默认为-1,表示不限制。

# 如果设为50000,表示占用50000/100000=50%的CPU

docker容器密码_进程组_08

现象:此时CPU的负载情况仍然没有发生变化,因为没有关联Pid的原因!

[root@docker1 x1]# dd if=/dev/zero of=/dev/null &
[1] 2962
[root@docker1 x1]# echo 2962 > tasks

2)聊一聊对Docker容器的限制

docker容器密码_进程组_09

优先级:在争抢的时候生效(默认是1024)!

docker容器密码_安全_10

docker容器密码_docker_11

docker容器密码_docker_12

(2)聊一聊对内存的限制

1)对系统进程的内存限制

docker容器密码_进程组_13

说明:可用内存包括两个部分,物理内存和swap交换分区,如果物理内存不够,swap来补充!

Swap作用:操作系统没有物理内存,才会使用,加快用户和硬件的响应!

# 安装相应的软件包

yum install libcgroup-tools.x86_64

# 说明:下一步是在上一步做内存限制的基础上!

docker容器密码_docker_14

进一步:做swap的限制

docker容器密码_进程组_15

2)看对Docker的限制

# 容器可用内存包括两个部分:物理内存和swap交换分区。

#(1)--memory设置内存使用限额

#(2)--memory-swap设置swap交换分区限额

docker容器密码_进程组_16

cd 9612325e96f8faec6c6c1b2f8933eb9b2f4d152dfdff386f496bd2822c60e3a4

[root@docker1 9612325e96f8faec6c6c1b2f8933eb9b2f4d152dfdff386f496bd2822c60e3a4]# cat memory.memsw.usage_in_bytes
3698688
[root@docker1 9612325e96f8faec6c6c1b2f8933eb9b2f4d152dfdff386f496bd2822c60e3a4]# cat memory.usage_in_bytes
3698688

注意:但是此时无法以root用户删除x2的目录,需要特殊工具命令

cgdelete -g memory:x2

注意:最好不要删除,以免后面再创建,当然也可以删除,然后,再创建!

(3)对用户使用内存的限制(补充)

说明:由于linux是多用户的,所以对于某些不守规则的人要进行相应的内存限制!

docker容器密码_进程组_17

(4)对I/O的限制

## 了解这几个参数的含义!

read_bps (每妙I/O读的速率)

read_iops (每妙i/o的写次数)-->吞吐量的含义!

write_bps(每妙I/O写的速率)

write_iops(每妙i/o读的次数)-->吞吐量的含义!

# 目前的block IO限制只对direct IO有效,所以必须指明,不使用文件缓存!

docker容器密码_安全_18

(5)对容器状态的控制

生产环境中:有些顽固进程不能去kill掉,可以挂起或者暂停,不耗费资源!

docker容器密码_Docker_19

docker容器密码_安全_20

docker容器密码_安全_21

总结:Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存CPU、磁盘IO等资源

目的:确保当发生在容器内的资源压力不会影响到宿主机系统和其他容器,它可以防止拒绝服务攻击(DDoS)!

(6)资源隔离

上述引入:在容器内部和宿主机中看到内存是一样的,由于资源隔离没有做好(虽然内存生效)!

明确:但是看到的是虚假的,隔离的不好!

原因:直接挂载/proc -->跟宿主机一样!

如何做呢?利用LXCFS增强docker容器隔离性和资源可见性

docker容器密码_docker_22

docker容器密码_Docker_23

(7)用户权限(内核能力机制)

docker容器密码_安全_24

docker容器密码_安全_25

docker容器密码_docker_26

问题:资源太大

解决:黑白名单

docker容器密码_docker容器密码_27

[root@docker1 proc]# docker run --help|grep cap
      --cap-add list                   Add Linux capabilities
      --cap-drop list                  Drop Linux capabilities
[root@docker1 proc]#

docker容器密码_docker容器密码_28

capabilities手册

docker容器密码_docker容器密码_29

# 说明:需要在Docker 服务开启之前,进行初始化--->chroot

[root@docker1 docker]# ls -ld /var/lib/docker
drwx--x--x 14 root root 182 Aug  8  2019 /var/lib/docker

补充:  其他安全特性

docker容器密码_进程组_30

(6)安全加固

镜像的角度

docker容器密码_docker_31

容器的角度

docker容器密码_进程组_32

docker容器密码_docker容器密码_33

(7)Docker的安全遗留问题

docker容器密码_进程组_34

(8)顶尖的开源工具

docker容器密码_docker容器密码_35