DirectPV的故事

alt 2020 年,MinIO 为基于 Kubernetes 的 MinIO 存储部署实施了直接持久卷 (DirectPV)。DirectPV 类似于 LocalPV,但动态预配。

在这篇文章中,我将介绍创建 DirectPV 的有趣设计决策。但在深入了解设计细节之前,让我们先快速回顾一下直接持久卷与网络持久卷。

什么是DirectPV?

DirectPV 是用于直连存储的 Kubernetes 容器存储接口 (CSI) 驱动程序。它用于为工作负载置备本地卷。简单来说,使用 DirectPV 的工作负载将直接使用本地磁盘,而不是远程磁盘。与基于 SAN 或 NAS 的 CSI 驱动程序(网络 PV)不同,后者在数据路径中增加了另一层复制/纠删码和额外的网络跃点。这种额外的分解层会导致复杂性增加和性能不佳。

alt

使用 DirectPV,您可以发现、格式化和装载驱动器,使其准备好进行预配。初始化驱动器后,可以使用“directpv-min-io”存储类在驱动器上计划工作负载的卷。

设计中的挑战

“简约是极致的精致。”

除了解释 DirectPV 的功能和用例之外,我还想介绍一些在开发阶段做出的有趣的设计决策。

以下是 DirectPV 设计阶段面临的一些主要挑战。

挑战 1:匹配驱动器的本地状态和远程状态

DirectPV 在 Kubernetes 自定义资源中保存和维护本地驱动器状态。某些状态(如驱动器名称和排序)在节点重新启动或驱动器热插拔期间可能不会持续存在。持续保持本地设备状态与 DirectPV 记住的驱动器状态同步是必要的,因为它处理敏感操作,如格式化、装载等。这是一个关键部分,如果处理不当,可能会导致数据丢失。

早期版本的 DirectPV 通过识别 WWID、驱动器序列号和分区 UUID 等属性来匹配本地驱动器(来自主机)和远程驱动器(Kubernetes 驱动器资源)。

这种方法存在以下问题

(a) 探测这些设备成本更高,费力更大,并且有不良副作用。

alt

我们执行了 IOCTL 调用来读取驱动器的 S.M.A.R.T(自我监控、分析和报告技术)序列号信息。作为副作用,这会适得其反,导致 CHANGE udev 事件过多,导致 DirectPV udev 侦听器中的 CPU 峰值。

(b) 按驱动器的特性进行匹配至关重要

如前所述,需要持续保持驱动器与本地状态同步,因为 DirectPV 执行本地主机级操作,如格式化、挂载等。早期版本的 DirectPV 将驱动器与多个属性(如 WWID、序列号、主要-次要等)相匹配。由于不同驱动器供应商之间存在差异,因此此类状态无法可靠地进行匹配。并非所有驱动器供应商都提供有关驱动器的相同信息。这里的风险是驱动器的格式可能不正确,并且可能没有正确地映射到卷。本期将介绍一个这样的例子。

溶液:

现在,我们已经看到了探测设备以获取信息以及保持本地和远程驱动器状态同步的潜在挑战。我们发现了一种简单的方法来缩小 DirectPV 管理的驱动器的范围。

我们从管理群集中的所有驱动器转变为仅管理提供给 DirectPV 的驱动器。为了实现这一点,设计进行了一些更改。

# 列出集群中的可用驱动器
kubectl directpv drives ls

# 选择 directpv 应管理和格式化的驱动器
kubectl directpv drives format --drives /dev/sd{a...f} --nodes directpv-{1...4}

如上图所示,在旧版本的 DirectPV 中,服务器启动后,它会探测集群中所有节点中的所有驱动器,并在 Kubernetes 中创建相应的驱动器对象(自定义资源)。这些驱动器对象将列出并格式化。如前所述,如果驱动器状态不可靠,则可能会导致格式化错误的驱动器。

# Probe and save drive information to drives.yaml file.
# 探测驱动器信息并保存到 drives.yaml 文件中。
$ kubectl directpv discover
$ kubectl directpv 发现

# Initialize selected drives.
# 初始化选定的驱动器。
$ kubectl directpv init drives.yaml

最新版本的 DirectPV 执行按需探测。当用户执行命令“kubectl directpv discover”时,它会实时探测集群中的驱动器。与传统设计不同,这是无状态的,并且不会在 Kubernetes 中保存任何驱动器状态。用户查看探测驱动器的输出,然后通过发出“kubectl directpv init”命令将其添加到 DirectPV。

作为初始化过程的一部分,驱动器将使用唯一的文件系统 UUID 进行格式化。成功执行后,将使用 UUID 创建一个驱动器对象。此 FSUUID 对于“初始化”驱动器是唯一的,我们可以可靠地使用它进行匹配。它提供了一个强有力的事实和证据,表明如果初始化驱动器的 FSUUID 通过任何外部进程篡改或覆盖主机而发生更改,则无法匹配驱动器,并将被视为损坏的驱动器。除此之外,我们不再需要任何其他更昂贵的探头。

挑战 2:Hitman 风格的声明性格式和重试

根据定义,Kubernetes 中的事件控制器是声明性的,在维护资源的所需状态方面起着至关重要的作用。它会在出现任何错误时重试,直到达到所需状态。这是 Kubernetes 中管理和维护资源状态的成功方法。

DirectPV的旧版本遵循类似的方法。驱动器(自定义资源)事件控制器侦听格式驱动器请求并做出反应。格式化失败时,控制器会以增量回退的方式重试。当驱动器的状态在定期重试期间发生更改时,此方法是不安全的。这就像“派一个杀手去追捕磁盘并不断重试”。

