我认为我有一个 XY 问题,如果您能将其识别为 XY 问题,请相应地回答!
背景
我的主要目标是学习 Kubernetes,其次要目标是做家庭实验室的东西——为那些应该接触更多草的人托管各种小型服务。有了这个,我有一个运行 K3S 的 coolberetes 家庭实验室集群、一些工作节点、一个由 potato 驱动的集群管理器节点和一个 QNAP NAS 作为后端存储。
QNAP 在 RAID-6 中拥有 8x12TB 7200RPM 硬盘。它在持续传输方面表现出色,但随机 IO 使其表现不佳。这是由于工作负载和硬件而导致的。QNAP 位于 10gbit 交换机上,为工作者提供 2.5/1gbit 端口,因此带宽不是特别大,但我认为这足以满足我的需要。每个工作者本地都有一个 1TB NVMe 硬盘,我认为这在后面会用到。
问题
我运行的一些容器不是我构建的应用程序,因此无法轻易修改开发人员的设计选择。请记住这一点。
大多数容器被分成两类卷:data
、config
。这些data
卷是大批量文件,顺序访问。我一直通过 NFS/SMB 卷挂载来处理这些文件,这很好用。这些config
卷包括一些 YAML 文件、一个或两个 JSON 文件、一些日志文件夹、一个 SQLite 数据库等。这些卷执行很多通过 NFS 安装时情况会更糟,并且 SQLite 数据库会由于锁定问题而彻底失败。
迄今为止的解决方案以及被拒绝的原因
- “将配置卷放在 NFS 上”——SQLite 将因锁定错误而导致崩溃。这是 v3 和 v4。
- “停止使用 SQLite”——图片中的软件已硬编码使用该软件。重写该软件是不可行的。
- “只需将这些配置卷放在本地磁盘上”——纯本地卷如何允许我迁移或扩展任何服务?
- “将缓存放在 NAS 上”——QNAP 出于一些愚蠢的原因不允许我添加写入缓存
- “使用 rsync 来同步卷”——是的,这样做了,效果“良好”,但我怀疑这是否是官方的解决方案。
预期解决方案
我认为这就是我的 XY 问题所在,或者至少是完全缺乏知识。我的期望是有一种方法可以利用每个工作器上的 1TB NVMe 驱动器,并通过 NAS 导出块存储,作为分布式或集群文件系统。我希望我可以在本地安装这个分布式/集群文件系统,让容器在其上运行,并且在后台它将在正在运行的节点之间同步自身并返回 QNAP 进行备份。对于我正在做的事情,1TiB 文件系统将满足我对config
卷的需求。
如果存在这种解决方案,它叫什么?在哪里可以了解更多信息?如果这是错误的解决方案,那么“正确”的解决方案是什么?
答案1
您肯定需要一个用于集群部署的分布式存储解决方案。实际上,我正在设置一个非常类似的解决方案长角牛。Longhorn 对我来说是一个自然的选择,因为我正在使用 K3s,它(作为 Rancher 产品)内置了 Longhorn 集成,但只需稍微做一点工作它就可以与任何 Kubernetes 发行版集成。
免责声明:我还没有真正设置它,但我已经做了所有的研究,并准备在有空闲时间时立即启动它。我的理解是,它将管理物理数据的复制和同步,几乎完全按照您描述的那样,并且它支持NFS/SMB 作为备份目标。
我对此设置的唯一担忧是性能:正如我所说,我还没有设置它,所以我不知道它会如何发展,但我知道 Longhorn 会进行同步复制(在写入操作被视为“完成”之前,必须将所有内容写入副本),因此它肯定会比纯本地 NVMe 慢。慢多少还有待观察,但我猜这对您来说不是问题,尤其是在 10Gb 网络上,因为您不关心例如表现NFS 上的 SQLite,仅存在一致性问题。
一旦设置完成,我会尽量记得在这里发布更新(我计划本周花一些时间)。我会尝试对本地磁盘和 Longhorn 进行一些基本的性能测试。
值得一提的是,Longhorn 并不是唯一的选择。我研究过的其他名字包括比雷埃夫斯和林斯托,但我没有对它们进行太多研究,所以我不知道它们如何比较。
编辑:基准测试结果
我花了一整天时间fio
在各种配置下使用 Longhorn,我的结论是它虽然可行,但绝对不是高性能。它适合那些大部分时间处于空闲状态的东西(如自托管的 Web 应用程序),但如果你想在其上运行负载很重的关系数据库,我可能会建议你尝试其他东西。
我对每个测试的配置都进行了 3 次测试(好吧,是 6 次,因为我确实分别进行了读写操作)。测试内容如下:
- 最大带宽:队列深度为 16 时单个进程的 4MiB 读取/写入
- 最大 IOPS:16 个并行进程的 4k 随机读/写,每个进程的队列深度为 16(因此每次有 256 个操作未完成)
- 尝试针对我们正在讨论的情况模拟更“真实”的工作负载:在队列深度为 2 的情况下从单个进程进行 4k 随机读取/写入。我的目的是模拟由 SQLite 支持的轻负载 Web 应用程序(默认情况下使用 4k 页面 IIRC。)
我在以下情况下进行了这些测试:
- 直接针对本地磁盘,无需虚拟化
- 针对同一磁盘,但安装到具有
hostPath
- 通过 Longhorn 针对同一磁盘(具有 1 个副本)
- 从本地 pod(与副本在同一节点上运行)
- 从远程 pod(在与副本不同的节点上运行)
- 通过具有 2 个副本的 Longhorn 针对同一个磁盘(我目前在集群中只有 2 个节点,因此测试 3 个副本意义不大。)
服务器运行的是 Epyc 7262s (8c16t)、64G RAM,并通过 10GbE 连接。正在测试的磁盘是 SK Hynix Platinum P41s(额定读取速度为 7000MiB/s,写入速度为 6500MiB/s,IOPS 约为 1.5M)
这些表格有点令人困惑,因此需要澄清的是,行表示存储配置(例如,直接针对驱动器进行测试与通过 Longhorn 或其他方式进行测试),列表示工作负载。“BW - R”列指的是以最大吞吐量为目标的读取工作负载,“IOPS - W”列指的是以最大 IOPS 为目标的写入工作负载,等等。
结果 - 吞吐量 (MiB/s)
黑白 | 黑白 | 每秒输入/输出次数 | IOPS - 宽 | 光 - R | 光 - W | |
---|---|---|---|---|---|---|
直接的 | 7025 | 6333 | 5861 | 5584 | 174 | 143 |
主机路径 | 7027 | 6196 | 4789 | 5515 | 117 | 405 |
LH - 1R,本地 | 1512 | 354 | 118 | 67.2 | 19.6 | 19.1 |
LH - 1R,遥控 | 244 | 254 | 84.3 | 40.5 | 11.2 | 11.7 |
左手边 - 2R | 395 | 254 | 96.8 | 34.5 | 19.2 | 10.6 |
每秒输入/输出次数
黑白 | 黑白 | 每秒输入/输出次数 | IOPS - 宽 | 光 - R | 光 - W | |
---|---|---|---|---|---|---|
直接的 | 1756 | 1583 | 1.50米 | 1.43万 | 44.5万 | 36.6万 |
主机路径 | 1.75千 | 1.5千 | 1.2米 | 1.4米 | 29.9万 | 10.4万 |
LH - 1R,本地 | 377 | 88 | 30.1万 | 17.2万 | 5.0千 | 4.9千 |
LH - 1R,遥控 | 61 | 63 | 21.6万 | 10.1千 | 2.8千 | 2.9千 |
左手边 - 2R | 98 | 63 | 24.8万 | 8.8千 | 4.9千 | 2.7千 |
潜伏
黑白 | 黑白 | 每秒输入/输出次数 | IOPS - 宽 | 光 - R | 光 - W | |
---|---|---|---|---|---|---|
直接的 | 9.1毫秒 | 10.1毫秒 | 170微秒 | 357微秒 | 44.4微秒 | 54.2微秒 |
主机路径 | 9.1毫秒 | 10.2毫秒 | 208微秒 | 181微秒 | 65.9微秒 | 18.8微秒 |
LH - 1R,本地 | 42.3毫秒 | 181毫秒 | 8.5毫秒 | 14.9毫秒 | 396微秒 | 408微秒 |
LH - 1R,遥控 | 259毫秒 | 252毫秒 | 11.85毫秒 | 25.1毫秒 | 713微秒 | 680微秒 |
左手边 - 2R | 162毫秒 | 251毫秒 | 10.3毫秒 | 28.9毫秒 | 406微秒 | 738微秒 |
关于延迟的说明:我使用的是lat
产生的平均数fio
,我认为这是指从提交操作到读/写完成的时间。这就是为什么它对于最大吞吐量场景如此之高的原因:这些是 4k 操作大小的 1000 倍,因此它们必然会花费更长的时间。
要点:
无论如何,你都会牺牲一个很多与没有虚拟化的本地磁盘相比,其性能更高。
但我不确定这是否重要!特别是如果我们查看“轻量级”工作负载的 IOPS 和延迟数字,我们可以看到我们仍然获得 >1k IOPS,并且这些操作在 <1ms 内完成。在我看来,这对于日常轻量级使用来说很好。如果您的 Web 应用程序的数据库需要多次访问磁盘来处理请求,您仍然不会注意到差异,因为任何低于 1ms 的操作都绝对是矮小网络延迟。
如果你需要支撑很大的负载(公平地说,有点像预期的如果你运行的是 Kubernetes,情况就会如此——它绝对不是为家庭实验室设计的。)一旦你达到几千个并发用户,你就会真的开始感受到 IOPS 的压力。
长角牛正在努力他们的存储引擎 V2 声称“显著降低了 I/O 延迟,同时提高了 IOPS 和吞吐量”,但它仍处于开发阶段,尚不支持快照和备份等重要功能。也许一旦发布,我就会升级并重新进行这些基准测试。
与此同时,如果你需要的性能超出 Longhorn 所能提供的范围,也许 Piraeus/Linstor(显然 Piraeus 是建立在 Linstor 之上的)值得一看?据我所知,它可以进行异步复制,这非常适合你一次只运行 1 个给定事物并且只想要复制以便 pod 可以在节点之间跳转而不用担心的场景。
我最近遇到的另一种选择是维塔斯托,看起来很有趣,但非常非常偏僻。不过如果你尝试了,请告诉我,我很好奇它的效果如何。