前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分布式存储glusterfs原理,部署及k8s, Heketi集成

分布式存储glusterfs原理,部署及k8s, Heketi集成

原创
作者头像
iginkgo18
修改2021-10-26 17:04:08
2.4K3
修改2021-10-26 17:04:08
举报
文章被收录于专栏:devops_k8sdevops_k8s

1 分布式文件系统简介

分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源并不直接与本地节点相连,而是分布于计算网络中的一个或者多个节点的计算机上。目前意义上的分布式文件系统大多都是由多个节点计算机构成,结构上是典型的客户机/服务器模式。流行的模式是当客户机需要存储数据时,服务器指引其将数据分散的存储到多个存储节点上,以提供更快的速度,更大的容量及更好的冗余特性;

1.1 产生

计算机通过文件系统管理、存储数据,而现在数据信息爆炸的时代中人们可以获取的数据成指数倍的增长,单纯通过增加硬盘个数来扩展计算机文件系统的存储容量的方式,已经不能满足目前的需求。

       分布式文件系统可以有效解决数据的存储和管理难题,将固定于某个地点的某个文件系统,扩展到任意多个地点/多个文件系统,众多的节点组成一个文件系统网络。每个节点可以分布在不同的地点,通过网络进行节点间的通信和数据传输。人们在使用分布式文件系统时,无需关心数据是存储在哪个节点上、或者是从哪个节点从获取的,只需要像使用本地文件系统一样管理和存储文件系统中的数据;

1.2 代表-nfs

NFS(Network File System)即网络文件系统,它允许网络中的计算机之间通过TCP/IP网络共享资源。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样;

1.2.1 优点

1)节约使用的磁盘空间客户端经常使用的数据可以集中存放在一台机器上,并使用NFS发布,那么网络内部所有计算机可以通过网络访问,不必单独存储;

2)节约硬件资源NFS还可以共享软驱,CDROM和ZIP等的存储设备,减少整个网络上的可移动设备的数量;

3)用户主目录设定对于特殊用户,如管理员等,为了管理的需要,可能会经常登录到网络中所有的计算机,若每个客户端,均保存这个用户的主目录很繁琐,而且不能保证数据的一致性.实际上,经过NFS服务的设定,然后在客户端指定这个用户的主目录位置,并自动挂载,就可以在任何计算机上使用用户主目录的文件;

1.2.2 缺点

1) 存储空间不足,需要更大容量的存储;

2) 直接用NFS挂载存储,有一定风险,存在单点故障;

3) 某些场景不能满足要求,大量的访问磁盘IO是瓶颈;

4) 扩容,缩容影响服务器较多;

5) 目录层级不要太深,合理组织目录,数量不要太多,增大glusterfs目录缓存,另外还可以设计把元数据和数据分离,将元数据放到 内存数据库,并在ssd持久保存;

6) 小文件性能较差,它主要为大文件设计,对小文件优化很少, 虽然在客户端采用了元数据缓存md-cache提高小文件性能,但是md-cache大小有限,海量小文件缓存命中率会严重下降,优化效果会减小,需要增大元数据缓存或者将小文件合并为一个大文件,成为block

2 常见分布式存储

2.1 FastDFS:

一个开源的轻量级分布式文件系统,是纯C语言开发的。它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。FastDFS 针对大量小文件存储有优势。

2.2 GlusterFS:

主要应用在集群系统中,具有很好的可扩展性。软件的结构设计良好,易于扩展和配置,通过各个模块的灵活搭配以得到针对性的解决方案。GlusterFS适合大文件,小文件性能相对较差。

2.3 MooseFS:

比较接近GoogleFS的c++实现,通过fuse支持了标准的posix,支持FUSE,相对比较轻量级,对master服务器有单点依赖,用perl编写,算是通用的文件系统,可惜社区不是太活跃,性能相对其他几个来说较差,国内用的人比较多。

2.4 Ceph:

C++编写,性能很高,支持Fuse,并且没有单点故障依赖;Ceph 是一种全新的存储方法,对应于 Swift 对象存储。在对象存储中,应用程序不会写入文件系统,而是使用存储中的直接 API 访问写入存储。因此,应用程序能够绕过操作系统的功能和限制。在openstack社区比较火,做虚机块存储用的很多!

2.5 GoogleFS

GoogleFS:性能十分好,可扩展性强,可靠性强。用于大型的、分布式的、对大数据进行访问的应用。运用在廉价的硬件上。

3 Gluster存储基础梳理

GlusterFS系统是一个可扩展的网络文件系统,相比其他分布式文件系统,GlusterFS具有高扩展性、高可用性、高性能、可横向扩展等特点,并且其没有元数据服务器的设计,让整个服务没有单点故障的隐患。Glusterfs是一个横向扩展的分布式文件系统,就是把多台异构的存储服务器的存储空间整合起来给用户提供统一的命名空间。用户访问存储资源的方式有很多,可以通过NFS,SMB,HTTP协议等访问,还可以通过gluster本身提供的客户端访问;

GlusterFS是Scale-Out存储解决方案Gluster的核心,它是一个开源的分布式文件系统,具有强大的横向扩展能力,通过扩展能够支持数PB存储容量和处理数千客户端。GlusterFS借助TCP/IP或InfiniBand RDMA网络将物理分布的存储资源聚集在一起,使用单一全局命名空间来管理数据。GlusterFS基于可堆叠的用户空间设计,可为各种不同的数据负载提供优异的性能;

GlusterFS 适合大文件还是小文件存储?

弹性哈希算法和Stripe 数据分布策略,移除了元数据依赖,优化了数据分布,提高数据访问并行性,能够大幅提高大文件存储的性能。对于小文件,无元数据服务设计解决了元数据的问题。但GlusterFS 并没有在I/O 方面作优化,在存储服务器底层文件系统上仍然是大量小文件,本地文件系统元数据访问是一个瓶颈,数据分布和并行性也无法充分发挥作用。

因此,GlusterFS 适合存储大文件,小文件性能较差,还存在很大优化空间。

3.1 应用场景

GlusterFS 在企业中应用场景理论和实践上分析,GlusterFS目前主要适用大文件存储场景,对于小文件尤其是海量小文件,存储效率和访问性能都表现不佳。海量小文件LOSF问题是工业界和学术界公认的难题,GlusterFS作为通用的分布式文件系统,并没有对小文件作额外的优化措施,性能不好也是可以理解的;

Media:    文档、图片、音频、视频

Shared storage: 云存储、虚拟化存储、HPC(高性能计算)

Big data: 日志文件、RFID(射频识别)数据

3.2 术语

Brick: GlusterFS中的存储单元,通过是一个受信存储池中的服务器的一个导出目录。可以通过主机名和目录名来标识,如'SERVER:EXPORT'。Client:挂载了GlusterFS卷的设备;

GFID: GlusterFS卷中的每个文件或目录都有一个唯一的128位的数据相关联,其用于模拟inode;

Namespace: 每个Gluster卷都导出单个ns作为POSIX的挂载点;

Node: 一个拥有若干brick的设备;

RDMA: 远程直接内存访问,支持不通过双方的OS进行直接内存访问;

RRDNS: round robin DNS是一种通过DNS轮转返回不同的设备以进行负载均衡的方法;

Self-heal: 用于后台运行检测复本卷中文件和目录的不一致性并解决这些不一致;

Split-brain: 脑裂

