Glusterfs 碰撞测试。我们的经验

一年前,我们的好伙伴、同事和企业存储专家出现并说:“嗨,伙计们,我有一个很酷的 90 TB 存储,具有所有这些花哨的功能,你知道的。” 我不能说我们太需要它,但拒绝它会相当愚蠢。所以我们配置了几个备份并忘记了它。

不时地,我们使用该设备在主机之间移动大文件或为 Postgre 副本构建 WAL 等。最终,我们将与我们项目相关的所有零散的东西移到那里结束,并配置了 Rotate 和备份通知,都成功和失败的。一年来,这种存储成为我们运营团队的关键基础设施元素之一。


一切都很好......直到大师再次来找我们说他想要他的东西回来。即刻。紧急。现在。


我们有一点选择。事实上几乎没有:要么把我们的东西推到任何地方,要么用我们手头的东西建立我们自己的存储空间。那个时候聪明的老鸟,我们已经看到了很多不完全容错的系统,所以容错已经成为我们的嗡嗡声。


在众多替代方案中,我们选择了 Gluster。它看起来很有希望。于是我们开始了碰撞测试。

什么是 Gluster,我们为什么需要它?

它是一个与 Openstack 兼容并集成在 oVIrt/RHEV 中的分布式文件系统。尽管我们的 IaaS 不是基于 Openstack,但 Gluster 拥有一个庞大而活跃的社区,并且在 libgfapi 接口中支持原生 QEMU。因此,我们用一块石头杀死了两只鸟:


1. 获得一个我们可以支持自己的备份存储,而无需等待供应商提供替换部件

2. 测试新的卷类型以进一步提供给我们的客户

我们检查了是否:

1. Gluster 工作。——是的,确实如此。

2. Gluster 具有容错性:任何节点都可以在集群仍在运行且数据可用的情况下重新启动,甚至可以在不丢失数据的情况下重新启动多个节点。证明。

3. Gluster 是可靠的,不会自行崩溃,没有内存泄漏等——在某种程度上是正确的。花了一些时间才明白问题不在于我们,而是一个条带卷,它在我们构建的所有配置中仍然不稳定(请参阅下面的详细信息)。


一个月后,我们正在试验和构建不同的配置和版本。然后我们在生产环境中尝试将其作为技术备份的第二个目的地。在采用之前,我们在六个月内密切关注它,以确保它运作良好。

我们是怎么做到的?

我们有足够的硬件进行试验:一个带有戴尔 PowerEdge R510 的机架和一些在我们的旧版 S3 之后留下的不太快的 2 TB SATA 磁盘。20 TB 的存储空间似乎绰绰有余,我们花了大约半个小时在两台旧的 Dell PowerEdge R510 中的每台上安装 10 个磁盘,然后再添加一台服务器作为仲裁器,下载软件并部署所有这些东西。它看起来像这样:

mjnhbv.jpg

我们选择了带仲裁器的条带复制卷,因为它速度快(数据均匀地分布在多个砖块上)、足够可靠(副本 2),并且可以在没有裂脑的情况下在一个节点崩溃中幸存下来。男孩,我们错了吗?


当时的集群配置的一个主要缺点是通道非常狭窄(1G),这对我们来说不是问题,因为这篇文章是关于系统弹性和灾难恢复的,而不是它的速度。虽然我们计划采用带有 RDMA 的 Infiniband 56G 并测试性能,但这将是另一回事。

我不会深入研究集群创建,因为它非常简单:


为砖块制作目录:


for i in {0..9} ; do mkdir -p /export/brick$i ; done

在磁盘上为砖创建 xfs:

for i in {b..k} ; do mkfs.xfs /dev/sd$i ; done

将挂载点添加到 /etc/fstab:


/dev/sdb /export/brick0/ xfs defaults 0 0
/dev/sdc /export/brick1/ xfs defaults 0 0
/dev/sdd /export/brick2/ xfs defaults 0 0
/dev/sde /export/brick3/ xfs defaults 0 0
/dev/sdf /export/brick4/ xfs defaults 0 0
/dev/sdg /export/brick5/ xfs defaults 0 0
/dev/sdh /export/brick6/ xfs defaults 0 0
/dev/sdi /export/brick7/ xfs defaults 0 0
/dev/sdj /export/brick8/ xfs defaults 0 0
/dev/sdk /export/brick9/ xfs defaults 0 0

山:

mount -a
将名为 holodilnik 的卷的目录添加到砖块中:
for i in {0..9} ; do mkdir -p /export/brick$i/holodilnik ; done
Then make cluster hosts peers and create a volume:
Install software packages on all three hosts:
pdsh -w server[1-3] -- yum install glusterfs-server -y
启动 Gluster:

