容器技术:最下面是磁盘,容器镜像是放在磁盘disk上的,上层是容器引擎,容器引擎可以是docker,也可以是其他,引擎向下发一个请求比如创建容器,这个时候引擎就把磁盘上面的容器镜像运行成宿主机上的一个进程。

对于容器来说,最重要怎么保证进程用到的资源被隔离和被限制,在Linux内核上面有cgroup和namespace保证,下面看看docker怎么保证资源被隔离和被限制的。

docker用到了Linux上6中namespace隔离技术:mount(保证容器看到文件系统视图,看不到宿主机上其他文件),uts(隔离hostname和domain),pid(保证容器的init进程以1号进程开始启动),network,user(UID和gid),ipc(通信相关比如信号量),cgroup(可以让容器中看到cgroup视图以根的形式呈现,还可以容器内部使用cgroup变得更安全)。

namespace创立过程是用unshare命令实现。

cgroup用来限制资源的,docker容器有两种cgroup驱动:systemmd(保证所有写cgroup操作必须通过systemmd接口完成,不能手动更改cgroup文件)和cgroupfs(限制内存和cpu),docker容器常用的cgroup有6种:cpu(CPU share,cpuset),memory,device,freezer(容器停止的时候,会把当前进程进入cgroup,并冻结所有进程,防止进程fork并逃逸到宿主机上),blkio(iops和bps),pid(限制最大进程数量)。

容器镜像image是基于联合文件系统,意思是它允许文件存放在不同的层级上面,但最终通过统一的视图看到这些层级上的所有文件。

不同的层级可以被其他镜像image复用,当镜像被运行成容器的时候,最上层是一个读写层,读写层可以通过commit命令把它变成镜像顶层最新一层。

docker镜像存储,它的底层也是基于不同的文件系统,所有存储驱动也是针对不同的文件系统定制比如aufs,btrfs,devicemapper还有overlay(最下一层lower层就是镜像层,只读的,中间层读写层包含workdir和upper,最上面一层是视图层包含merged,整合了lower层和upper读写层显示出来的视图)。

docker通过graph driver驱动把镜像存储到磁盘上。

overlay文件操作:读,如果upper层没有副本,数据从lower读上来;写,容器创建出来,upper层是空的,只有对文件写操作时才从lower层拷贝文件上来,对副本进行修改;删,删除操作不影响lower层,删除的时候进行标记,使文件无法显示,2中方式:whiteout,设置目录xattr的"trusted.overlay.opaqur"=y。

容器引擎架构:左右看右边是runtime,对容器生命周期管理,左边是storage,对存储管理表明,包括拉取,镜像的存储。上下层次看,第一层是grpc,对上层提供服务,中间层是对容器的存储,包含metadata,tasks,events,最下层是runtime,包含runc和容器安全。容器的start,包含容器引擎,containerd,container-shim,container。

容器的exec跟start类似,区别在于,exec的时候把进程进入到一个已有的namespace上面,start的时候容器进程的namespace需要专门去创建。