dokcer理解 | 青训营笔记

120 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记

docker底层实现/核心技术

容器其实就是Namespace+Cgroups

  • Namespace:帮助容器实现各种资源的隔离
  • Cgroups:主要对容器使用某种资源量的多少做一个限制
  • UnionFS:联合文件系统

Namespace

名字空间是Linux内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。

1.pid名字空间

不同用户的进程就是通过pid名字空间隔离开的,且不同名字空间中可以有相同pid。所有的LXC进程在Docker中的父进程为Docker进程,每个LXC进程具有不同的名字空间。同时由于允许嵌套,因此可以很方便的实现嵌套的Docker容器。

2.net名字空间

有了pid名字空间,每个名字空间中的pid能够相互隔离,但是网络端口还是共享host的端口。网络隔离是通过net名字空间实现的,每个net名字空间有独立的网络设备,IP地址,路由表,/proc/net目录。这样每个容器的网络就能隔离开来。Docker默认采用veth的方式,将容器中的虚拟网卡同host上的一个Docker网桥docker0连接在一起

3.ipc名字空间

容器中进程交互还是采用了Linux常见的进程间交互方法(interprocesscommunication–IPC),包括信号量、消息队列和共享内存等。然而同VM不同的是,容器的进程间交互实际上还是host上具有相同pid名字空间中的进程间交互,因此需要在IPC资源申请时加入名字空间信息,每个IPC资源有一个唯一的32位id。

4.mnt名字空间

类似chroot,将一个进程放到一个特定的目录执行。mnt名字空间允许不同名字空间的进程看到的文件结构不同,这样每个名字空间中的进程所看到的文件目录就被隔离开了。同chroot不同,每个名字空间中的容器在/proc/mounts的信息只包含所在名字空间的mountpoint。

5.uts名字空间

UTS(“UNIXTime-sharingSystem”)名字空间允许每个容器拥有独立的hostname和domainname,使其在网络上可以被视作一个独立的节点而非主机上的一个进程。

6.user名字空间

每个容器可以有不同的用户和组id,也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。

进程号隔离:每一个容器内运行的第一个进程,进程号总是从1开始起算。

网络隔离:容器的网络与宿主机或其他容器的网络是隔离的、分开的,也就是相当于两个网络。

进程间通隔离:容器中的进程与宿主机或其他容器中的进程是互相不可见的,通信需要借助网络。

文件系统挂载隔离:容器拥有自己单独的工作目录。

内核以及系统版本号隔离:容器查看内核版本号或者系统版本号时,查看的是容器的,而非宿主机的。

  • Namespace重点在“隔离”,是Linux内核用来隔离资源的方式。
  • 每个Namespace下的资源对于其他Namespace都是不透明,不可见的。
  • 简单来说,容器和容器之间不要相互影响,容器和宿主机之间不要相互影响。

控制组

CGroups(ControlGroups)重点在“限制”。限制资源的使用,包括CPU、内存、磁盘的使用,体现出对资源的管理能力。

为docker容器提供硬件层面的隔离,控制组能控制应用程序所使用的硬件资源。基于该性质,控制组帮助docker引擎将硬件资源共享给容器使用,并且加以约束和限制。如控制容器所使用的内存大小。

  • 控制组(CGroup)一个CGroup包含一组进程,并可以在这个CGroup上增加LinuxSubsystem的各种参数配置,将一组进程和一组Subsystem关联起来。
  • Subsystem子系统是一组资源控制模块,比如CPU子系统可以控制CPU时间分配,内存子系统可以限制CGroup内存使用量。可以通过lssubsys-a命令查看当前内核支持哪些Subsystem。
  • Hierarchy层级树主要功能是把CGroup串成一个树型结构,使CGruop可以做到继承,每个Hierarchy通过绑定对应的Subsystem进行资源调度。
  • Task在CGroups中,task就是系统的一个进程。一个任务可以加入某个CGroup,也可以从某个CGroup迁移到另外一个CGroup。

联合文件系统

联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(uniteseveraldirectoriesintoasinglevirtualfilesystem)。

联合文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

另外,不同Docker容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。

Docker中使用的AUFS(AnotherUnionFS)就是一种联合文件系统。AUFS支持为每一个成员目录(类似Git的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限,同时AUFS里有一个类似分层的概念,对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。

Docker目前支持的联合文件系统种类包括AUFS,btrfs,vfs和DeviceMapper。