systemctl enable glusterd
systemctl start glusterd
请记住,Gluster 有几个进程:

glusterd = management daemon.
它是一个主守护进程,用于管理卷和其他控制砖块和数据恢复的守护进程。

glusterfsd = per-brick daemon
它为每块砖启动自己的 glusterfsd 守护进程。

glustershd = self-heal daemon
它会在集群节点故障的情况下重建复制卷上的数据

glusterfs = usually client-side, but also NFS on servers
例如,它可能带有 glusterfs-fuse 原生客户端包 Make nodes peers:

gluster peer probe server2
gluster peer probe server3
组装一个卷(砖的顺序在这里很重要,复制的砖必须彼此跟随):

gluster volume create holodilnik stripe 10 replica 3 arbiter 1 transport tcp server1:/export/brick0/holodilnik server2:/export/brick0/holodilnik server3:/export/brick0/holodilnik server1:/export/brick1/holodilnik server2:/export/brick1/holodilnik server3:/export/brick1/holodilnik server1:/export/brick2/holodilnik server2:/export/brick2/holodilnik server3:/export/brick2/holodilnik server1:/export/brick3/holodilnik server2:/export/brick3/holodilnik server3:/export/brick3/holodilnik server1:/export/brick4/holodilnik server2:/export/brick4/holodilnik server3:/export/brick4/holodilnik server1:/export/brick5/holodilnik server2:/export/brick5/holodilnik server3:/export/brick5/holodilnik server1:/export/brick6/holodilnik server2:/export/brick6/holodilnik server3:/export/brick6/holodilnik server1:/export/brick7/holodilnik server2:/export/brick7/holodilnik server3:/export/brick7/holodilnik server1:/export/brick8/holodilnik server2:/export/brick8/holodilnik server3:/export/brick8/holodilnik server1:/export/brick9/holodilnik server2:/export/brick9/holodilnik server3:/export/brick9/holodilnik force
为了获得稳定的 Gluster,我们必须尝试许多参数组合、内核版本(3.10.0、4.5.4)和 Glusterfs 本身的版本(3.8、3.10、3.13)。最终,我们还得出了以下参数值:

gluster volume set holodilnik performance.write-behind on
gluster volume set holodilnik nfs.disable on
gluster volume set holodilnik cluster.lookup-optimize off
gluster volume set holodilnik performance.stat-prefetch off
gluster volume set holodilnik server.allow-insecure on
gluster volume set holodilnik storage.batch-fsync-delay-usec 0
gluster volume set holodilnik performance.client-io-threads off
gluster volume set holodilnik network.frame-timeout 60
gluster volume set holodilnik performance.quick-read on
gluster volume set holodilnik performance.flush-behind off
gluster volume set holodilnik performance.io-cache off
gluster volume set holodilnik performance.read-ahead off
gluster volume set holodilnik performance.cache-size 0
gluster volume set holodilnik performance.io-thread-count 64
gluster volume set holodilnik performance.high-prio-threads 64
gluster volume set holodilnik performance.normal-prio-threads 64
gluster volume set holodilnik network.ping-timeout 5
gluster volume set holodilnik server.event-threads 16
gluster volume set holodilnik client.event-threads 16
其他有用的参数:

sysctl vm.swappiness=0
sysctl vm.vfs_cache_pressure=120
sysctl vm.dirty_ratio=5
echo "deadline" > /sys/block/sd[b-k]/queue/scheduler
echo "256" > /sys/block/sd[b-k]/queue/nr_requests
echo "16" > /proc/sys/vm/page-cluster
blockdev --setra 4096 /dev/sd[b-k]
虽然这些值在我们的情况下是好的,当它全部与备份有关时,即线性操作,随机读/写需要不同的东西。

现在让我们谈谈不同Gluster安装类型的优缺点和失败的测试结果。

我们测试了所有基本的卷挂载选项:



具有 backupvolfile-server 参数的 Gluster Native Client (glusterfs-fuse)

有什么不好:

  • 要安装的其他客户端软件
  • 速度

不好,但还可以:

  • 如果一个集群节点发生故障,则长期无法访问数据。要解决此问题,请在服务器端使用 network.ping-timeout 参数。如果我们将其设置为 5,则对共享文件夹的访问将丢失 5 秒。

有什么好的:

  • 运行比较稳定,文件损坏问题很少

Gluster Native Client (gluster-fuse) + VRRP (keepalived)

我们配置了一个在两个集群节点之间迁移的 IP 并关闭其中一个。


有什么不好:

  • 要安装的附加软件

