14 May 2020
我不是docker和容器方面的专家,甚至连熟练使用都算不上。此文只是自己在学习容器路上的一个个人认识的小结和浅谈,大家不要根据此文章的内容当做自己技术成长的依据,一定要结合大牛的技术文章来看。
学习过docker的都知道,docker是CS结构,其中服务端这个daemon(在19.03之前)是必须要用root启动的。docker的daemon控制了启动容器的生命,同时,docker的daemon是可以远程访问的,且并没有强制tls加密。
这就造成了docker daemon就像是一个镇国大将军(linux kernel是皇帝,拥有最高权限),它拥有很高的权限(root运行、能控制容器的一切),又对自己收到的情报从不验证(无tls通信验证)。这样就导致了,一旦有敌国的人欺骗了这位大将军,传递了错误的信息,就有可能造成很大破坏。
同时,不光是敌国假消息欺骗(因为没有通信验证)方面,如果内部的间谍(别有用心的用户)假借将军虎符(使用特权模式启动容器),并挟持了敌国的要害(挂载了宿主机根目录到容器中)。那么敌国真的是可以为所欲为了。
docker daemon其实就是一个容器管理服务端,关于容器的实现,其实都是linux kernel提供的能力。和虚拟机不同,容器其实是在一定的资源隔离的情况下(kernel提供的能力),来给某个进程提供了一个独立的运行环境。
所以容器,其实就是一个特殊环境下的进程,本身所有的进程,应该是按照树状结构挂在linux系统上面的,但是因为docker的daemon设计,导致了所有容器进程,都挂在了docker-daemon下面。这样的设计带来了几个问题
并没有一个机制来保证容器的镜像内部是安全的,我记得我道听途说过一个数据,说是现在docker hub上的热门镜像中,高危漏洞的就有67%,其中就包括nginx。当然,且不论这个数据是否准确,确实现在在常规的容器操作流程里面,没有镜像的安全检查和审核这样一个机制。
在19.03版本之前,docker daemon只能用root运行,而且运行的容器与宿主机的uid是一致的。这样就导致一个问题,如果容器内进程用户是root,那么对于映射到容器中的文件来说,和宿主机的root访问这些文件是一样的效果。
另一个问题是,kernel只做了cgroups和namespace的隔离,并未实现资源的完整隔离。这就导致,我们无法获取容器本身分配资源的使用情况,因为你在容器内部使用free和top等命令的时候,获取的是宿主机的资源情况。在应用的使用方面,造成的困扰举个例子的话,就是nginx的auto配置,nginx是无法准确的获取到宿主机给容器分配了多少cpu资源的。
当然,关于磁盘方面亦是,因为不完整的资源隔离,某一个容器如果无限制的使用磁盘,会影响整个系统。
安全无小事,容器虽然因为其优点,被广泛应用,但是对于其安全上的缺陷,我们还是要慎之又慎,直面缺陷,做好防护
参考文档: