当前位置: 首页 > news >正文

OpenStack Cinder 创建卷

Cinder 的卷创建(create volume)是块存储服务的核心操作,涉及从请求接收、调度决策到存储后端实际创建的完整流程。

1、流程概览

创建卷的完整流程涉及 Cinder 多个组件的协同工作,整体流程如下:

客户端 → cinder-api → 消息队列 → cinder-scheduler → 消息队列 → cinder-volume → 存储后端↓                    ↓数据库                数据库(更新状态)
  1. 客户端发起请求:通过 CLI、Dashboard 或 API 调用创建卷。
  2. API 服务处理:验证请求、解析参数、初始化卷元数据。
  3. 调度器选择后端:基于过滤和权重策略选择最优存储节点 / 后端。
  4. 卷服务执行操作:调用存储后端驱动创建实际卷,并更新状态。
  5. 返回结果:将卷状态(如 available)返回给客户端。

2、源码分析

2.1 客户端请求发起

客户端通过 OpenStack API 发起卷创建请求,示例 CLI 命令:


openstack volume create --size 10 --type lvm-type my-volume

该命令会向 cinder-api 发送 HTTP POST 请求(默认端点:http://<controller>:8776/v3/<project-id>/volumes)。

2.2 API 服务处理(cinder-api)

cinder-api 负责接收并验证请求cinder/api/v3/volumes.py关键逻辑

  1. 验证请求合法性(权限、配额、参数格式)。
  2. 生成卷元数据并保存到数据库(初始状态 creating)。
  3. 通过 volume_api.create_volume 向消息队列发送异步任务。
# cinder/api/v3/volumes.py
class VolumeController(wsgi.Controller):@wsgi.response(202)@validation.schema(volumes_schema.create)def create(self, req, body):"""处理卷创建请求"""context = req.environ['cinder.context']volume_data = body['volume']# 1. 参数解析与验证size = volume_data.get('size')  # 卷大小(GB)volume_type = volume_data.get('volume_type')  # 卷类型(关联存储后端)availability_zone = volume_data.get('availability_zone')  # 可用区# 验证权限、配额(如是否允许创建10GB卷)self._check_volume_quota(context, size)# 2. 初始化卷元数据volume = {'size': size,'status': 'creating',  # 初始状态为创建中'volume_type_id': self._get_volume_type_id(volume_type),'availability_zone': availability_zone,# 其他元数据:名称、描述、项目ID等}# 3. 保存初始状态到数据库volume_ref = objects.Volume(context=context, **volume)volume_ref.create()  # 调用ORM保存到数据库# 4. 发送创建任务到消息队列,由scheduler或volume服务处理self.volume_api.create_volume(context,volume_ref,filter_properties=self._get_filter_properties(req, volume_data))# 5. 返回卷信息(状态为creating)return self._view_builder.detail(req, volume_ref)

2.3 调度器选择存储后端(cinder-scheduler)

cinder-scheduler 从消息队列接收任务,选择最优存储后端, cinder/scheduler/filter_scheduler.py

# cinder/scheduler/filter_scheduler.py
class FilterScheduler(scheduler.Scheduler):def schedule_create_volume(self, context, request_spec, filter_properties):"""选择存储后端创建卷"""# 1. 获取候选存储后端hosts = self.host_manager.get_all_host_states(context)# 2. 过滤后端(排除不符合条件的存储节点)filtered_hosts = self.host_manager.filter_hosts(hosts, request_spec, filter_properties)if not filtered_hosts:raise exception.NoValidHost(reason="No suitable storage backend found")# 3. 计算权重并排序(选择最优后端)weighed_hosts = self.host_manager.weigh_hosts(filtered_hosts, request_spec, filter_properties)best_host = weighed_hosts[0]  # 得分最高的后端# 4. 向目标存储节点的cinder-volume发送创建请求self._schedule_create_volume(context, best_host, request_spec)
2.3.1 过滤阶段(Filters)
  • CapacityFilter(cinder/scheduler/filters/capacity_filter.py):检查后端可用容量是否满足卷大小。
class CapacityFilter(filters.BaseHostFilter):def host_passes(self, host_state, filter_properties):# 所需容量 = 卷大小 + 预留空间required = filter_properties['request_spec']['volume_size']# 可用容量 = 总容量 - 已用容量 - 预留容量available = host_state.free_capacity_gb - host_state.reserved_percentagereturn available >= required
  • AvailabilityZoneFilter(cinder/scheduler/filters/availability_zone_filter.py):过滤不在指定可用区的后端。
  • CapabilitiesFilter(cinder/scheduler/filters/capabilities_filter.py):检查后端是否支持卷类型要求的特性(如 thin_provisioning)
2.3.2 权重阶段(Weighters)

默认启用 CapacityWeigher(cinder/scheduler/weights/capacity.py),优先选择可用容量多的后端

class CapacityWeigher(weights.BaseWeigher):def weigh(self, host_state, weight_properties):# 可用容量越高,权重越大return host_state.free_capacity_gb * self.weight_multiplier

2.4 卷服务执行创建操作(cinder-volume)

目标存储节点的 cinder-volume 服务从消息队列接收任务,调用存储后端驱动创建卷,cinder/volume/manager.py

# cinder/volume/manager.py
class VolumeManager(manager.SchedulerDependentManager):def create_volume(self, context, volume, host):"""执行卷创建操作"""# 1. 锁定卷(避免并发操作)volume = self._get_volume_and_lock(context, volume['id'])try:# 2. 调用存储后端驱动创建卷driver = self.driver  # 如LVM驱动、Ceph驱动# 驱动创建卷(返回卷在后端的路径/标识)provider_location = driver.create_volume(volume)# 3. 更新卷状态为可用(available)volume.update({'status': 'available','provider_location': provider_location,  # 存储后端中的卷标识})volume.save()except Exception as e:# 出错时更新状态为errorvolume.update({'status': 'error'})volume.save()raise exception.VolumeCreationFailed(reason=str(e))

2.5 存储后端驱动实现(以 LVM 为例)

LVM 驱动代码位于 cinder/volume/drivers/lvm.pycreate_volume 方法实际调用 LVM 命令创建逻辑卷:

# cinder/volume/drivers/lvm.py
class LVMVolumeDriver(volume_driver.VolumeDriver):def create_volume(self, volume):"""通过LVM创建卷"""# 卷大小(转换为MB)size_in_mb = volume['size'] * 1024# 卷名(通常为volume-<uuid>)volume_name = self._get_volume_name(volume)# 卷组名(从配置读取,如cinder-volumes)vg_name = self.configuration.lvm_volume_group# 执行lvcreate命令:创建指定大小的逻辑卷self._execute('lvcreate', '-L', f'{size_in_mb}M', '-n', volume_name, vg_name,run_as_root=True)# 返回卷路径(如/dev/cinder-volumes/volume-xxx)return f"/dev/{vg_name}/{volume_name}"

3、常用配置(cinder.conf)

3.1 核心配置([DEFAULT] 段)

[DEFAULT]
# 默认卷类型(未指定时使用)
default_volume_type = lvm-type# 卷大小限制(最小/最大GB)
min_volume_size = 1
max_volume_size = 10240# 并发创建卷的最大数量
volume_api_workers = 4  # 建议与CPU核心数一致# 消息队列配置(与其他组件通信)
transport_url = rabbit://openstack:password@controller:5672/

3.2 调度器配置([scheduler] 段)

[scheduler]
# 启用的过滤器(按执行顺序)
enabled_filters = CapacityFilter,AvailabilityZoneFilter,CapabilitiesFilter# 启用的权重器
enabled_weighters = CapacityWeigher# 容量权重乘数(值越大,可用容量影响越强)
capacity_weight_multiplier = 1.0# 调度器缓存过期时间(秒)
scheduler_cache_expiry = 60

3.3 存储后端配置(以 LVM 为例)

# 定义LVM存储后端
[lvm]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group = cinder-volumes  # LVM卷组名
target_protocol = iscsi  # 共享协议(iscsi或fc)
target_helper = tgtadm  # iSCSI目标管理工具
volume_backend_name = lvm-backend  # 后端名称(用于卷类型关联)# 可选:配置thin provisioning(瘦分配)
lvm_type = thin
thin_pool_name = cinder-thin-pool  # 瘦池名称

3.4 多后端部署

通过配置多个后端段(如 [lvm]、[ceph])支持混合存储,示例:

[DEFAULT]
enabled_backends = lvm,ceph[lvm]
# LVM后端配置...[ceph]
volume_driver = cinder.volume.drivers.rbd.RBDDriver
rbd_pool = volumes
rbd_ceph_conf = /etc/ceph/ceph.conf
volume_backend_name = ceph-backend

4、常见问题

日志位置

  • /var/log/cinder/api.log(API 层)
  • /var/log/cinder/scheduler.log(调度层)
  • /var/log/cinder/volume.log(卷服务层)。
    常见原因:
  • 存储后端容量不足(CapacityFilter 过滤)。
  • 卷类型与后端不匹配(CapabilitiesFilter 过滤)。
  • 驱动执行失败(如 LVM 卷组不存在)。
http://www.wxhsa.cn/company.asp?id=4817

相关文章:

  • 西电微机原理-第二章 Intel单核处理器
  • 二叉树的迭代遍历(非递归)
  • 记录---用好了 defineProps 才叫会用 Vue3,90% 的写法都错了
  • 今日流水账-2025年9月15日
  • c#给原文件重命名
  • tcpdump常用随笔
  • 2025年HR经理必备:10款高效人力资源管理软件推荐
  • GAS中GA变量数据的同步
  • 提升员工绩效的5大人才管理软件评测与分析
  • 【触想智能】工业显示屏与普通显示屏的八大区别以及应用领域分析
  • LLaVA- Improved Baselines with Visual Instruction Tuning - jack
  • 042-WEB 攻防:PHP 应用 MYSQL 架构 SQL 注入 跨库查询 文件读写 权限操作
  • Dsu On Tree 笔记
  • 西电微机原理-第一章 序论:微型计算机概述
  • Liunx 硬盘扩容
  • 船舶航向控制算法
  • pyside6 1
  • 基于WSL下载Hadoop和HBASE
  • 应用多、交付快,研发运维怎么管?看云效+SAE 如何一站式破局
  • revit二次开发之 钢筋功能详细分析
  • java-wxj02
  • 停止win10自动升级操作
  • vue3 - elementPlus
  • GAS_Aura-Target Data
  • windows 把恢复分区调整到 c 盘前面
  • wso2~对已发布api的元信息管理
  • 利用Myo臂环采集肌电信号和角速度来实现实时手势识别
  • 实用指南:leetcode 966. 元音拼写检查器 中等
  • 三轴传感开发新纪元:exvib扩展库让精准检测触手可及!
  • List与Dictionary区别