
1. 为什么要单独加一个存储节点先想清楚再动手先说个我遇到过的场景。某天值班群突然炸了提示某个计算节点的本地磁盘使用率已经到92%云主机在创建快照和做备份的时候明显变慢甚至有台实例因为磁盘IO等待直接把负载拉满了。翻了一圈监控才发现这个节点当初规划的时候就是“计算本地存储”一肩挑既跑nova-compute又挂cinder原生的LVM卷组结果业务一多存储最先扛不住。在OpenStack里给集群“增加一个存储节点”本质上做的不是装个软件而是把存储职责从计算节点里拆出来单独落地一套可以提供块存储Cinder或者对象存储Swift能力的后端。这个动作看着不复杂但实际上牵扯到控制节点的注册配置、网络连通性、存储后端的选型以及原有卷迁移或者新建卷走新路径的验证。如果前期规划不到位后面扩容的过程会在各种隐蔽的地方卡住。适合看这篇内容的人我默认分两种一种是集群已经跑了一段时间控制节点和计算节点都正常但存储确实见底了想加一台专门的存储节点来缓解压力另一种是刚接手一套OpenStack环境还没搞清楚这个集群“块存储是怎么做的”“卷到底存在哪”对加节点这事心里没底。两种情况我都会覆盖到。在做任何操作之前我得先泼一盆冷水OpenStack的存储节点不是把cinder-volume装上去就能用的。它需要和消息队列RabbitMQ、数据库通常是MySQL/MariaDB里的cinder库、认证服务Keystone全部打通。也就是说新节点像一个新员工入职不光要给它工位还得给它建邮箱、加企业微信、配权限。下面每一步我都会说清楚要配什么、为什么要配。2. 存储节点扩容前的现状梳理与后端选型逻辑2.1 先摸清楚你现有环境里存储是怎么部署的这是所有工作的起点。我对环境的判断有一个固定顺序按这个顺序排查一遍基本就能确定“新节点该怎么接”控制节点上/etc/cinder/cinder.conf里的enabled_backends字段是什么这决定了这个集群当前的块存储后端类型。常见的有lvm、ceph、nfs或者结合multi-backend配置的多个后端。计算节点的/etc/nova/nova.conf里[cinder]字段的catalog_info确认计算节点是通过哪个卷类型去调用Cinder的。是否启用了Swift对象存储。如果启用了那/etc/swift/下的配置以及rings目录里的分布情况也要搞清楚因为加Swift节点的话还需要重新构建ring并下发。各个节点的操作系统版本、内核版本、NTP时间是否同步。OpenStack节点之间对时间同步要求很高尤其是在做卷挂载、数据库交互时会话超时、消息队列消息过期这些奇怪问题很大概率都和时钟偏移有关。我之前接手过一个环境控制节点是CentOS 7.9计算节点是CentOS 7.6卷后端是LVM结果加了新存储节点后新节点上报给Cinder scheduler的容量一直为0。查了半天发现是系统版本低导致lvm2和device-mapper-multipath的版本和预期不一致卷组出现了缓存数据不同步。这种基础问题在排查阶段如果不做后面会浪费大量时间。2.2 块存储Cinder与对象存储Swift的取舍区间加存储节点之前必须得想明白加的到底是哪一种存储。这里有一个常见误区有人觉得把新节点的磁盘挂到计算节点上然后创建一个新的本地卷组再在cinder.conf里多加一个lvm后端就完事了。这不算错但只能算“缓解”而不是“扩容”。如果业务对持久化要求高、需要挂载给云主机当系统盘或数据盘那就应该走Cinder块存储路线。以一个业务系统举例业务方申请了一块500G的云硬盘挂到虚拟机里这块盘的最终归宿应该是某个存储节点上的LVM逻辑卷、Ceph的RBD块设备或者NFS导出的一个qcow2文件。如果新节点继续做LVM那就需要配置cinder用户对/dev设备的访问权限或使用tgtadm或者targetcli来暴露iSCSI Target计算节点再通过Open-iSCSI initiator去连接。如果是图片、备份文件、日志归档这类海量非结构化数据Swift更合适。Swift的存储节点有专门的swift-storage角色它通过swift-ring来决定数据放在哪台设备上加节点需要重建.builder文件并重新均衡这个过程比Cinder要繁琐但扩容后的扩展性会更好。还有一条路是直接把新节点做成一个NFS后端在节点上通过exports把一个大目录共享出来Cinder配置为NFS驱动。这种方案的优点是不用折腾iSCSI、不用碰LVM缺点是高可用和性能受限。我在小规模测试环境里用过NFS后端运维省心很多但生产环境我更偏向于LVM或者Ceph。2.3 容量规划的一个简单数学题假设当前集群有3个计算节点每个节点上有2T本地磁盘作为cinder卷组卷组使用率已经75%也就是还剩大约1.5T可用。新业务上来之后一个月内预计要新增云硬盘约3T加上快照占用的空间新增存储节点建议至少给到4T裸容量。注意这4T是裸容量你还需要考虑LVM的metadata空间一般会给卷组留1%左右的PE、文件系统预留空间ext4或xfs默认会预留一部分、以及未来快照增长。拿我自己的做法来算一块4T的裸盘可用空间我会按3.6T来预估剩余400G留给系统、元数据以及文件系统的预留空间。如果在计算节点和存储节点之间做网络规划我强烈建议存储网络单独用一个VLAN或者独立物理网卡/网段不要和控制节点、计算节点之间的管理网络混在一起。原因有两个一是iSCSI的数据流量通常很大和OpenStack内部API流量混在一起会互相挤压二是如果存储节点网卡故障导致iSCSI disconnect会影响所有挂载了该后端卷的虚拟机。就这一条我踩过好几次网卡负载过高导致iscsi会话超时的坑。3. 新存储节点的系统准备与基础环境配置3.1 操作系统、分区与文件系统的细化处理新存储节点我推荐使用和现有控制节点/计算节点同大版本的操作系统。比如现有环境是CentOS 7新节点就不要贪新去装CentOS 8 Stream或者Rocky 9否则后面在yum源、Python版本、systemd服务单元文件上都会遇到兼容性问题。OpenStack社区对跨版本混用的支持并不好尤其是PackStack安装的集群本身就默认绑定了一套版本组合。磁盘分区这块如果机器有独立的系统盘一般建议SSD容量不需要大128G以上即可系统、日志、临时文件都丢这里和数据盘机械盘或SSD取决于你业务的性能要求那分区就很简单系统盘按操作系统默认全部分给/数据盘留出来做后续的物理卷PV。这里有一个坑如果你的数据盘以前被用过上面有旧的分区表那你需要先清一遍。用blkid看一下是否有残留的UUID再用wipefs -a /dev/sdb这样的命令把文件系统签名擦掉。否则你在创建PV的时候会提示Device /dev/sdb excluded by a filter这是很常见的坑。时间同步必须要提前做好。OpenStack组件之间大量依赖消息队列和数据库如果新节点的时间偏差超过几十秒你会看到各种奇怪的认证失败、数据库连接超时。我一般会单独加上一个ntpdate的定时任务并同时用chronyd做主同步保证一旦某个同步源失效还有备份。3.2 安装基础依赖与OpenStack仓库的准备如果整个集群是基于PackStack安装的那么新存储节点最简单的接入方式是复用PackStack生成的answer.txt或者直接用packstack --install-hosts新节点IP把相关组件带起来。但实际生产运维中我很少在扩容时重新跑一遍PackStack因为那会把控制节点上现有配置推倒重来一遍风险太大。更稳妥的方式是手工在新节点上装依赖包和仓库。以Cinder的LVM后端为例需要安装的软件包大致是yum install -y centos-release-openstack-train yum update -y yum install -y openstack-cinder targetcli lvm2 device-mapper-multipath open-iscsi注意openstack-cinder这个包会把cinder-api、cinder-scheduler、cinder-volume全部装进去。但新存储节点往往只需要跑cinder-volume所以在安装后需要显式禁用cinder-api和cinder-scheduler的服务只保留cinder-volume否则这个节点会尝试接入消息队列去抢调度任务造成不可预知的后果。targetcli在新版本系统里已经流行起来但老的CentOS 7上有时还需要scsi-target-utils这种老牌包。建议查看现有计算节点/控制节点上cinder-volumes是怎么启动的后端驱动再决定装哪个。如果是lioadm驱动那就是targetcli如果是tgtadm驱动那就要装的是scsi-target-utils并启动tgtd服务。3.3 网络配置与防火墙的最小化放通存储节点上需要保证几个端口的连通管理网络与RabbitMQ的5672端口、MySQL的3306端口、Keystone的5000端口、Nova的8774端口等能通。iSCSI的3260端口默认是targetcli起服务时监听在3260需要确保计算节点能访问到新存储节点的3260。Swift如果也要在这台节点上跑那对象存储的6000account server和6001container server端口、以及代理节点访问的8080端口要放通。我遇到过一种情况防火墙本身放通了但是OpenStack安全组规则里拦了内部流量。这类问题排查起来很闹心建议先把firewalld直接停掉或者仅在network zone里放通内部网段然后等所有功能验证完毕后再根据实际抓包结果收紧规则。4. 块存储后端落库Cinder对接新节点的完整配置4.1 创建LVM卷组并配置tgt/iet的iSCSI Target在新存储节点上假设数据盘是/dev/sdb分一个整块物理卷然后建卷组pvcreate /dev/sdb vgcreate cinder-volumes /dev/sdb这里有一个隐患如果计算节点上nova-compute本地也用了LVM并且命名了cinder-volumes这个卷组那么新存储节点也要用同名卷组但两台机器没有关系。cinder-volume进程只在本机看到卷组然后通过iSCSI把逻辑卷暴露出去。如果新节点卷组名不是cinder-volumes那后续cinder配置里lvm_type和volume_group字段都要跟着改。接着开放iSCSI Target。以targetcli为例systemctl enable targetcli systemctl start targetcli然后创建后端的backstore指向卷组里的逻辑卷。但是这里我要提醒不要手动去targetcli里手工一个个加LUN。Cinder的LVM驱动会在创建卷时自动调用tgtadm或lioadm去创建target和LUN。你只需要保证cinder-volume用户有权限调用这些命令并且target相关服务已经在运行。4.2 修改cinder.confenabled_backends、LVM参数与volume_driver新节点的/etc/cinder/cinder.conf需要至少包含以下核心项[DEFAULT] transport_url rabbit://openstack:passwordcontroller-ip:5672/ enabled_backends lvm-1 [lvm-1] volume_backend_name LVM_iSCSI volume_driver cinder.volume.drivers.lvm.LVMVolumeDriver volume_group cinder-volumes target_protocol iscsi target_helper lioadm iscsi_helper lioadm这里最关键的是volume_backend_nameCinder scheduler在调度的时候根据volume_type的backend_name来匹配到底用哪一个后端。如果你现有集群里已经有一个LVM_iSCSI的backend name那新节点上也保持一致创建卷的时候两个节点都会参与调度如果想让新卷只往新节点上放需要定义一个不同的volume_backend_name并创建一个新的volume_type关联到它。target_helper的选择也很微妙。如果节点上安装的是targetcli那就是lioadm如果是老式的tgtadm那么iscsi_helper tgtadm。写错的话cinder-volume会在创建卷时报No valid iscsi target helper相关的错误。判断方法很简单执行rpm -qa | grep scsi-target-utils看有没有装老包。数据库里cinder的services表会通过这个新后端上报状态。如果你看到cinder-volume服务在openstack volume service list里已经出现但状态是down多半是数据库里没有对应写入或者消息队列认证失败。4.3 在控制节点上完成注册DB同步、服务启用与后端状态确认新存储节点的/etc/cinder/cinder.conf配置完成后第一件要做的事是初始化数据库。在新存储节点上执行cinder-manage db sync我建议先等这个命令顺利跑完再去启动cinder服务。这个命令会往cinder库里同步新后端相关的数据表如果不执行cinder-volume会一直处在“无法注册到数据库”的状态。然后启动服务并设置开机自启systemctl enable openstack-cinder-volume systemctl start openstack-cinder-volume回到控制节点上执行openstack volume service list正常情况下能看到一个新的cinder-volume条目Host名是新节点的hostnameZone是默认的nova。这个时候再检查一下新节点的容量是否被识别openstack volume service list --long以及查看所有主机上的容量openstack host list如果新节点的容量没有出现在列表里别急着调参数先看cinder-volume日志/var/log/cinder/cinder-volume.log里有没有报错。常见错误有两类一是Invalid volume backend说明enabled_backends里写的名称和配置块不一致二是Database schema is outdated说明cinder-manage db sync没有跑成功。我这里遇到过最隐蔽的一个问题控制节点上已有的cinder-api版本是Train版新节点装的是Ussuri版两个版本的cinder服务之间会存在消息格式不兼容。消息队列里大量报错新节点一直无法注册。后来把新节点的版本降到和控制节点一致才解决。所以新存储节点的OpenStack组件版本最好小版本也对齐不要差一个大版本。5. 卷创建链路测试验证新后端参与调度与挂载5.1 创建卷类型并绑定新后端如果新节点的volume_backend_name和现有后端一样那现有卷类型会自动覆盖到新节点。如果新节点定义了独立的后端名比如LVM_NEW_NODE那你需要在控制节点创建卷类型并指定后端openstack volume type create lvm_new openstack volume type set --property volume_backend_nameLVM_NEW_NODE lvm_new这一步很关键因为你不做这一步新节点虽然注册成功了但永远不会有人把卷调度到它上面。OpenStack的调度器会根据volume_type的属性去匹配后端的volume_backend_name两边对得上才会考虑这台存储节点。5.2 创建和挂载的完整验证命令链创建验证卷openstack volume create --size 5 --type lvm_new test-vol观察状态是否从creating变成available。然后找一个云主机挂载openstack server add volume instance-1 test-vol挂载成功后在实例里执行lsblk应该能看到一块5G的新盘。格式化、建文件系统、写数据再卸载重复几次确认读写的稳定性。这里有一个细节容易被忽略在计算节点上跑iscsiadm -m session可能会看到多条会话。如果发现旧卷的iSCSI连接还是指向老存储节点而新卷指向新节点说明调度是成功的存储访问路径是分离的。这是验证“前后端分离”最直接的方式。5.3 新存储节点上检查实际落盘路径在存储节点上查看创建的卷对应的逻辑卷lvs正常情况下你会看到类似volume-xxxx cinder-volumes -wi-a- 5.00g然后查看target会话targetcli ls你能看到一个iqn开头的target中LUN 0对应的就是刚才创建的卷。这个验证能保证数据确实在新节点上落盘而不是因为后端配置错误导致卷被创建到了老节点。如果lvs里没有新卷但卷在OpenStack层面显示available这种情况很少见一旦出现说明cinder-volume持有的是旧卷组元数据缓存。重启一下openstack-cinder-volume服务即可。6. 常见故障排查链路与日常运维的补充建议6.1 新节点容量始终为0的排查路径我先把日志路径放在最前面任何存储节点问题第一反应都是看这三类日志/var/log/cinder/cinder-volume.logcinder-volume自己的运行日志。/var/log/message系统级的iscsi、multipath相关报错。控制节点上的/var/log/cinder/cinder-scheduler.log用以确认调度器是否把新后端纳入了可选范围。如果openstack host list里新节点的容量始终是0常见的原因之一是filter里针对容量计算的配置文件不对。比如/etc/cinder/cinder.conf里没有启用CapacityFilter。在DEFAULT段加一行scheduler_default_filters AvailabilityZoneFilter,CapacityFilter,CapabilityFilter然后重启控制节点上的cinder-scheduler。6.2 iSCSI会话不稳定的根因MTU、多路径与网卡绑定存储网络MTU如果不一致会导致iSCSI传输缓慢和偶发超时。建议存储网络MTU设为9000jumbo frame所有节点包括交换机端口都要一致。现代网卡普遍支持配置后性能提升明显。如果你在计算节点上看到了iscsiadm报错connection timed out先查路径上的交换机和网卡有没有丢包。另外多路径device-mapper-multipath如果没配置好计算节点可能无法正确识别新存储节点的磁盘设备。安装device-mapper-multipath后需要配置/etc/multipath.conf把cinder卷的wwid加入黑名单否则multipath会接管新增的SCSI设备导致nova-compute无法正常使用。6.3 从运维角度补上自动化与监控节点加完、验证通过才算完成了一半工作。我强烈建议在监控系统里加上对新增存储节点容量、IO延迟、iSCSI会话数的监控项并设置告警阈值。比如卷组使用率超过85%就告警iSCSI会话数突然归零说明网络分区或target服务崩溃这些都是需要第一时间感知的异常事件。另外数据库里定期清理过期的卷和快照是很多团队忽略的事。OpenStack的cinder-manage提供了purge命令可以清理软删除记录。如果你的存储节点多了建议配置定时任务把状态为error、deleted的资源周期性地删除。我个人的习惯是每次扩容存储节点后会在本地记录一份简单的变更单包括新节点的IQN、卷组名、backend name、新增的卷类型以及验证命令的输入输出。后面再扩容或者排障时这些记录能省很多时间。最后再分享一个小技巧在新存储节点落库前先跑一次cinder-manage service list看看当前和服务端的通信是否正常。这一步能快速暴露数据库连接、版本兼容、消息队列认证等问题比直接起服务然后从日志里翻错误更有效率。