[Docker 底层技术]
docker底层的 2 个核心技术分别是 Namespaces 和 Control groups
在操作系统中,网络配置,进程,用户,IPC(进程之间的调用)等信息之间的操作,都是可以被所有进程查看到的,除了这些资源信息,我们还需要隔离进程之间能够共享的信息,而Namespaces用于实现进程之间信息隔离的
关于Linux命名空间,实现进程间信息的独立与隔离需要在操作系统内核层面进行实现的
Mount Namespaces:挂载命名空间,用于隔离挂载目录
为什么要通过Mount namespace隔离挂载目录?
如果说隔离在某个namespace中的程序,可所挂载的目录进行修改,那么另一个nemaspace中运行的程序也能察觉到,这样就在无形之中影响了其他Namespace中程序的运行,显然达不达这样的隔离效果;
所以要进行程序之间的隔离,
首先是要把程序所使用的挂载目录进行隔离,让不同的Nemaspaces拥有独立挂载结构,而程序对挂载信息的修改,也不会影响到其他的namespace中程序的运行; UTS Namespaces:UTS命名空间,用于隔离主机及网络域等信息
通过UTS命名空间,可以为不同的Namespaces设置不同的主机名和网络域 能够简单的将程序隔离到一个独立的网络命名空间 IPC Namespaces:用于隔离进程之间的调用,也就是隔离进程之间的通信;
主要针对系统信号量,消息队列以及共享内存;但是需要注意的是,IPC对于需要进行进程之间通信的程序,只能与同一个命名空间进行通信,无法做到不同命名空间进行信息交换通信; PID Namespaces:进程命名空间,用于隔离进程的运行信息
进程是程序运行最直接的体现方式,要实现进程隔离,将进程信息进行隔离是必须的,为了最大的节约转换的损耗,每一个运行在Namespaces中的进程,其实就真是的运行在Linux系统中,我们虽然可以在宿主机中找到Namespaces隔离
的进程信息,但是namespaces中的PID与宿主机系统中你那个的进程PID并不相同,这也就是得益于PIDNamespaces实现的进程信息的隔离,PID Namespaces为命名空间设置了一个独立的进程管理栈,其中就包括了独立的进程号管理
,每个运行在Namespaces中的进程,会分配到一个属于这个命名空间 Network Namespaces:网络命名空间,用于隔离网络配置和访问 User Namespace:用于隔离用户和用户组信息
通过专门的用户隔离机制,防止运行在Namespaces中的程序直接操作宿主机系统中的用户,以避免影响其他Namespaces中的运行程序;
有了以上 6 种 NameSpaces 从进程、网络、IPC、文件系统、UTS和用户角度的隔离,一个 container 就可以对外展现出一个独立计算机的能力,并且不同 container 从 OS 层面实现了隔离。然而不同 namespace 之间资源还是相互竞争的,仍然需要类似ulimit来管理每个 container 所能使用的资源 - -cgroup。
cgroups(Control groups)实现了对资源的配额和度量。
【控制组】
关于Linux控制组也就是Cgroups(控制组群),其作用于是记录,限制,隔离进程所使用的CPU,内存,文件IO等计算机资源; cgroups通过插入程序对计算机硬件 资源调用的过程,实现了控制进程使用资源目的,作为 容器的两大关键技术,Namespaces主要实现了进程信息,用户,挂载目录,网络配置等软件资源的隔离,
而Cgroups实现呃对CPU,内存,文件IO等硬件资源的控制; PS:通过Namespaces来实现不同容器中进程之间隔离,相互之间不能访问,但是如果缺少cgroups对硬件资源的控制,就是避免不了容器中的程序对资源抢占,从而影响其他容器中程序的运行 Cgroups的组成 从功能层面来说: #Resource Limiting:资源限制。Cgroups能够成为每一个控制组设置使用资源的上限,一旦此类控制分配的资源达到了上线,既不会再分配过多的资源给这个控制组 #Prioritization:优先级分配,Cgroups可以为不同的控制组设置不同的优先级,优先级较高的控制组,可以优先得到Cgroups为其分配的计算机资源 #Accounting:资源统计。对于每个控制组,cgroups都能掌握它们对资源的使用情况,如CPU的使用时长,内存消耗,句柄数等
#Control:进程控制,Cgroups还能对控制组中的进程进行挂起,恢复等操作 Cgroups以下几个重要的组成结构 Task:任务。分配计算机资源就是为了执行特定的任务, Cgroup:控制组,由任务组成的任务组成为控制组,在cgroups中,控制组是分配和控制资源分配的单位 Subsystem:子系统,也就是资源调度的控制器。 Hierachy:继承树,用于处理控制组和子系统的关系。能够将控制组制成树状关系,并让子系统依附到对应的内存子系统中
【容器与控制组】
CGroup主要能够从blikio(块设备IO控制)cpu(CPU使用限制),cpuacct(CPU资源报告),cpuset(多核CPU核心使用控制),devices(设备访问控制),freezer(进程挂起控制),memory(内存使用控制),net_cls(网络控制)和ns(名称空间子系统)等方面限制计算机资源的使用
【联合文件系统】
UFS是联合文件系统的简称,所谓的联合文件系统,就是能够多个目录挂载成同一个文件系统换句话说就是将多个目录挂载成同一个目录,主要特点就是能够从不同的文件系统里将文件挂载到虚拟的联合文件 系统中,还能够把多个目录挂载合并成同一个目录
Docker利用UFS实现镜像技术,,是docker容器技术够被广泛使用的一个杀手锏。UFS制成的镜像大幅度缩小了占用空间,并且能够以分拆的方式在镜像之间共享数据。特别是对于镜像的更新,docker能够在不修改原有的镜像同时,以最小的空间消耗对存储文件的修改
【Docker Engine架构】
我们把docker Engine中所包含的提供doker容器支持的服务程序被dockr daemon。把能够操作docker Engine的客户端成为docker CLI。
docker daemon与docker cli之间是通过docker API进行通信的,也就是说,通过 Docker CLI下达指令,Docker CLI转换为对应的Docker API后,被提交到docker daemon;其实他们两者的关系是非常松散的,不相互依存。Docker CLI既可以直接通过 进程间的通信方式与本机的Docker Daemon连接。也可以通过socket向其他机器上的docker daemon下达操作指令,甚至能够同时操作多个docker daemon;
#Docker Daemon:是实现docker核心程序,管理包括镜像,容器,网络,数据卷 等在内的所有docker组成的模块;docker daemon使用的是linux进程通信接口,且只允许本地的根用户访问。所以需要在root环境操作,执行docker cli提供的docker命令,如果想让docker daemon监听选定的网络地址。可以通过dockerd命令,配合-H或者--host参数,给出监听的网络地址
dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:9876
#Docker CLI其实就是在终端命令行中使用的docker程序,能够将下达的命令行指令转换为docker API请求,在发送到与之关联的docker daemon中
docker CLI工作流程:
每个操作指令与docker daemon相关,首先docker CLI根据指令的类型转换为对应的docker API请求,然后docker CLI请求与之关联的docker Daemon并等待处理结果,docker daemon收到请求操作指令之后,会根据指令内容进行操作,并将结果返回给docekr CLI,docker CLI收到docker daemon返回结果后,会解析结果中的数据,并打印到终端上;
dockerd -H tcp://127.0.0.1:9876 version