Cinder 深度解析:OpenStack 块存储服务原理与实践
定位与职责
Cinder 是 OpenStack 的块存储服务,提供持久化的块设备(云硬盘):
- 创建、删除、扩容云硬盘(Volume)
- 挂载/卸载到虚拟机
- 快照(Snapshot)与备份(Backup)
- 从快照/镜像创建卷
- 卷类型(Volume Type)与 QoS 策略
Cinder 只管理块设备的生命周期,不关心文件系统,格式化是 VM 内部的事。
架构总览
1 2 3 4 5 6 7 8 9 10 11 12
| cinder-api ← REST API 入口 │ RPC ▼ cinder-scheduler ← 选择存储后端(FilterScheduler) │ RPC ▼ cinder-volume ← 实际操作存储后端 │ ├── LVM Driver → 本地 LVM 逻辑卷 ├── Ceph RBD Driver → Ceph 分布式存储 ├── NFS Driver → NFS 共享存储 └── 第三方 Driver → NetApp/EMC/Pure Storage 等
|
进程职责
| 进程 |
职责 |
| cinder-api |
接收 HTTP 请求,写入数据库,发送 RPC 消息 |
| cinder-scheduler |
根据卷类型和后端能力选择合适的 cinder-volume |
| cinder-volume |
调用存储驱动执行实际操作 |
| cinder-backup |
卷备份到对象存储(Swift/S3/Ceph) |
卷驱动体系
驱动接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
class VolumeDriver: """所有存储驱动的基类"""
def create_volume(self, volume): """创建卷""" raise NotImplementedError
def delete_volume(self, volume): """删除卷""" raise NotImplementedError
def create_snapshot(self, snapshot): """创建快照""" raise NotImplementedError
def initialize_connection(self, volume, connector): """返回连接信息(iSCSI target/Ceph mon 地址等)""" raise NotImplementedError
def attach_volume(self, context, volume, instance_uuid, host_name, mountpoint): """挂载卷到实例""" raise NotImplementedError
|
LVM Driver(本地存储)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
class LVMVolumeDriver(VolumeDriver): def create_volume(self, volume): self.vg.create_volume(volume.name, volume.size, ...)
def initialize_connection(self, volume, connector): return { 'driver_volume_type': 'iscsi', 'data': { 'target_portal': '10.0.0.1:3260', 'target_iqn': 'iqn.2010-10.org.openstack:volume-xxx', 'target_lun': 1, } }
|
Ceph RBD 集成(生产主流方案)
Ceph 是 OpenStack 生产环境最常用的存储后端,Nova/Cinder/Glance 都可以对接 Ceph。
架构
1 2 3 4 5 6 7 8
| Nova compute 节点 │ librbd(直接访问,无需 iSCSI) ▼ Ceph RBD Pool ├── volumes/ ← Cinder 卷 ├── images/ ← Glance 镜像 ├── vms/ ← Nova 实例磁盘(ephemeral) └── backups/ ← Cinder 备份
|
Ceph RBD Driver 关键实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
class RBDDriver(VolumeDriver): def create_volume(self, volume): with RADOSClient(self) as client: rbd.RBD().create( client.ioctx, volume.name, volume.size * units.Gi, order=22, old_format=False, features=client.features, )
def initialize_connection(self, volume, connector): return { 'driver_volume_type': 'rbd', 'data': { 'name': f'{self.configuration.rbd_pool}/{volume.name}', 'hosts': self.configuration.rbd_ceph_conf, 'auth_username': self.configuration.rbd_user, 'auth_enabled': True, 'secret_type': 'ceph', 'secret_uuid': self.configuration.rbd_secret_uuid, } }
|
Ceph 对接配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| [DEFAULT] enabled_backends = ceph
[ceph] volume_driver = cinder.volume.drivers.rbd.RBDDriver rbd_pool = volumes rbd_ceph_conf = /etc/ceph/ceph.conf rbd_flatten_volume_from_snapshot = false rbd_max_clone_depth = 5 rbd_store_chunk_size = 4 rados_connect_timeout = -1 rbd_user = cinder rbd_secret_uuid = <libvirt-secret-uuid> volume_backend_name = ceph
|
快照机制
快照原理(COW)
1 2 3 4 5 6 7 8 9 10
| 原始卷(Volume) │ ▼ 创建快照(瞬间完成,COW) 快照(Snapshot)← 记录创建时刻的数据指针 │ ▼ 后续写入 原始卷继续写入新数据,快照保留旧数据的引用
从快照创建新卷: 快照 → clone → 新卷(Ceph 中是 COW clone,极快)
|
Ceph 快照链
1 2 3 4 5 6 7 8 9
| rbd snap ls volumes/volume-xxx
volumes/volume-xxx └── @snap-yyy └── volumes/volume-zzz (clone) └── @snap-aaa └── volumes/volume-bbb (clone)
|
注意:Ceph clone 深度过深会影响性能,rbd_max_clone_depth = 5 超过后会自动 flatten。
卷挂载流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Nova 请求挂载卷 │ ▼ nova-compute 调用 os-brick 库 │ ▼ os-brick 根据连接类型选择 connector ├── iSCSI Connector → iscsiadm 登录 target ├── RBD Connector → 映射 rbd 设备 └── NFS Connector → mount NFS 路径 │ ▼ 返回本地设备路径(/dev/sdb 或 /dev/rbd0) │ ▼ libvirt 将设备 attach 到 VM(热插拔)
|
卷类型与 QoS
卷类型(Volume Type)
1 2 3 4 5 6 7 8 9 10 11 12 13
| openstack volume type create ssd-high-iops \ --property volume_backend_name=ceph-ssd \ --property replication_enabled=True
openstack volume qos create high-iops-qos \ --consumer front-end \ --property read_iops_sec=10000 \ --property write_iops_sec=5000
openstack volume qos associate high-iops-qos ssd-high-iops
|
多后端调度
1 2 3 4 5 6 7 8 9 10 11 12 13
| [DEFAULT] enabled_backends = ceph-ssd,ceph-hdd,lvm-local
[ceph-ssd] volume_driver = cinder.volume.drivers.rbd.RBDDriver rbd_pool = ssd-volumes volume_backend_name = ceph-ssd
[ceph-hdd] volume_driver = cinder.volume.drivers.rbd.RBDDriver rbd_pool = hdd-volumes volume_backend_name = ceph-hdd
|
源码关键路径
1 2 3 4 5 6 7 8 9 10 11 12
| cinder/ ├── api/v3/ ├── volume/ │ ├── manager.py │ ├── driver.py │ └── drivers/ │ ├── rbd.py │ ├── lvm.py │ └── nfs.py ├── scheduler/ ├── backup/ └── db/
|
生产运维要点
卷状态异常处理
1 2 3 4 5 6 7 8
| openstack volume set --state available <volume-id>
openstack volume delete --force <volume-id>
cinder reset-state --state error <volume-id>
|
容量监控
1 2 3 4 5 6 7
| cinder get-pools --detail
openstack_cinder_volume_gb_total openstack_cinder_volume_gb_used openstack_cinder_pool_capacity_gb_free
|