存储架构¶
在设计 OpenStack 云时,有许多不同的存储架构可供选择。OpenStack 平台中编排和自动化的融合使得能够快速配置存储,而无需像卷创建和挂载等传统手动流程那样繁琐。
然而,在选择存储架构之前,应该先回答几个通用的问题
随着云的增长,存储架构是否会线性扩展,它的限制是什么?
期望的挂载方法是什么:NFS、iSCSI、FC 或其他?
该存储是否已在 OpenStack 平台上得到验证?
供应商在社区内提供的支持级别是什么?
Cinder 驱动程序支持哪些 OpenStack 功能和增强功能?
它是否包含帮助故障排除和解决性能问题的工具?
它是否与您计划在云中使用的所有项目互操作?
选择存储后端¶
用户对他们的云架构会有不同的需求。有些人可能需要对许多不常更改的对象进行快速访问,或者希望为文件设置生存时间 (TTL) 值。另一些人可能只访问使用文件系统本身挂载的存储,但希望在启动新实例时立即进行复制。对于其他系统,临时存储是首选。在选择 存储后端 时,请从用户的角度考虑以下问题
首先最重要的是
我需要块存储吗?
我需要对象存储吗?
我需要基于文件的存储吗?
接下来回答以下问题
我需要支持实时迁移吗?
我的持久存储驱动器应该包含在我的计算节点中,还是应该使用外部存储?
我需要什么样的性能,关于 IOPS?总 IOPS 和每个实例的 IOPS?我是否有具有 IOPS SLA 的应用程序?
我的存储需求主要是读、写还是混合?
哪些存储选择能实现我所追求的最佳性价比?
我如何操作性地管理存储?
存储的冗余和分布程度如何?如果存储节点发生故障会发生什么?它可以在多大程度上缓解我的数据丢失灾难场景?
我的公司目前正在使用什么,我是否可以在 OpenStack 中使用它?
我需要一个以上的存储选择吗?我需要分层性能存储吗?
虽然这不是所有可能问题的明确列表,但希望上述列表能够帮助缩小可能的存储选择范围。
各种各样的用例需求决定了存储后端的性质。以下是一些这样的需求示例
公共、私有或混合云(性能配置文件、共享存储、复制选项)
存储密集型用例,如 HPC 和大数据云
Web 规模或开发云,其中存储通常是临时的
数据安全建议
我们建议对数据进行传输中和静态加密。为此,请仔细选择磁盘、设备和软件。不要假设所有存储解决方案都包含这些功能。
确定您组织的安全性策略,并了解您云地理位置的数据主权,并相应地进行规划。
如果您计划使用实时迁移,我们强烈建议使用共享存储配置。这允许实例的操作系统和应用程序卷驻留在计算节点之外,并在实时迁移时显著提高性能。
要仅使用通用硬件部署存储,可以使用许多开源软件包,如 持久文件存储支持 中所述。
对象 |
块 |
文件级别 |
|
|---|---|---|---|
Swift |
|
||
LVM |
|
||
Ceph |
|
|
实验 |
Gluster |
|
|
|
NFS |
|
|
|
ZFS |
|
||
Sheepdog |
|
|
此开源文件级别共享存储解决方案列表并非详尽无遗。您的组织可能已经部署了您可以使用的文件级别共享存储解决方案。
注意
存储驱动程序支持
除了开源技术之外,还有许多由 OpenStack 块存储官方支持的专有解决方案。您可以在 CinderSupportMatrix wiki 上找到所有受支持的块存储驱动程序提供的功能的矩阵。
此外,您需要决定是否要在云中支持对象存储。在计算云中提供对象存储的两个常见用例是
为用户提供用于存储图像和视频等对象的持久存储机制。
用于 OpenStack 虚拟机镜像的可扩展、可靠的数据存储。
一个由 API 驱动的 S3 兼容对象存储,供应用程序使用。
选择存储硬件¶
存储硬件架构是通过选择特定的存储架构来确定的。通过根据关键因素、用户需求、技术考虑因素和操作考虑因素评估可能的解决方案来确定存储架构的选择。在选择存储硬件时,请考虑以下因素
- 成本
存储可能是整个系统成本的重要组成部分。对于关注供应商支持的组织,建议使用商业存储解决方案,尽管它价格较高。如果初始资本支出需要最小化,则设计基于通用硬件的系统适用。权衡是潜在的更高的支持成本以及更大的不兼容性和互操作性问题风险。
- 性能
基于块的存储的性能通常以每秒对非连续存储位置执行的最大读写操作次数来衡量。此测量通常适用于 SAN、硬盘和固态硬盘。虽然 IOPS 可以广泛测量并且不是官方基准,但许多向量喜欢被供应商用来传达性能水平。由于没有用于测量 IOPS 的真正标准,供应商的测试结果可能会有所不同,有时甚至差异很大。但是,IOPS 连同测量数据可以传输到连续存储位置的速度的传输速率一起使用,可以用于性能评估。通常,传输速率以每秒字节数计算表示,但 IOPS 以整数来衡量。
- 要计算单个驱动器的 IOPS,可以使用
IOPS = 1 / (平均延迟 + 平均寻道时间) 例如:单个磁盘的平均延迟 = 2.99 毫秒或 0.00299 秒 单个磁盘的平均寻道时间 = 4.7 毫秒或 0.0047 秒 IOPS = 1/(.00299 + .0047) IOPS = 130
- 要计算磁盘阵列的最大 IOPS
最大读取 IOPS:为了准确计算磁盘阵列的最大读取 IOPS,请将每个磁盘的 IOPS 乘以每个磁盘的最大读取或写入 IOPS。 maxReadIOPS = nDisks * diskMaxIOPS 例如,15 个 10K 旋转磁盘的测量方式如下:maxReadIOPS = 15 * 130 maxReadIOPS = 1950
- 阵列的最大写入 IOPS
确定最大写入IOPS 有点不同,因为大多数管理员使用 RAID 配置磁盘复制,由于 RAID 控制器本身需要 IOPS,因此存在写入惩罚。写入惩罚的严重程度取决于使用的 RAID 类型。
Raid 类型
惩罚
1
2
5
4
10
2
注意
Raid 5 具有最坏的惩罚(具有最多的跨磁盘写入)。因此,在使用上述示例时,使用 RAID 5 的 15 个磁盘阵列能够实现 1950 读取 IOPS,但是,在确定写入IOPS 时,我们需要添加惩罚
maxWriteIOPS = 1950 / 4
maxWriteIOPS = 487.5
RAID 5 阵列只有读取 IOPS 的 25%,而本例中的 RAID 1 阵列将产生最大 975 IOPS。
- 关于 SSD?DRAM SSD?
在 HDD 中,数据传输是顺序的。实际的读/写磁头“寻道”到硬盘上的一个点来执行操作。寻道时间很重要。传输速率也可能受到文件系统碎片和布局的影响。最后,硬盘的机械性质也存在一定的性能限制。
在 SSD 中,数据传输不是顺序的;它是随机的,因此速度更快。由于 SSD 没有读/写磁头,因此不存在由于磁头移动(寻道)造成的延迟,因此具有一致的读取性能,因为数据的物理位置无关紧要。
注意
一些小读/写的基本基准
HDD:小读 – 175 IOPS,小写 – 280 IOPS
Flash SSD:小读 – 1075 IOPS(6 倍),小写 – 21 IOPS(0.1 倍)
DRAM SSD:小读 – 4091 IOPS(23 倍),小写 – 4184 IOPS(14 倍)
- 可扩展性
可扩展性以及可扩展性是通用 OpenStack 云中的一个重要考虑因素。由于没有针对通用云建立使用模式,因此可能难以预测最终的预期大小。为了适应增长和用户需求,可能需要扩展初始部署。许多供应商已经实施了自己的解决方案来解决这个问题。一些使用跨多个设备的集群文件系统,而另一些则使用类似的技术来扩展块存储超出固定容量。Ceph 是一种分布式存储解决方案,它提供块存储,旨在解决此扩展问题,并且没有其他基于设备的模型的域、集群或规模限制。
- 可扩展性
可扩展性是通用 OpenStack 云中存储解决方案的一个主要架构因素。一个可以扩展到 50 PB 的存储解决方案被认为比只能扩展到 10 PB 的解决方案更具可扩展性。该指标与可扩展性相关,可扩展性是解决方案在扩展时的性能度量。
实施块存储¶
使用高级 RAID 控制器和高性能磁盘配置块存储资源节点,以在硬件级别提供容错能力。
我们建议部署高性能存储解决方案,例如 SSD 驱动器或闪存存储系统,以满足块存储设备对额外性能的要求。
在对块存储有大量需求的的环境中,我们建议使用多个存储池。在这种情况下,每个设备的池在所有硬件节点上都应具有相似的硬件设计和磁盘配置。这允许设计为应用程序提供对各种块存储池的访问,每个池具有自己的冗余、可用性和性能特征。在部署多个存储池时,还需要考虑对负责跨资源节点配置存储的块存储调度程序的影响。理想情况下,确保应用程序可以在多个区域安排卷,每个区域都有自己的网络、电源和冷却基础设施。这将使租户可以选择构建分布在多个可用区中的容错应用程序。
除了块存储资源节点之外,还必须设计 API 和相关服务的可用性和冗余,这些服务负责配置和提供对存储的访问。我们建议设计一层硬件或软件负载均衡器,以实现适当的 REST API 服务的可用性,从而提供不间断的服务。在某些情况下,可能还需要部署额外的负载均衡层,以提供对负责服务和存储块存储卷状态的后端数据库服务的访问。使用高度可用的数据库集群来存储块存储元数据至关重要。
在对块存储有重大需求的云中,网络架构应考虑实例使用可用存储资源所需的 East-West 带宽量。所选网络设备应支持巨型帧以传输大块数据,并使用专用网络为实例和块存储提供连接。
实施对象存储¶
虽然一致性和分区容错性都是对象存储服务的固有特性,但设计整体存储架构以确保实现的系统满足这些目标非常重要。OpenStack 对象存储服务将特定数量的数据副本作为对象放置在资源节点上。副本分布在整个集群中,基于也存储在每个节点中的一致哈希环。
在设计集群时,您必须考虑耐用性和可用性,这取决于数据的分布和放置,而不是硬件的可靠性。
考虑副本数量的默认值,即三个。这意味着在将对象标记为已写入之前,至少存在两个副本,以防单个服务器写入失败,第三个副本可能在写入操作最初返回时尚未存在。更改此数字会增加数据的鲁棒性,但会减少可用的存储空间。请查看服务器的放置。考虑将其广泛分布在数据中心的网络和断电区域中。区域是机架、服务器还是磁盘?
考虑对象存储网络的主要流量
对象存储频繁地在托管数据的服务器之间进行通信。即使是一个小型集群也会产生每秒数兆字节的流量。
考虑一个整个服务器发生故障,需要“立即”传输 24 TB 的数据以保持三份副本的情况——这可能会给网络带来显著的负载。
另一个考虑因素是,当正在上传新文件时,代理服务器必须写入与副本数量一样多的流,从而使网络流量倍增。对于一个三副本集群,10 Gbps 的输入意味着 30 Gbps 的输出。将此与之前的高带宽私有网络与公有网络推荐相结合,复制的需求导致了私有网络的带宽必须明显高于公有网络所需的带宽。OpenStack 对象存储为了提高性能,在内部使用未加密、未认证的 rsync 进行通信,因此需要私有网络。
带宽的剩余一点是面向公众的部分。swift-proxy 服务是无状态的,这意味着您可以轻松添加更多并使用 HTTP 负载均衡方法在它们之间共享带宽和可用性。更多的代理意味着更多的带宽。
您应该考虑设计对象存储系统,使其具有足够的区域数量,以提供为定义的副本数量提供的法定人数。例如,如果在 swift 集群中配置了三个副本,为了实现法定人数,建议在对象存储集群中配置五个区域。虽然可以使用较少的区域部署解决方案,但这样做隐含的风险是某些数据可能不可用,并且对集群中存储的某些对象的 API 请求可能会失败。因此,请确保在对象存储集群中正确考虑区域数量。
对象存储的每个区域应包含在其自身可用性区域内。每个可用性区域应独立访问网络、电力和冷却基础设施,以确保不间断地访问数据。此外,一个提供对对象节点上存储的数据访问的对象存储代理服务器池应服务于每个可用性区域。每个区域的对象代理应利用本地读取和写入亲和性,以便尽可能地利用本地存储资源来访问对象。我们建议部署上游负载均衡,以确保代理服务分布在多个区域,并且在某些情况下,可能需要使用第三方解决方案来帮助地理分布服务。
对象存储集群中的一个区域是一个逻辑划分。以下任何一项都可能代表一个区域
单个节点中的一个磁盘
每个节点一个区域
每个节点集合一个区域
多个机架
多个数据中心
选择适当的区域设计对于允许对象存储集群扩展同时提供可用和冗余存储系统至关重要。可能需要配置具有不同副本、保留和其他因素要求的存储策略,这些因素可能会严重影响特定区域中的存储设计。
规划和扩展存储容量¶
随着时间的推移运行云的一个重要考虑因素是预测增长和利用率趋势,以便为短期和长期规划资本支出。收集计算、网络和存储的利用率指标,以及这些指标的历史记录。虽然获得大型锚定租户可以导致资源利用率的快速增长,但通过正常使用对云服务的平均采用率也需要仔细监控。
扩展块存储¶
您可以升级块存储池以添加存储容量,而不会中断整个块存储服务。通过安装和配置适当的硬件和软件,然后允许该节点通过消息总线报告到正确的存储池来添加节点。块存储节点通常报告到调度器服务,以通告其可用性。因此,在节点联机并可用后,租户可以立即使用这些存储资源。
在某些情况下,块存储上的需求可能会耗尽可用的网络带宽。因此,设计服务于块存储资源的网络基础设施,以便您可以轻松添加容量和带宽。这通常涉及使用动态路由协议或高级网络解决方案来轻松地为下游设备添加容量。
注意
从一开始就应该到位足够的监控和数据收集,以便能够及时做出关于容量、输入/输出指标 (IOPS) 或存储相关带宽的决策。
扩展对象存储¶
将后端存储容量添加到对象存储集群需要仔细的规划和预见。在设计阶段,重要的是确定对象存储服务所需的最大分区能力,这决定了可以存在的最大分区数。对象存储将数据分布到所有可用存储,但一个分区不能跨越一个磁盘,因此最大分区数只能与磁盘数一样多。
例如,从单个磁盘和分区能力为 3 的系统开始,可以有 8 (2^3) 个分区。添加第二个磁盘意味着每个磁盘都有 4 个分区。每个磁盘一个分区的限制意味着该系统永远不能拥有超过 8 个磁盘,从而限制了其可扩展性。但是,从单个磁盘和分区能力为 10 的系统开始,最多可以有 1024 (2^10) 个磁盘。
随着您向系统添加后端存储容量,分区映射会在存储节点之间重新分配数据。在某些情况下,这涉及复制非常大的数据集。在这些情况下,我们建议使用不与租户访问数据竞争的后端复制链路。
随着越来越多的租户开始访问集群中的数据,并且他们的数据集不断增长,需要添加前端带宽来服务数据访问请求。向对象存储集群添加前端带宽需要仔细规划和设计租户用来访问数据的对象存储代理,以及实现代理层轻松扩展的高可用性解决方案。我们建议设计一个前端负载均衡层,租户和消费者可以使用该层来访问集群中存储的数据。该负载均衡层可以分布在区域、区域甚至地理边界上,这可能还需要设计包含地理位置解决方案。
在某些情况下,您必须向服务于代理服务器和存储节点之间请求的网络资源添加带宽和容量。因此,用于访问存储节点和代理服务器的网络架构应采用可扩展的设计。
冗余¶
在使 swift 更加冗余时,一种方法是添加额外的代理服务器和负载均衡。HAProxy 是提供负载均衡和高可用性的方法之一,通常与 keepalived 或 pacemaker 结合使用,以确保 HAProxy 服务维护稳定的 VIP。可以在 OpenStack HA 指南 中找到示例 HAProxy 配置。
复制¶
对象存储中的副本独立运行,并且客户端只需要大多数节点响应请求才能认为操作成功。因此,瞬态故障(如网络分区)会迅速导致副本发散。修复这些差异最终由异步的、对等复制器进程协调。复制器进程遍历它们本地的文件系统,同时执行操作,从而在物理磁盘上平衡负载。
复制使用推送模型,记录和文件通常仅从本地复制到远程副本。这很重要,因为节点上的数据可能不属于那里(如在交接和环变更的情况下),并且复制器无法知道集群中其他地方存在哪些数据应该拉取。任何包含数据的节点都有责任确保数据到达其应有的位置。副本放置由环处理。
系统中的每个删除的记录或文件都通过墓碑标记,以便可以与创建一起复制删除。复制过程在称为一致性窗口的时间段后清理墓碑。一致性窗口包括复制持续时间和瞬态故障可以使节点从集群中删除的时间长度。墓碑清理必须与复制相关联才能达到副本收敛。
如果复制器检测到远程驱动器已失败,则复制器使用环的 get_more_nodes 接口来选择要与之同步的替代节点。复制器可以在磁盘故障的情况下保持所需的副本级别,尽管某些副本可能不在立即可用的位置。
注意
复制器不会在发生其他故障(如整个节点故障)时保持所需的副本级别,因为大多数故障是瞬态的。
复制是一个积极开发中的领域,实现细节可能会随着时间的推移而变化。
有两种主要的复制器:db 复制器,它复制帐户和容器,以及对象复制器,它复制对象数据。
有关更多信息,请参阅 Swift 复制页面。