Docker容器的隔离与限制

Linux容器中用来实现“隔离”的技术手段:Namespace。 Namespace实际上修改了应用进程看待整个计算机“视图”,即它的“视线”被操作系统做了限制,只能“看到”某些指定的内容对于宿主机来说,这些被“隔离”了的进程跟其他进程并没有区别。

一、Namespace 技术

Namespace 并不是一个新技术,它是Linux操作系统默认提供的API,包括 PID Namespace、Mount Namespace、IPC Namespace、Network Namespace等等。

以 PID Namespace 为例,它的功能是可以让我们在创建进程的时候,告诉Linux系统,我们要创建的进程需要一个新的独立进程空间,并且这个进程在这个新的进程空间里的PID=1,也就是说,这个进程只看得到这个新进程空间里的东西,看不到外面宿主机环境里的东西,也看不到其它进程。

另外,Network Namespace 的技术原理也类似,让这个进程只能看到当前Namespace空间里的网络设备,看不到宿主机真实情况。Namespace 技术其实就是修改了应用进程的视觉范围,但应用进程的本质却没有变化。

二、Cgroups 技术

Cgroup 其功能就是限制进程组所使用的最大资源(这些资源可以是 CPU、内存、磁盘等等)。

Namespace 技术只能改变一下进程组的视觉范围,并不能真实的对资源做出限制。那么为了防止容器(进程)之间互相抢资源,甚至某个容器把宿主机资源全部用完导致其它容器也宕掉的情况发生。因此,必须采用 Cgroup 技术对容器的资源进行限制。

Cgroup 技术也是Linux默认提供的功能,在Linux系统的 /sys/fs/cgroup 下面有一些子目录 cpu、memory等,Cgroup技术提供的功能就是可以基于这些目录实现对这些资源进行限制。Cgroup 对其它内存、磁盘等资源也是采用同样原理做限制。

三、Namespace隔离机制相比于虚拟化技术有很多不足之处

1、多个容器之间使用的还是同一宿主机的操作系统内核

在容器里通过 Mount Namespace 单独挂载其他不同版本的操作系统文件,比如 CentOS 或者 Ubuntu,但这并不能改变共享宿主机内核的事实。这代表如果要在Windows宿主机上运行Linux容器,或者在低版本的Linux宿主机上运行高版本的Linux容器,都是impossible!

2、Linux内核中很多资源和对象是不能被Namespace化 

最典型的例子:时间
如果你的容器中的程序使用settimeofday(2)系统调用修改了时间,整个宿主机的时间都会被随之修改,这显然不符合用户的预期 相比于在虚拟机里面可以随便折腾,在容器里部署应用的时候,“什么能做,什么不能做”,都是用户必须考虑的问题。
 

3、容器给应用暴露出来的攻击面是相当大

应用“越狱”的难度自然也比虚拟机低得多。
尽管可以使用Seccomp等技术,过滤和甄别容器内部发起的所有系统调用来进行安全加固,但这就多了一层对系统调用的过滤,一定会拖累容器的性能。何况,默认情况下,谁也不知道到底该开启哪些系统调用,禁止哪些系统调用。
所以,在生产环境中,没有人敢把运行在物理机上的Linux容器直接暴露到公网上。
 

4、限制容器 

以PID Namespace为例

虽然容器内的第1号进程在“障眼法”的干扰下只能看到容器里的情况,但是宿主机上,它作为第100号进程与其他所有进程之间依然是平等竞争关系。 这就意味着,虽然第100号进程表面上被隔离了起来,但是它所能够使用到的资源(比如CPU、内存),却可随时被宿主机上其他进程(或容器)占用的。当然,这个100号进程自己也可能把所有资源吃光。这些情况,显然都不是一个“沙盒”应该表现出来的合理行为。

Linux Cgroups就是Linux内核中用来为进程设置资源限制的一个重要功能。

5、Docker对JVM内存的限制

为了使jvm保留根据容器规范的内存,必须设置标志:

-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap

如果将这两个标志与Xms和Xmx标志一起设置,那么jvm的行为将是什么?一个标志会覆盖另一个标志吗? 

例如:如果我们有java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Xms -Xms2500M -Xmx2500M -jar myjar.jar在具有容器的容器中,请求的限制为4Gi,响应的限制为4Gi。在具有128Gi内存的主机中,JVM会保留多少内存?

最佳答案
-Xmx标志将覆盖-XX:+ UseCGroupMemoryLimitForHeap标志。
标志-XX:+ UseCGroupMemoryLimitForHeap使JVM可以检测容器中的最大堆大小。
-Xmx标志将最大堆大小设置为固定大小。

示例答案:JVM将保留2500M的堆空间。对于非堆和jvm的东西,还会有一些额外的内存使用情况。

你可能感兴趣的:(K8S,docker,容器,运维)