Volfile: Glusterfs进程的配置文件,通常位于/var/lib/glusterd/vols/volname;

Volume: 一组bricks的逻辑集合;

a)Trusted Storage Pool• 一堆存储节点的集合

• 通过一个节点“邀请”其他节点创建,这里叫probe

• 成员可以动态加入,动态删除

代码语言:javascript
复制
添加命令如下:
node1# gluster peer probe node2

删除命令如下:
node1# gluster peer detach node3

2)Bricks:

Brick是一个节点和一个导出目录的集合,e.g. node1:/brick1

• Brick是底层的RAID或磁盘经XFS或ext4文件系统格式化而来,所以继承了文件系统的限制

• 每个节点上的brick数是不限的

• 理想的状况是,一个集群的所有Brick大小都一样。

3)Volumes• Volume是brick的逻辑组合

• 创建时命名来识别

• Volume是一个可挂载的目录

• 每个节点上的brick数是不变的,e.g.mount –t glusterfs www.std.com:test /mnt/gls

• 一个节点上的不同brick可以属于不同的卷

• 支持如下种类:

a) 分布式卷

b) 条带卷

c) 复制卷

d) 分布式复制卷

e) 条带复制卷

f) 分布式条带复制卷

3.1)分布式卷• 文件分布存在不同的brick里

• 目录在每个brick里都可见

• 单个brick失效会带来数据丢失

• 无需额外元数据服务器

3.2)复制卷

• 同步复制所有的目录和文件

• 节点故障时保持数据高可用

• 事务性操作,保持一致性

• 有changelog

• 副本数任意定

3.3)分布式复制卷

• 最常见的一种模式

• 读操作可以做到负载均衡

3.4)条带卷

• 文件切分成一个个的chunk,存放于不同的brick上

• 只建议在非常大的文件时使用(比硬盘大小还大)

• Brick故障会导致数据丢失,建议和复制卷同时使用

• Chunks are files with holes – this helps in maintaining offset consistency.

3.3 GlusterFS无元数据设计

元数据是用来描述一个文件或给定区块在分布式文件系统中所在的位置,简而言之就是某个文件或某个区块存储的位置。传统分布式文件系统大都会设置元数据服务器或者功能相近的管理服务器,

主要作用就是用来管理文件与数据区块之间的存储位置关系。相较其他分布式文件系统而言,GlusterFS并没有集中或者分布式的元数据的概念,取而代之的是弹性哈希算法。集群中的任何服务器和客户端都可以利用哈希算法、路径及文件名进行计算,就可以对数据进行定位,并执行读写访问操作;

这种设计带来的好处是极大的提高了扩展性,同时也提高了系统的性能和可靠性;另一显著的特点是如果给定确定的文件名,查找文件位置会非常快。但是如果要列出文件或者目录,性能会大幅下降,因为列出文件或者目录时,需要查询所在节点并对各节点中的信息进行聚合。此时有元数据服务的分布式文件系统的查询效率反而会提高许多。

GlusterFS服务器间的部署

在之前的版本中服务器间的关系是对等的,也就是说每个节点服务器都掌握了集群的配置信息,这样做的好处是每个节点度拥有节点的配置信息,高度自治,所有信息都可以在本地查询。每个节点的信息更新都会向其他节点通告,保证节点间信息的一致性。但如果集群规模较大,节点众多时,信息同步的效率就会下降,节点信息的非一致性概率就会大大提高。因此GlusterFS未来的版本有向集中式管理变化的趋势。

3.4 Gluster技术特点

GlusterFS在技术实现上与传统存储系统或现有其他分布式文件系统有显著不同之处,主要体现在如下几个方面。

a)完全软件实现(SoftwareOnly)

GlusterFS认为存储是软件问题,不能够把用户局限于使用特定的供应商或硬件配置来解决。GlusterFS采用开放式设计,广泛支持工业标准的存储、网络和计算机设备,而非与定制化的专用硬件设备捆绑。对于商业客户,GlusterFS可以以虚拟装置的形式交付,也可以与虚拟机容器打包,或者是公有云中部署的映像。开源社区中,GlusterFS被大量部署在基于廉价闲置硬件的各种操作系统上,构成集中统一的虚拟存储资源池。简言之,GlusterFS是开放的全软件实现,完全独立于硬件和操作系统。

b)完整的存储操作系统栈(CompleteStorage Operating System Stack)

GlusterFS不仅提供了一个分布式文件系统,而且还提供了许多其他重要的分布式功能,比如分布式内存管理、I/O调度、软RAID和自我修复等。GlusterFS汲取了微内核架构的经验教训,借鉴了GNU/Hurd操作系统的设计思想,在用户空间实现了完整的存储操作系统栈。

c)用户空间实现(User Space)

与传统的文件系统不同,GlusterFS在用户空间实现,这使得其安装和升级特别简便。另外,这也极大降低了普通用户基于源码修改GlusterFS的门槛,仅仅需要通用的C程序设计技能,而不需要特别的内核编程经验。

d)模块化堆栈式架构(ModularStackable Architecture)

GlusterFS采用模块化、堆栈式的架构,可通过灵活的配置支持高度定制化的应用环境,比如大文件存储、海量小文件存储、云存储、多传输协议应用等。每个功能以模块形式实现,然后以积木方式进行简单的组合,即可实现复杂的功能。比如,Replicate模块可实现RAID1,Stripe模块可实现RAID0,通过两者的组合可实现RAID10和RAID01,同时获得高性能和高可性。

e)原始数据格式存储(DataStored in Native Formats)

GlusterFS无元数据服务设计(NoMetadata with the Elastic Hash Algorithm)以原始数据格式(如EXT3、EXT4、XFS、ZFS)储存数据,并实现多种数据自动修复机制。因此,系统极具弹性,即使离线情形下文件也可以通过其他标准工具进行访问。如果用户需要从GlusterFS中迁移数据,不需要作任何修改仍然可以完全使用这些数据。

对Scale-Out存储系统而言,最大的挑战之一就是记录数据逻辑与物理位置的映像关系,即数据元数据,可能还包括诸如属性和访问权限等信息。传统分布式存储系统使用集中式或分布式元数据服务来维护元数据,集中式元数据服务会导致单点故障和性能瓶颈问题,而分布式元数据服务存在性能负载和元数据同步一致性问题。特别是对于海量小文件的应用,元数据问题是个非常大的挑战。

GlusterFS独特地采用无元数据服务的设计,取而代之使用算法来定位文件,元数据和数据没有分离而是一起存储。集群中的所有存储系统服务器都可以智能地对文件数据分片进行定位,仅仅根据文件名和路径并运用算法即可,而不需要查询索引或者其他服务器。这使得数据访问完全并行化,从而实现真正的线性性能扩展。无元数据服务器极大提高了GlusterFS的性能、可靠性和稳定性;

GlusterFS存储特点

a)扩展性和高性能

GlusterFS利用双重特性来提供几TB至数PB的高扩展存储解决方案。Scale-Out架构允许通过简单地增加资源来提高存储容量和性能,磁盘、计算和I/O资源都可以独立增加,支持10GbE和InfiniBand等高速网络互联。Gluster弹性哈希(Elastic Hash)解除了GlusterFS对元数据服务器的需求,消除了单点故障和性能瓶颈,真正实现了并行化数据访问。

b)高可用性

