窥探Docker中的Volume Plugin内幕

编者注:

本文根据有容云技术实施团队原创分享内容整理。对Docker技术感兴趣、或对本文中细节需继续探讨的朋友,欢迎加入我们参与讨论!

特别鸣谢中生代技术群分享支持。

 

注:本期分享由张朝潞原创,有容云整理发布,转载请注明出处

 

作者介绍:

张朝潞,有容云(Yourun Cloud)平台存储架构师。曾工作于UIT,华三,腾讯,专注分布式存储的研究和开发,对云计算存储解决方案方面有很深的技术造诣和行业理解。

 

本次交流将与大家分享Docker Volume plugin相关的内容。今日主题是窥探Docker中的Volume plugin内幕。

 

因为应用数据对安全,可用性,共享,性能等方面的要求和Root Image的要求完全不一样,所以Docker并不推荐采用Root Image的存储方式来存储应用数据,而是采用了Volume这样一个独立的数据访问接口。

 

应用通过Volume去访问相关的数据,Volume的实现和CoW的分层文件系统完全独立,通过Volume plugin机制可轻易驱动外部存储。

 

下面我们就围绕Volume Plugin  Introduction、Container and Volume、Docker Volume Plugin、自定义Volume Plugin四个方面来展开。

 

一. Volume Plugin Introduction

通过Volume机制,Docker可以轻易地将主机目录挂载到容器中;通过Docker的Volume Plugin机制,使Docker能够方便地整合第三方存储,为Docker提供Volume。

 

 

出处链接:https://github.com/docker/docker/blob/master/docs/extend/plugins.md

 

二. Container and Volume

 

1 .Container如何使用Volume?

   Volume机制可以使容器访问存储都使用统一的接口(文件接口),对于容器中的进程来说,Volume就是一个已挂载的目录,容器内进程使用该目录就与普通目录一样。

 

   Docker使用Container结构管理容器,Container结构中有map类型的MountPoints变量,用于存储Container中所有已挂载的Volume即是MountPoint结构,MountPoint结构保存挂载目录和Volume结构的基本信息,并且管理目录的权限控制、挂载传播方式等特性。

 

Volume是个interface,Docker实现两种Volume:①基于主机文件系统。②基于Volume Plugin。

Container中的Volume

 

 

2.基于主机文件系统提供Volume

    容器启动:docker run -i -v /data  ubuntu:latest /bin/bash

容器内看到的挂载信息:

 

 

/etc/resolv.conf、/etc/hostname和/etc/hosts三个文件是为了解决每个Container都拥有自己的Hostname和DNS配置,使用了bind mount将主机的文件,挂载到Container内部。/data也是使用了同样的方式将主机的目录挂载到Container中。下面是主机挂载到Container的文件:

 

 

查看/dev/disk/by-uuid/88f22c9e-9d5d-4c7e-8984-eba8446361e6是链接文件指向/dev/sda2,这是主机的根目录文件系统。

 

 

3 .Container中的Volume

容器启动:

docker run -i -v cvol1:/data –volume-driver=convoy ubuntu:latest /bin/bash

将volume: dockervol挂载到容器目录/data

    容器内看到的挂载信息:

 

此时挂载卷信息:

 

 

三. Docker Volume Plugin

 

1. Docker Volume Plugin框架

Docker volume框架

1.) Docker Daemon对Volume的管理

 

Docker Daemon中的Volume

 

如上图,Docker Daemon结构中有个成员Volumes,类型是VolumeStore类型,包含一组管理Volume的函数:Create、Remove、List、Get、Refs ...。通过两个变量,管理Container和Volume的关系。

  • names : map结构,Key是Volume的name,value是实现Volume接口的结构对象。存储该Daemon内所有的Volume。
  • ReFS: map结构,key是volume的name,value是string数组保存引用该Volume的Container ID。

Docker Daemon通过Volumes变量,就可以管理所有的Volume,提供如下命令:

 

 

