内容简介:探讨分享 - 容器与持久化存储
本文内容来源于3月28日有容云 Docker 技术交流群微信群分享活动,根据有容云技术实施团队原创分享内容整理而成。对Docker技术感兴趣、或对本文中细节需继续探讨的朋友,欢迎加入有容云Docker技术交流群参与讨论!(关注有容云微信公众号,回复“加群”)
分享主题
-
容器正逐渐成为云上应用的标准部署单元,容器该如何解决持久化存储的需求?
-
容器编排系统已成当红炸子鸡,在无状态的容器中,存储系统面临哪些新的挑战?
-
容器与持久化存储系统是融合架构还是分离架构?
本次交流与大家围绕上述几个问题探讨容器和持久化存储相关知识。
容器对存储插件的定义
以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、RancherConvoy,REX-Ray等)。
容器正逐渐成为云计算平台应用程序的标准部署单元,容器能轻易的将各式各样的应用程序及其runtime打包成统一的对象,于是编排调度系统能把各种应用程序当成统一的容器进行处理,大大简化编排调度系统的复杂度。结合Docker对存储插件的定义,不难看出Docker希望容器的运行环境独立而纯粹,不希望引入有状态和复杂的存储系统。
存储插件
Convoy作为一个Dockervolume plugin,支持不同的后端存储,为Docker提供MountPoint,也就是一个的目录,可能是挂载了后端存储、本地块设备或者就是本地目录。
Convoy的代码从结构、风格和使用的库,都与Docker十分相似,并且比Docker简单很多。在源码级别上值得留意的点,我感觉有两点。①插件式结构与Interface的运用。② 作者对事物的抽象能力与方法。
1、Convoy Daemon (Convoy/Daemon)
Daemon是主要的功能模块,可以接收来自Convoy client和Docker的命令,对Backend存储进行了抽象,以便统一管理。下面先从Daemon的启动开始。
1.1Daemon进程启动
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建立所需要环境和配置。
3)Driver初始化,优先从配置文件读取信息忽略命令行输入的参数,如果配置文件不存在则根据命令行参数初始化。
图2. Convoy配置文件内容
遍历DriverList,找到配置文件或命令行指定的Driver,执行初始化函数Init,并添加到Daemon.ConvoyDrivers中。
4)根据Convoy的工作目录的内容,更新管理元数据,图1中也有相应的模块。
-
-
NameUUIDIndex: volume name : volume UUID
-
SnapshotVolumeIndex:snapshot UUID : volume UUID
-
图3.convoy工作目录和volume配置文件
5)Router注册:Router提供两部分的路由,并将Daemon的Router指向该Router。
① 处理Convoy Client的命令Client Request Router,处理客户端发送的http request。
②处理来自Docker的请求Docker Volume Plugin Router,Convoy本身就是Docker的Volume Plugin,提供了如下的接口。
6) http server启动,根据sockFile=/var/run/convoy/convoy.sock 和 上一步骤的Router,启动http server。
2.2 Daemon的请求处理逻辑
Daemon启动后便可以处理请求(Convoy client或Docker),主要处理逻辑Router收到HTTP请求,将请求分发给各个模块:Docker、Volume、Snapshot、Backup。这个4个逻辑模块根据Drivername(指定的或者默认的)从Daemon.ConvoyDrivers中获取对应的Driver。ConvoyDrivers中的Driver是实现了ConvoyDriver interface的结构。
图4.convoy daemon请求处理逻辑
从图4中可以看出ConvoyDriver接口规定了3组接口对应Volume,Snapshot,Backup的操作,用于操作Backend Storage。逻辑处理最终调用这些接口访问Backend Storage。
2.3 ConvoyDriver implement
截止到0.4.3版本,Convoy支持4中后端存储(实现了ConvoyDriver接口),如下表。Convoy是如何对后端存储进行抽象和管理的,主要使用了4种结构Driver:
Volume,Snapshot,Device:
-
Driver:主要实现了ConvoyDriver接口,提供对Volume,Snapshot,Backup等功能。
-
Volume:管理提供到Docker或者Convoy Client的Volume。
-
Snapshot:用于管理Volume的快照。
-
Device:管理后端存储提供的存储空间,如:Devicemapper的Device;Glusterfs的Volume;Vfs的目录等。
图5.ConvoyDriver的实现
图5Device结构内容,记录了该Driver的后端存储的信息。
2.4 Objectstore提供实现备份的框架
Objectstore模块是实现BackupOperations接口所需要的基本功能,目前实现了两种备份后端:S3和VFS。提供了两种备份方案:DeltaBlockBackup(增量块)和BackupFile(备份文件)。
-
Devicemapper使用DeltaBlockBackup方式备份,实现了DeltaBlockBackupOperations接口。
-
Vfs使用BackFile方式备份。
-
Volume,Snapshot,Backup用于管理备份存储的数据。
-
ObjectStoreDriver后端备份存储需要实现的接口。
-
S3ObjectStoreDriver,VfsObjectStoreDriver实现ObjectStoreDriver。
Ebs在实现BackupOperations接口时,使用Ebs自身的Client来实现Backup。Ebs本身就是一个分布式存储系统,不再需要额外的Objectstore对其进行备份。
图6. objectstore框架
通过Vfs备份的目录结构:
Volume.Cfg的内容,保存图6中的Volume结构
Backup_[id].cfg,保存图6中的Backup结构
Blocks目录保存了Snapshot存储的真实数据,以Block的形式存储在不同目录。
容器、应用程序、持久化存储
容器与持久化存储,在我看来本不该拿来一起讨论,二者关联性是比较弱的。容器是一种打包方式,基于这种打包方式带来了一系列的好处,如部署、程序运行环境统一,编排,调度等,诚然这些貌似与外部持久化存储真心没太大关系。其实对持久化存储真正有需求的是容器里面的应用程序,应用程序对存储的需求是多种多样的。基于容器化应用程序带来的好处,运维工程师都是期望能将更多的应用程序容器化,以减轻运维负担。
对于无状态应用程序,容器化几乎带来的只有好处。但对于一些有状态的应用程序,如数据库,需要进行容器化时,便面临持久化存储的问题。下面是一个外部持久化存储解决 mysql 容器化问题的例子。
三台运行Mysql数据库的主机将持久化存储系统的虚拟磁盘映射上,Mysql将数据写入这些虚拟磁盘中。
当其中一个MySQLl数据库发生故障时,在新的主机上将故障主机的虚拟磁盘映射上,供MySQL使用,可以快速恢复数据库故障。
此时,将MySQL数据库容器化将变得十分简单,编排调度系统,能够快速发现MySQL集群异常,并快速调度其他主机上,减少故障时间。
由上述讨论,其实无论容器在或不在,存储还是存储。当然为了适应容器的快速迁移(相对于虚拟机),多种多样的应用程序对存储也提出了细粒度控制、应用感知、快速创删等新的需求,但存储作为以稳定性为重的基础设施,依然万变不离其宗。
持久化存储系统的选择
持久化存储系统可分为开源存储系统和商业存储系统。通常商业存储系统会由厂商解决所有问题,这里就不谈商业化存储了。开源分布式存储方案如下:
-
块存储: Ceph rbd,Sheepdog
-
文件存储: Glusterfs,Cephfs,Hdfs
-
对象存储: OpenStack Swift,Ceph Rgw
块存储、文件存储、对象存储三种存储访问方式不同的存储系统,最合适容器的,我想应该是对象存储系统,对象存储系统是通过URL访问的,应用程序只需要知道对象存储系统的URL就可以直接访问存储系统,这种方式更贴近容器的无状态、临时性和快速调度。
为什么选择分布式存储系统?
1. 云计算时代,传统存储不能满足虚拟化、容器对存储的需求
-
传统存储缺少灵活性,虚拟机、容器的部署及其负载是快速变化的,并且容器还是快速迁移的。
-
传统存储缺少自动化
-
传统存储缺少细粒度控制
-
传统存储的配置是非常严格的
2. 构建存储的TCO(总拥有成本)十分高昂
-
数据量成指数级增长,但存储的预算却没有相应的增长,传统存储的价格是无法承受之痛。
-
数据规模快速增长,企业往往需要过度预算,过度采购,因为传统存储的扩展,升级和替换是十分昂贵的。
3. 高昂的存储系统运营成本(OPEX)
-
需要专业的存储管理团队,不仅需要学习专业的存储知识,还要学习存储厂商指定的技巧。
-
处理存储系统问题是相当花费时间。
当然开源分布式存储系统,只解决了第1,2点,第3点并没有得到有效的解决,反而有点加深的趋势。
Q&A
Q1:有容云在Ceph上遇到哪些坑?都是怎么解决的?
A:有容云并没有使用ceph,我们考虑到Ceph本身过于庞大和复杂,产品化难度太大,于是完全自研一套分布式存储产品。
Q2:Ceph做过哪些优化?
A:Ceph结与 Linux 都有许多参数进行调优,Ceph本身也有多种Cache,目前也使用Spdk进行优化。
Q3:问个与存储无关的问题,在优化了DockerFile后,构建 Java 镜像还是大约要6分钟左右,还有其他优化方案吗?每天开发环境要构建上100次感觉太慢了。
A:这个需要先找到构建镜像的瓶颈在哪里,是否存在需要在网络上下载安装包,还是编译时间太长,导致构建缓慢。针对瓶颈解决问题。
Q4:Gluster与Ceph的区别是啥?应用场景有哪些不同?
A:Gluster支持文件接口,Ceph支持块,文件,对象接口;简单的Gluster比较简单,社区版本就已经足够稳定,但是海量小文件问题比较突出。Ceph随着OpenStack已经十分火了,社区很活跃,也有不少存储厂商基于Ceph做分布式存储产品。
Q5:我用了Glusterfs,我想问下有什么需要注意和优化的地方?
A:Glusterfs社区版本就足够稳定了,在规划初期尽量避免出现单卷出现海量小文件问题。
Q6:Convoy不支持Ceph?并没有说明Docker怎么与Ceph结合使用。
A:Convoy不支持Ceph,并且已经不再更新,Docker跟Ceph结合非常简单,或者说Docker跟所有外部存储结合都非常简单,就像分享内容提到的满足几个接口就行了。
Q7:对象存储,和块存储是不是有不同的技术选型?
A:当然两者应用场景不一样,块存储主要是在虚拟化环境、数据库场景。对象存储优势在于大规模海量数据和HTTP接口上。 针对不同的应用场景选型,如果需要非常大规模的,跨区域的场景建议使用OpenStack Swift,简单好用。如果应用场景既需要块存储,对象存储只需要中小规模的情况,一个Ceph搞定所有,也是不小的诱惑。如果公司内部没有专业的研发和运维团队,谨慎使用开源存储上生产。
Q8:开源化存储Ceph和Sheepdog的Iops能达到多少?这两种存储的使用场景。
A:具体的IOPS跟物理的存储介质和如何设置Cache的关系太大了,Ceph用的最多的地方就是块存储,Sheepdog是块存储。个人感觉,Ceph的设计比较学院派,大而全,数据拆分很细,元数据很多,维护难度较大,但是社区活跃,找人比较容易一些。Sheepdog体量小,架构复杂度较低,但出问题估计找人难度大。两者都可以块存储,应用场景类似。
Q9:Docker已经提供了Volume功能,Convoy做为Docker的插件,在那方面有做改进或者优化?而且我们在实际部署Docker应用的时候,一般都没有考虑过存储的问题,都是通过存储工程师分配好的文件(包含共享存储),为何要引入Convoy?
A:Docker的Volume是使用本地存储系统,通过Volume Plugin机制访问外部存储,如Convoy就是Docker Volume Plugin的一种实现。
Q10:Ceph的稳定性和性能如何?
A:无异常情况稳定性还是可以的,分布式存储系统性能都是个问题,最好有专门的工程师进行调优和维护,任何软件长时间运行总是会出问题的,必须找到人救火。
Q11:我刚来没太看清楚,但是对最后那个MySQL的例子比较感兴趣,我的理解是三个MySQL实例同时连接到存储,然后一个挂了后,另起一个实例,我的问题是,这之前的三个存储是共享数据的Cluster集群环境嘛?如果是怎么保证数据的一致性和写入冲突问题?
A:多个MySQL最好不要挂同一个存储空间,数据的性能瓶颈在于存储端,多个挂一个存储卷并不会提升性能。通常都是有上层业务来实现分表分库,负载均衡,从而避免一致性问题。例子中是每个MySQL实例挂载一个单独卷。
Q12:Kafka、Zk、Redius这些本地集群化组件,是否有必要容器化部署,有什么衡量标准?
A:还是容器化带来一系列好处吧,快速部署,开发测试运行环境统一、灵活,扩容缩容等。具体没什么衡量标准,由架构决定是否需要容器化。建议尽可能多的容器化。
Q13:能说下Ceph的瓶颈在哪方面吗?
A:磁盘和网络,计算机体系结构中最慢的两个部件。Ceph的代码级没有什么可以优化的空间。当然Ceph的强一致性,造成io路径加长会影响性能。
以上所述就是小编给大家介绍的《探讨分享 - 容器与持久化存储》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JavaScript & jQuery
David Sawyer McFarland / O Reilly / 2011-10-28 / USD 39.99
You don't need programming experience to add interactive and visual effects to your web pages with JavaScript. This Missing Manual shows you how the jQuery library makes JavaScript programming fun, ea......一起来看看 《JavaScript & jQuery》 这本书的介绍吧!