溶液: 我们更改了设计以遵守以下规则:

格式化时不会自动重试

验证驱动器并在格式化前 100% 确定

alt 初始化(格式化)是实时的,没有自动重试。最重要的是,不会对缓存的驱动器状态执行任何关键驱动器操作。

如果初始化成功或失败,将传达错误,用户将重试初始化。

alt

提供给 init 命令的配置文件将具有驱动器唯一的驱动器哈希值。在格式化之前,DirectPV服务器将验证请求中的此哈希值是否与计算的哈希值匹配。如果没有,那么它就会出错,抱怨状态已经改变。

总结

“简单不仅仅是消除杂乱无章。这是为了让复杂性变得清晰......“ - 阿南德·巴布·佩里亚萨米

对于在 Kubernetes 上运行 MinIO 存储的 MinIO 客户来说,DirectPV 是向前迈出的一大步。到达那里并不容易。这篇文章探讨了 MinIO 工程在实施 DirectPV 时面临的两个高级挑战。这些挑战是 Hitman 风格的重试,并将本地状态与驱动器的远程状态相匹配。

如果你有任何问题,请务必与我们联系!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/538837.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Logseq电脑端+安卓端同步gitee或github

文章目录 0.初衷1.电脑端1.1 新建仓库1.2 克隆项目,生成秘钥1.3 添加图谱,选择文件目录,我是原本就有笔记,所以会如下所示。1.4 下载脚本文件1.5赋权限 (windows可跳过)1.6 修改脚本命令1.7 logseq设置同步…

es 聚合操作(二)

书接上文,示例数据在上一篇,这里就不展示了 一、Pipeline Aggregation 支持对聚合分析的结果,再次进行聚合分析。 Pipeline 的分析结果会输出到原结果中,根据位置的不同,分为两类: Sibling - 结果和现有…

CentOS无法解析部分网站(域名)

我正在安装helm软件,参考官方文档,要求下载 get-helm-3 这个文件。 但是我执行该条命令后,报错 连接被拒绝: curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 # curl: (7) Fai…

2.MongoDB与关系数据库对比

MongoDB的简单操作与比较 与关系数据库对比 MySQL与MongoDB都是开源的常用数据库,但是MySQL是传统的关系型数据库,MongoDB则是非关系型数据库,也叫文档型数据库,是一种NoSQL的数据库。它们各有各的优点,来看看他们之…

两个高斯分布的KL散度绘制动画

KL散度 KL散度用于衡量两个变量分布之间的差异性 K L ( P ∣ ∣ Q ) ∫ − ∞ ∞ p ( x ) log ⁡ p ( x ) q ( x ) d x (1) KL(P\ ||\ Q)\int_{-\infty}^{\infty}p(x)\log\frac{p(x)}{q(x)}dx\tag{1} KL(P ∣∣ Q)∫−∞∞​p(x)logq(x)p(x)​dx(1) P、Q为随机变量X的两个概…

经典数组和指针笔试题解析——C语言

【本节内容】 1. 数组和指针笔试题解析 2. 指针运算笔试题解析 1. 数组和指针笔试题解析 1.1 一维数组 #include <stdio.h> int main() {int a[] { 1,2,3,4 };printf("%zd\n", sizeof(a));printf("%zd\n", sizeof(a 0));printf("%zd\n&qu…

Docker常见指令

1.docker search mysql &#xff1a;从docker镜像仓库搜索和mysql有关的镜像 docker search mysql 2.docker pull mysql &#xff1a;从docker仓库拉取mysql镜像 docker pull mysql 3.docker run mysql &#xff1a;启动mysql镜像 docker run mysql 4.docker ps &#xff…

消除PyCharm的黄色波浪线和右侧黄色短线

旧版pycharm看这个链接&#xff1a;https://blog.csdn.net/weixin_39450145/article/details/113574921 新版pycharm往下看 消除代码中的黄色波浪线&#xff1a;在设置&#xff0c;编辑器&#xff0c;配色方案&#xff0c;常规里面。然后选择错误和警告。 消除右侧黄色短线&am…

msfconsole数据库连接不了的问题【已解决】

msfconsole数据库连接 1.msf数据库端口 msf使用的是postgresql&#xff0c;这个数据库默认端口是5432 单个模块的使用可以不需要数据库&#xff0c;但是模块与模块之间需要沟通的时候就会用到数据库。 2.查看msf数据库连接状态 db_status #msf内部查看systemctl status p…

想零基础转行Python开发,怎么学习呢?

转行零基础学Python编程开发难度大吗&#xff1f;从哪学起&#xff1f;近期很多小伙伴问我&#xff0c;如果自己转行学习Python&#xff0c;完全0基础能否学会呢&#xff1f;Python的难度到底有多大&#xff1f;今天&#xff0c;小编就来为大家详细解读一下这个问题。 学习 Py…

MySQL:概念简章

1.SQL通用语法 SQL单行、多行书写&#xff0c;以分号结尾SQL可以以空格有缩进增加代码可读性SQL语句不区分大小写 2.SQL语句分类 2.1 DDL&#xff08;数据定义语言&#xff09; 用于数据库、数据表、字段的定义的语言 create by 表名 &#xff08;表里有什么字段&#xff09;…

软考--软件设计师(磁盘管理的例题)

流水线的理论公式&#xff1a; 单缓冲区&#xff1a;同一时间内只能允许一个进程进行写入读出&#xff0c;所以每个盘块经过缓冲区的时间是&#xff08;155微秒&#xff09;&#xff0c;之后再用1微秒的时间进行处理。在处理的同时&#xff0c;下一个盘块写入缓冲区&#xff0c…