1,810 views

软件沙箱技术3 – Linux LXC

image

前文chroot效果不错,但属简易技术,它仅更改进程中的root directory项,仅针对文件系统隔离,易被跳出。此后有不少OS级别隔离技术基于chroot的思想发展出来,例如FreeBSD的Jail,Linux的LXC。他们和chroot的性质相同,都是user space隔离的技术,共享内核。

 

1.简介

 

LXC是“Linux Container”的简称,它是火火的docker的基础。

 

LXC 包括两部分实现

1.内核空间实现

2.用户空间LXC管理工具

 

内核部分又基于两大技术

1.namespace

用于隔离

 

2.cgroups

用于资源限制(因为隔离的容器共享内核,需要保护内核资源,所谓“资源限制”可类比QoS)

 

这里关注内核部分的两项技术。

 

2.Namespace

Linux kernel的namespace的概念可以类比C++中的name space。隔离的是操作系统的资源和内核对象。namespace的创建是通过“unshare”命令,或者通过clone系统调用中的flag。隔离的对象有如下几类:

 

2.1.PID namespace

用CLONE_NEWPID标记来调用clone创建进程。chroot是创建出新的根目录,而PID namespace是创建出pid为“1”的根进程。但是ps还可以列出系统内所有的进程,原因是ps从/proc虚拟文件系统读取内容,这部分没有做隔离,它的隔离工作在mount namespace里完成。

 

2.2.Network namespace

物理网卡设置为杂凑模式,创建虚拟网卡放到容器内部。

 

2.3.UTS namespace

在clone系统调用中,使用CLONE_NEWUTS flag创建进程,容器的hostname被设置为指定hostname。

 

2.4.Mount namespace

使用CLONE_NEWNS标记的clone创建进程,内部调用“mount -t proc proc /proc”进行mount,隔离系统全局的/proc。

之后ps只能显示容器内部的process了。

 

2.5.IPC namespace

同理,用于隔离IPC对象,容器内部只能看到自身创建的IPC对象。

 

2.6.User namespace

使用CLONE_NEWUSER参数,隔离user id。

之后容器内部的id就虚拟化了,实现的原理是使用映射表映射容器内可见uid和外部可见uid。

参照【2】

“需要修改 /proc/<pid>/uid_map/proc/<pid>/gid_map 这两个文件。这两个文件的格式为:

ID-inside-ns ID-outside-ns length

其中:

  • 第一个字段ID-inside-ns表示在容器显示的UID或GID,
  • 第二个字段ID-outside-ns表示容器外映射的真实的UID或GID。
  • 第三个字段表示映射的范围,一般填1,表示一一对应。”

 

3.cgroups(资源)控制组

Cgroups是control groups的缩写,控制进程组使用的资源,如cpu、memory。

cgroup所做的事情就是将process组织成层次结构,针对这个层次结构enforce policy。这里policy是subsystem组成的。每个subsystem用于控制一种资源,例如对于CPU subsystem,它的一个例子是控制“某组进程最多消耗20%CPU”。

 

这里的一幅图是cgroup的概念图,第一个cgroup占用了6,7两个CPU核以及第三部分内存。第二个cgroup占用了,1、2、3、5四个核以及前两部分内存。

image

 

cgroup有两次大的实现,已有的第一版实现即将被新版替代,细节很多,我只是从原理角度写一下。

 

已有cgroup模型

 

image

上图是,按我理解的已有cgroup实现。

Cgroup允许任意个层次,每个层次允许任意个controller(总数一定)。
1.每个controller只能有一个实例
2.在层次结构确定之后,controller不能移动。
3.所有绑定在一个层次上的controller都只能对下面所有的儿子默认打开(have same view)

4.cgroup中的进程fork的进程,仍然属于这个cgroup。

 

(这里controller的概念可以理解为等同subsystem)

 

cgroup v2 – unified hierarchy

image

上图是新版的Cgroup unified hierarchy,参照作者的介绍文档。

主要的改进是增加了两个文件做控制:

1.cgroup.subtree_control控制直接子group的controller,它的内容是空格隔开的controller,如cpu,memory等。

2.cgroup.controllers是Parent的设置的镜像

通过cgroup.subtree_control的逐层配置,可以做到最细的力度控制。

 

下面是针对v2版本的两点辨析

 

1.是否“只有叶子节点可以存在tasks,非叶子节点只进行资源控制。”

不完全正确。原文是“Except for the root, only cgroups which don’t contain any task may have controllers enabled in their “cgroup.subtree_control” files”.

也就是并不是只有叶子节点包括task。

 

2.是否controller只能设置在root cgroup上

作者原文是“All controllers which support the unified hierarchy and are not bound to other hierarchies are automatically bound to unified hierarchy and show up at the root of it.”

可以设置在内部节点,不一定是root。

 

cgroup实际操作可以参照【1】,其中给出了几个subsystem的配置例子。

 

3.LXC的优点

LXC技术从六个方面对系统内核对象进行了全面的隔离和模拟,加之提供了资源控制,对外展现出完整的虚拟机形态,几乎可匹敌传统的虚拟化技术。和传统虚拟化技术相比它有如下优势:

1.没有hypervisior层,不需要指令翻译,和host共享kernel,性能好

2.轻量级,资源占用小,移动方便。

 

有关docker,如果把容器理解为一个待发布的应用,docker就是这个应用的InstallShield。方便容器的移动和部署,它并不设计沙箱技术,不再赘述。

 

【参考】

1.Linux CGroup,http://coolshell.cn/articles/17049.html

2Docker基础技术:Linux Namespace(下),http://coolshell.cn/articles/17029.html

3.LXC,https://en.wikipedia.org/wiki/Operating-system-level_virtualization

4.cgroup, https://en.wikipedia.org/wiki/Cgroups

发表评论

电子邮件地址不会被公开。 必填项已用*标注