容器的隔离和限制

容器是怎么隔离的?

随着云计算的火爆,近几年说得最多的是什么?无疑是容器和容器编排技术。近几年火热的一些词,比如PasS , SaaS ,Serverless ,Service Mesh 等等,无一不是和容器有关。

下面咱们就来说一说容器到底是怎么隔离的?

我们知道程序其实是数据加上代码本身的二进制文件放在磁盘上的,当我们运行一个程序时,它就从磁盘上的二进制文件变成了计算机内存中的数据,寄存器里的值,堆栈信息,被打开的文件以及各种设备状态信息的集合,也就是我们常说的进程。

而容器隔离技术,其实就是通过约束和修改进程的动态表现,从而创造出一个边界。

我们知道一个运行在linux里面的进程,会有一个pid进行唯一标识,比如第一百个启动的进程PID=100,通过docker运行这样的程序,就会给这个进程施加一个障眼法,使他看不到其他的进程,这种机制其实是对被隔离应用的进程空间动了手脚,使这些进程只能看到重新计算过的进程编号,如进程会看到自己的PID=1,可实际上在宿主机上它还是原来100的进程。
在这里插入图片描述

其实这种技术早就在linux实现了,就是Namespace机制,Namespace机制是在linux新建进程的时候传递一个可选参数。

int pid =  clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL); 

此时,新创建的进程就会看到一个全新的进程空间,在这个空间里面它的PID就是1。

其实我们还可以多次执行上面的系统调用,创建多个PID Namespace,而每个Namespace里的应用进程,都会认为自己是1号进程,他们既看不到宿主机里真正的进程空间,也看不到其他 PID Namespace 里的具体情况。

其实除了PID Namespace,Linux 操作系统还提供了 Mount、UTS、IPC、Network 和 User 这些 Namespace,用来对各种不同的进程上下文进行障眼法操作。

Mount Namespace,用于让被隔离进程只看到当前 Namespace 里的挂载点信息;

Network Namespace,用于让被隔离进程看到当前 Namespace 里的网络设备和配置。

我们通常会通过Mount Namespace挂载一个完整的操作系统,比如 CentOS 或者 Ubuntu,但这并不能改变共享宿主机内核的事实。这意味着,如果你要在 Windows 宿主机上运行 Linux 容器,或者在低版本的 Linux 宿主机上运行高版本的Linux 容器,都是行不通的。

这,就是 Linux 容器最基本的实现原理了,其实说白了,容器就是一个特殊的进程而已。

容器的限制

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

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

Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。

在 Linux 中,Cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。
在这里插入图片描述
可以看到,在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。这些都是我这台机器当前可以被 Cgroups 进行限制的资源种类。而在子系统对应的资源种类下,你就可以看到该类资源具体可以被限制的方法。比如CPU子系统
在这里插入图片描述
cfs_period 和 cfs_quota 这两个参数需要组合使用,可以用来限制进程在长度为 cfs_period 的一段时间内,只能被分配到总量为 cfs_quota 的 CPU 时间。

当我们在这个目录下创建一个目录,比如container目录时,这个目录就称为一个“控制组”。你会发现,操作系统会在你新创建的 container 目录下,自动生成该子系统对应的资源限制文件。
在这里插入图片描述

除 CPU 子系统外,Cgroups 的每一项子系统都有其独有的资源限制能力

Linux Cgroups 的设计还是比较易用的,简单粗暴地理解呢,它就是一个子系统目录加上一组资源限制文件的组合。而对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值