2026年5月

OpenStack 一年俩版本,业内大部分集群都落后 5-10 个版本。本文讲跨 3+ 版本升级的策略。

一个个升 vs 一次跨

官方支持N→N+1 升级(如 Yoga→Zed)。跨多版本理论上不支持,实操有 3 种思路:

思路 1:逐版本升

最稳,但慢。8 个版本就要做 8 次维护窗口。

思路 2:fast-forward upgrade(FFU)

社区工具支持 4-5 个版本一次跨。Red Hat 的 director、Mirantis 的 mcp 都有 FFU 流程。

思路 3:新搭一套 + 数据迁移

最暴力但最干净。适合升级跨度太大、原集群一堆历史包袱的场景。

我推荐:思路 2(FFU)

实际流程(以 Yoga → 2024.2 为例):

1. 准备阶段(不影响业务)

  • 备份所有数据库:Keystone、Nova、Glance、Neutron、Cinder
  • 备份配置文件/etc/{keystone,nova,glance,neutron,cinder,heat}
  • 导出 inventory:所有 VM、网络、卷的元数据
  • 跑 release notes 检查:每个版本的 breaking change

2. 控制面升级(业务能跑)

按依赖顺序升:

Keystone → Glance → Placement → Nova → Neutron → Cinder → Heat → Horizon

每个组件:

# 1. 停服务
systemctl stop neutron-server
# 2. 升包
pip install --upgrade neutron==X.Y.Z
# 或 dnf upgrade openstack-neutron
# 3. 数据库迁移
neutron-db-manage upgrade head
# 4. 起服务
systemctl start neutron-server
# 5. 验证
openstack network list

控制面升级期间 API 不可用(5-15 分钟),但已有 VM 正常运行。

3. 数据面升级(要 live-migrate)

Nova-compute、Neutron-agent 升级要节点逐个滚动:

for node in compute1 compute2 compute3; do
    # 1. 把 VM 迁走
    openstack server migrate --live $other_node <vm>
    # 2. 节点上升级
    ssh $node 'dnf upgrade openstack-nova-compute openstack-neutron-*'
    # 3. 重启服务
    ssh $node 'systemctl restart openstack-nova-compute neutron-*-agent'
done

必看 breaking changes

跨版本升级最容易翻车的点:

  • placement 从 Nova 拆出来(Stein 之后是独立服务)
  • neutron ML2/OVS 转 OVN(Yoga 之后官方推 OVN)
  • glance 镜像格式变化(不再支持某些老格式)
  • keystone v2 API 移除(Train 之后)
  • mysql 5.7 → 8.0 兼容性

回滚预案

每个组件升级前打 snapshot:

  • 数据库:mysqldump 全备
  • 配置:tar 整个 /etc/<service>/
  • 包:记下当前版本 dnf list installed | grep openstack

回滚 = 还原包 + 还原配置 + 还原 DB。

教训:跨 3+ 版本不要赌一把成功——先在 staging 完整演练一遍,把每个组件的坑都踩出来再上生产。

新搭 OpenStack 必问:Cinder 后端选啥?本文按生产场景对比 4 种主流方案。

对比表

后端 性能 HA 快照 复杂度 推荐场景
Ceph RBD 通用,强推
NFS 看 NAS 小集群、测试
iSCSI (SAN) 已有商用 SAN
LVM (本地) 最高 单节点、性能极致

Ceph RBD(最常见)

[ceph]
volume_driver = cinder.volume.drivers.rbd.RBDDriver
rbd_pool = volumes
rbd_user = cinder
rbd_secret_uuid = <uuid>
rbd_flatten_volume_from_snapshot = false
rbd_max_clone_depth = 5
volume_backend_name = ceph

优点:
- VM 可以在线迁移:所有 compute 节点都能访问同一个 RBD
- 从镜像 boot 秒级:Glance 镜像也存 Ceph 时,clone 而非 copy
- 快照便宜:COW,几乎不占空间

缺点:
- 延迟比本地 LVM 高(网络往返)
- Ceph 自己也得运维

NFS

[nfs]
volume_driver = cinder.volume.drivers.nfs.NfsDriver
nfs_shares_config = /etc/cinder/nfs_shares
nfs_mount_options = vers=4.1,proto=tcp,rsize=1048576,wsize=1048576

优点:简单到不能再简单。

