导读:容器得到了越来越广泛的使用,以下问题困扰架构师:
容器正逐渐成为云上应用的标准部署单元,容器该如何解决持久化存储的需求?
容器编排系统已成当红炸子鸡,在无状态的容器中,存储系统面临哪些新的挑战?
容器与持久化存储系统是融合架构还是分离架构?
本文探讨了容器和持久化存储相关知识,由张朝潞在高可用架构群分享,转载请注明来自高可用架构公众号 ArchNotes。
张朝潞
有容云平台存储架构师
张朝潞,有容云平台存储架构师。曾工作于UIT、华三、腾讯、专注分布式存储的研究和开发,对云计算存储解决方案方面有很深的技术造诣和行业理解。
一.容器对存储插件的定义
以 Docker 为例, Docker 对存储卷定义了一组简单的接口,外部存储只要实现简单的接口便可以和外部存储对接。
Docker daemon 和 plugin daemon 基于 UNIX 域套接字,使用 RESTful API 进行通信,下面是详细的 API:
Plugin.Activate : 握手。
VolumeDriver.Create : 创建卷。
VolumeDriver.Mount : 挂载卷。
VolumeDriver.Path : 获取卷的路径。
VolumeDriver.Unmount : 卸载卷。
VolumeDriver.Remove : 删除卷。
VolumeDriver.List : 获取 volume 列表。
VolumeDriver.Get : 获取 volume 信息。
VolumeDriver.Capabilities : 获取 volume 属性
从上面这组接口可以看出, Docker 容器是通过 mount 的方式将外部存储挂载到本地目录,尽量使内部应用程序对存储是无感知的,应用程序就像使用本地目录一样使用外部存储卷,而将外部存储的管理交给存储 Plugin 负责(如 Flocker、Rancher Convoy,REX-Ray 等)。
容器正逐渐成为云计算平台应用程序的标准部署单元,容器能轻易的将各式各样的应用程序及其 runtime 打包成统一的对象,于是编排调度系统能把各种应用程序当成统一的容器进行处理,大大简化编排调度系统的复杂度。结合 Docker 对存储插件的定义,不难看出 Docker 希望容器的运行环境独立而纯粹,不希望引入有状态和复杂的存储系统。
二、存储插件
Convoy 作为一个 Docker volume plugin,支持不同的后端存储,为 Docker 提供 MountPoint,也就是一个的目录,可能是挂载了后端存储、本地块设备或者就是本地目录。
Convoy 的代码从结构、风格和使用的库,都与 Docker 十分相似,并且比 Docker 简单很多。
(小编:下面展开介绍一下 convoy 源代码的部分模块,不需要了解细节的读者可以直接跳到第三部分:容器、应用程序、持久化存储。)
Convoy 在源码级别上值得留意的点,我认为有两点:①插件式结构与 interface 的运用。② 作者对事物的抽象能力与方法。
1、convoy daemon (convoy / daemon)
图 1 中黑色部分
daemon 是主要的功能模块,可以接收来自 convoy client 和 Docker 的命令,对 backend 存储进行了抽象,以便统一管理。下面先从 daemon 的启动开始。
1.1、daemon 进程启动
1)执行命令:
convoy daemon --drivers glusterfs --driver-opts glusterfs.servers=192.168.0.3 --driver-opts glusterfs.defaultvolumepool=vol2
2) convoy 程序解析参数,获得 daemon 子命令,调用到 daemon.Start 函数(convoy/daemon/daemon.go), Start 函数中主要围绕 daemon struct 建立所需要环境和配置。