GlusterFS可以对文件进行自动复制,如镜像或多次复制,从而确保数据总是可以访问,甚至是在硬件故障的情况下也能正常访问。自我修复功能能够把数据恢复到正确的状态,而且修复是以增量的方式在后台执行,几乎不会产生性能负载。GlusterFS没有设计自己的私有数据文件格式,而是采用操作系统中主流标准的磁盘文件系统(如EXT3、ZFS)来存储文件,因此数据可以使用各种标准工具进行复制和访问。

c)全局统一命名空间

全局统一命名空间将磁盘和内存资源聚集成一个单一的虚拟存储池,对上层用户和应用屏蔽了底层的物理硬件。存储资源可以根据需要在虚拟存储池中进行弹性扩展,比如扩容或收缩。当存储虚拟机映像时,存储的虚拟映像文件没有数量限制,成千虚拟机均通过单一挂载点进行数据共享。虚拟机I/O可在命名空间内的所有服务器上自动进行负载均衡,消除了SAN环境中经常发生的访问热点和性能瓶颈问题。

d)弹性哈希算法

GlusterFS采用弹性哈希算法在存储池中定位数据,而不是采用集中式或分布式元数据服务器索引。在其他的Scale-Out存储系统中,元数据服务器通常会导致I/O性能瓶颈和单点故障问题。GlusterFS中,所有在Scale-Out存储配置中的存储系统都可以智能地定位任意数据分片,不需要查看索引或者向其他服务器查询。这种设计机制完全并行化了数据访问,实现了真正的线性性能扩展。

e)弹性卷管理

数据储存在逻辑卷中,逻辑卷可以从虚拟化的物理存储池进行独立逻辑划分而得到。存储服务器可以在线进行增加和移除,不会导致应用中断。逻辑卷可以在所有配置服务器中增长和缩减,可以在不同服务器迁移进行容量均衡,或者增加和移除系统,这些操作都可在线进行。文件系统配置更改也可以实时在线进行并应用,从而可以适应工作负载条件变化或在线性能调优。

f)基于标准协议

Gluster存储服务支持NFS, CIFS, HTTP, FTP以及Gluster原生协议,完全与POSIX标准兼容。现有应用程序不需要作任何修改或使用专用API,就可以对Gluster中的数据进行访问。这在公有云环境中部署Gluster时非常有用,Gluster对云服务提供商专用API进行抽象,然后提供标准POSIX接口。

Glusterfs整体工作流程-数据访问流程

a)首先是在客户端, 用户通过glusterfs的mount point 来读写数据, 对于用户来说,集群系统的存在对用户是完全透明的,用户感觉不到是操作本地系统还是远端的集群系统。b)用户的这个操作被递交给 本地linux系统的VFS来处理。

c)VFS 将数据递交给FUSE 内核文件系统:在启动 glusterfs 客户端以前,需要想系统注册一个实际的文件系统FUSE,如上图所示,该文件系统与ext3在同一个层次上面, ext3 是对实际的磁盘进行处理, 而fuse 文件系统则是将数据通过/dev/fuse 这个设备文件递交给了glusterfs client端。所以, 我们可以将 fuse文件系统理解为一个代理。

d)数据被fuse 递交给Glusterfs client 后, client 对数据进行一些指定的处理(所谓的指定,是按照client 配置文件据来进行的一系列处理, 我们在启动glusterfs client 时需要指定这个文件。

e)在glusterfs client的处理末端,通过网络将数据递交给 Glusterfs Server,并且将数据写入到服务器所控制的存储设备上。

这样, 整个数据流的处理就完成了;

GlusterFS客户端访问流程

当客户端访问GlusterFS存储时,首先程序通过访问挂载点的形式读写数据,对于用户和程序而言,集群文件系统是透明的,用户和程序根本感觉不到文件系统是本地还是在远程服务器上。读写操作将会被交给VFS(Virtual File System)来处理,VFS会将请求交给FUSE内核模块,而FUSE又会通过设备/dev/fuse将数据交给GlusterFS Client。最后经过GlusterFS Client的计算,并最终经过网络将请求或数据发送到GlusterFS Server上;

4 GlusterFS集群模式

GlusterFS分布式存储集群的模式只数据在集群中的存放结构,类似于磁盘阵列中的级别。

分布式卷(Distributed Volume)

默认模式,DHT

又称哈希卷,近似于RAID0,文件没有分片,文件根据hash算法写入各个节点的硬盘上,优点是容量大,缺点是没冗余;

gluster volume create test-volume server1:/exp1 server2:/exp2 server3:/exp3 server4:/exp4

复制卷(Replicated Volume)

复制模式,AFR相当于raid1,复制的份数,决定集群的大小,通常与分布式卷或者条带卷组合使用,解决前两种存储卷的冗余缺陷。

缺点是磁盘利用率低。复本卷在创建时可指定复本的数量,通常为2或者3,复本在存储时会在卷的不同brick上,因此有几个复本就必须提供至少多个brick,当其中一台服务器失效后,可以从另一台服务器读取数据,因此复制GlusterFS卷提高了数据可靠性的同时,还提供了数据冗余的功能。

gluster volume create test-volume replica 2 transport tcp server1:/exp1 server2:/exp2

避免脑裂,加入仲裁:

gluster volume create replica 3 arbiter 1 host1:brick1 host2:brick2 host3:brick3

分布式复制卷(Distributed Replicated Volume)

最少需要4台服务器

gluster volume create test-volume replica 2 transport tcp server1:/exp1 server2:/exp2 server3:/exp3 server4:/exp4

条带卷(Striped Volume)

相当于raid0,文件是分片均匀写在各个节点的硬盘上的,优点是分布式读写,性能整体较好。缺点是没冗余,分片随机读写可能会导致硬盘IOPS饱和。

# gluster volume create test-volume stripe 2 transport tcp server1:/exp1 server2:/exp2

分布式条带卷(Distributed Striped Volume)

最少需要4台服务器。

当单个文件的体型十分巨大,客户端数量更多时,条带卷已经无法满足需求,此时将分布式与条带化结合起来是一个比较好的选择。其性能与服务器数量有关。

# gluster volume create test-volume stripe 4 transport tcp server1:/exp1 server2:/exp2 server3:/exp3 server4:/exp4 server5:/exp5 server6:/exp6 server7:/exp7 server8:/exp8

5 Glusterfs功能简介

1)基本管理功能GlusterFS服务管理:启动、停止、重启服务;TrustedStorage Pools管理:增加或删除peer;

Volume管理:增加卷、启动卷、停止卷;

上述这些基本的管理功能不再做介绍。

2)TuningVolume Options(调整卷配置)

GlustreFS提供了45项配置用来调整Volume属性,包括端口、cache、安全、存储空间、自愈、日志、扩展性、通讯协议、性能等配置项。用户可以通过gluster volume info命令来查看自定义配置项。

3)ConfiguringTransport Types for Volume(配置传输类型)

创建卷的时候,可以选择client与brick的通讯协议。

也可以通过"gluster volume set volnameconfig.transport tcp,rdma OR tcp OR rdma"命令更改通讯协议,需要注意的在更改通讯协议前,必须先停止volume。

默认情况是TCP,根据部署场景可选择RDMA或RDMA+TCP组合,而选择RDMA协议需要相应硬件的支持。

4)ExpandingVolumes(扩容)

GlusterFS集群的扩容就是通过增加volume来实现,通过"glustervolume add-brick"命令增加卷。

