橘子学K8S01之容器中所谓的隔离和限制

我们一直都在说容器就是一个沙盒,沙盒技术顾名思义就是像一个集装箱一样,把应用(服务,进程之类的)装起来的技术,这样每个进程在自己的沙盒中和其他的沙盒隔离开来,每个沙盒之间存在一个边界使得他们互不干扰,而被装入这个盒子中的应用也就很方便的可以跟着沙盒搬来搬去,这是一种很方便很理想的管理状态。
于是围绕这个状态的实现,需要一种可以真实落地的技术。也就是隔离和限制技术。

一、Namespace隔离技术

1、隔离的现象

我们说容器的核心功能就是通过约束和修改进程的动态表现,从而创造出一个边界,而Cgroups技术就是用来制造约束的能力,而我们这里要说的NameSpace则是用来修改进程的视图的技术,修改视图其实就是修改进程视角下自己能看到的内容。
我们先来操作一下,所以我们需要准备一个Linux环境和docker项目,至于你是哪个Linux的发行版本这不重要。我的环境如下:

CentOS Linux release 7.8.2003
Docker Engine - Community 20.10.14

首先我们先创建一个容器:执行docker run -it busybox /bin/sh命令来创建容器

#root  docker run -it busybox /bin/sh
这句命令的参数我们逐一来解释一下:
-it :在启动docker容器之后,给我们分配一个文本的输入输出环境,有了这个输入输出环境,我们就能在输入端和docker交互然后在输出端
获得交互的结果。

/bin/sh :就是我们在docker容器中运行的程序,bin/sh是一个常用的shell。

所以上面这句话的意思最终表达就是:请帮我启动一个容器,并且在容器里面执行/bin/sh这个shell,并且在启动之后就分配一个命令行的
终端来让我和这个容器交互。

在做完了以上操作之后,我的Linux机器就变成了宿主机,而这个运行着/bin/sh的容器 busybox 就运行在我的这台宿主机里。

在执行完以上这句命令之后,其实我们就进入了容器内部,并且可以通过终端交互。界面如下。
在这里插入图片描述
此时我们在交互终端指定ps,列出容器内的所有进程。
在这里插入图片描述
我们发现里面只有两个进程,我们在启动时运行的/bin/sh就是这个容器内部的一号进程(PID为1),第二个则就是我们执行的ps进程。此时这两个进程已经被隔离在我们这个容器中了。也就是所谓的沙盒世界。那么其中的原理又是为何呢?

2、隔离的原理

本来在我们没有容器的时候,我们直接在宿主机上运行一个/bin/sh程序,此时就会启动一个/bin/sh的进程,操作系统就会给他这个进程分配一个进程ID(PID),这个类似于编号一样的PID,是这个进程的唯一标识,就像一个公司中的员工的工号一眼。比如系统为他分配的是100,那么他就等同于工号为100的员工。公司的boss就是编号为1的员工。

但是此时我们有了容器了,当我们把程序运行在容器中的时候,docker就会给这个进程施展一个障眼法,让他感知不到前面的进程,看不到其他前面的99个员工,此时他就以为自己是1号员工,此时他就在一种忽悠的状态下,认为自己的ID就是1。

所以这种机制类比在linux中,就是在隔离的空间中运行的进程只能看到计算过后的编号,PID=1。实际上,你还是在操作系统上运行,在操作系统的视角看,你还是你100号员工,妄想成为1号,那是你自己认为。
这就是Linux中的Namespace机制,而对应在Linux中的实现中,namespace的实现方式,其实就是Linux创建进程的一个传入的可选参数,在linux中创建进程的系统函数为clone(),也就是如下:

int pid = clone(main_function,stack_size,SIGCHLD,NULL);
这行代码会创建一个进程,然后返回值是这个进程的PID,也就是那个编号。而玄机就在第三个参数中,第三个
形参可以有两种传入实参,CLONE_NEWPID和SIGCHLD,当我们传入的是SIGCHLD就创建真实的进程,不做任何
障眼法,而当我们把参数指定为CLONE_NEWPID,创建出来的进程,就会在自己的视角看到一个全新的空间,在
这个进程空间中,他的PID就是1,而这一切都是一个障眼法,在宿主机的真实的进程空间中,他的进程PID还是
真实的数字,比如100,而不是1.

如果你创建多个这样的进程,他们自己的视角中自己都是PID=1的进程,他们看不到宿主机的真实进程空间,同时也看不到其他的沙盒里面的状况,换言之,他们实现了隔离。
而且在PID的Namespace隔离之外,Linux还提供了诸如Mount,UTS,IPC,Network,User这些Namespace,用来对其他的网络设备和其他配置做隔离,这样每个进程都只能看到自己的空间里面的隔离内容了。

二、总结

所以我们可以看到,所谓的docker容器,实际就是在创建容器进程的时候,指定了一组关于这个进程需要启动的Namespace,隔离了进程的PID,文件,设备,配置等等。而对于宿主机以及其他和这个进程不相关的进程,他是完全看不到的。

所以,容器,其实就是一种特殊的进程。只是他做了隔离。
所以在这个概念之上,我们就知道,所谓容器,在使用的时候其实并没有一个真实的容器存在,docker启动的其实还是原来的应用,只是在创建这些进程的时候docker加上了很多Namespace参数来限制进程的视角。
当限制完成之后,这些进程就觉得自己是各自的PID Namespace里面的1号进程,只能看到自己各自的Mount Namespace挂载的目录和文件,只能访问各自Network Namespace里面的网络设备,只能看到自己被限制的那一组namespace空间中的内容,仿佛与世隔绝一样。所以一切都是障眼法。

而在完成了隔离之后,在自己那一亩三分地运行的进程对于资源也是需要做限制的,而这个限制就是所谓的Cgroups技术,也就是下面的主角。

相关推荐

  1. 橘子K8S03容器理解

    2023-12-11 07:10:05       28 阅读
  2. k8s,pod服务状态pod里面容器状态关系

    2023-12-11 07:10:05       21 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-11 07:10:05       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-11 07:10:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-11 07:10:05       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-11 07:10:05       20 阅读

热门阅读

  1. Django实现热加载原理(从源码开始分析)

    2023-12-11 07:10:05       36 阅读
  2. 安卓和ios针对于new Date()数据格式的兼容问题

    2023-12-11 07:10:05       39 阅读
  3. USB连接器

    2023-12-11 07:10:05       33 阅读
  4. 物联网IC

    2023-12-11 07:10:05       35 阅读
  5. 一次事务失效问题的排查

    2023-12-11 07:10:05       30 阅读
  6. GIT和SVN

    GIT和SVN

    2023-12-11 07:10:05      39 阅读
  7. 深度学习测试流程

    2023-12-11 07:10:05       33 阅读
  8. vscode 编写爬虫爬取王者荣耀壁纸

    2023-12-11 07:10:05       43 阅读
  9. Linux数据库Mysql增删改查

    2023-12-11 07:10:05       35 阅读
  10. esp32服务器与android客户端的tcp通讯

    2023-12-11 07:10:05       37 阅读
  11. rust宏(macro)详解

    2023-12-11 07:10:05       42 阅读
  12. MYSQL数据类型详解

    2023-12-11 07:10:05       41 阅读