有什么好的:

  • 集群节点故障时可配置的故障转移超时

事实证明,指定 backupvolfile-server 参数或设置 keepalived 是不必要的,因为客户端可以连接到 Gluster 守护程序(使用任何地址),获取其他地址并开始写入所有集群节点。我们观察到从客户端到 server1 和 server2 的对称流量。即使您指定了 VIP 地址,客户端仍然使用 Glusterfs 集群地址。因此,当启动客户端尝试连接到 glusterfs 服务器,发现它无法访问,然后连接到在 backupvolfile-server 中指定的主机时,此参数很有用。


来自白皮书的评论:

FUSE 客户端允许使用 GlusterFS «round robin» 样式连接进行挂载。在 /etc/fstab 中,使用一个节点的名称;但是,内部机制允许该节点发生故障,并且客户端将滚动到受信任存储池中的其他连接节点。性能比基于测试的 NFS 方法稍慢,但不是很明显。收益是自动 HA 客户端故障转移,这通常值得对性能产生影响。

带有 Pacemaker 的 NFS-Ganesha 服务器

如果出于任何原因不想使用本机客户端,建议使用挂载类型


有什么不好:

NFSv3 和 NLM + VRRP(保持活动状态)

具有锁定支持和 IP 在两个集群节点之间迁移的经典 NFS


有什么好的:

  • 节点故障时的快速故障转移
  • keepalived的简单设置
  • nfs-utils 默认安装在我们所有的客户端主机上

有什么不好:

  • NFS 客户端在通过 RSYNC 将数据复制到挂载点几分钟后挂在 D 状态
  • 运行客户端的节点完全崩溃 — BUG:软锁定 — CPU 因 Xs 卡住!
  • 许多情况下,文件因«stale file handle»、«Directory not empty at rm -rf»、«Remote I/O error»和其他错误而损坏

这个选项是最糟糕的,甚至在后来的 Glusterfs 版本中被弃用了。


最后,我们选择了没有keepalived和backupvolfile-server参数的glusterfs-fuse,因为尽管速度相对较低,但它是唯一稳定的选择。

除了配置高可用的解决方案外,在生产使用方面,我们还必须能够在灾难后恢复服务。这就是为什么,最终有了一个稳定的集群,我们进行了破坏性测试:

旧重启

我们从一个客户端对大量文件启动 rsync,硬关闭集群节点之一,得到了非常有趣的结果。节点崩溃后,写入首先停止 5 秒(由 network.ping-timeout = 5 定义),然后写入共享文件夹的速度翻倍,因为客户端无法再复制数据并开始发送所有流量到剩余的节点,同时受到我们 1G 信道的限制。

iuyg.png

服务器重启后,glustershd 守护进程自动运行数据修复,速度急剧下降。

您可以查看节点崩溃后正在修复的文件数:


	 [16:41]:[root@sl051 ~]# gluster volume heal holodilnik info


	 ...

	 Brick server2:/export/brick1/holodilnik

	 /2018-01-20-weekly/billing.tar.gz 

	 Status: Connected

	 Number of entries: 1

	 Brick server2:/export/brick5/holodilnik

	 /2018-01-27-weekly/billing.tar.gz 

	 Status: Connected

	 Number of entries: 1

	 Brick server3:/export/brick5/holodilnik

	 /2018-01-27-weekly/billing.tar.gz 

	 Status: Connected

	 Number of entries: 1
...

愈合后,计数器归零并恢复写入速度。


磁盘故障和更换

无论是故障还是用砖块更换磁盘都不会减慢写入共享文件夹的速度。也许,这里的瓶颈是节点之间的通道而不是磁盘速度。一旦我们有额外的 Infiniband 卡,我们就会尝试更快的频道。

请注意,故障磁盘和替换磁盘在 sysfs (/dev/sdX) 中必须具有相同的名称。虽然新磁盘经常被分配下一个字母,但不要让它保持原样,否则在下一次重新启动后磁盘会得到它的旧名称,块设备名称会改变,砖块将无法工作。这就是为什么要采取某些行动的原因。

旧的磁盘挂载点很可能遗留在系统的某个地方。所以,做卸载。


	 umount /dev/sdX

此外,检查哪些进程可能持有该设备:


	 lsof | grep sdX

并停止它。

然后重新扫描:

