Docker安全

2022/03/10 Docker

Docker安全

Docker自诞生以来,其安全性问题一直饱受诟病。随着Docker的发展,它自身面临的挑战也越来越大,安全问题也越来越受到人们的关注。

Docker的安全性

Docker的安全性主要体现在如下几个方面:

  • Docker容器的安全性:这是指容器是否会危害到host或其他容器。
  • 镜像的安全性:用户如何确保下载下来的镜像是可信的、未被篡改过的。
  • Docker daemon的安全性:如何确保发送给daemon的命令是由可信用户发起的。用户通过CLI或者REST API向daemon发送命令以完成对容器的各种操作,例如通过docker exec命令删除容器里的数据,因此需要保证client与daemon的连接是可信的。

这里面容器的安全性是最大的问题,也是备受关注的问题,因此下文介绍的安全策略大多是针对容器安全性的。

Docker容器的安全性

容器安全性问题的根源在于,容器和host共用内核,因此受攻击面特别大,没有人能信心满满地说不可能由容器入侵到host。共用内核导致的另一个严重问题是,如果某个容器里的应用导致Linux内核崩溃,那么整个系统都会崩溃。在这方面,虚拟机的表现就相对好多了,虚拟机与host的接口是非常有限的,攻击面自然也就非常小了,并且虚拟机崩溃一般不会导致host崩溃。

在共用内核这个前提下,容器主要通过内核的Cgroup和Namespace这两大特性来达到容器隔离和资源限制的目的。目前Cgroup对系统资源的限制已经比较完善了,但Namespace的隔离还是不够完善,只有PID、mount、network、UTS、IPC和user这几种。而对于未隔离的内核资源,容器访问时也就会存在影响到host及其他容器的风险。

比如,procfs里的很多接口都没有被隔离,因此通过procfs可以查询到整个系统的信息,例如系统的CPU、内存等资源信息。这也是为什么Docker容器的procfs是以只读方式挂载的,否则修改procfs里的内核参数,将会影响甚至破坏整个host。再例如,内核syslog也是没有被隔离的,因此在容器内可以看到容器外其他进程产生的内核syslog。

Namespace的隔离非但是不完善的,甚至可以说是不可能完善的。这是共用内核导致的固有缺陷,并且未来Linux内核社区也不会对此做太多的改进。

安全策略

正是因为容器由于内核层面隔离性差导致安全性不足,所以Docker社区开发了很多安全特性,业界也总结了一些经验,下文将给出一些主要的安全策略。

Cgroup

Cgroup用于限制容器对CPU、内存等关键资源的使用,防止某个容器由于过度使用资源,导致host或者其他容器无法正常运作,下面将详细介绍Docker如何使用Cgroup。

  • 限制CPU Docker能够指定一个容器的CPU权重,这是一个相对权重,与实际的处理速度无关。事实上,没有办法限制一个容器只可以获得1GHZ的CPU。每个容器默认的CPU权重是1024,简单地说,假设只有两个容器,并且这两个容器竞争CPU资源,那么CPU资源将在这两个容器之间平均分配。如果其中一个容器启动时设置的CPU权重是512,那它相对于另一个容器只能得到一半的CPU资源,因此这两个容器可以得到的CPU资源分别是33.3%和66.6%。但如果另外一个容器是空闲的,第一个容器则会被允许使用100%的CPU。也就是说,CPU资源不是预先硬性分配好的,而是跟各个容器在运行时对CPU资源的需求有关。 例如,可以为容器设置CPU权重为100,如下:
    $ docker run --rm -ti -c 100 ubuntu bash
    

    另一方面,Docker也可以明确限制容器对CPU资源的使用上限,如下:

    $ docker run –-rm –ti --cpu-period=500000 --cpu-quota=250000 ubuntu /bin/bash
    

    上面的命令表示这个容器在每个0.5秒里最多只能运行0.25秒。 除此之外,Docker还可以把容器的进程限定在特定的CPU上运行,例如将容器限定在0号和1号CPU上运行:

    $ docker run -it --rm --cpuset-cpus=0,1 ubuntu bash
    
  • 限制内存 除了CPU,内存也是应用不可或缺的一个资源,因此一般来说必须限制容器的内存使用量。限制命令如下:
    $ docker run --rm -ti -m 200M ubuntu bash
    

    这个例子将容器可使用的内存限制在200MB。不过事实上还不是这么简单,我们知道系统在发现内存不足时,会将部分内存置换到swap分区里,因此如果只限制内存使用量,可能会导致swap分区被用光。通过–memory-swap参数可以限制容器对内存和swap分区的使用,如果只是指定-m而不指定–memory-swap,那么总的虚拟内存大小(也即memory加上swap)是-m参数的两倍。

Search

    微信好友

    博士的沙漏

    Table of Contents