内容简介:探讨分享 - 容器与持久化存储
本文内容来源于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路径加长会影响性能。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Tango with Django
David Maxwell、Leif Azzopardi / Leanpub / 2016-11-12 / USD 19.00
Tango with Django is a beginner's guide to web development using the Python programming language and the popular Django web framework. The book is written in a clear and friendly style teaching you th......一起来看看 《Tango with Django》 这本书的介绍吧!