缺点:
- 性能受 NAS 限制,IOPS 一般
- 单 NAS 挂了所有卷不可用
- 文件锁、缓存一致性偶尔翻车

实际场景:小公司、开发测试环境、已有 NAS 设备。

iSCSI(基于商用 SAN)

[hpe-3par]
volume_driver = cinder.volume.drivers.hpe.hpe_3par_iscsi.HPE3PARISCSIDriver
hpe3par_api_url = https://<3par>:8080/api/v1
hpe3par_username = ...

优点:商用 SAN 自带高可用、压缩去重,性能强。

缺点:
- 贵
- 厂商绑定,换设备就要换驱动
- 配置每家 SAN 不一样

实际场景:传统企业、已有 SAN 投资。

LVM(本地盘)

[lvm]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group = cinder-volumes
target_protocol = iscsi
target_helper = lioadm

优点:
- 性能最高(直接本地 NVMe)
- 配置最简单

缺点:
- 卷绑定到 compute 节点,VM 不能跨节点迁移
- 节点挂了卷就丢

实际场景:单节点 all-in-one、性能极致要求。

我的推荐

  • 通用生产:Ceph RBD,没有之一
  • 已有 SAN 投资:iSCSI,但只在那一栋楼里用
  • POC / 学习:LVM 起步,玩明白了再上 Ceph

教训:千万别多种后端混用——卷迁移、备份、监控都会成倍复杂。

默认 Nova 调度有 10+ filter,但大集群下默认配置往往不够。本文是我的调优实战记录。

调度流程

  1. 拉所有 hypervisor 列表
  2. 过 filter 链,每个 filter 排除一批
  3. 剩下的过 weigher,按权重排序
  4. 取 top 1(或前 N,从中随机选)

性能瓶颈:filter 链越长越慢。1000 节点集群默认配置,调度一次要 5+ 秒。

减 filter

不需要的 filter 直接删,比如:

[filter_scheduler]
enabled_filters = AvailabilityZoneFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,ServerGroupAffinityFilter

我删掉的:
- RetryFilter:默认重试机制,集群正常时无用
- CoreFilter / RamFilter / DiskFilter:已被 PlacementFilter 取代(Ocata 之后)
- SameHostFilter / DifferentHostFilter:很少用到
- PciPassthroughFilter:没 GPU/PCI 场景删掉

Placement 是关键

Pike 之后 Nova 引入 Placement API,资源跟踪从 Nova-scheduler 移到 Placement service。优先用 Placement 而不是 filter 做资源筛选

[scheduler]
query_placement_for_image_type_support = True
limit_tenants_to_placement_aggregate = True

Placement 查询是 SQL JOIN,10000 节点也是毫秒级,filter 是 Python 循环。

Weigher 调优

[filter_scheduler]
weight_classes = nova.scheduler.weights.all_weighers
ram_weight_multiplier = 1.0
disk_weight_multiplier = 0.5
io_ops_weight_multiplier = -2.0
build_failure_weight_multiplier = -1000000.0

实战意义:
- ram_weight_multiplier > 0:偏好 RAM 多的节点(spread 模式)
- < 0:偏好 RAM 少的节点(pack 模式,节省机器)
- build_failure_weight_multiplier 负超大:最近构建失败的节点强制避开

大集群必加:host subset size

[filter_scheduler]
host_subset_size = 5

调度时不取 top 1,而是从前 5 个里随机选。避免羊群效应——同时多个 VM 调度都选同一个最空节点,结果撞车。

监控

# scheduler 调度时间
grep "Scheduling decision" /var/log/nova/nova-scheduler.log | awk '{print $NF}'

# 失败率
grep NoValidHost /var/log/nova/nova-scheduler.log | wc -l

教训:1000 节点以上集群 nova-scheduler 跑得慢,第一步是看 Placement 有没有用上,filter 越少越好。

Keystone 是 OpenStack 的认证中心,挂了整个云就废了。本文是我在生产部署的 3 节点 HA 方案。

架构

        VIP (HAProxy keepalived)
         |
   +-----+-----+
   |     |     |
 Key1  Key2  Key3   (Apache + mod_wsgi)
   |     |     |
   +-----+-----+
         |
      Galera Cluster (MariaDB 3 节点)

