博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
docker graphdriver之aufs
阅读量:5783 次
发布时间:2019-06-18

本文共 3921 字,大约阅读时间需要 13 分钟。

hot3.png

aufs dirver的类型为:

type Driver struct {    root       string    sync.Mutex // Protects concurrent modification to active    active     map[string]int}

其中,root代表aufs驱动所在的根目录,为/var/lib/docker/aufs。active属性为map类型,key为DockerImage的ID,value为int类型,代表该层镜像layer被引用的次数总和。

aufs驱动类型的存储结构如下所示:

├── layers // Metadata of layers│   ├── 1│   ├── 2│   └── 3├── diff  // Content of the layer│   ├── 1  // Contains layers that need to be mounted for the id│   ├── 2│   └── 3└── mnt    // Mount points for the rw layers to be mounted    ├── 1    ├── 2    └── 3

其中,layers、diff、mnt为目录/var/lib/docker/aufs下的三个子目录,1、2、3是镜像ID,分别代表三个镜像。三个目录下的1均代表同一个镜像ID。其中,layers目录下代表每一个镜像的元数据,这些元数据是这个镜像的祖先镜像ID列表;diff目录下存储每一个镜像所在的layer,具体包含的文件系统的内容;mnt目录下每一个文件都是一个镜像ID,代表在该层镜像之上挂载的读写的layer。

下面分析一些函数的作用:

func getParentIds(root, id string) ([]string, error) {    f, err := os.Open(path.Join(root, "layers", id))    ...    out := []string{}    s := bufio.NewScanner(f)    for s.Scan() {        if t := s.Text(); t != "" {            out = append(out, s.Text())        }     }     return out, s.Err() }

以上参数,root为/var/lib/docker/aufs,id为镜像ID,返回该镜像的所有父镜像的ID列表。

aufs这种文件系统的实现,在合并多个镜像时起到重要作用。创建镜像路径的源码如下所示:

func (a *Driver) Create(id, parent string) error {    if err := a.createDirsFor(id); err != nil {        return err    }    // Write the layers metadata    f, err := os.Create(path.Join(a.rootPath(), "layers", id))    if err != nil {        return err    }    defer f.Close()        if parent != "" {        ids, err := getParentIds(a.rootPath(), parent)        if err != nil {            return err        }        if _, err := fmt.Fprintln(f, parent); err != nil {            return err        }        for _, i := range ids {            if _, err := fmt.Fprintln(f, i); err != nil {                return err            }        }   }   return nil}

1、docker daemon首先通过

f, err := os.Create(path.Join(a.rootPath(), "layers", id))

打开layers目录下镜像ID文件。

2、然后,通过

ids, err := getParentIds(a.rootPath(), parent)

获取父镜像的祖先镜像ID列表ids。

3、其次,将父镜像ID写入f。

4、最后,将父镜像的祖先镜像的ID列表写入f。

下面这个函数返回镜像的根目录,并且进行了读写层的挂载。

func (a *Driver) Get(id, mountLabel string) (string, error) {    ids, err := getParentIds(a.rootPath(), id)    if err != nil {        if !os.IsNotExist(err) {            return "", err         }         ids = []string{}     }          // Protect the a.active from concurrent access     a.Lock()     defer a.Unlock()          count := a.active[id]          // If a dir does not have a parent ( no layers )do not try to mount     // just return the diff path to the data     out := path.Join(a.rootPath(), "diff", id)     if len(ids) > 0 {         out = path.Join(a.rootPath(), "mnt", id)                  if count == 0 {             if err := a.mount(id, mountLabel); err != nil {                 return "", err             }         }     }     a.active[id] = count + 1     return out, nil}

补充:

aufs这种驱动同时实现了下面这个接口:

type Differ interface {    Diff(id string) (archive.Archive, error)    Changes(id string) ([]archive.Change, error)    ApplyDiff(id string, diff archive.ArchiveReader) error    DiffSize(id string) (bytes int64, err error)}
// Returns an archive of the contents for the idfunc (a *Driver) Diff(id string) (archive.Archive, error) {    return archive.TarWithOptions(path.Join(a.rootPath(), "diff", id), &archive.TarOptions{        Compression: archive.Uncompressed,    })}func (a *Driver) ApplyDiff(id string, diff archive.ArchiveReader) error {    return archive.Untar(diff, path.Join(a.rootPath(), "diff", id), nil)}// Returns the size of the contents for the idfunc (a *Driver) DiffSize(id string) (int64, error) {    return utils.TreeSize(path.Join(a.rootPath(), "diff", id))}func (a *Driver) Changes(id string) ([]archive.Change, error) {    layers, err := a.getParentLayerPaths(id)    if err != nil {        return nil, err    }    return archive.Changes(layers, path.Join(a.rootPath(), "diff", id))}

转载于:https://my.oschina.net/stevenKelly/blog/649882

你可能感兴趣的文章
利用rand7()构造rand10()
查看>>
MySQL 备份与恢复
查看>>
吃午饭前,按书上的代码写会儿--Hunt the Wumpus第一个版本
查看>>
easyui中combobox的值改变onchang事件
查看>>
Eclipse魔法堂:任务管理器
查看>>
一周自学动态站点设计
查看>>
eclipse中查看某个方法(函数)被谁调用
查看>>
poj万人题
查看>>
Android-Universal-Image-Loader
查看>>
Java从零开始学四(数据类型)
查看>>
Android 从硬件到应用:一步一步向上爬 4 -- 使用 JNI 方法调硬件驱动
查看>>
windows 如何查看端口占用情况?
查看>>
根据ImageView的大小来压缩Bitmap,避免OOM
查看>>
TEST
查看>>
loadrunner 的Administration Page里面设置
查看>>
程序员喜欢怎样的职位描述?(转)
查看>>
威胁快报|ProtonMiner挖矿蠕虫扩大攻击面,加速传播
查看>>
<<深入PHP面向对象、模式与实践>>读书笔记:面向对象设计和过程式编程
查看>>
架构的“一小步”,业务的一大步
查看>>
聊聊flink JobManager的heap大小设置
查看>>