clone(),使用clone可以在创建一个新的进程的同时,来创建新的namespace,使用方法如下:
int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg); 参数child_func传入子进程运行的程序主函数。参数child_stack传入子进程使用的栈空间参数flags表示使用哪些CLONE_*标志位参数args则可用于传入用户参数使用sents可以将进程从原先的namespace,加入到一个新建好的namespace
Int setns(int fd, int nstype); 参数fd表示我们要加入的namespace的文件描述符参数nstyle表示是否检查指向的namespace符合我们的实际要求,如果写0则表示不检查不启动新进程就可以起到隔离的效果,相当于跳出了原先的namespace进行操作。这个方法在Docker中没有被使用过。
在PID中,无论调用unshare还是sentc,其调用者都不会和其他的namespace一样进入新的PID namespace。因为在进程创建之后,其PID被认为是一个常量,不能被变更。
UTS namespace 提供了主机名和域名之间的隔离,Docker中使用这种隔离,为每个Docker容器配 置独立的主机名和域名。
提供了进程之间通信的资源的隔离,其中包括信号量、消息队列、共享内存等在同一个IPC namespace下的进程彼此可见,而不同的IPCnamespace下的进程相互不可见。
对进程的PID重新标号,使得在不通namespace下的进程可以有相同的PID。
通过隔离文件系统挂载点对隔离文件系统提供支持,在创建新的mount namespace时,会把当前的文件结构复制给新的namespace,其中的所有操作都不会对外界产生任何影响。
但是这样的方法太过严格,父进程的很多操作在挂载的过程中容易受到影响,例如CD等,因此引入了挂载传播,其中有共享关系、从属关系等。挂载的具体类型可以分为:共享挂载、从属挂载、共享挂载、私有挂载、不可绑定挂载。如下图所示,为Linux系统中的常用的挂载情况
主要提供了关于网络资源的隔离,包括网络设备、IPV4和IPV6协议、IP路由表、套接字等。一个物理网络设备最多存在于一个network namespace中,可以通过创建veth pair在不通的network namespace间创建通道,以达到通信的目的。
容器额经典做法就是创建一个veth pair,一端放置在新的namespace中,通常命名为eth0,一端放在原先的namespace中连接物理网络设备,再通过把多个设备接入网桥或者进行路由转发来实现通信 的目的。具体结构入下图所示:
在veth pair建立之前,新旧namespace通过pipe(管道)进行通信,知道veth设备启动起来之后,管道才会关闭起来,并且结束初始化状态。
主要隔离了安全相关的标识符和属性,例如用户ID、用户组ID、root目录以及特 殊权限。通俗来讲,相当于一个普通用户的进程在创建新的进程时,可以拥有不同的用户和用户组,相当于没有特权的普通用户也可以创建拥有超级权限的进程。这一方式给了容器很大的自由,但是由于安全问题,在很多版本的linux系统中并不支持。