provision

负责管理容器镜像。目前支持docker和APPC格式的镜像。

src/slave/containerizer/mesos/provisioner/docker/message.proto

对象定义

src/slave/containerizer/mesos/provisioner/provisioner.hpp

ProvisionerProcess对象的主要成员有:

  • 141:flags
  • 148:rootDir,根目录的绝对路径,是在由--work_dir指定的目录下的一个目录
  • 150:stores,Image类型与Store的hash映射表
  • 151:backends,字符串与Backend对象的hash映射表
  • 154-157:Info,rootfses。。。。
  • 159:infos,容器ID与Info的hash映射表
  • 161-167:metrics,统计信息

Store对象定义在store.hpp和store.cpp中

当创建Store对象时,根据不同类型分别调用appc::Store::create或docker::Store::create

初始化

Provisioner::create

  • 60-76:创建工作目录
  • 78-81:创建镜像本地存储与类型名称的hash映射表
  • 83-92:创建provision的后端
  • 94-99:创建Provisioner

Provisioner::Provisioner

启动内部对应的ProvisionerProcess进程

ProvisionerProcess::ProvisionerProcess

创建新的对象,根据参数初始化对象的内部变量flags/rootDir/stores/backends

Provisioner的函数

119-149:recover/provision/destroy都是调用ProvisionerProcess类对应的函数,原样传递参数

ProvisionerProcess::provision

参数:

  • containerId
  • image

流程:

  • 263-267:判断image的类型合法
  • 270-271:先调用image具体类型的get,得到结果再调用_provision

ProvisionerProcess::_provision

参数:

  • containerId
  • image
  • imageInfo

流程:

  • 283:从命令行flags中得到镜像后端存储名称,包括aufs/bind/copy/overlay,缺省是copy(见src/slave/flags.cpp,115-119行)。
  • 284:检查该名称合法
  • 286:生成一个随机的UUID作为rootfsID
  • 288-292:得到rootfs目录
  • 299-303:。。。。。。。。。。。。。。。。
  • 305-308:得到后端目录
  • 310-314:调用指定后端的get函数,再调用__provision

copy 后端

CopyBackendProcess::provision

参数:

  • layers
  • rootfs

流程:

  • 98-104:layers是镜像各层对应的路径名;rootfs是容器根文件系统在系统中的路径名,这里判断他们的合法性
  • 106-110:创建根文件系统的目录
  • 111-117:对镜像的每一层,创建一个函数调用插入到一个列表futures,函数调用是_provision
  • 119-120:对futures中的每个元素等待它完成,元素是刚刚创建的函数调用。这里的collect是否会并行??????

CopyBackendProcess::_provision

参数:

  • layers
  • rootfs

流程:

  • 131-141:构建命令"cp....",将layers目录内容拷贝到rootfs目录,cp的说明:
    • -a :相当于 -pdr 的意思
    • -d :若来源文件为连结文件的属性(link file),则复制连结文件属性而非档案本身
    • -p :保持指定的属性(默认:模式,所有权,时间戳)
    • -r :递归持续复制,用于目录的复制行为;
    • -T :将目标目录视作普通文件
  • 143-168:创建子进程,运行刚刚创建的命令

这样逐层拷贝,得到完整的根文件系统内容。

CopyBackendProcess::destroy

  • 174-185:创建子进程,调用删除命令,删除容器的根文件系统
  • 187-197:判断子进程是否正确执行

AUFS后端

AUFS概述

UnionFS就是把不同物理位置的目录合并mount到同一个目录中。UnionFS的一个最主要的应用是,把一张CD/DVD和一个硬盘目录给联合 mount在一起,然后,你就可以对这个只读的CD/DVD上的文件进行修改(当然,修改的文件存于硬盘上的目录里)。

