各位用OpenStack的朋友,尤其是自己搭过一套Yoga版本环境的,应该都体会过这种状态:Nova、Neutron都折腾通了,虚拟机也能起来了,结果一到Cinder就卡壳。建卷、挂卷、分离卷、删卷,看起来就是几个命令的事,但真正用起来,卷状态卡住、挂载后设备不出现、删卷删不掉这类问题一个接一个。这篇就是专门讲Cinder基本使用和这些高频坑的,按我自己的实操顺序来写,从环境准备到卷的完整生命周期,再到Yoga版本里容易踩的卷分离失败问题,一条线捋下来。
Cinder在OpenStack里的定位就是块存储服务,说直白点就是给虚拟机提供“云硬盘”。它跟你自己电脑上加一块物理硬盘是一个思路,但这块盘不在本地,而是由Cinder统一管理,通过iSCSI、NFS、RBD等协议把存储后端的能力抽象成Volume提供给Nova使用。这篇内容适合刚搭完OpenStack、正准备把存储用起来的读者,也适合已经在用Cinder但遇到各种状态异常的运维同学,我会把每一步为什么要这么做、底层发生了什么都说清楚,不搞那种“你照着敲就行”的流水账教程。
我在实际环境里用的是一套三节点的Yoga部署,控制节点跑cinder-api、cinder-scheduler,存储节点跑cinder-volume,后端用的LVM。下面所有的操作和现象,我都基于这套环境来讲,命令过了验证,可以直接抄。
1. 先把Cinder的几个概念和组件理清楚
1.1 Cinder到底在管什么
Cinder管的是Block Storage,也就是块存储。它和Swift、Manila最大的区别在于使用方式:块设备是不能直接通过HTTP协议访问的,它必须被“挂”到一台虚拟机上,然后像使用普通硬盘一样使用。这意味着Cinder非常依赖底层状态的一致性——这块卷到底被谁占了、后端存储上的逻辑卷映射关系对不对、连接信息有没有失效,任何一个环节不一致,都会表现成你看到的“卷状态不对”。
Cinder自身是一套完整的服务集群,核心组件有四个:
- cinder-api:对外提供OpenStack API入口,接收所有卷操作的HTTP请求,做权限校验和请求分发。
- cinder-scheduler:负责决定一块新卷应该创建在哪个存储后端上,类似Nova的scheduler。
- cinder-volume:直接跟存储后端打交道的组件,创建、删除、扩展、快照这些底层操作都由它执行。
- cinder-backup:提供卷备份能力,可以把卷备份到Swift、NFS等对象存储里。
除此之外,还有一个隐藏角色叫cinder-brick,它是嵌在cinder-volume和nova-compute里的代码库,负责实际执行“把后端的块设备映射到宿主机”的底层操作,比如LVM的lvcreate、iSCSI的target配置、RBD的map操作。很多人排障时觉得奇怪,为什么我一个卷操作会影响到宿主机上的多路径设备,原因就在这里。
1.2 卷的状态机,是你必须背下来的东西
Cinder的卷是有状态机的。所有异常问题,本质上都可以归结为“卷落到了某个状态,却没有按预期流转下去”。我这边把最常用的几个状态列出来:
| 状态 | 含义 | 常见卡住原因 |
|---|---|---|
| available | 卷已创建,未挂载到任何实例 | 正常状态 |
| creating | 正在创建中 | 后端无响应、镜像拉取失败 |
| in-use | 已挂载给某台实例 | 正常状态 |
| attaching | 正在挂载中 | Nova与Cinder通信异常、底层连接超时 |
| detaching | 正在分离中 | Yoga版常见bug,后面会细讲 |
| error | 创建或操作失败 | 后端存储满、驱动报错 |
| error_deleting | 删除失败 | LVM逻辑卷仍被占用 |
一个从创建到挂载的完整流转是:
code复制creating → available → attaching → in-use
从实例卸载卷的流转是:
code复制in-use → detaching → available
我遇到的所有Cinder使用疑难杂症,几乎都是卡在这两条链路中间。理解状态机是排障的第一步。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 正式操作前,环境准备和命令工具
2.1 认证环境变量是第一步
Cinder的所有操作都走OpenStack API认证,在那之前必须先加载你的租户环境变量。我平时用的admin用户文件叫admin-openrc,内容大概是这样:
bash复制export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=admin
export OS_TENANT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=你的密码
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
加载方式和验证:
bash复制source /root/admin-openrc
openstack volume list
如果返回的是空列表而不是报认证错误,说明认证已经通了。我个人建议每次新开终端都先做这个检查,不要直接敲volume create,因为认证失败时的报错信息有时候会误导你往网络方向排查。
2.2 一个容易踩的坑:不同OpenStack客户端的命令歧义
这里必须提醒一下,操作Cinder有两种命令工具:一种是老牌的cinder命令(python-cinderclient),另一种是统一的openstack命令(python-openstackclient)。两者功能大部分重叠,但参数和输出格式有差异。在Yoga版本里,我强烈建议你统一用openstack volume *这一套,新环境默认都只带这个,cinder命令基本已经变成兼容层了。
实际上,很多时候你从网上搜到的旧教程还是cinder create --display-name xxx这种老语法,拿到Yoga环境里直接会报参数错误。这也是很多人刚上手时觉得“明明按教程敲的,怎么跑不起来”的原因。
2.3 没有 dashboard 时,怎么快速确认环境
如果在纯命令行环境,我一般用这组命令来快速探知Cinder的现状:
bash复制openstack volume service list
openstack volume type list
openstack volume list
openstack volume service list是最容易忽略但最有用的一个命令,它会显示所有cinder服务组件的运行状态和最近一次心跳时间。如果某个服务显示down,后面所有卷操作都可能异常。
volume type list是看当前有哪些卷类型。如果没有创建过任何卷类型,这里会返回空。先记住这点,后面讲多后端时会详细用。
3. Cinder核心操作全流程实录
3.1 创建卷:从命令到后端的完整过程
创建卷的命令很简单,但背后发生的事情值得了解。
bash复制openstack volume create --size 10 --name data-volume-01
这行命令的意思是创建一个10GB、名字叫data-volume-01的卷。输出里你会看到id、size、status等字段,status一开始会是creating,过几秒变成available。
创建成功后,我用这几个命令确认它的实际信息:
bash复制openstack volume show data-volume-01
openstack volume list
show能看到这个卷的完整属性,包括挂在哪个实例上、后端是谁、有没有快照属性。list只看概要。
实际操作中,我注意到不少新手会忽略--availability-zone参数。这个参数指定卷创建在哪个可用域,如果环境是多AZ部署的,而你没有指定,cinder-scheduler会按默认策略找可用后端。如果后续裸机或者虚机调度时发现卷和你实例不在同一个AZ,会有额外的跨AZ流量开销。实际测试环境里一般就一个AZ,不用纠结。
创建时,cinder-api会先做项目配额校验,然后是cinder-scheduler挑选后端,最终由cinder-volume执行真正的LVM创建操作。整个链路任何一个环节出问题,你看到的都是status一直停在creating。排查的时候不要只盯着控制端,要去cinder-volume日志里看后端的实际操作结果。
3.2 挂载卷到虚拟机
卷创建好之后,最重要的动作就是挂载到实例上。命令:
bash复制openstack server add volume 实例名或ID 卷名或ID --device /dev/vdb
这里--device参数可以指定设备名,不指定的情况下,系统会自动分配一个可用的设备名。我建议显式指定,方便后面在实例内部查找对应设备。
执行完命令后,卷状态会从available变成attaching,然后变成in-use。这个过程依赖于Nova和Cinder的配合,具体流程是:Nova收到挂载请求后,调用cinder的接口拿到卷的连接信息(比如LVM的iSCSI target),然后通过os-brick库在计算节点完成iSCSI连接,最后把设备附加给虚拟机。
等状态变成in-use后,进入虚拟机内部:
bash复制ssh root@虚拟机IP
lsblk
正常可以看到一个vdb设备(或sdb,取决于虚拟机和驱动)。然后就是格式化、挂载:
bash复制mkfs.ext4 /dev/vdb
mkdir -p /data
mount /dev/vdb /data
df -h | grep data
这里有个很重要的点:如果虚拟机内部看不到新设备,不要急着反复敲命令。先看Nova侧的状态,再看计算节点的块设备情况。
计算节点上执行:
bash复制lsblk | grep -i volume
如果计算节点能看到类似vg_cinder-volumes-lv_name的LVM逻辑卷,说明底层连接已经建立。问题通常出在虚拟机内部的virtio驱动或者设备热插拔时序上。这时候重启实例是最快的验证方式,重启后设备大概率会出现。
3.3 云硬盘的扩容操作
卷创建后默认是固定大小。如果你的数据增长了,需要扩展卷容量,Cinder支持在线扩容和离线扩容两种方式。
先看一下当前卷大小:
bash复制openstack volume show data-volume-01
然后执行扩容:
bash复制openstack volume extend data-volume-01 20
如果卷处于available状态,扩容操作会在几秒钟内完成。如果卷处于in-use状态(已经挂载给虚拟机),Cinder会尝试在线扩容,这取决于后端和底层驱动的支持情况。LVM后端情况下,in-use扩容需要底层LVM的lvresize和文件系统的配合,有时会有问题,所以我在生产环境里习惯先分离卷再扩容,扩容完成后再挂回去。
卷扩容完成后,虚拟机内部的文件系统也需要扩展。这一步很多人会漏掉,结果卷显示20GB,但虚拟机里还是认成10GB。
bash复制# ext4文件系统
resize2fs /dev/vdb
# xfs文件系统
xfs_growfs /data
3.4 分离卷和删除卷,顺序不能乱
分离卷的命令是:
bash复制openstack server remove volume 实例名或ID 卷名或ID
执行完后,卷状态会从in-use回到available。这个步骤依赖Nova先断开虚拟机与卷的关联,再通知Cinder解除底层连接。
我在实际使用中总结了三条经验:
第一,一定先在虚拟机内部umount文件系统,再做卷分离。如果不umount直接分离,数据可能还没完全落盘,极端情况下文件系统会损坏。
第二,删除卷之前先确认没有挂载在实例上。如果一个in-use状态的卷你执行delete,Cinder会返回错误信息阻止删除,这是保护机制。
第三,分离操作若长时间卡在detaching状态,不要反复执行remove volume命令,要先排查状态不流转的原因,后面会有专门一节讲这个。
真正删除卷:
bash复制openstack volume delete data-volume-01
delete操作执行后,卷会进入deleting状态,很快消失。如果长时间处于deleting或直接变成error_deleting,说明底层LVM清理失败了,常见原因是逻辑卷仍被某台计算节点占用。
3.5 快照与从快照创建卷
快照是Cinder最重要的数据保护手段之一。创建快照:
bash复制openstack volume snapshot create --volume data-volume-01 --name data-volume-01-snap-01
快照创建后,可以对快照做列表查询:
bash复制openstack volume snapshot list
从快照创建一个新卷,用于数据恢复或克隆一个同样的盘:
bash复制openstack volume create --size 10 --snapshot data-volume-01-snap-01 --name data-volume-01-restore
如果快照里的数据分区比新卷小,新卷创建后就可以直接把分区挂载出来。
快照有个概念必须说清楚:Cinder创建快照时,底层驱动通常用的是写时复制机制,也就是说快照刚创建时非常快,几乎不占额外空间,仅是原数据和快照共享存储块。一旦原卷上的数据发生修改,就会产生新的存储块,快照里记录的还是旧数据。这也是为什么LVM后端的快照如果长期不删除,存储池会逐渐被耗尽。
提示:不要拿快照当备份来用,快照只是某一个时间点的数据状态,它依赖原始卷仍然存在。如果原卷被删了,快照数据也会丢失。要长期保存数据,应该用cinder-backup把卷备份到存储后端。
4. 卷类型和多后端配置:基础使用里最容易被忽略的能力
4.1 卷类型是Cinder资源调度的关键
很多新手在基础使用时完全不会碰卷类型,因为默认创建卷时如果不指定类型,Cinder会用默认的配置,看起来也没问题。但一旦你有多种存储后端(比如一部分用SSD,一部分用HDD),卷类型就成了唯一的路由依据。
我举个例子。假设环境里有两类后端:
bash复制openstack volume type create ssd
openstack volume type create hdd
然后给类型打上后端属性标签:
bash复制openstack volume type set ssd --property volume_backend_name=LVM_SSD
openstack volume type set hdd --property volume_backend_name=LVM_HDD
创建卷时指定类型:
bash复制openstack volume create --type ssd --size 50 --name fast-vol
openstack volume create --type hdd --size 200 --name slow-vol
这样cinder-scheduler就会根据volume_type和后端的volume_backend_name做匹配,把不同的卷调度到不同后端去。
实际上,多后端配置的核心在于cinder.conf中的enabled_backends参数。我这边贴一段实际配置片段:
ini复制[DEFAULT]
enabled_backends = lvm-ssd,lvm-hdd
[lvm-ssd]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = LVM_SSD
volume_group = cinder-volumes-ssd
target_protocol = iscsi
target_helper = tgtadm
[lvm-hdd]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = LVM_HDD
volume_group = cinder-volumes-hdd
target_protocol = iscsi
target_helper = tgtadm
这里给列一下配置参数的含义:
| 参数 | 作用 |
|---|---|
| enabled_backends | 控制本节点启动哪些后端服务 |
| volume_driver | 指定驱动类型,LVM、RBD、NFS各不相同 |
| volume_group | LVM的卷组名,必须预先创建好 |
| target_helper | iSCSI target的辅助工具 |
| target_protocol | 传输协议,iSCSI或FC等 |
修改配置后需要重启cinder-volume服务,然后用openstack volume service list验证新的后端是否注册成功。
4.2 卷QoS设置
卷类型除了可以绑定后端,还可以绑定QoS规格,限制卷的最大IOPS和带宽。这个在我们真实环境里用于给不同用户提供差异化性能保障。
创建QoS并绑定到卷类型:
bash复制openstack volume qos create --consumer front-end qos-ssd
openstack volume qos set qos-ssd --property max_iops=5000 --property max_bw=500
openstack volume type set ssd --qos qos-ssd
设置完成后,创建该类型的卷会直接继承QoS策略,后端的限速规则会在驱动层生效。LVM后端对QoS的支持比较弱,生产环境中如果要精细控制性能,一般会用Ceph RBD作为后端,RBD在QoS上的控制能力更强。这一点对于要上规模的人提前了解很有价值。
5. Yoga版本卷分离失败:一个真实存在的坑
5.1 问题现象和影响范围
如果你用的是OpenStack Yoga版本,尤其是早期维护版本,在批量操作或者高负载场景下,很容易遇到卷分离失败的问题。我自己的环境里出现过好几次,最典型的场景是这样的:
执行openstack server remove volume后,卷状态一直卡在detaching,或者显示available但实际后端连接还没断开。这时候再把这个卷挂载给另一台实例,会报错,提示卷仍被占用。有时候还会出现实例删除后,卷无法自动分离,导致卷状态一直是in-use,但实例已经不存在了。
这个问题的根源我定位过多次,它不是一个单一原因。在Yoga版本中,Nova侧调用Cinder的os-detach接口时,如果和cinder-volume侧的连接状态清理不同步,os-brick尝试清理计算节点上的iSCSI设备时可能失败,导致Cinder认为卷还在使用中。尤其是后端是LVM加iSCSI的组合时,计算节点残留的SCSI设备或multipath映射没有清理干净,状态就会卡住。
5.2 排查路径
遇到这种问题,我建议按下面的顺序排查:
第一步,确认卷的真实状态。
bash复制openstack volume show 卷名或ID
看os-vol-host-attr:host、attachments等字段,确认卷当前被哪个计算节点和实例引用。
第二步,检查计算节点上的实际连接状态。
到nova-compute节点上执行:
bash复制lsblk
iscsiadm -m session
查看有没有残留的SCSI设备。
第三步,查cinder-volume和nova-compute日志。
cinder-volume的日志在/var/log/cinder/volume.log,nova-compute的日志在/var/log/nova/nova-compute.log。重点找分离操作相关的错误信息,比如TGTD或iscsiadm报的timeout。
5.3 处理方案
如果确认是卷分离失败且实例已经不存在,或者实例还在但底层连接已经断开。有一个兜底方案可以做——强制重置卷状态:
bash复制openstack volume set --state available 卷名或ID
这个命令会把卷状态硬改回available。但它有个重要风险:如果底层连接并没有真正断开,强制改状态会导致两块实例同时使用一个卷,数据一致性会出问题。所以千万不要一上来就执行这个,要先用前面提到的步骤确认底层连接已断开,再重置状态。
另外还有一个办法是重启nova-compute服务,有时候只是os-brick的连接清理没有完成,重启后残留连接会被重新梳理。
如果这个问题反复出现,我有三点建议:
- 升级到Yoga的后期维护版本。早期Yoga版本里的bug很多在后续维护版中已经修复,这一点经常被忽略,很多人把环境装好就一直不打补丁。
- 升级os-brick到最新稳定版。os-brick负责底层连接管理,很多分离失败问题实际上出在这里。
- 改变操作顺序。删除实例前先手动把卷分离出来,而不是靠nova的自动分离逻辑。这一步在运行关键业务的卷上很重要。
我在自己的环境里选了升级维护包+改操作顺序的组合,之后这类问题就很少出现了。
6. 基础使用中的其他高频问题与排查速查
做Cinder使用运维,有一类问题出现的概率简直可以排进前三:创建卷卡在creating状态。这个状态卡住后,无论你等多久都不会自动恢复。我的排查路径是从cinder-api日志看请求有没有分发到cinder-scheduler,然后从cinder-volume日志看实际创建有没有收到请求。如果两者日志里连请求都看不到,问题多半在消息队列或cinder-api本身;如果cinder-volume收到了但创建失败,问题在后端。
另一类问题是虚拟机内部看不到挂载好的卷设备。这种情况不用急着重装系统,我先确认Nova侧attach动作是否完成,再登录计算节点查LVM状态,最后才看虚拟机内部驱动。很多时候是设备名被覆盖或者virtio驱动加载慢,重启实例就能解决。
我还碰到过删除卷时报error_deleting,出现这种情况一般是LVM的逻辑卷被占用了。可以用下面的命令检查:
bash复制lvs
如果逻辑卷状态显示为open,说明有进程在访问。在计算节点上执行iscsiadm -m session,确认没有连接后手动清理:
bash复制iscsiadm -m node -u
iscsiadm -m node -o delete
清理完后回到控制节点重新尝试删除卷。
把我在实际中遇到的问题整理成一个速查表,方便大家对照:
| 问题现象 | 可能原因 | 排查命令 | 处理建议 |
|---|---|---|---|
| 卷长期creating | 后端无响应/LVM卷组空间不足 | openstack volume show、vgs |
查看cinder-volume日志定位失败原因 |
| 创建卷报错OverLimit | 项目配额不足 | openstack quota show |
调整配额或删除无用卷 |
| 卷挂载后实例内看不到设备 | 设备名冲突或驱动未加载 | openstack server show、计算节点lsblk |
重启实例或手工attach |
| 删除卷报error_deleting | LVM逻辑卷被占用 | lvs、iscsiadm -m session |
先清理计算节点残留连接 |
| 卷分离后状态仍in-use | os-brick清理失败 | openstack volume show、nova日志 |
确认底层断开后重置状态 |
| 卷扩容后内部不识别 | 文件系统未扩展 | df -h |
执行resize2fs或xfs_growfs |
| 快照创建失败 | 后端LVM快照空间不足 | vgs、lvs |
释放空间或更换后端 |
整体用下来,我对Cinder最深的感受是:它本身的架构并不复杂,真正复杂的是状态流转和底层存储驱动之间的协作。基础使用操作命令就那么几个,你完全可以在短时间内跑通,但如果你想在真实环境里稳定使用,一定要花时间理解状态机和底层连接的原理。特别是Yoga版本这一批部署,建议把补丁更新到最新维护版,操作上尽量保持明确顺序,这比任何排障技巧都管用。
最后再分享一个小技巧:每次做Cinder操作时,养成及时记录卷ID和状态流转的习惯。尤其是关键操作前后,用openstack volume show留个快照信息,出问题的时候你会感谢自己当时的这个习惯。
