Docker通过namespace(命名空间)实现资源隔离。Namespace是Linux系统提供的资源隔离机制,只有在同一个namespace下的进程可以互相联系,但无法感受外部进程的存在,从而实现资源隔离。
Namespace | 系统调用参数 | 隔离内容 |
---|---|---|
UTS | Clone_UTS | 主机和域名 |
IPC | Clone_NewIPC | 信号量,消息队列和共享内存 |
PID | Clone_NewPID | 进程编号 |
Network | Clone_NewNet | 网络设备,网络栈,端口等 |
Mount | Clone_NewNS | 挂载点(文件系统) |
User | Clone_NewUser | 用户和用户组 |
分时系统(Time-sharing System)中一台主机连接了若干个终端,每个终端有一个用户在使用。
用户交互式地向系统提出命令请求,系统接受每个用户的命令,采用时间片轮转方式处理服务请求,并通过交互方式在终端上向用户显示结果。用户根据上步结果发出下道命令。
分时操作系统将CPU的时间划分成若干个片段,称为时间片。操作系统以时间片为单位,轮流为每个终端用户服务。每个用户轮流使用一个时间片而使每个用户并不感到有别的用户存在。
UTS(Unix Time-sharing System) namespace提供了主机名和域名的隔离,使每个Docker容器可以拥有独立的主机名和域名,在网络上可以视为独立的节点。
Linux进程间通信由System V IPC,基于Socket的IPC和POSIX IPC发展而来,主要的通信手段有:
• 只能用于具有亲缘关系的进程之间的通信(父子进程或者兄弟进程之间)
• 半双工的通信模式,具有固定的读端和写端
• 是一种特殊的文件,不属于其他任何文件系统并且只存在于内存中
• 使互不相关的两个进程间实现彼此通信
• 可以通过路径名来指出,并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当做普通文件一样进行读写操作
• 先进先出规则
用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身
有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。
克服了信号承载信息量少,管道只能承载无格式字节流(要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息等)以及缓冲区大小受限等缺点。
使得多个进程可以访问同一块内存空间。
主要用于进程间以及同一进程不同线程之间的同步。
可用于不同机器之间的进程间通信,必须包含
• 地址,由 ip 与 端口组成,像192.168.0.1:80。
• 协议,socket 所用的传输协议 TCP、UDP、raw IP。
IPC资源包括信号量、消息队列和共享内存。
IPC namespace中包含系统IPC标识符以及实现POSIX消息队列的文件系统。
同一个IPC namespace下的进程彼此可见,不同IPC namespace下的进程互相不可见。
通过IPC namespace可以实现容器与宿主机、容器与容器之间的IPC隔离。
PID是大多数操作系统的内核用于唯一标识进程的一个数值。
这一数值可以作为许多函数调用的参数,以使调整进程优先级、杀死进程之类的进程控制行为成为可能。
PID为1的进程是init,作为所有进程的父进程,不会处理来自其他进程的信号(信号屏蔽),并维护一张进程表,当有子进程变成孤儿时会回收其资源并结束进程。
PID namespace隔离对进程PID重新编号,两个不同namespace下的进程没有关系,因此PID也可以相同。内核为所有的PID namespace维护了一个树状结构。
其中:
mount namespace 通过隔离文件系统挂载点隔离文件系统,它是第一个Linux namespace,标识位为CLONE_NEWNS。隔离之后不同的mount namespace中的文件结构互不影响。
可以通过/proc/[pid]/mounts查看所有挂载在当前namespace中的文件系统。进程创建mount namespace时把当前文件结构复制给新的namespace。
挂载传播(mount propagation)定义了挂载对象之间的关系,解决了文件结构复制过程中子节点namespace影响父节点namespace文件系统的问题。
network namespace提供了关于网络资源的隔离,包括网络设备、IPv4和IPv6协议栈、IP路由表、防火墙、/proc/net目录、/sys/class/net目录、套接字(socket)等。
注意:
user namespace主要隔离了安全相关的标识符和属性(用户ID、用户组ID、root目录、key(密钥)、特殊权限)。
因此用clone()创建的新进程在新的user namespace中可以拥有不同的用户和用户组,在新进程创建的容器中,它是超级用户,但在容器之外只是普通用户。
Linux中,特权用户的user ID是0,user ID非0的进程启动user namespace后user ID可以变为0。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。