注意,扩容复制卷的时候,必须同时增加卷的数量是replica的倍数。例如replica 2的集群扩容,需要同时增加2个volume;replica3的集群扩容,需要同时增加3个volume。

5)ShrinkingVolumes(缩容)

集群缩减存储空间通过删除卷的“glustervolume remove-brick”命令实现,删除卷的命令执行后,GlustreFS会启动数据迁移,若迁移的数据较大,迁移过程将耗时较长,可能通过命令观察迁移状态。

6)Replacefaulty brick(更换坏块)

用好的brick替换故障的brick。

使用方法如下:"glustervolume replace-brick test-volume server3:/exp3 server5:/exp5 commit force",将test-volume卷中的server3:/exp3故障brick替换掉。

7)RebalancingVolumes(负载调整)

扩容或缩容卷,集群中可能会出现不同卷的存储利用率较大的不均衡的现象。通过Rebalancing机制,在后台以人工方式来执行负载平滑,将进行文件移动和重新分布,此后所有存储服务器都会均会被调度。为了便于控制管理,rebalance操作分为两个阶段进行实际执行,即FixLayout和MigrateData。

a)FixLayout:修复layout以使得新旧目录下新建文件可以在新增节点上分布上。

b)MigrateData:新增或缩减节点后,在卷下所有节点上进行容量负载平滑。为了提高rebalance效率,通常在执行此操作前先执行FixLayout。

8)TriggeringSelf-Heal on Replicate(文件自愈)

在复制卷中,若出现复本间文件不同步的情况,系统每十分钟会自动启动Self-Heal。

也可以主动执行"glustervolume heal"命令触发Self-Heal,通过"gluster volume heal info"可以查看需要heal的文件列表。

在healing过程中,可以通过"gluster volume heal info healed"查看已修复文件的列表;

通过"gluster volume heal info failed"查看修复失败的文件列表。

9)Geo-replication(异地备份)

异地备份可以提供数据的灾难恢复。以本地集群作为主存储,异地存储为备份,通过局域网或互联网持续、增量、异步备份数据。

使用"gluster volume geo-replication"相关的命令实现异地备份创建管理。

10)Quota(限额管理)

GlusterFS提供目录或卷的存储使用空间的限制设置功能。通过目录限额可以实现对用户按存储容量计费的功能。

使用方法为:"gluster volume quota"

11)VolumeSnapshots(卷快照)

卷快照功能用于卷的备份和恢复,在非复制卷的应用场景,通过卷快照实现数据冗余备份。

12)MonitoringWorkload(性能监控)

监控每一个brick文件操作的IO性能,主要监控打开fd的数量和最大fd数量、最大读文件调用数、最大写文件调用数、最大打开目录调用数、brick读性能、brcik写性能等。

使用方法:"gluster volume profile"

6 Gluster缺点详细

GlusterFS(GNU ClusterFile System)是一个开源的分布式文件系统,它的历史可以追溯到2006年,最初的目标是代替Lustre和GPFS分布式文件系统。经过八年左右的蓬勃发展,GlusterFS目前在开源社区活跃度非常之高,这个后起之秀已经俨然与Lustre、MooseFS、CEPH并列成为四大开源分布式文件系统。由于GlusterFS新颖和KISS(KeepIt as Stupid and Simple)的系统架构,使其在扩展性、可靠性、性能、维护性等方面具有独特的优势,目前开源社区风头有压倒之势,国内外有大量用户在研究、测试和部署应用。

当然,GlusterFS不是一个完美的分布式文件系统,这个系统自身也有许多不足之处,包括众所周知的元数据性能和小文件问题。没有普遍适用各种应用场景的分布式文件系统,通用的意思就是通通不能用,四大开源系统不例外,所有商业产品也不例外。每个分布式文件系统都有它适用的应用场景,适合的才是最好的。这一次我们反其道而行之,不再谈GlusterFS的各种优点,而是深入谈谈GlusterFS当下的问题和不足,从而更加深入地理解GlusterFS系统,期望帮助大家进行正确的系统选型决策和规避应用中的问题。同时,这些问题也是GlusterFS研究和研发的很好切入点;

1)元数据性能

GlusterFS使用弹性哈希算法代替传统分布式文件系统中的集中或分布式元数据服务,这个是GlusterFS最核心的思想,从而获得了接近线性的高扩展性,同时也提高了系统性能和可靠性。GlusterFS使用算法进行数据定位,集群中的任何服务器和客户端只需根据路径和文件名就可以对数据进行定位和读写访问,文件定位可独立并行化进行。

这种算法的特点是,给定确定的文件名,查找和定位会非常快。但是,如果事先不知道文件名,要列出文件目录(ls或ls -l),性能就会大幅下降。对于Distributed哈希卷,文件通过HASH算法分散到集群节点上,每个节点上的命名空间均不重叠,所有集群共同构成完整的命名空间,访问时使用HASH算法进行查找定位。列文件目录时,需要查询所有节点,并对文件目录信息及属性进行聚合。这时,哈希算法根本发挥不上作用,相对于有中心的元数据服务,查询效率要差很多。

从接触的一些用户和实践来看,当集群规模变大以及文件数量达到百万级别时,ls文件目录和rm删除文件目录这两个典型元数据操作就会变得非常慢,创建和删除100万个空文件可能会花上15分钟。如何解决这个问题呢?

我们建议合理组织文件目录,目录层次不要太深,单个目录下文件数量不要过多;增大服务器内存配置,并且增大GlusterFS目录缓存参数;网络配置方面,建议采用万兆或者InfiniBand。从研发角度看,可以考虑优化方法提升元数据性能。比如,可以构建全局统一的分布式元数据缓存系统;也可以将元数据与数据重新分离,每个节点上的元数据采用全内存或数据库设计,并采用SSD进行元数据持久化。

2)小文件问题

理论和实践上分析,GlusterFS目前主要适用大文件存储场景,对于小文件尤其是海量小文件,存储效率和访问性能都表现不佳。海量小文件LOSF问题是工业界和学术界公认的难题,GlusterFS作为通用的分布式文件系统,并没有对小文件作额外的优化措施,性能不好也是可以理解的。

对于LOSF而言,IOPS/OPS是关键性能衡量指标,造成性能和存储效率低下的主要原因包括元数据管理、数据布局和I/O管理、Cache管理、网络开销等方面。从理论分析以及LOSF优化实践来看,优化应该从元数据管理、缓存机制、合并小文件等方面展开,而且优化是一个系统工程,结合硬件、软件,从多个层面同时着手,优化效果会更显著。GlusterFS小文件优化可以考虑这些方法,这里不再赘述,关于小文件问题请参考“海量小文件问题综述”一文。

3)集群管理模式

GlusterFS集群采用全对等式架构,每个节点在集群中的地位是完全对等的,集群配置信息和卷配置信息在所有节点之间实时同步。这种架构的优点是,每个节点都拥有整个集群的配置信息,具有高度的独立自治性,信息可以本地查询。但同时带来的问题的,一旦配置信息发生变化,信息需要实时同步到其他所有节点,保证配置信息一致性,否则GlusterFS就无法正常工作。在集群规模较大时,不同节点并发修改配置时,这个问题表现尤为突出。因为这个配置信息同步模型是网状的,大规模集群不仅信息同步效率差,而且出现数据不一致的概率会增加。

