简介

Linux `Namespace`提供了一种内核级别隔离系统资源的方法,通过将系统的全局资源放在不同的`Namespace`中,来实现资源隔离的目的。不同`Namespace`的程序,可以享有一份独立的系统资源。目前Linux中提供了六类系统资源的隔离机制,分别是:
  • Mount: 隔离文件系统挂载点
  • UTS: 隔离主机名和域名信息
  • IPC: 隔离进程间通信
  • PID: 隔离进程的ID
  • Network: 隔离网络资源
  • User: 隔离用户和用户组的ID

下面简单的介绍一下这些Namespace的使用和功能。

使用

涉及到`Namespace`的操作接口包括`clone()`、`setns()`、`unshare()`以及还有`/proc`下的部分文件。为了使用特定的`Namespace`,在使用这些接口的时候需要指定以下一个或多个参数:
  • CLONE_NEWNS: 用于指定Mount Namespace
  • CLONE_NEWUTS: 用于指定UTS Namespace
  • CLONE_NEWIPC: 用于指定IPC Namespace
  • CLONE_NEWPID: 用于指定PID Namespace
  • CLONE_NEWNET: 用于指定Network Namespace
  • CLONE_NEWUSER: 用于指定User Namespace

下面简单概述一下这几个接口的用法。

clone系统调用

可以通过clone系统调用来创建一个独立Namespace的进程,它的函数描述如下:

int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg);

它通过flags参数来控制创建进程时的特性,比如新创建的进程是否与父进程共享虚拟内存等。比如可以传入CLONE_NEWNS标志使得新创建的进程拥有独立的Mount Namespace,也可以传入多个flags使得新创建的进程拥有多种特性,比如:

flags = CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC;

传入这个flags那么新创建的进程将同时拥有独立的Mount NamespaceUTS NamespaceIPC Namespace

通过/proc文件查看已存在的Namespace