2.) docker volume 管理

 

基于本地文件系统的volume框架

 

Docker提供两个接口Volume和Driver,所有提供给Docker使用的Volume必须实现Volume接口。后端驱动需要实现Driver接口。Driver是对提供出去的Volume进行管理。目前Docker实现了两种Volume &Driver。

 

 ① 基于本地文件系统的Volume

 

可以在执行Docker create或Docker run时,通过-v参数将主机的目录作为容器的数据卷。这部分功能便是基于本地文件系统的volume管理。上图中蓝色部分LocalVolume和Root。这两个结构就是对主机目录和文件进行管理,具体的对应关系如下图:

 

 

从上图可以看出,基于本地文件系统的卷管理,Driver便是卷的根目录/var/lib/docker/volumes。一个卷就是根目录下的一个子目录。

 

 ② 适配Plugin的Volume

    Docker为了支持第三方存储方案,在1.8版本引入Volume Plugin机制,Volume Adapter和Volume Driver Adapter分别实现了接口Volume和Driver接口,用于表示由Plugin提供的Volume和Plugin driver。在下一小节详细描述。

 

基于本地文件系统的Volume框架中,全局变量drivers保存了所有注册到Docker Daemon的Driver。Docker Daemon需要对Volume进行管理操作时,通过GetDriver函数从drivers变量中获取指定名称的Driver,通过Driver可以通过Create,Remove,List,Get对Driver中Volume进行管理。通过Get函数获取Volume结构,可以对卷进行管理操作:Name,DriverName,Path,Mount,Unmount。

 

3 .) docker plugin 实现原理

 

Volume Plugin实现原理

① Docker Plugin机制

 

     上一节已经说过Docker针对Volume Plugin实现了两个适配类型Volume Driver Adapter和Volume Adapter。

  • Volume Driver Adapter : 实现Driver接口,用于抽象各种Plugin的驱动,该类型可以适配所有符合规范的Volume Plugin,对Plugin进行管理。
  • Volume Adapter :  实现Volume接口,用于抽象所有Plugin提供的Volume,该类型可以适配所有符合规范的Volume Plugin提供的类型,对Volume进行管理。

     通过抽象,对于Plugin和其提供的Volume,Docker Daemon结构和Container结构使用上述两个适配类型,对Plugin和Volume进行管理和使用。  

 

上述两个类型都有一个Volume Driver Proxy结构变量proxy,用于与Plugin进行通信。Volume Driver Proxy结构实现了与plugin通信的接口volume Driver,提供Create、Remove、Path、Mount、Unmount、List、Get接口与通信。Volume Driver Proxy结构的client变量,使用这个变量与Plugin Daemon进行通信。client变量是Plugin结构中的Client变量是Client结构类型,包含了http.Client类型对象。

 

    上图中左下方,Plugins结构类型的全局变量Storage保存所有被Docker Daemon发现的Plugin结构,Plugin结构代表外部插件。

 

    ② Docker Plugin的发现过程

Docker Daemon通过Unix域套接字与Plugin Daemon进行通信。所以Plugin需要让Docker Daemon知道Plugin的Unix域套接字文件的路径。再执行命令:docker run ... -v volumename:/data --volume-driver=convoy

 