实际上,大规模集群管理应该是采用集中式管理更好,不仅管理简单,效率也高。可能有人会认为集中式集群管理与GlusterFS的无中心架构不协调,其实不然。GlusterFS 2.0以前,主要通过静态配置文件来对集群进行配置管理,没有Glusterd集群管理服务,这说明glusterd并不是GlusterFS不可或缺的组成部分,它们之间是松耦合关系,可以用其他的方式来替换。从其他分布式系统管理实践来看,也都是采用集群式管理居多,这也算一个佐证,GlusterFS 4.0开发计划也表现有向集中式管理转变的趋势。

4)容量负载均衡

GlusterFS的哈希分布是以目录为基本单位的,文件的父目录利用扩展属性记录了子卷映射信息,子文件在父目录所属存储服务器中进行分布。由于文件目录事先保存了分布信息,因此新增节点不会影响现有文件存储分布,它将从此后的新创建目录开始参与存储分布调度。这种设计,新增节点不需要移动任何文件,但是负载均衡没有平滑处理,老节点负载较重。GlusterFS实现了容量负载均衡功能,可以对已经存在的目录文件进行Rebalance,使得早先创建的老目录可以在新增存储节点上分布,并可对现有文件数据进行迁移实现容量负载均衡。

GlusterFS目前的容量负载均衡存在一些问题。由于采用Hash算法进行数据分布,容量负载均衡需要对所有数据重新进行计算并分配存储节点,对于那些不需要迁移的数据来说,这个计算是多余的。Hash分布具有随机性和均匀性的特点,数据重新分布之后,老节点会有大量数据迁入和迁出,这个多出了很多数据迁移量。相对于有中心的架构,可谓节点一变而动全身,增加和删除节点增加了大量数据迁移工作。GlusterFS应该优化数据分布,最小化容量负载均衡数据迁移。此外,GlusterFS容量负载均衡也没有很好考虑执行的自动化、智能化和并行化。目前,GlusterFS在增加和删除节点上,需要手工执行负载均衡,也没有考虑当前系统的负载情况,可能影响正常的业务访问。GlusterFS的容量负载均衡是通过在当前执行节点上挂载卷,然后进行文件复制、删除和改名操作实现的,没有在所有集群节点上并发进行,负载均衡性能差。

5)数据分布问题

Glusterfs主要有三种基本的集群模式,即分布式集群(Distributed cluster)、条带集群(Stripe cluster)、复制集群(Replica cluster)。这三种基本集群还可以采用类似堆积木的方式,构成更加复杂的复合集群。三种基本集群各由一个translator来实现,分别由自己独立的命名空间。对于分布式集群,文件通过HASH算法分散到集群节点上,访问时使用HASH算法进行查找定位。复制集群类似RAID1,所有节点数据完全相同,访问时可以选择任意个节点。条带集群与RAID0相似,文件被分成数据块以Round Robin方式分布到所有节点上,访问时根据位置信息确定节点。

哈希分布可以保证数据分布式的均衡性,但前提是文件数量要足够多,当文件数量较少时,难以保证分布的均衡性,导致节点之间负载不均衡。这个对有中心的分布式系统是很容易做到的,但GlusteFS缺乏集中式的调度,实现起来比较复杂。复制卷包含多个副本,对于读请求可以实现负载均衡,但实际上负载大多集中在第一个副本上,其他副本负载很轻,这个是实现上问题,与理论不太相符。条带卷原本是实现更高性能和超大文件,但在性能方面的表现太差强人意,远远不如哈希卷和复制卷,没有被好好实现,连官方都不推荐应用。

6)数据可用性问题

副本(Replication)就是对原始数据的完全拷贝。通过为系统中的文件增加各种不同形式的副本,保存冗余的文件数据,可以十分有效地提高文件的可用性,避免在地理上广泛分布的系统节点由网络断开或机器故障等动态不可测因素而引起的数据丢失或不可获取。GlusterFS主要使用复制来提供数据的高可用性,通过的集群模式有复制卷和哈希复制卷两种模式。复制卷是文件级RAID1,具有容错能力,数据同步写到多个brick上,每个副本都可以响应读请求。当有副本节点发生故障,其他副本节点仍然正常提供读写服务,故障节点恢复后通过自修复服务或同步访问时自动进行数据同步。

一般而言,副本数量越多,文件的可靠性就越高,但是如果为所有文件都保存较多的副本数量,存储利用率低(为副本数量分之一),并增加文件管理的复杂度。目前GlusterFS社区正在研发纠删码功能,通过冗余编码提高存储可用性,并且具备较低的空间复杂度和数据冗余度,存储利用率高。

GlusterFS的复制卷以brick为单位进行镜像,这个模式不太灵活,文件的复制关系不能动态调整,在已经有副本发生故障的情况下会一定程度上降低系统的可用性。对于有元数据服务的分布式系统,复制关系可以是以文件为单位的,文件的不同副本动态分布在多个存储节点上;当有副本发生故障,可以重新选择一个存储节点生成一个新副本,从而保证副本数量,保证可用性。另外,还可以实现不同文件目录配置不同的副本数量,热点文件的动态迁移。对于无中心的GlusterFS系统来说,这些看起来理所当然的功能,实现起来都是要大费周折的。不过值得一提的是,4.0开发计划已经在考虑这方面的副本特性。

7)数据安全问题

GlusterFS以原始数据格式(如EXT4、XFS、ZFS)存储数据,并实现多种数据自动修复机制。因此,系统极具弹性,即使离线情形下文件也可以通过其他标准工具进行访问。如果用户需要从GlusterFS中迁移数据,不需要作任何修改仍然可以完全使用这些数据。

然而,数据安全成了问题,因为数据是以平凡的方式保存的,接触数据的人可以直接复制和查看。这对很多应用显然是不能接受的,比如云存储系统,用户特别关心数据安全。私有存储格式可以保证数据的安全性,即使泄露也是不可知的。GlusterFS要实现自己的私有格式,在设计实现和数据管理上相对复杂一些,也会对性能产生一定影响。

GlusterFS在访问文件目录时根据扩展属性判断副本是否一致,这个进行数据自动修复的前提条件。节点发生正常的故障,以及从挂载点进行正常的操作,这些情况下发生的数据不一致,都是可以判断和自动修复的。但是,如果直接从节点系统底层对原始数据进行修改或者破坏,GlusterFS大多情况下是无法判断的,因为数据本身也没有校验,数据一致性无法保证。

8)Cache一致性

为了简化Cache一致性,GlusterFS没有引入客户端写Cache,而采用了客户端只读Cache。GlusterFS采用简单的弱一致性,数据缓存的更新规则是根据设置的失效时间进行重置的。对于缓存的数据,客户端周期性询问服务器,查询文件最后被修改的时间,如果本地缓存的数据早于该时间,则让缓存数据失效,下次读取数据时就去服务器获取最新的数据。

dGlusterFS客户端读Cache刷新的时间缺省是1秒,可以通过重新设置卷参数Performance.cache-refresh-timeout进行调整。这意味着,如果同时有多个用户在读写一个文件,一个用户更新了数据,另一个用户在Cache刷新周期到来前可能读到非最新的数据,即无法保证数据的强一致性。因此实际应用时需要在性能和数据一致性之间进行折中,如果需要更高的数据一致性,就得调小缓存刷新周期,甚至禁用读缓存;反之,是可以把缓存周期调大一点,以提升读性能。

7 安装Gluster

7.1 配置hosts