在3.8内核开始,用户可以在/proc/$pid/ns文件下看到本进程所属的Namespace的文件信息。例如PID为2704进程的情况如下图所示:![](https://img-blog.csdnimg.cn/img_convert/4e47d67c573c40c29151da7a1be7c6bf.png#align=left&display=inline&height=416&margin=[object Object]&originHeight=416&originWidth=1324&size=0&status=done&style=none&width=1324)其中4026531839是Namespace的ID,如果两个进程的Namespace ID相同表明进程同处于一个命名空间中。这里需要注意的是:只/proc/$pid/ns/对应的Namespace文件被打开,并且该文件描述符存在,即使该PID所属的进程被销毁,这个Namespace会依然存在。可以通过挂载的方式打开文件描述符:

touch ~/mnt
mount --bind /proc/2704/mnt ~/mnt

这样就可以保留住PID为2704的进程的Mount Namespace了,即使2704进程被销毁或者退出,ID为4026531840的Mount Namespace依然会存在。

setns加入已存在的Namepspace

setns()函数可以把进程加入到指定的Namespace中,它的函数描述如下:

int setns(int fd, int nstype);

它的参数描述如下:

  • fd参数:表示文件描述符,前面提到可以通过打开/proc/$pid/ns/的方式将指定的Namespace保留下来,也就是说可以通过文件描述符的方式来索引到某个Namespace
  • nstype参数:用来检查fd关联Namespace是否与nstype表明的Namespace一致,如果填0的话表示不进行该项检查。

通过在程序中调用setns来将进程加入到指定的Namespace中。

unshare脱离到新的Namespace

unshare()系统调用用于将当前进程和所在的Namespace分离,并加入到一个新的Namespace中,相对于setns()系统调用来说,unshare()不用关联之前存在的Namespace,只需要指定需要分离的Namespace就行,该调用会自动创建一个新的Namespaceunshare()的函数描述如下:

int unshare(int flags);

其中flags用于指明要分离的资源类别,它支持的flagsclone系统调用支持的flags类似,这里简要的叙述一下几种标志:

  • CLONE_FILES: 子进程一般会共享父进程的文件描述符,如果子进程不想共享父进程的文件描述符了,可以通过这个flag来取消共享。
  • CLONE_FS: 使当前进程不再与其他进程共享文件系统信息。
  • CLONE_SYSVSEM: 取消与其他进程共享SYS V信号量。
  • CLONE_NEWIPC: 创建新的IPC Namespace,并将该进程加入进来。

注意事项

这里需要注意的是unshare()setns()系统调用对PID Namespace的处理不太相同,当unshare PID namespace时,调用进程会为它的子进程分配一个新的PID Namespace,但是调用进程本身不会被移到新的Namespace中。而且调用进程第一个创建的子进程在新Namespace中的PID为1,并成为新Namespace中的init进程。setns()系统调用也是类似的,调用者进程并不会进入新的PID Namespace,而是随后创建的子进程会进入。为什么创建其他的Namespace时unshare()setns()会直接进入新的Namespace,而唯独PID Namespace不是如此呢?因为调用getpid()函数得到的PID是根据调用者所在的PID Namespace而决定返回哪个PID,进入新的PID namespace会导致PID产生变化。而对用户态的程序和库函数来说,他们都认为进程的PID是一个常量,PID的变化会引起这些进程奔溃。换句话说,一旦程序进程创建以后,那么它的PID namespace的关系就确定下来了,进程不会变更他们对应的PID namespace。

小结

通过上面简单的概述,对于Namespace的操作有以下方式:

  • 1、可以在进程刚创建的时候通过clone系统调用为新进程分配一个或多个新的Namespace
  • 2、通过setns()将进程加入到已有的Namespace中。
  • 3、通过unshare()为已存在的进程创建一个或多个新的Namespace

接下来详细的介绍一下各个Namespace的功能和特性。

Mount Namespace

Mount Namespace用来隔离文件系统的挂载点,不同Mount Namespace的进程拥有不同的挂载点,同时也拥有了不同的文件系统视图。Mount Namespace是历史上第一个支持的Namespace,它通过CLONE_NEWNS来标识的。

挂载的概念

挂载的过程是通过mount系统调用完成的,它有两个参数:一个是已存在的普通文件名,一个是可以直接访问的特殊文件,一个是特殊文件的名字。这个特殊文件一般用来关联一些存储卷,这个存储卷可以包含自己的目录层级和文件系统结构。mount所达到的效果是:像访问一个普通的文件一样访问位于其他设备上文件系统的根目录,也就是将该设备上目录的根节点挂到了另外一个文件系统的页节点上,达到给这个文件系统扩充容量的目的。可以通过/proc文件系统查看一个进程的挂载信息,具体做法如下:

cat /proc/$pid/mountinfo

其输出结果如下:![](https://img-blog.csdnimg.cn/img_convert/b94ced25492e9971773e72d9788468b0.png#align=left&display=inline&height=334&margin=[object Object]&originHeight=298&originWidth=1440&size=0&status=done&style=none&width=1612)其中输出的格式如下:![](https://img-blog.csdnimg.cn/img_convert/ec38de8bfdf29ffb6352621cb3335fc2.png#align=left&display=inline&height=820&margin=[object Object]&originHeight=703&originWidth=1440&size=0&status=done&style=none&width=1680)

挂载传播

进程在创建Mount Namespace时,会把当前的文件结构复制给新的Namespace,新的Namespace中的所有mount操作仅影响自身的文件系统。但随着引入挂载传播的特性,Mount Namespace变得并不是完全意义上的资源隔离,这种传播特性使得多Mount Namespace之间的挂载事件可以相互影响。挂载传播定义了挂载对象之间的关系,系统利用这些关系来决定挂载对象中的挂载事件对其他挂载对象的影响。其中挂载对象之间的关系描述如下:

  • 共享关系(MS_SHARED):一个挂载对象的挂载事件会跨Namespace共享到其他挂载对象。
  • 从属关系(MS_SLAVE): 传播的方向是单向的,即只能从Master传播到Slave方向。
  • 私有关系(MS_PRIVATE): 不同Namespace的挂载事件是互不影响的(默认选项)。
  • 不可绑定关系(MS_UNBINDABLE): 一个不可绑定的私有挂载,与私有挂载类似,但是不能执行挂载操作。

其中给挂载点设置挂载关系的例子如下:

mount --make-shared /mntS      # 将挂载点设置为共享关系属性mount --make-private /mntP     # 将挂载点设置为私有关系属性mount --make-slave /mntY       # 将挂载点设置为从属关系属性mount --make-unbindable /mntU  # 将挂载点设置为不可绑定属性

注意在设置私有关系属性时,在本命名空间下的这个挂载点是Slave,而父命名空间下这个挂载点是Master,挂载传播的方向只能由Master传给Slave。

绑定挂载

绑定挂载的引入使得mount的其中一个参数不一定要是一个特殊文件,也可以是该文件系统上的一个普通文件目录。Linux中绑定挂载的用法如下:

mount --bind /home/work /home/alpha
mount -o bind /home/work /home/alpha

其中/home/work是磁盘上的存在的一个目录,而不是一个文件设备(比如磁盘分区)。如果需要将Linux中两个文件目录链接起来,可以通过绑定挂载的方式,挂载后的效果类似于在两个文件目录上建立了硬链接。在绑定挂载中同时会涉及到挂载的传播特性,挂载传播的特性参考:Linux绑定挂载

UTS Namespace

UTS Namespace提供了主机名和域名的隔离,也就是struct utsname里的nodenamedomainname两个字段。不同Namespace中可以拥有独立的主机名和域名。那么为什么需要对主机名和域名进行隔离呢?因为主机名和域名可以用来代替IP地址,如果没有这一层隔离,同一主机上不同的容器的网络访问就可能出问题。

IPC Namespace

IPC Namespace是对进程间通信的隔离,进程间通信常见的方法有信号量、消息队列和共享内存。IPC Namespace主要针对的是SystemV IPC和Posix消息队列,这些IPC机制都会用到标识符,比如用标识符来区分不同的消息队列,IPC Namespace要达到的目标是相同的标识符在不同的Namepspace中代表不同的通信介质(比如信号量、消息队列和共享内存)。原文

更多深度文章,关注:二进制社区

Docker核心技术Namespace浅析相关推荐

  1. 【重识云原生】第六章容器6.1.8节——Docker核心技术UnionFS

    <重识云原生系列>专题索引: 第一章--不谋全局不足以谋一域 第二章计算第1节--计算虚拟化技术总述 第二章计算第2节--主流虚拟化技术之VMare ESXi 第二章计算第3节--主流虚拟 ...

  2. 深入剖析docker核心技术(namespace、cgroups、union fs、网络)

    深入剖析docker核心技术 前言 docker概述 为什么要用docker Namespace 概述 实现 操作方法 隔离性 常用操作 Cgroups 概述 实现 配额和度量 CPU 子系统 Lin ...

  3. 沉淀,再出发:docker的原理浅析

    沉淀,再出发:docker的原理浅析 一.前言 在我们使用docker的时候,很多情况下我们对于一些概念的理解是停留在名称和用法的地步,如果更进一步理解了docker的本质,我们的技术一定会有质的进步 ...

  4. Docker核心技术

    整理自<Docker技术入门与实践>(杨保华 戴王剑 曹亚仑) - Docker核心技术一文. Docker是一种基于Linux Container(LXC)技术实现的容器虚拟化技术,现又 ...

  5. Docker核心技术之联合文件系统

    本文来说下docker核心技术之联合文件系统 文章目录 概述 概述

  6. 后端技术杂谈10:Docker 核心技术与实现原理

    Docker 核心技术与实现原理 30 NOV 2017  docker  namespaces  cgroups  unionfs  aufs  server Namespaces 进程 网络 挂载 ...

  7. 【云原生进阶之容器】第一章Docker核心技术1.6节——UnionFS

    <重识云原生系列>专题各章首节索引: 第一章--不谋全局不足以谋一域 第二章计算第1节--计算虚拟化技术总述 第三章云存储第1节--分布式云存储总述 第四章云网络第一节--云网络技术发展简 ...

  8. Docker核心技术学习笔记

    Docker核心技术 文章目录 Docker核心技术 一 .Docker简介 二.Docker安装 前提说明 Docker 的基本组成 安装 centos 7 安装docker 启动hello-wor ...

  9. Docker 底层原理浅析

    作者:vitovzhong,腾讯 TEG 应用开发工程师 容器的实质是进程,与宿主机上的其他进程是共用一个内核,但与直接在宿主机执行的进程不同,容器进程运行在属于自己的独立的命名空间.命名空间隔离了进 ...

最新文章

  1. quilleditor 字体大小设置_vue-quill-editor如何设置字体默认大小?
  2. 用JavaScript访问SAP云平台上的服务遇到跨域问题该怎么办
  3. CNN卷积神经网络:权值更新公式推导
  4. memcpy函数的实现
  5. 台达plc自由口通讯_自由口通讯问题无法接收数据
  6. 公式冒号是什么意思_冒号是什么意思
  7. 变形金刚2影院版完整字幕
  8. 2017第49周二乌镇互联网大会总结
  9. 5G室内定位来了,化工厂人员定位,电厂室内定位都有用它!-新导智能
  10. 破解Navicat全家桶
  11. 刻章不要钱 5个在线印章制作工具
  12. qiankun 基座下发组件
  13. 智能手机的发展演变,智能手机对人类带来的影响
  14. linux驱动开发5之字符设备驱动新接口
  15. 30岁的程序员,你迷惘了吗?
  16. 8.1 (电脑配置) 联想 启天M4390 台式电脑台式机电脑配置
  17. 闭关之 C++ 函数式编程笔记(二):偏函数、组合、可变状态与惰性求值
  18. iReport实现金额大写
  19. 2021年中国机械100大企业排行榜:上海汽车集团股份有限公司位居榜首,年度销售收入高达7421.32亿元(附年榜TOP100详单)
  20. 我的世界java1.16.3村庄种子,我的世界:1.16最神奇的种子,自然生成的石头雕像,基岩能用!...

热门文章

  1. 股票入门基础知识16:财务比率的局限性
  2. GIS大讨论(十一):当前地理信息产业发展动向与趋势
  3. 小视频app源码,邻接矩阵实现图的相关代码
  4. “政务上链” 能否解决新数据孤岛、安全风险等问题
  5. 无比强大!Python抓取cssmoban网站的模版并下载
  6. python3-编程题之商品价格计算器
  7. 拓扑排序(依次加入入度为0的节点)
  8. 低代码平台,企业服务新战场
  9. MyEclipse/Eclipse 导出带目录结构的.class
  10. eclispe启动报错