检查 dmesg-H 以获取有关故障磁盘位置的更多详细信息。



	 [Feb14 12:28] quiet_error: 29686 callbacks suppressed

	 [ +0.000005] Buffer I/O error on device sdf, logical block 122060815

	 [ +0.000042] lost page write due to I/O error on sdf

	 [ +0.001007] blk_update_request: I/O error, dev sdf, sector 1952988564

	 [ +0.000043] XFS (sdf): metadata I/O error: block 0x74683d94 ("xlog_iodone") error 5 numblks 64

	 [ +0.000074] XFS (sdf): xfs_do_force_shutdown(0x2) called from line 1180 of file fs/xfs/xfs_log.c. Return address = 0xffffffffa031bbbe

	 [ +0.000026] XFS (sdf): Log I/O Error Detected. Shutting down filesystem

	 [ +0.000029] XFS (sdf): Please umount the filesystem and rectify the problem(s)

	 [ +0.000034] XFS (sdf): xfs_log_force: error -5 returned.

	 [ +2.449233] XFS (sdf): xfs_log_force: error -5 returned.

	 [ +4.106773] sd 0:2:5:0: [sdf] Synchronizing SCSI cache

	 [ +25.997287] XFS (sdf): xfs_log_force: error -5 returned.

其中 sd 0:2:5:0 是:



	 h == hostadapter id (first one being 0)

	 c == SCSI channel on hostadapter (first one being 2), which is also a PCI slot

	 t == ID (5), which is also slot number of a failed disk

	 l == LUN (first one being 0)

重新扫描:



	 echo 1 > /sys/block/sdY/device/delete

	 echo "2 5 0" > /sys/class/scsi_host/host0/scan

其中 sdY 是要替换的磁盘的错误名称。

然后,对于砖块更换,创建一个新目录进行挂载,创建文件系统并挂载它:



	 mkdir -p /export/newvol/brick

	 mkfs.xfs /dev/sdf -f

	 mount /dev/sdf /export/newvol/

更换砖块:



	 gluster volume replace-brick holodilnik server1:/export/sdf/brick server1:/export/newvol/brick commit force

开始治疗:



	 gluster volume heal holodilnik full

	 gluster volume heal holodilnik info summary

仲裁失败:

hgff.png

共享文件夹的相同 5-7 秒不可访问以及与仲裁节点的元数据同步导致的 3 秒下垂。


概括

破坏性测试结果鼓励我们将其部分用于生产用途,但这只是短暂的快乐……


问题 1,这也是一个已知的错误:

在删除大量文件和目录(大约 100,000 个)时,我们得到以下信息:



	 rm -rf /mnt/holodilnik/*

	 rm: cannot remove ‘backups/public’: Remote I/O error

	 rm: cannot remove ‘backups/mongo/5919d69b46e0fb008d23778c/mc.ru-msk’: Directory not empty

	 rm: cannot remove ‘billing/2018-02-02_before-update_0.10.0/mongodb/’: Stale file handle

自 2013 年以来,我已经阅读了大约 30 份类似的用户投诉。这个问题没有解决方案。


Red Hat 建议更新版本,但对我们没有帮助。

https://access.redhat.com/solutions/1264803

我们的解决方法是简单地清除所有节点上的砖块中剩余的损坏目录

pdsh -w server[1-3] -- rm -rf /export/brick[0-9]/holodilnik/<failed_dir_path>

振作起来,最糟糕的还没有到来。


问题2,最糟糕的:

我们试图解压一个包含许多文件的存档,该存档包含在条带卷上的共享文件夹中,结果 tar xvfz 处于“不间断睡眠”状态,只能通过重新启动客户端节点来治愈。


在意识到我们再也无法忍受之后,我们选择了唯一尚未尝试但相当棘手的配置——擦除编码。关于它的唯一困难是理解它的卷创建原理。Red Hat 提供了一个很好的示例手册

https://access.redhat.com/documentation/en-us/red_hat_gluster_storage/3.1/html/administration_guide/chap-recommended-configuration_dispersed。


在运行所有相同的破坏性测试后,我们获得了同样令人鼓舞的结果。我们编写然后删除了数百万个文件。我们所有打破分散体积的尝试都失败了。我们观察到更高的 CPU 负载,但这对我们来说并不重要,目前还不是。


现在,它存储我们的基础设施段备份,并用作我们内部需求的文件仓库。我们想花一些时间使用它,看看它在各种负载下的表现。到目前为止,很明显条带卷以一种奇怪的方式工作,而其他卷则表现得非常好。我们还计划在具有宽 Infiniband 通道的 6 台服务器上构建一个 50 TB 的分散卷(4 + 2),测试其性能,并继续研究其运行原理。

原文地址:https://cloud.croc.ru/en/blog/about-technologies/glusterfs-crash-test-our-experience/
posted @ 2022-03-26 01:51  十支穿云箭  阅读(415)  评论(0编辑  收藏  举报