代码语言:javascript
复制
192.168.0.204  op-node-204
192.168.0.205  op-node-205
192.168.0.220  op-node-220
192.168.0.221  op-node-221

7.2 安装

代码语言:javascript
复制
yum install centos-release-gluster -y
yum install -y glusterfs glusterfs-server glusterfs-fuse glusterfs-rdma

7.3 启动并配置开机自启动

代码语言:javascript
复制
systemctl restart glusterd.service && systemctl enable glusterd.service

7.4 将节点添加入集群

代码语言:javascript
复制
gluster peer probe master
gluster peer probe node1
gluster peer probe node2

7.5 查看集群状态并安装client测试

代码语言:javascript
复制
[root@op-node-204 ~]# gluster peer status
Number of Peers: 3

Hostname: op-node-205
Uuid: 06e01704-11dc-4e0d-819d-bd066e72446d
State: Peer in Cluster (Connected)

Hostname: op-node-220
Uuid: 3c3ae6c8-0dc9-4609-94c2-8dd1c20ebdac
State: Peer in Cluster (Connected)

Hostname: op-node-221
Uuid: b8007019-46c5-417e-ae6e-bf3e2c4bb576
State: Peer in Cluster (Connected)


yum install -y glusterfs glusterfs-fuse
# 创建数据目录,节点都要操作
mkdir /data/gluster/data -p

7.6 创建volume并查看

代码语言:javascript
复制
gluster volume create models replica 4 op-node-205:/data/gluster/data op-node-204:/data/gluster/data op-node-220:/data/gluster/data op-node-221:/data/gluster/data force

查看volume

代码语言:javascript
复制
[root@op-node-204 ~]# gluster volume info
Volume Name: models
Type: Replicate
Volume ID: 93fd7cfd-50a8-4099-be59-0fd34ecc2a49
Status: Created
Snapshot Count: 0
Number of Bricks: 1 x 4 = 4
Transport-type: tcp
Bricks:
Brick1: op-node-205:/data/gluster/data
Brick2: op-node-204:/data/gluster/data
Brick3: op-node-220:/data/gluster/data
Brick4: op-node-221:/data/gluster/data
Options Reconfigured:
cluster.granular-entry-heal: on
storage.fips-mode-rchecksum: on
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

7.7 启动models并尝试挂载

代码语言:javascript
复制
gluster volume start models

挂载

代码语言:javascript
复制
mount -t glusterfs op-node-204:models /data

7.8 简单调优

代码语言:javascript
复制
# 开启 指定 volume 的配额
gluster volume quota k8s-volume enable
# 限制 指定 volume 的配额
gluster volume quota k8s-volume limit-usage / 1TB
# 设置 cache 大小, 默认32MB
gluster volume set k8s-volume performance.cache-size 4GB

# 设置 io 线程, 太大会导致进程崩溃
gluster volume set k8s-volume performance.io-thread-count 16
# 设置 网络检测时间, 默认42s
gluster volume set k8s-volume network.ping-timeout 10
# 设置 写缓冲区的大小, 默认1M
gluster volume set k8s-volume performance.write-behind-window-size 1024MB

K8S 的存储卷使用稍有点古怪,Gluster FS 的使用,需要首先定义一个 Endpoint + Service 形式的代理,来定义 Gluster FS 集群,然后就可以通过持久卷或者用 Pod 直接加载了。

8 k8s集成glusterfs

8.1 在各节点安装客户端

代码语言:javascript
复制
yum install -y glusterfs glusterfs-fuse

8.2 配置endpoints

修改glusterfs-endpoints.json,配置GlusterFS集群信息

代码语言:javascript
复制
{
  "kind": "Endpoints",
  "apiVersion": "v1",
  "metadata": {
    "name": "glusterfs-cluster"
  },
  "subsets": [
    {
      "addresses": [
        {
          "ip": "op-node-204",
          "ip": "op-node-205",
          "ip": "op-node-220",
          "ip": "op-node-221",
        }
      ],
      "ports": [
        {
          "port": 2020
        }
      ]
    }
  ]
}

port可以随意写,ip为GlusterFS的IP地址

创建配置文件

代码语言:javascript
复制
[root@op-node-201 kubectl apply -f glusterfs-endpoints.json
[root@op-node-201 glusterfs]# kubectl get ep
NAME                ENDPOINTS            AGE
fuseim.pri-ifs      <none>               10h
glusterfs-cluster   192.168.0.204:2020   12s
kubernetes          192.168.0.201:6443   3d8h

8.3 创建Serivce

修改配置文件,我这里仅修改了端口

代码语言:javascript
复制
{
  "kind": "Service",
  "apiVersion": "v1",
  "metadata": {
    "name": "glusterfs-cluster"
  },
  "spec": {
    "ports": [
      {"port": 2020}
    ]
  }
}

创建配置文件对象

代码语言:javascript
复制
# kubectl apply -f glusterfs-service.json
# kubectl get svc
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
glusterfs-cluster   ClusterIP   10.254.44.189   <none>        2020/TCP   10m
kubernetes          ClusterIP   10.254.0.1      <none>        443/TCP    27d

8.4 创建测试Pod

1 . 修改配置文件,修改volumes下的path为我们上面创建的volume名

代码语言:javascript
复制
{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        "name": "glusterfs"
    },
    "spec": {
        "containers": [
            {
                "name": "glusterfs",
                "image": "nginx",
                "volumeMounts": [
                    {
                        "mountPath": "/mnt/glusterfs",
                        "name": "glusterfsvol"
                    }
                ]
            }
        ],
        "volumes": [
            {
                "name": "glusterfsvol",
                "glusterfs": {
                    "endpoints": "glusterfs-cluster",
                    "path": "models",
                    "readOnly": true
                }
            }
        ]
    }
}

2 . 创建Pod

代码语言:javascript
复制
# kubectl apply -f glusterfs-pod.yaml
# kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
glusterfs   1/1     Running   0          51s
pod-demo    1/1     Running   8          25h
# kubectl exec -it glusterfs -- df -h
Filesystem                  Size  Used Avail Use% Mounted on
overlay                      17G  2.5G   15G  15% /
tmpfs                        64M     0   64M   0% /dev
tmpfs                       910M     0  910M   0% /sys/fs/cgroup
/dev/mapper/centos-root      17G  2.5G   15G  15% /etc/hosts
10.1.10.128:gluster_volume   17G  5.3G   12G  31% /mnt/glusterfs
shm                          64M     0   64M   0% /dev/shm
tmpfs                       910M   12K  910M   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                       910M     0  910M   0% /proc/acpi
tmpfs                       910M     0  910M   0% /proc/scsi
tmpfs                       910M     0  910M   0% /sys/firmware

我们可以看到挂载成功;

9 用PVC挂载

9.1 example1

(1) . 创建PV

代码语言:javascript
复制
apiVersion: v1
kind: PersistentVolume
metadata:
  name: glusterfs-pv
spec:
  capacity:
    storage: 5Mi
  accessModes:
  - ReadWriteMany
  glusterfs:
    endpoints: glusterfs-cluster
    path: gluster_volume
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: glusterfs-pvc
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 5Mi

2 创建存储

代码语言:javascript
复制
# kubectl apply -f  glusterfs-pv.yaml
# kubectl get pv
NAME           CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS   REASON   AGE
glusterfs-pv   5Mi        RWX            Retain           Bound    default/glusterfs-pvc                           15s
# kubectl get pvc
NAME            STATUS   VOLUME         CAPACITY   ACCESS MODES   STORAGECLASS   AGE
glusterfs-pvc   Bound    glusterfs-pv   5Mi        RWX                           18s