要点:

  • Keystone 服务无状态,水平扩容
  • 数据库用 Galera 多主同步
  • 前面挂 HAProxy + VIP,单点故障不影响

关键配置 keystone.conf

[database]
connection = mysql+pymysql://keystone:password@<VIP>:3306/keystone
max_pool_size = 50
max_overflow = 100

[token]
provider = fernet
expiration = 3600

用 fernet token,不要用旧的 uuid token:

  • fernet 不存数据库,纯加密 token
  • 性能好 10 倍以上
  • token rotation 自动化

Fernet key 同步

3 个节点的 fernet key 必须一致:

# 主节点生成
keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone

# rsync 到其他节点
rsync -av /etc/keystone/fernet-keys/ node2:/etc/keystone/fernet-keys/
rsync -av /etc/keystone/fernet-keys/ node3:/etc/keystone/fernet-keys/

# 定期 rotate(crontab,每 24h)
keystone-manage fernet_rotate --keystone-user keystone --keystone-group keystone

rotate 后必须同步到所有节点,否则部分节点 token 验证失败。

HAProxy 配置

listen keystone_api
    bind <VIP>:5000
    balance source           # 同一客户端固定到同一后端,防 session 漂
    option httpchk GET /v3
    server key1 <node1>:5000 check inter 2000 rise 2 fall 3
    server key2 <node2>:5000 check inter 2000 rise 2 fall 3
    server key3 <node3>:5000 check inter 2000 rise 2 fall 3

balance source 比 roundrobin 更稳,但流量分布略不均。

监控要看的指标

  • Keystone API 响应时间(>500ms 报警)
  • Token 创建 QPS
  • Galera 集群同步延迟(wsrep_local_recv_queue)
  • Fernet key 文件 mtime 一致性

一个真实事故

某次我们的 HAProxy 健康检查写成 option httpchk GET / ——返回 300 重定向。HAProxy 把所有节点判 down,Keystone 全部摘除,整个云挂 20 分钟。

教训:健康检查 URL 一定要返回 2xx,别用根路径。

副本(replication)和纠删码(EC)是 Ceph 两种数据保护机制。新人最纠结的就是怎么选。本文给一个决策框架。

一图概括

维度 3 副本 EC 4+2 EC 8+3
空间利用率 33% 67% 73%
容忍失败 OSD 2 个 2 个 3 个
写性能
读性能
修复速度
CPU 开销
小对象友好

选副本的场景

  • 块存储 RBD(VM 盘、数据库):高 IOPS、小 IO,必须副本
  • CephFS 热数据池:小文件多,EC 性能跌得厉害
  • 小集群(OSD < 30):EC 性能开销占比太大

选 EC 的场景

  • 对象存储 RGW 冷桶:大对象、读为主
  • 备份/归档:写入一次、几乎不读
  • 大集群存视频/影像:对象大且数量少

EC 怎么选 K+M

  • K+M 不能超过 host 数(默认 failure domain=host)
  • K 越大空间利用率越高,但修复越慢
  • M 决定能挂多少 OSD

我的默认:

  • 中等集群(30-50 OSD):EC 4+2,平衡空间和性能
  • 大集群(>100 OSD):EC 8+3,最佳空间利用

一个新手陷阱:混合 pool

很多人想"热数据副本池、冷数据 EC 池,自动迁移"——这叫 cache tier。Reef 之后官方已经 deprecated cache tier,不再推荐用。

替代方案:

  • RGW 桶级 storage class,新对象写入 EC 池
  • 应用层冷热分离(用户访问频次驱动)

实际数据规划公式

裸容量 = 业务数据 ÷ 利用率 ÷ 平均使用率(0.7)

例:要存 100TB 业务数据,用 EC 4+2
裸容量 = 100 / 0.67 / 0.7 ≈ 213 TB

那 0.7 哪来的?Ceph 推荐 OSD 使用率 ≤70%,超过会触发 backfillfull 限制写入。

极端但有用的组合

临时数据池(如 K8s emptyDir 持久化):

ceph osd pool create tmp 32 32 replicated
ceph osd pool set tmp size 2
ceph osd pool set tmp min_size 1

size=2/min_size=1 在生产是反模式(容易丢数据),但临时数据可接受,省一倍空间。

教训:选 EC 前先用 rados bench 在你的硬件上跑一遍——纸面性能和实际差距经常很大。