Aufs是一种Union FS, 简单来说就是支持将不同的目录挂载到同一个虚拟文件系统下,并实现一种layer的概念。Aufs将挂载到同一虚拟文件系统下的多个目录分别设置成read-only,read-write以及whiteout-able权限,对read-only目录只能读,而写操作只能实施在read-write目录中。重点在于,写操作是在read-only上的一种增量操作,不影响read-only目录。当挂载目录的时候要严格按照各目录之间的这种增量关系,将被增量操作的目录优先于在它基础上增量操作的目录挂载,待所有目录挂载结束了,继续挂载一个read-write目录,如此便形成了一种层次结构。

传统的Linux加载bootfs时会先将rootfs设为read-only,然后在系统自检之后将rootfs从read-only改为read-write,然后我们就可以在rootfs上进行写和读的操作了。但Docker的镜像却不是这样,它在bootfs自检完毕之后并不会把rootfs的read-only改为read-write。而是利用union mount(UnionFS的一种挂载机制)将一个或多个read-only的rootfs加载到之前的read-only的rootfs层之上。在加载了这么多层的rootfs之后,仍然让它看起来只像是一个文件系统,在Docker的体系里把union mount的这些read-only的rootfs叫做Docker的镜像。但是,此时的每一层rootfs都是read-only的,我们此时还不能对其进行操作。当我们创建一个容器,也就是将Docker镜像进行实例化,系统会在一层或是多层read-only的rootfs之上分配一层空的read-write的rootfs。

例如,我们docker pull一个ubuntu:14.04的镜像,使用docker images -tree查看结果如下:

[root@qingze qingze]# docker images -tree
Warning: '-tree' is deprecated, it will be removed soon. See usage.
└─511136ea3c5a Virtual Size: 0 B
  └─3b363fd9d7da Virtual Size: 192.5 MB
   └─607c5d1cca71 Virtual Size: 192.7 MB
     └─f62feddc05dc Virtual Size: 192.7 MB
       └─8eaa4ff06b53 Virtual Size: 192.7 MB Tags: ubuntu:14.04,

可以看到Ubuntu的镜像中有多个长ID的layer,且以一种树状结构继承下来,如下图。其中,第n+1层继承了第n层,并在此基础上有了自己的内容,直观上的表现就是第n+1层占用磁盘空间增大。并且,不同的镜像可能会有相同的父镜像。例如,图中Tomcat和Nginx 继承于同一个Vim 镜像,这种组织方式起到共享的作用,节约了镜像在物理机上占用的空间。

AufsBackendProcess::provision

参数:

  • layers
  • rootfs
  • backendDir

流程:

  • 115-124:创建根文件系统目录,判断参数合法性
  • 126-137:创建工作目录:。。。。。。。。。。。。。
  • 146:将各层反过来,得到的options是这样的:"dirs=工作目录:layer0目录:layer1目录:....."
  • 150-161:调用mount系统调用,安装根文件系统
  • 164-188:安装根文件系统,shared+slave

AufsBackendProcess::destroy

  • 196-199:得到系统安装的文件系统列表
  • 201-220:对于每个安装的文件系统,若其是容器安装的根文件系统,先做umount,再将对应的目录删除

docker镜像的处理

store.cpp定义了对象StoreProcess,其中包含了MetadataManager

store.hpp定义了对象Store,其中包含了一个StoreProcess

provisioner.hpp中定义了对象ProvisionerProcess,其中包含了一个hash映射表stores

MesosContainerizerProcess中包含了provisioner对象

MetadataManagerProcess::recover

  • 202-208:得到存储docker镜像的目录(通常是/tmp/mesos/store/docker,在命令行可设置)
  • 210-220:得到镜像描述(通过protobuf反序列化),镜像描述的格式定义在src/slave/containerizer/mesos/provisioner/docker/message.proto中
  • 222:对每一个镜像,执行以下动作:
    • 225:对镜像的每一个layer执行以下动作:
      • 226-231:检查该层rootfs路径是否有效,如果有无效的,则跳过整个镜像(236-239行)
    • 234:得到镜像名字
    • 241-243:若当前已经缓冲了该镜像,报警告
    • 244-246:否则将镜像记录在storedImages中

results matching ""

    No results matching ""