发现步骤:

  • Docker Daemon首先会在/run/docker/plugins搜索对应的套接字文件,套接字文件名必须和Volume Driver名一致,如上述命令,便是搜索convoy.sock。
  • 如果上一步搜索不到,则到/etc/docker/plugins和/usr/lib/docker/plugins两个目录搜索spec或json文件。文件中指定套接字文件的URL。如:unix:///var/run/convoy/convoy.sock 。
  • 根据前面两步发现的Unix域套接字URL,构建Plugin对象,并将新建对象加入到全局变量storage的Plugins字段中。     

 

    ③ Docker Volume Plugin的使用

    执行docker run命令时,指定参数--volume-driver=convoy。Docker Daemon会先从storage.plugins中寻找Plugin结构,如果没有找到,就发起②的发现流程。找到则直接使用Client构建volume Driver Proxy。

 

    ④ Docker Daemon与Plugin Daemon通信的API

    前面已经提到过,Docker Daemon和Plugin Daemon基于Unix域套接字,使用Restful API进行通信,下面是详细的API:

  • Plugin.Activate : 发送一个请求到Plugin,Plugin返回其类型,如convoy就返回Volume Driver。相当于Docker和Plugin Daemon直接的连接建立的握手报文。
  • VolumeDriver.Create : 创建一个卷,Docker会发送卷名称和参数发送给插件,卷插件会根据Docker发送过来的参数创建一个卷,并和这个卷名称关联。
  • VolumeDriver.Mount : 挂载一个卷到本机,Docker会把卷名称和参数发送给参数。插件会返回一个本地路径给Docker,这个路径就是卷所在的位置。Docker在创建容器的时候,会将这个路径挂载到容器中。
  • VolumeDriver.Path : 一个卷创建成功后,Docker会调用Path API来获取这个卷的路径,随后Docker通过调用Mount API,让插件将这个卷挂载到本机。
  • VolumeDriver.Unmount : 当容器退出时,Docker daemon会发送Umount API给插件,通知插件这个卷不再被使用,插件可以对该卷做些清理工作(比如引用计数减一,不同的插件行为不同)。
  • VolumeDriver.Remove : 删掉特定的卷时调用,当运行"docker rm -v"命令时,Docker会调用该API发送请求给插件。
  • VolumeDriver.List :  执行docker volume ls命令时,会向plugin发送该请求,获取volume list。
  • VolumeDriver.Get :  获取Plugin Volume的详细信息。

四. 自定义Volume Plugin

为了方便实现Volume Plugin,Docker提供go-plugins-helper包(https://github.com/docker/go-plugins-helpers),提供基础的功能,仅仅需要实现一个接口volume.Driver,并启动http server便可。

 

例子:GlusterFS就是使用这个包,基于GlusterFS提供Volume。https://github.com/calavera/docker-volume-glusterfs

 

 

关于Docker存储方面的内容,我们之前分享过一篇叫《Docker容器对存储的定义(Volume 与 Volume Plugin) 》的文章,感兴趣的朋友可以关注有容云搜索下。好的,我们今天的分享先告一个段落,谢谢大家!

 

 

 

 

 

分享:窥探Docker中的Volume Plugin内幕

有容云-构筑企业容器云 www.youruncloud.com

调查问卷

1、您所在的公司在IT方面面临哪些挑战? (最少选1项)

技术架构老旧过时,业务需要IT从传统架构转向互联网架构
需要管理使用多个云,避免vendor locked-in
IT资产(例如虚拟机或者物理服务器)的资源利用低,成本高昂难以承受
业务有强烈弹性需求 (比如,短期内用户访问量剧增)
使用微服务架构
开发、测试、生产环境不统一,企业内缺乏统一交付标准
运维工作复杂、自动化程度低,产品交付周期长
缺乏服务于内部其他业务部门或者第三方应用,且具备完善的计费及权限模块的PaaS平台
其他

2、您所在的公司在使用哪些私有、公有云解决方案?(最少选1项)

OpenStack
CloudStack
VMware
AWS
Azure
阿里云
金山云
腾讯云
UCloud
青云
其他

3、您是如何看待开源软件的?您所在的公司是否有使用开源软件?


没有,但有意向
没有,不接受

4、请问您所在的公司所属行业是?

传统金融、新金融
运营商
互联网
其他

5、您所在的公司在使用哪些容器管理方案?(最少选1项)

Kubernetes
Mesos
Docker Swarm
Rancher
没有

6、您所在的公司在使用容器管理方案时,认为其最需要改善的功能项是?(最少选1项)

网络管理方案
存储管理方案
易用性
完整性
没有
           

文章归档