example2

代码语言:javascript
复制
[root@op-node-201 glusterfs]# cat gluster-mysql-pv-pvc.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: gluster
  labels:
    type: glusterfs
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: "glusterfs"
    path: "lwl"
    readOnly: false

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: gluster
spec:
  selector:
    matchLabels:
      type: glusterfs
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

mysql.yaml

代码语言:javascript
复制
vim mysql-rc.yml 
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      volumes:
        - name: mysql
          persistentVolumeClaim:
            claimName: gluster
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          volumeMounts:
            - name: mysql
              mountPath: /var/lib/mysql
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'

10 用SC动态创建PVC

10.1 . 安装Heketi

Heketi提供了一个RESTful管理界面,可以用来管理GlusterFS卷的生命周期。Heketi会动态在集群内选择bricks构建所需的volumes,从而确保数据的副本会分散到集群不同的故障域内。同时Heketi还支持任意数量的ClusterFS集群。

(1)、安装

代码语言:javascript
复制
yum -y install heketi heketi-client

(2)、配置Heketi

/etc/heketi/heketi.json

代码语言:javascript
复制
{
  "_port_comment": "Heketi Server Port Number",
  "port": "48080",			# 请求端口,默认是8080

  "_use_auth": "Enable JWT authorization. Please enable for deployment",
  "use_auth": false,

  "_jwt": "Private keys for access",
  "jwt": {
    "_admin": "Admin has access to all APIs",
    "admin": {
      "key": "admin@P@ssW0rd"			# 管理员密码
    },
    "_user": "User only has access to /volumes endpoint",
    "user": {
      "key": "user@P@ssW0rd"			# 普通用户密码
    }
  },

  "_glusterfs_comment": "GlusterFS Configuration",
  "glusterfs": {
    "_executor_comment": [
      "Execute plugin. Possible choices: mock, ssh",
      "mock: This setting is used for testing and development.",
      "      It will not send commands to any node.",
      "ssh:  This setting will notify Heketi to ssh to the nodes.",
      "      It will need the values in sshexec to be configured.",
      "kubernetes: Communicate with GlusterFS containers over",
      "            Kubernetes exec api."
    ],
    "executor": "ssh",

    "_sshexec_comment": "SSH username and private key file information",
    "sshexec": {
      "keyfile": "/etc/hekeit/private_key",			# ssh私钥目录
      "user": "root",														# ssh用户
      "port": "22",															# ssh端口
      "fstab": "/etc/fstab"
    },

    "_kubeexec_comment": "Kubernetes configuration",
    "kubeexec": {
      "host" :"https://kubernetes.host:8443",
      "cert" : "/path/to/crt.file",
      "insecure": false,
      "user": "kubernetes username",
      "password": "password for kubernetes user",
      "namespace": "OpenShift project or Kubernetes namespace",
      "fstab": "Optional: Specify fstab file on node.  Default is /etc/fstab"
    },

    "_db_comment": "Database file name",
    "db": "/var/lib/heketi/heketi.db",

    "_loglevel_comment": [
      "Set log level. Choices are:",
      "  none, critical, error, warning, info, debug",
      "Default is warning"
    ],
    "loglevel" : "debug"
  }
}

(3)、配置免密

代码语言:javascript
复制
# ssh-keygen -t rsa -q -f /etc/heketi/private_key -N ""
# ssh-copy-id -i /etc/heketi/private_key.pub root@10.1.10.128
# ssh-copy-id -i /etc/heketi/private_key.pub root@10.1.10.129
# ssh-copy-id -i /etc/heketi/private_key.pub root@10.1.10.130

(4)、启动Heketi

代码语言:javascript
复制
# systemctl enable heketi.service && systemctl start heketi.service
# 测试
# curl http://10.1.10.128:48080/hello
Hello from Heketi

(5)、配置Topology

代码语言:javascript
复制
{
    "clusters": [
        {
            "nodes": [
                {
                    "node": {
                        "hostnames": {
                            "manage": [
                                "glusterfs-master"
                            ],
                            "storage": [
                                "10.1.10.128"
                            ]
                        },
                        "zone": 1
                    },
                    "devices": [
                        "/dev/sdb1"	# 必须是未创建文件系统的裸磁盘
                    ]
                },
                {
                    "node": {
                        "hostnames": {
                            "manage": [
                                "glusterfs-node01"
                            ],
                            "storage": [
                                "10.1.10.129"
                            ]
                        },
                        "zone": 1
                    },
                    "devices": [
                        "/dev/sdb1"
                    ]
                },
                {
                    "node": {
                        "hostnames": {
                            "manage": [
                                "glusterfs-node02"
                            ],
                            "storage": [
                                "10.1.10.130"
                            ]
                        },
                        "zone": 1
                    },
                    "devices": [
                        "/dev/sdb1"
                    ]
                }
            ]
        }
    ]
}
代码语言:javascript
复制
# echo "export HEKETI_CLI_SERVER=http://10.1.10.128:48080" >> /etc/profile.d/heketi.sh
# echo "alias heketi-cli='heketi-cli --user admin --secret admin@P@ssW0rd'" >> ~/.bashrc
# source /etc/profile.d/heketi.sh
# source ~/.bashrc
# echo $HEKETI_CLI_SERVER
http://10.1.10.128:48080

添加Cluster

代码语言:javascript
复制
# heketi-cli --server $HEKETI_CLI_SERVER --user admin --secret admin@P@ssW0rd topology load --json=/etc/heketi/topology.json
Creating cluster ... ID: 48a31ff76104514d187f7e7ef8c2e056
	Allowing file volumes on cluster.
	Allowing block volumes on cluster.
	Creating node glusterfs-master ... ID: e374f9d94f47e0fd3223732a383b7d03
		Adding device /dev/sdb1 ... OK
	Creating node glusterfs-node01 ... ID: 68f16b2d54acf1c18e354ec46aa736ad
		Adding device /dev/sdb1 ... OK
	Creating node glusterfs-node02 ... ID: 86f5a124f8c4c296042d6207a641cf81
		Adding device /dev/sdb1 ... OK

查看集群信息

代码语言:javascript
复制
# heketi-cli cluster list
Clusters:
Id:48a31ff76104514d187f7e7ef8c2e056 [file][block]

# 查看详细信息
# heketi-cli cluster info 48a31ff76104514d187f7e7ef8c2e056
Cluster id: 48a31ff76104514d187f7e7ef8c2e056
Nodes:
68f16b2d54acf1c18e354ec46aa736ad
86f5a124f8c4c296042d6207a641cf81
e374f9d94f47e0fd3223732a383b7d03
Volumes:

Block: true

File: true

# 查看节点信息
# heketi-cli node list
Id:68f16b2d54acf1c18e354ec46aa736ad	Cluster:48a31ff76104514d187f7e7ef8c2e056
Id:86f5a124f8c4c296042d6207a641cf81	Cluster:48a31ff76104514d187f7e7ef8c2e056
Id:e374f9d94f47e0fd3223732a383b7d03	Cluster:48a31ff76104514d187f7e7ef8c2e056

