说说linux容器的隔离

  • 2020 年 2 月 13 日
  • 笔记

前言:

说到docker,大家都懂。但是LXC可能就比较陌生。Docker的起源于LXC。LXC的英文全称是Linux Container,相比较其他虚拟机而言,是一种轻量级虚拟化技术,它介于Chroot(linux的一个改变根目录挂载点的机制)和完整开发的虚拟机之间。LXC不使用单独的内核资源,但是可以创建一个类似的Linux操作系统环境。

Linux Daemon(LXD)是一个轻量级容器管理程序,他是凌驾于LXC之上而衍生的一套外部管理工具。Docker也使用类似技术。LXD使用了LXC API来管理LXC,而且新增RESTful API。

这边文章通过研究LXC的隔离特征来说明容器的一些原理。

一、独立的命名空间

每个容器都有一套独立的Linux环境命名空间。命名空间的作用是对每一个环境做隔离,使用环境的用户来看,好像是一个新的机器环境。命名空间是linux内核用来隔离内核资源的方式。通过 namespace 可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的资源,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进程的相关资源指定在同一个 namespace 中。

一套独立的环境需要做到有用户id独立、进程id独立、root根目录独立、网络独立、UTS(UNIX Time-sharing System 的缩写,主机名和NIS域名)独立。

二、用户和用户组ID独立

每个Linux系统要求的uid可选范围都不一样,但是uid通常是由32位,也就是最大值可以是2^31-2(范围:1~4294967295)。路径/etc/login.defs文件的UID_MIN、UID_MAX限定了用户useradd新用户自己设置uid的最小值和最大值,2^31-1是个无效id,实验测试以下命令不能成功。

useradd -u 4294967296 test

Uid的取值区间范围作了划分,不同发行商的Linux系统有不一样的划分,但是一般是这么约定:

  • 0-99系统用户uid:
  • 100-500:系统管理管理员程序或者安装脚本产生的用户
  • 1000-x:用户uid,系统登录uid限制于了登录uid的最小值和最大值
  • 网络uid:更偏向于高值
  • 6553x:nobody

三、进程ID独立

每个Linux系统要求的pid可选范围都不一样,最大值可以设置到 4194304 (= 222) 。

在64位可以设置到222差不多400w左右。Linux代码设计者认为这个数已经足够了。如果是32位,pid最大值是32768.进程id一旦赋予就不会改变。

图1、进程id的最大值

每个系统的设置查看cat /proc/sys/kernel/pid_max。

我在ubuntu 16和centos 7分别得到了131072(= 217)和32768(= 215)。

3.1 那如果到达了最大值,会怎么样?

Pid是顺序产生的。当pid到达最大值,它会从0继续开始找最近可用的pid,如果都没有pid,会报错。

四、UTS(hostname独立)

以下测试了hostname在每个命名空间是独立存在的。

unshare --uts --fork bash  hostname//查看继承的原来hostname  hostname modified //修改成新的hostname  hostname //确认修改成功  eixt //退出  hostname //此时hostname还是原来的hostname
图2、hostname独立

五、网络隔离

在每个容器所需要的最少网卡接口包括默认的lo回环link(这个有什么用):

除开lo,一般隔离的网络还有一对veth-pair。除了veth-pair,linux网卡方式还有其他

这个可以使用ip link help查看到。这里提一下,ip是个很强大的命令,包含但不止于ifconfig和route的功能,是个很强大的工具,link这里指的是链路层。对应的ip addr是网络层。

图3、网络连接type