文章目录
- OpenStack存储管理
-
- OpenStack存储概述
- 块存储服务Cinder
-
- 块存储服务Cinder
- Cinder在OpenStack中的定位
- Cinder作用
- Cinder与其他服务的交互关系
- Cinder架构
- Cinder架构说明
- Cinder架构部署:以SAN存储为例
- Cinder组件-API
- Cinder组件-Scheduler
- Cinder组件-Volume
- Cinder创建卷流程
- [Cinder创建卷流程-Cinder API](#Cinder创建卷流程-Cinder API)
- [Cinder创建卷流程-Cinder Scheduler](#Cinder创建卷流程-Cinder Scheduler)
- [Cinder创建卷流程-Cinder Volume](#Cinder创建卷流程-Cinder Volume)
- Cinder挂载卷流程
- Cinder主要操作
- 对象存储服务Swift
-
- 对象存储服务Swift
- Swift在OpenStack中的定位
- Swift在OpenStack中的作用
- Swift特点
- Swift与其他服务的交互关系
- Swift架构
- Swift数据模型
- Swift系统架构
- Swift组件
- Swift组件
- Swift组件
- [Swift API](#Swift API)
- Swift工作原理概述
- Swift关键技术
OpenStack存储管理
OpenStack存储概述
OpenStack存储类型
- Ephemeral Storage,临时存储
- 临时存储是指数据被虚拟机实例使用,虚拟机实例被关机、重启或删除,该实例中的所有数据信息会丢失
- 如果只部署了Nova服务,则默认分配给虚拟机的磁盘是临时的,当虚拟机终止后,存储空间也会被释放
- 默认情况下,临时存储以文件形式放置在计算节点的本地磁盘上
- Persistent Storage,持久存储
- 持久存储维护数据持续可用,保证数据安全性,持久化存储设备的生命周期独立于任何其他系统设备或资源,无论虚拟机实例是否终止
- 目前OpenStack的持久存储包括:块存储、对象存储和文件系统存储
!tip
临时磁盘来源:
计算节点的本地磁盘。
通过NFS挂载的外部存储(使用此方式创建临时磁盘时,可以在多个计算节点之间迁移虚拟机,因为虚拟机实例的根磁盘位于可被多个物理主机访问的共享存储上)。
OpenStack存储类型对比
| 用途 | 访问方式 | 访问客户端 | 管理服务 | 数据生命周期 | 存储设备容量 | 典型使用案例 | |
|---|---|---|---|---|---|---|---|
| 临时存储 | 运行操作系统和提供启动空间 | 通过文件系统访问 | 虚拟机 | Nova | 虚拟机终止 | 管理员配置的Flavor指定容量 | 虚拟机中第一块磁盘10 GB,第二块磁盘20 GB |
| 块存储 | 为虚拟机添加额外的持久化存储 | 块设备被分区、格式化后挂载访问(例如 /dev/vdc) | 虚拟机 | Cinder | 被用户删除 | 用户创建时指定 | 1 TB磁盘 |
| 对象存储 | 存储海量数据,包括虚拟机镜像 | REST API | 任何客户端 | Swift | 被用户删除 | 可用物理存储空间和数据副本数量 | 10 TB级数据集存储 |
| 共享文件系统存储 | 为虚拟机添加额外的持久化存储 | 共享文件系统存储被分区、格式化后挂载访问(例如 /dev/vdc) | 虚拟机 | Manila | 被用户删除 | •用户创建时指定•扩容时指定•用户配额指定•管理员指定容量 | NFS |
OpenStack持久存储简介
-
块存储(Cinder)
- 操作对象是磁盘,直接挂载到主机,一般用于主机的直接存储空间和数据库应用,DAS和SAN都可以提供块存储
-
对象存储(Swift)
- 操作对象是对象(object),一个对象名称就是一个域名地址,可以直接通过REST API的方式访问对象
-
文件存储(Manila)
- 操作对象是文件和文件夹,在存储系统上增加了文件系统,再通过NFS或CIFS协议进行访问
-
因Manila目前使用较少,本章节只重点介绍Cinder和Swift
块存储服务Cinder
块存储服务Cinder
- CINDER
- 提供块存储服务,为虚拟机实例提供持久化存储
- 调用不同存储接口驱动,将存储设备转化成块存储池,用户无需了解存储实际部署位置或设备类型
- 首次出现在OpenStack的"Folsom"版本中
- 依赖Keystone认证服务
Cinder在OpenStack中的定位

- Cinder
- Cinder是OpenStack 块存储服务,为Nova虚拟机、Ironic裸机、容器提供卷
- Cinder为后端不同的存储设备提供了统一的接口,不同的块设备服务厂商在Cinder中实现其驱动,使其可以被OpenStack整合管理
!tip
cinder的前身是nova中的nova-volume组件,后来才被单独提出来成为一个OpenStack组件,因此cinder的设计架构和nova十分相像,具体体现在它们各个子组件的功能基本都能对应。
Cinder作用
- Cinder在虚拟机与具体存储设备之间引入了一层"逻辑存储卷"的抽象,Cinder本身不是一种存储技术,并没有实现对块设备的实际管理和服务
- Cinder只是提供了一个中间的抽象层,为后端不同的存储技术,提供了统一的接口
- 不同的块设备服务厂商在Cinder中以驱动的形式实现上述接口与OpenStack进行整合
!tip
Cinder提供了一个中间的抽象层,为不同的存储技术,如DAS、NAS、SAN、对象存储及分布式文件系统等,提供了统一的接口。
Cinder与其他服务的交互关系
- CINDER
- Cinder依赖Keystone认证服务
- 通过Nova模块创建虚拟机实例,Cinder为虚拟机实例提供持久化块存储能力
- Cinder创建的卷备份支持存储到Swift
Cinder架构

!tip
Cinder Client封装Cinder提供的rest接口,以CLI形式供用户使用。
Cinder API对外提供rest API,对操作需求进行解析,对API进行路由寻找相应的处理方法。包含卷的增删改查(包括从源卷、镜像、快照创建)、快照增删改查、备份、volume type管理、挂载/卸载(Nova调用)等。
Cinder Scheduler负责收集backend上报的容量、能力信息,根据设定的算法完成卷到指定cinder-volume的调度。
Cinder Volume多节点部署,使用不同的配置文件、接入不同的backend设备,由各存储厂商插入driver代码与设备交互完成设备容量和能力信息收集、卷操作。
Cinder Backup实现将卷的数据备份到其他存储介质(目前SWIFT/Ceph/TSM提供了驱动)。
SQL DB提供存储卷、快照、备份、service等数据,支持MySQL、PG、MSSQL等SQL数据库。
Cinder架构说明

- 存储模块对外的服务接口,接收并转发外部请求到不同的cinder组件进行处理
- 调度选择合适的主机进行创卷等操作
- 执行卷、快照相关的业务,通过调用不同的driver管理不同的存储后端
!tip
Cinder默认使用LVM(Logical Volume Manager)作为后端存储(Backend Storage),而LVM通过在操作系统与物理存储资源之间引入逻辑卷(Logical Volume)的抽象来解决传统磁盘分区管理工具的问题。
LVM将众多不同的物理存储资源(物理卷、Physical Volume,如磁盘分区)组成卷组。LVM从卷组中创建一个逻辑卷,然后将ext3、ReiserFS等文件系统安装在这个逻辑卷上。
除了LVM,目前Cinder已经以驱动的形式支持众多存储技术或存储厂商的设备作为后端存储,如SAN(Storage Area Network)、Ceph、Sheepdog,以及EMC、华为等厂商的设备。
Cinder架构部署:以SAN存储为例

- Cinder-api,Cinder-Scheduler,Cinder-Volume可以选择部署到一个节点上,也可以分别部署
- API采用AA模式,HAproxy作为LB,分发请求到多个Cinder API
- Scheduler也采用AA模式,有rabbitmq以负载均衡模式向3个节点分发任务,并同时从rabbitmq收取Cinder volume上报的能力信息,调度时,scheduler通过在DB中预留资源从而保证数据一致性
- Cinder Volume也采用AA模式,同时上报同一个backend容量和能力信息,并同时接受请求进行处理
- RabbitMQ,支持主备或集群
- MySQL,支持主备或集群
Cinder组件-API
- Cinder API对外提供REST API,对操作需求进行解析,并调用处理方法:
- 卷create/delete/list/show
- 快照create/delete/list/show
- 卷attach/detach (Nova调用)
- 其他:
- Volume types
- Quotas
- Backups
Cinder组件-Scheduler
- Cinder scheduler负责收集后端上报的容量、能力信息,根据设定的算法完成卷到指定cinder-volume的调度
- Cinder scheduler通过过滤和权重,筛选出合适的后端:

!tip
根据后端的能力进行筛选:
Drivers定期报告后端的能力和状态。
管理员创建的卷类型(volume type )。
创建卷时,用户指定卷类型。
Cinder组件-Volume
- Cinder volume多节点部署,使用不同的配置文件、接入不同的后端设备,由各存储厂商插入Driver代码与设备交互,完成设备容量和能力信息收集、卷操作等

!tip
Cinder默认的后端驱动是LVM。
Cinder创建卷流程

!tip
创建卷类型的目的是为了筛选不同的后端存储,例如SSD、SATA、高性能、低性能等,通过创建不同的自定义卷类型,创建卷时自动筛选出合适的后端存储。
Cinder创建卷流程-Cinder API

- Cinder API
- 检查参数合法性(用户输入,权限,资源是否存在等)
- 准备创建的参数字典,预留和提交配额
- 在数据库中创建对应的数据记录
- 通过消息队列将请求和参数发送到Scheduler
Cinder创建卷流程-Cinder Scheduler

- Cinder Scheduler服务
- 提取接收到的请求参数
- 通过配置的filter和输入参数对后端进行过滤
- Availability_zone_filter
- Capacity_filter
- Capabilities_filter
- Affinity_filter(SameBackendFilter/DifferentBackendFilter)
- ......
- Weigher计算后端进行权重
- CapacityWeigher/AllocatedCapacityWeigher
- ChanceWeigher
- GoodnessWeigher
- ......
- 选取最优的Backend并通过消息队列将请求发送到指定的后端
!tip
和Nova Scheduler类似,Cinder Scheduler也是经过Filter筛选符合条件的后端,然后使用Weigher计算后端进行权重排序,最终选择出最合适的后端存储。
Cinder创建卷流程-Cinder Volume

- Cinder Volume服务
- 提取接收到的请求参数
- 调用对应的Driver在后端创建实际的卷
- 使用Driver返回的模型更新数据库中的记录
Cinder挂载卷流程

- 挂卷流程: 挂卷是通过Nova和Cinder的配合最终将远端的卷连接到虚拟机所在的Host节点上,并最终通过虚拟机管理程序映射到内部的虚拟机中
!tip
Nova调用Cinder API创建卷,传递主机的信息,如hostname,iSCSI initiator name,FC WWPNs。
Cinder API将该信息传递给Cinder Volume。
Cinder Volume通过创建卷时保存的host信息找到对应的Cinder Driver。
Cinder Driver通知存储允许该主机访问该卷,并返回该存储的连接信息(如iSCSI iqn,portal,FC Target WWPN,NFS path等)。
Nova调用针对于不同存储类型进行主机识别磁盘的代码( Cinder 提供了brick模块用于参考)实现识别磁盘或者文件设备。
Nova通知Cinder已经进行了挂载。
Nova将主机的设备信息传递给hypervisor来实现虚拟机挂载磁盘。
Cinder主要操作
| 功能分类 | 功能 | 功能分类 | 功能 |
|---|---|---|---|
| 卷操作 | create | 快照操作 | snapshot-create |
| delete | snapshot-delete | ||
| show | snapshot-list | ||
| rename | snapshot-rename | ||
| upload-to-image | snapshot-reset-state | ||
| extend | snapshot-show | ||
| force-delete | snapshot-metadata | ||
| list | snapshot-metadata-show | ||
| migrate | snapshot-metadata-update-all | ||
| reset-state | 备份操作 | backup-create | |
| rate-limits | backup-delete | ||
| retype | backup-list | ||
| set-bootable | backup-restore | ||
| manage | backup-show | ||
| unmanage | backup-export | ||
| metadata | backup-export |
- Cinder主要操作三个资源:
- Volume:块设备卷,提供创建,删除,扩容,挂载/卸载等功能
- Snapshot:针对于块设备卷的快照创建、删除、回滚等功能
- Backup:提供对块设备卷的备份,恢复能力
对象存储服务Swift
对象存储服务Swift
- SWIFT
- 提供高度可用、分布式、最终一致的对象存储服务
- 可以高效、安全且廉价地存储大量数据
- 非常适合存储需要弹性扩展的非结构化数据
- 首次出现在OpenStack的"Austin"版本中
- 为其他OpenStack服务提供对象存储服务
!tip
OpenStack Object Storage (swift) 用于冗余、可扩展的数据存储,使用标准化服务器集群来存储PB级的可访问数据。它是一种可长期检索和更新大量静态数据的存储系统。对象存储使用没有中央控制点的分布式架构,可提供更高的可扩展性、冗余性和持久性。对象被写入多个硬件设备,OpenStack软件负责确保整个集群的数据复制和完整性。存储集群通过添加新节点来水平扩展。如果一个节点发生故障,OpenStack会从其他活动节点复制其内容。因为OpenStack使用软件逻辑来确保跨不同设备的数据复制和分发。
对象存储是具有成本效益的横向扩展存储的理想选择。它提供了一个完全分布式的、API可访问的存储平台,可以直接集成到应用程序中或用于备份、归档和数据保留。
Swift在OpenStack中的定位

- Swift
- Swift是OpenStack对象存储服务,可以存储虚拟机实例创建所需的镜像
- Swift作为OpenStack持久存储之一,比较适合存放静态数据
!tip
Swift是OpenStack最初两大项目之一,由Rackspace于2010年贡献给OpenStack,并与Nova一起开启了OpenStack元年。
静态数据:是指长期不会更新或者一定时期内更新频率比较低的数据,如虚拟机的镜像、多媒体数据、备份文件等。
如果需要实时地更新数据,Cinder更为合适。
Swift在OpenStack中的作用

- Swift并不是文件系统或者实时的数据存储系统,它称为对象存储,用于永久类型的静态数据的长期存储,这些数据可以检索、调整,必要时进行更新
- 最适合存储的数据类型的例子是虚拟机镜像、图片存储、邮件存储和存档备份
- 因为没有中心单元或主控结点,Swift提供了更强的扩展性、冗余和持久性
!tip
Swift经常用于存储镜像或用于存储虚拟机实例卷的备份副本。
与其他OpenStack项目一样,Swift提供了RESTful API作为访问的入口,存储的每个对象都是一个RESTful资源,并且拥有一个唯一的URL。
我们既可以发送HTTP请求将一些数据作为一个对象传递给Swift,也可以从Swift中请求一个之前存储的对象。
Swift特点

!tip
极高的数据持久性
从理论上测算过,Swift在5个Zone、5×10个存储节点的环境下,数据复制份是为3,数据持久性的SLA能达到10个9。
完全对称的系统架构
"对称"意味着Swift中各节点可以完全对等,能极大地降低系统维护成本。
无限的可扩展性
这里的扩展性分两方面,一是数据存储容量无限可扩展;二是Swift性能(如QPS、吞吐量等)可线性提升。因为Swift是完全对称的架构,扩容只需简单地新增机器,系统会自动完成数据迁移等工作,使各存储节点重新达到平衡状态。
无单点故障
在互联网业务大规模应用的场景中,存储的单点一直是个难题。例如数据库,一般的HA方法只能做主从,并且"主"一般只有一个;还有一些其他开源存储系统的实现中,元数据信息的存储一直以来是个头痛的地方,一般只能单点存储,而这个单点很容易成为瓶颈,并且一旦这个点出现差异,往往能影响到整个集群。
Swift的元数据存储是完全均匀随机分布的,并且与对象文件存储一样,元数据也会存储多份。整个Swift集群中,也没有一个角色是单点的,并且在架构和设计上保证无单点业务是有效的。
Swift与其他服务的交互关系
- SWIFT
- Swift依赖Keystone认证服务
- Swift可以存储虚拟机实例创建所需的镜像
- Cinder创建的卷备份副本支持存储到Swift
Swift架构

!tip
如图所示,Swift从架构上可以划分为两个层次:访问层(Access Tier)与存储层(Storage Nodes)。
访问层主要包括两部分,即Proxy Node(代理服务节点)与Authentication(认证),分别负责RESTful请求与用户身份的认证。
在Proxy Node节点上运行着Proxy Server,负责处理用户的RESTful请求,在接收到用户请求时,需要对用户的身份进行认证,此时用户所提供的身份资料会被转发给认证服务进行处理。
Proxy Server可以使用Memcached(高性能的分布式内存对象缓存系统)进行数据和对象的缓存,减少数据库读取的次数,提高用户的访问速度。
Proxy Node在收到用户的访问请求时,会将其转发到相应的存储节点上。
存储层由一系列的物理存储节点组成,负责对象数据的存储。
存储层在物理上分为以下5个层次:
Region:地理上隔绝的区域,每个Swift系统默认至少有1个Region。
Zone:在每个Region的内部又划分了不同的Zone来实现硬件上的隔绝。可以简单地将其理解为一个Zone代表了一组独立的存储节点。
Storage Node:存储对象数据的物理节点。
Device:可以简单地理解为磁盘。
Partition:仅仅指在Device上的文件系统的目录,和我们通常所理解的硬盘分区是完全不同的概念。
Swift数据模型

- Swift存储对象的逻辑结构:Account/Container/Object(即帐户/容器/对象)
- 每层节点数均没有限制,可以任意扩展
!tip
如图所示,每个Storage Node上存储的对象在逻辑上又分为3个层次组成:Account、Container和Object。
需要注意的是:Container不能嵌套,不能包含下级的Container;对象由元数据和内容两部分组成,Swift要求一个对象必须存储在某个Container中,因此一个Account应该至少由一个Container来提供对象的存储。
与上述3层组织结构相对应,在Storage Node上运行以下3种服务:Account Server、Container Server和Object Server。(后续Swift组件详细介绍)
使用命令swift stat可以显示Swift中的帐户、容器和对象的信息。
Swift为帐户,容器和对象分别定义了Ring(环)将虚拟节点(分区)映射到一组物理存储设备上,包括Account Ring、Container Ring 、Object Ring。
Ring记录了存储对象与物理位置的映射关系,通过Zone、Device、Partition和Replica来维护映射信息。
Swift系统架构

!tip
存储位置有如下三种:
/account
帐户存储位置是唯一命名的存储区域,其中包含帐户本身的元数据(描述性信息)以及帐户中的容器列表。
请注意,在Swift中,帐户不是用户身份。当您听到帐户时,请考虑存储区域。
/account/container
容器存储位置是帐户内的用户定义的存储区域,其中包含容器本身和容器中的对象列表的元数据。
/account/container/object
对象存储位置存储了数据对象及其元数据的位置。
Swift组件
| Proxy Server | Authentication Server | Cache Server |
|---|---|---|
| 代理服务,对外提供对象服务 API,由于采用无状态的 REST 请求协议,可以进行横向扩展来均衡负载 | 认证服务,验证访问用户的身份信息,并获得一个对象访问令牌(Token),在一定的时间内会一直有效,验证访问令牌的有效性并缓存下来直至过期时间 | 缓存服务,缓存的内容包括对象服务令牌,账户和容器的存在信息,但不会缓存对象本身的数据;缓存服务采用Memcached集群,Swift会使用一致性散列算法来分配缓存地址 |
!tip
Proxy Server可以说是Swift的核心,运行着swift-proxy-server进程。它提供Swift API服务,负责Swift其余组件间的通信。对于每个客户端的请求,它在Ring中查询相应的Account、Container以及Object的位置,并且转发这些请求。
Swift组件
| Account Server | Container Server | Object Server |
|---|---|---|
| 帐户服务,提供帐户元数据和统计信息,并维护所含容器列表的服务,每个帐户的信息被存储在一个 SQLite 数据库中 | 容器服务,提供容器元数据和统计信息,并维护所含对象列表的服务,每个容器的信息也存储在一个 SQLite 数据库中 | 对象服务,提供对象元数据和内容服务,每个对象的内容会以文件的形式存储在文件系统中,元数据会作为文件属性来存储,建议采用支持扩展属性的XFS文件系统 |
Swift组件
| Auditor | Replicator | Updater |
|---|---|---|
| 审计服务,检查对象,容器和帐户的完整性,如果发现比特级的错误,文件将被隔离,并复制其他的副本以覆盖本地损坏的副本;其他类型的错误会被记录到日志中 | 复制服务,检测本地分区副本和远程副本是否一致,发现不一致时会采用推式(Push)更新远程副本,并且确保被标记删除的对象从文件系统中移除 | 更新服务,当对象由于高负载的原因而无法立即更新时,任务将会被序列化到在本地文件系统中进行排队,以便服务恢复后进行异步更新 |
!tip
Account Reaper:帐户清理服务,移除被标记为删除的帐户,删除其所包含的所有容器和对象。
Swift API
- Swift通过Proxy Server向外提供基于HTTP的REST服务接口,对帐户、容器和对象进行CRUD等操作
| 资源类型 | URL | GET | PUT | POST | DELETE | HEAD |
|---|---|---|---|---|---|---|
| 帐户 | /account/ | 获取容器列表 | - | - | - | 获取帐户元数据 |
| 容器 | /account/container | 获取对象列表 | 创建容器 | 更新容器元数据 | 删除容器 | 获取容器元数据 |
| 对象 | /account/container/object | 获取对象内容和元数据 | 创建、更新或复制对象 | 更新对象元数据 | 删除对象 | 获取对象元数据 |
!tip
CRUD:指在做计算处理时的增加(Create)、检索(Retrieve)、更新(Update)和删除(Delete)几个单词的首字母简写。
Swift API主要提供了以下功能:
存储对象,并没有限制对象的个数。单个对象的大小默认最大值为5 GB,这个最大值用户可以自行配置。
对于超过最大值的对象,可以通过大对象中间件进行上传和存储。
压缩对象。
删除对象,支持批量删除。
Swift工作原理概述
- Proxy Server负责处理用户的对象存取请求,Authentication(认证服务)负责对用户的身份进行认证,Proxy Server在接收到用户请求后,会把请求转发给存储节点上的Account Server、Container Server与Object Server进行具体的对象操作,而对象与其各个副本之间的数据一致性则由Auditor、Updater和Replicator来负责
Swift关键技术

- Swift是基于一致性哈希技术,通过计算将对象均匀分布到虚拟空间的虚拟节点上,在增加或删除节点时可大大减少需移动的数据量
- Swift放弃严格一致性,而采用最终一致性模型(Eventual Consistency),来达到高可用和无限水平扩展能力;如果数据出现了不一致,后台服务进程会在一定的时间窗口内通过检测和复制协议来完成数据同步,从而保证达到最终一致性
- Ring将虚拟节点(partition)均衡地映射到一组物理设备上,Swift中Ring使用zone来保证数据的物理隔离,每个partition的replica都确保放在不同的zone中
!tip
虚拟空间的大小通常采用2的n次幂,便于进行高效的移位操作;然后通过独特的数据结构Ring(环)再将虚拟节点映射到实际的物理存储设备上,完成寻址过程。