# 查看节点详细信息
# heketi-cli node info 68f16b2d54acf1c18e354ec46aa736ad
Node Id: 68f16b2d54acf1c18e354ec46aa736ad
State: online
Cluster Id: 48a31ff76104514d187f7e7ef8c2e056
Zone: 1
Management Hostname: glusterfs-node01
Storage Hostname: 10.1.10.129
Devices:
Id:dacaffdbd8a2a00bb76acdc7b2420fbd   Name:/dev/sdb1           State:online    Size (GiB):500     Used (GiB):0       Free (GiB):500     Bricks:0       

创建volume

代码语言:javascript
复制
# heketi-cli volume create --size=2 --replica=2
Name: vol_4f1a171ab06adf80460c84f2132e96e0
Size: 2
Volume Id: 4f1a171ab06adf80460c84f2132e96e0
Cluster Id: 48a31ff76104514d187f7e7ef8c2e056
Mount: 10.1.10.129:vol_4f1a171ab06adf80460c84f2132e96e0
Mount Options: backup-volfile-servers=10.1.10.130,10.1.10.128
Block: false
Free Size: 0
Reserved Size: 0
Block Hosting Restriction: (none)
Block Volumes: []
Durability Type: replicate
Distribute Count: 1
Replica Count: 2

# heketi-cli volume list
Id:4f1a171ab06adf80460c84f2132e96e0    Cluster:48a31ff76104514d187f7e7ef8c2e056    Name:vol_4f1a171ab06adf80460c84f2132e96e0

# heketi-cli volume info 4f1a171ab06adf80460c84f2132e96e0
Name: vol_4f1a171ab06adf80460c84f2132e96e0
Size: 2
Volume Id: 4f1a171ab06adf80460c84f2132e96e0
Cluster Id: 48a31ff76104514d187f7e7ef8c2e056
Mount: 10.1.10.129:vol_4f1a171ab06adf80460c84f2132e96e0
Mount Options: backup-volfile-servers=10.1.10.130,10.1.10.128
Block: false
Free Size: 0
Reserved Size: 0
Block Hosting Restriction: (none)
Block Volumes: []
Durability Type: replicate
Distribute Count: 1
Replica Count: 2

# 挂载
# mount -t glusterfs 10.1.10.129:vol_4f1a171ab06adf80460c84f2132e96e0 /mnt

# 删除
# heketi-cli volume delete 4f1a171ab06adf80460c84f2132e96e0
10.2 . 在k8s中测试

(1)、创建连接使用的secret(heketi-secret.yaml)

代码语言:javascript
复制
apiVersion: v1
kind: Secret
metadata:
  name: heketi-secret
data:
  key: YWRtaW5AUEBzc1cwcmQ=
type: kubernetes.io/glusterfs

(2)、创建sc(heketi-storageclass.yaml)

代码语言:javascript
复制
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: heketi-storageclass
parameters:
  resturl: "http://10.1.10.128:48080"
  clusterid: "cca360f44db482f03297a151886eea19"
  restauthenabled: "true"                                       #若heketi开启认证此处也必须开启auth认证
  restuser: "admin"
  secretName: "heketi-secret"                           #name/namespace与secret资源中定义一致
  secretNamespace: "default"
  volumetype: "replicate:3"
provisioner: kubernetes.io/glusterfs
reclaimPolicy: Delete

(3)、创建pvc(heketi-pvc.yaml)

代码语言:javascript
复制
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: heketi-pvc
  annotations:
    volume.beta.kubernetes.io/storage-class: heketi-storageclass
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

(4)、查看PVC情况

代码语言:javascript
复制
# kubectl get sc
NAME                  PROVISIONER               RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
heketi-storageclass   kubernetes.io/glusterfs   Delete          Immediate           false                  6m53s
# kubectl get pvc
NAME            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
glusterfs-pvc   Bound    glusterfs-pv                               5Mi        RWX                                  26h
heketi-pvc      Bound    pvc-0feb8666-6e7f-451d-ae6f-7f205206b225   1Gi        RWO            heketi-storageclass   82s

(5)、创建Pod测试挂载

heketi-pod.yaml

代码语言:javascript
复制
kind: Pod
apiVersion: v1
metadata:
  name: heketi-pod
spec:
  containers:
  - name: heketi-container
    image: busybox
    command:
    - sleep
    - "3600"
    volumeMounts:
    - name: heketi-volume
      mountPath: "/pv-data"
      readOnly: false
  volumes:
  - name: heketi-volume
    persistentVolumeClaim:
      claimName: heketi-pvc

创建Pod并查看结果

代码语言:javascript
复制
# kubectl get pod
NAME         READY   STATUS    RESTARTS   AGE
glusterfs    1/1     Running   0          26h
heketi-pod   1/1     Running   0          2m55s

创建文件测试

代码语言:javascript
复制
# kubectl exec -it heketi-pod -- /bin/sh
/ # cd /pv-data/
/pv-data # echo "text" > 1111.txt
/pv-data # ls
1111.txt

然后在本地查看

代码语言:javascript
复制
# cd /var/lib/heketi/mounts/vg_bffb11849513dded78f671f64e76750c/brick_6ff640a2d45a7f146a296473e7145ee7
[root@k8s-master brick_6ff640a2d45a7f146a296473e7145ee7]# ll
total 0
drwxrwsr-x 3 root 2000 40 Feb  7 14:27 brick
[root@k8s-master brick_6ff640a2d45a7f146a296473e7145ee7]# cd brick/
[root@k8s-master brick]# ll
total 4
-rw-r--r-- 2 root 2000 5 Feb  7 14:27 1111.txt

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 分布式文件系统简介
    • 1.1 产生
      • 1.2 代表-nfs
        • 1.2.1 优点
        • 1.2.2 缺点
    • 2 常见分布式存储
      • 2.1 FastDFS:
        • 2.2 GlusterFS:
          • 2.3 MooseFS:
            • 2.4 Ceph:
              • 2.5 GoogleFS
              • 3 Gluster存储基础梳理
                • 3.1 应用场景
                  • 3.2 术语
                    • 3.3 GlusterFS无元数据设计
                      • 3.4 Gluster技术特点
                        • GlusterFS存储特点
                          • Glusterfs整体工作流程-数据访问流程
                            • GlusterFS客户端访问流程
                              • 分布式卷(Distributed Volume)
                              • 复制卷(Replicated Volume)
                              • 分布式复制卷(Distributed Replicated Volume)
                              • 条带卷(Striped Volume)
                              • 分布式条带卷(Distributed Striped Volume)
                          • 4 GlusterFS集群模式
                          • 5 Glusterfs功能简介
                          • 6 Gluster缺点详细
                          • 7 安装Gluster
                            • 7.1 配置hosts
                              • 7.2 安装
                                • 7.3 启动并配置开机自启动
                                  • 7.4 将节点添加入集群
                                    • 7.5 查看集群状态并安装client测试
                                      • 7.6 创建volume并查看
                                        • 7.7 启动models并尝试挂载
                                          • 7.8 简单调优
                                          • 8 k8s集成glusterfs
                                            • 8.1 在各节点安装客户端
                                              • 8.2 配置endpoints
                                                • 8.3 创建Serivce
                                                  • 8.4 创建测试Pod
                                                  • 9 用PVC挂载
                                                    • 9.1 example1
                                                    • 10 用SC动态创建PVC
                                                      • 10.1 . 安装Heketi
                                                        • 10.2 . 在k8s中测试
                                                    相关产品与服务
                                                    容器服务
                                                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                                                    领券
                                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档