news 2026/9/19 3:50:03

OpenStack 8节点高可用集群部署实战:从节点规划到故障演练

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenStack 8节点高可用集群部署实战:从节点规划到故障演练

接手过一堆OpenStack环境之后,我越来越觉得"高可用"这三个字被用得太随意了。前两年帮一家公司救火,他们架了8台物理机,架构图花花绿绿画得挺唬人,数据库、消息队列、控制节点全部分散部署,号称“双副本高可用”。结果某天一台控制节点宕机,整个云平台API直接瘫痪,nova list卡到超时,重启故障机之后集群状态乱成一锅粥。后来排查发现,数据库是单点,RabbitMQ没做镜像队列,所谓的高可用只是把服务“分别装在三台机器上”而已。

这套东西之所以让人头疼,是因为OpenStack高可用集群涉及的角色太多:数据库、消息队列、无状态API、有状态调度器、网络代理、块存储网关,每一层的高可用玩法都不一样,不是装个keepalived就能糊弄过去的。这篇文章我按8节点生产级高可用集群的完整实施路径来写,把节点规划、基础环境、控制面组件、计算存储接入、故障演练、上线验收这些环节一次讲透。写给正在搭OpenStack、或者已经在运维但想补齐HA能力的团队,读完至少能避开我踩过的那几类大坑。

1. 为什么是8台:一套经得起故障演练的节点规划

1.1 角色分配:3控制 + 5超融合计算

8这个数字不是拍脑袋来的。先看控制面:OpenStack的控制服务几乎全是无状态API(Keystone、Glance、Nova API、Neutron Server),真正有状态的是数据库和消息队列。数据库如果用MariaDB Galera,至少要3个节点才能形成多数派仲裁;RabbitMQ做镜像队列同样需要奇数节点。所以控制节点最少3台,这是硬底线,2台在脑裂场景下根本没法自愈。

剩下5台怎么分?我推荐超融合方案:5台全部作为计算节点,同时每台挂若干块数据盘作为Ceph OSD。这样既省掉独立存储节点,又让Ceph的故障域天然覆盖到整个集群。如果一定要独立存储节点,也可以改成3控制 + 3计算 + 2存储的经典布局,但2个OSD节点做Ceph副本会很尴尬,要么接受size=2的弱副本策略,要么再压一台出来。比较下来,8台机器最舒服的分配就是3控制 + 5超融合计算。

这个拓扑下各节点跑的服务如下:

节点角色承载服务
c1/c2/c3控制节点keystone、glance、placement、nova-api/scheduler/conductor、neutron-server、horizon、cinder-api/scheduler、galera(MariaDB)、rabbitmq、memcached、haproxy、keepalived、ceph-mon
cmp1~cmp5超融合计算节点nova-compute、neutron-ovs-agent、l3-agent(可选)、dhcp-agent(可选)、ceph-osd、openvswitch

控制节点上的Galera和RabbitMQ是集群模式,三个节点同时提供服务,不存在主备切换的等待时间;无状态API层通过VIP + HAProxy负载均衡,任何一个控制节点挂掉,请求自动打到另外两台。计算节点之间通过Ceph共享存储实现虚拟机热迁移,这是后面所有高可用能力的基础。

1.2 硬件配置建议:按角色分开配,别图省事统一采购

很多团队为了采购方便,8台机器买一模一样的配置,这在OpenStack项目里非常浪费。控制节点不需要大容量存储,但对内存和网卡稳定性敏感;计算节点才是吃CPU和内存的大户,同时还要为Ceph提供裸盘,磁盘数量直接决定存储池容量。

我给的参考配置如下:

项目控制节点(c1~c3)计算节点(cmp1~cmp5)
CPU2路 16核起步2路 24核或32核
内存128GB起步,建议256GB256GB起步,建议512GB
系统盘2×300GB SSD,RAID12×480GB SSD,RAID1
数据盘不需要6~12块1.92TB SSD(或HDD),直接作为Ceph OSD
网卡4×10GbE,或2×10GbE + 2×25GbE4×10GbE,或2×25GbE + 2×10GbE

控制节点的内存大不是因为OpenStack控制面本身多能吃,而是Galera和RabbitMQ都吃内存,尤其是RabbitMQ,内存水位默认是物理内存的40%,节点越小越容易触发阻塞。计算节点的内存大头在虚拟机本身和Ceph的页缓存上,rbd后端读写时,宿主机page cache能显著提升性能,所以内存尽量给足。

数据盘有个容易被忽略的细节:如果OSD盘是SSD,务必确认固件支持掉电保护(Power Loss Protection)。Ceph对断电很敏感,没有掉电保护的SSD在异常掉电后可能丢数据或产生大量慢请求,这是我在实际项目中吃过亏的地方。

1.3 网络平面划分:管理、数据、存储、外部,四条网段必须物理隔离

网络规划是整个集群最容易返工的部分。OpenStack生产环境至少需要四个网络平面,而且不建议用VLAN在同一个物理网卡上硬隔离存储流量和租户流量,尤其Ceph副本流量很大,混在一起会把管理面拖死。

网段网卡用途关键地址
管理网 10.10.0.0/24eth0SSH、OpenStack内部API通信、数据库/消息队列心跳c1~c3分别10.10.0.11/12/13,cmp1~5为10.10.0.21~25,VIP 10.10.0.10
数据网 10.20.0.0/24eth1VXLAN隧道、租户东西向流量各节点10.20.0.x
存储网 10.30.0.0/24eth2Ceph public/client网络、OSD副本流量各节点10.30.0.x
外部网 192.168.100.0/24eth3浮动IP、公网API入口外部VIP 192.168.100.10

四条网段我建议至少把存储网和租户数据网放到独立的物理网卡上。租户跑大流量业务时,VXLAN封包和Ceph数据复制同时在网卡上挤,经常导致OSD heartbeat超时,严重的时候整个存储集群会抖动。如果设备紧张,管理网和外部网可以共用一对bond,存储网和数据网各占一对bond,但必须通过bonding的mode 4(LACP)保证链路冗余。

顺带说一句:OpenStack里的controllercompute这些hostname别乱起,后面所有配置文件和RabbitMQ的节点名都靠它,名字一乱,集群join的时候哭都来不及。

2. 基础环境是大多数部署失败的根源:装机、时区、源、SSH

2.1 操作系统与磁盘分区:别在装系统那天埋雷

生产环境我不推荐用太新的发行版,OpenStack和Ceph的版本匹配需要时间消化。我用得最顺的组合是Rocky Linux 8.x + OpenStack Yoga + Ceph Quincy,兼容性好,社区资料也多。装系统时磁盘分区有一个关键原则:系统盘和数据盘物理隔离。Ceph OSD的裸盘不能和系统分区混在一起,否则后续添加OSD、故障替换磁盘时非常被动。

系统盘分区建议如下:/boot给1GB,/给80~100GB,/var给100GB以上(日志和数据库文件都在这里,Galera的binlog、RabbitMQ的持久化消息都会占空间),/tmp独立分20GB,swap视内存而定,内存256GB以上的机器可以不要swap。别把全部空间都给/然后指望后期扩容,逻辑卷虽然支持扩,但生产环境动根文件系统是有风险的。

Ceph的数据盘在装机阶段什么也不要做,不要格式化,不要分区,留给cephadm直接接管。我见过有人手贱把OSD盘格式化成ext4,结果要清掉重新加,白折腾一晚上。

2.2 hostname、hosts、SSH免密:看似简单却最多返工

装完系统第一件事就是统一hostname和/etc/hosts,这事看似基础,却是RabbitMQ集群、Galera集群、Ceph mon之间互相解析的关键。/etc/hosts必须在所有节点保持一致,包括控制节点和计算节点,格式如下:

10.10.0.11 c1 10.10.0.12 c2 10.10.0.13 c3 10.10.0.21 cmp1 10.10.0.22 cmp2 10.10.0.23 cmp3 10.10.0.24 cmp4 10.10.0.25 cmp5

注意不要用全限定域名做OpenStack服务注册的主机名,统一用短主机名,这样后续RabbitMQ节点名(如rabbit@c1)、Ceph hostname不会出现"c1.localdomain"和"c1"对不上的尴尬。

SSH免密配置也建议做,虽然OpenStack本身不依赖SSH,但Ceph的cephadm、日常巡检、批量执行命令都要用。生产环境可以用专门的部署用户(比如cloudadmin)做免密,不建议直接用root。生成密钥后批量ssh-copy-id,装完顺手验证一遍:所有节点之间两两SSH都要通,不是只从管理机到节点通就行。

很多集群搭到一半发现RabbitMQ join失败,erlang_cookie一致了、端口也通了,最后定位到是/etc/hosts有一台机器的IP写错了。这种低级错误最费时间,所以基础网络检查一定要用脚本批量跑一遍,别靠眼睛看。

2.3 chrony时间同步:证书、token、数据库全部依赖它

OpenStack对时间同步的要求比想象中高得多。Keystone的Fernet token带时间戳,时间偏差超过阈值直接认证失败;Galera的冲突检测、RabbitMQ的消息TTL、Ceph的mon选举也对时间敏感。所以统一用chrony做主从同步,控制节点c1作为时间源,其余节点向它同步。

c1的/etc/chrony.conf配置大致如下:

server 0.cn.pool.ntp.org iburst allow 10.10.0.0/24 local stratum 10

其他节点配置为:

server c1 iburst

有必要的话把管理网口的时间同步流量单独加防火墙放行。装完所有节点执行chronyc sources -v确认同步状态,把时间偏差控制在50毫秒以内再往后走。时间不同步这个问题很隐蔽,它不会让你哪个服务起不来,但会让你在排查认证偶发失败时绕一大圈。

3. 控制平面的真正骨架:Galera、RabbitMQ、Memcached

3.1 MariaDB Galera:三节点同时可读写,别忽略它的两个限制

控制面里的数据库是我最看重的组件。这里用MariaDB Galera集群,三节点同时可读写,通过wsrep协议做同步复制。它的优势是任何节点都能写,不存在主从切换的真空期。

安装时三个节点都要装mariadb-server-galera,然后在/etc/my.cnf.d/galera.cnf里配置:

[mysqld] wsrep_on=ON wsrep_provider=/usr/lib64/galera/libgalera_smm.so wsrep_cluster_name="os-cluster" wsrep_cluster_address="gcomm://c1,c2,c3" wsrep_node_address="10.10.0.11" wsrep_node_name="c1" wsrep_sst_method=mariabackup wsrep_sst_auth=wsrep_sst:密码 bind-address=0.0.0.0

注意三个节点的wsrep_node_address分别写自己的IP。首次启动必须选一个节点执行galera_new_cluster引导集群,另外两个节点正常systemctl start mariadb即可加入。如果这个顺序搞反了,全部用systemctl start mariadb启动,集群会因为没有初始节点而一直无法形成primary组件。

Galera有两个限制你必须知道。第一,事务引擎必须是InnoDB,CREATE TABLE的时候别再用MyISAM;第二,写入冲突的报错是deadlock found,应用层要做好重试,虽然OpenStack各服务对数据库重试做得还行,但批量脚本直连数据库时要注意。另外,wsrep_sst_method我推荐用mariabackup而不是rsync,前者可以在线做SST,不会长时间锁库。

Galera的备份也别掉以轻心,我一般在一个节点上做mariabackup全量备份,然后配合binlog做增量,恢复时先恢复到一致快照,再追增量日志。直接mysqldump在数据量大时恢复时间太长,生产环境吃不消。

3.2 RabbitMQ:镜像队列与erlang cookie的坑

RabbitMQ是OpenStack所有服务之间通信的枢纽,它挂了,整个平台的消息传递都会停摆。三节点RabbitMQ集群的搭建本身不难,但有几个关键点一错就全崩。

首先,三台机器必须共享同一个erlang cookie,文件在/var/lib/rabbitmq/.erlang.cookie,权限必须是400,属主必须是rabbitmq用户。把c1的cookie复制到c2和c3后,重启rabbitmq-server。然后依次执行:

rabbitmqctl stop_app rabbitmqctl join_cluster rabbit@c1 rabbitmqctl start_app

在c2、c3上执行join,c1不要执行。集群起来后,用rabbitmqctl cluster_status确认三个节点都在运行。

OpenStack的队列必须做镜像,否则队列只落在某一个节点上,节点挂了消息全丢。执行:

rabbitmqctl set_policy ha-all "^(?!amq\.).*" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

这条策略把所有非amq.开头的队列都镜像到全部节点,开启自动同步。如果不设置,RabbitMQ集群只是"元数据共享",队列实体还是单点的,这跟没做高可用没有本质区别。

还要注意内存和磁盘阈值。OpenStack的默认配置里,RabbitMQ的vm_memory_high_watermark是0.4,意思是内存使用超过40%就停止接收新消息。消息积压时服务会表现为"卡住",排查起来很痛苦。我习惯把水位提到0.6,并给/var/lib/rabbitmq所在分区独立预留足够空间,同时把disk_free_limit设成mem_relative2.0以上。

3.3 VIP与HAProxy:让所有服务只认一个地址

控制面的API是无状态的,多台机器提供服务时,客户端不能感知到节点切换,这就需要VIP + HAProxy这一层。

VIP我用keepalived来管理,控制节点c1作为master,c2/c3作为backup,配置大致如下:

vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 unicast_src_ip 10.10.0.11 unicast_peer { 10.10.0.12 10.10.0.13 } virtual_ipaddress { 10.10.0.10/24 } }

注意生产环境我强烈建议用unicast_peer而不是默认的组播224.0.0.18,因为很多机房交换机禁组播,或者跨网段部署时组播广播不过去,用unicast最省心。另外,管理网VIP和外网VIP都可以用keepalived管理,分别走不同网卡即可。

HAProxy配置的核心是把OpenStack各个API端口的请求负载到三台控制节点上。端口对应关系如下:

OpenStack服务默认端口HAProxy后端
Keystone5000c1~c3的5000端口
Glance9292c1~c3的9292端口
Nova API8774c1~c3的8774端口
Placement8778c1~c3的8778端口
Neutron9696c1~c3的9696端口
Cinder8776c1~c3的8776端口
Horizon80/443c1~c3的80/443端口

数据库、RabbitMQ、Memcached也可以走HAProxy的TCP转发,但我更推荐另一种做法:OpenStack各服务的配置文件里的connectiontransport_url直接写VIP,由HAProxy做四层转发。这样服务端不需要感知后端节点变化,切换对业务完全透明。

keepalived和HAProxy这套方案比Pacemaker+Corosync轻量很多,够用而且是行业最常见的组合。如果你还需要管理多组VIP的依赖关系、要做节点fencing,那就上Pacemaker,但在8节点这个规模下,keepalived基本够用。

4. 服务部署顺序为什么是Keystone→Glance→Placement→Nova→Neutron

4.1 Keystone先行的原因:认证、endpoint与服务目录

OpenStack所有服务之间的调用都要经过Keystone认证,服务要互相发现依赖服务目录(Service Catalog),所以Keystone必须第一个部署。装Keystone的关键不只是装包和起服务,而是建好服务项目、服务用户、endpoint,并且所有endpoint的URL都要指向VIP。

初始化命令大致如下:

keystone-manage bootstrap --bootstrap-password 管理员密码 \ --bootstrap-admin-url http://10.10.0.10:5000/v3/ \ --bootstrap-internal-url http://10.10.0.10:5000/v3/ \ --bootstrap-public-url http://192.168.100.10:5000/v3/ \ --bootstrap-region-id RegionOne

三个URL分别对应管理面、内部面、公共面。内部和管理走10.10.0.10(管理网VIP),公共走192.168.100.10(外部VIP),这是生产环境的常规做法。如果内外部都写同一个IP,后续做南北向隔离会非常痛苦。

Fernet密钥是个高频踩坑点。Keystone的token认证依赖Fernet密钥,三个控制节点必须共用同一套密钥。初始化时生成的/etc/keystone/fernet-keys/目录里有一个0号密钥文件,要把这个目录完整复制到c2和c3,否则c1签发的token在c2上无法校验,会出现"时好时坏"的认证故障。这个现象特别有迷惑性,因为你单测c1是好的,单测c2也是好的,但c2上就是无法用c1的token,非常容易让人怀疑是网络问题。

Keystone在httpd里以mod_wsgi方式运行,需要确保Listen 5000和对应的虚拟主机配置在三个节点都存在,防火墙放行5000端口。装完用openstack token issue验证一下,确认token能签发、能校验、能访问外网VIP地址。

4.2 Placement与Nova控制面:conductor和scheduler的分工

Placement从Nova里拆出来之后,它的部署要放在Nova之前。Placement负责跟踪所有资源提供者的资源使用情况(vCPU、内存、磁盘),Nova scheduler在调度虚拟机时要查Placement的资源视图。

openstack service create --name placement --description "Placement" placement openstack endpoint create --region RegionOne placement public http://192.168.100.10:8778 openstack endpoint create --region RegionOne placement internal http://10.10.0.10:8778 openstack endpoint create --region RegionOne placement admin http://10.10.0.10:8778

Placement API本身很轻,关键是它的数据库表结构要初始化好,并在placement.conf里把数据库连接指向Galera集群。

Nova控制面由几个角色组成,各自的职责要理清:

  • nova-api:无状态API,负责接收REST请求,全部走VIP + HAProxy。
  • nova-scheduler:无状态调度器,从Placement查询可用资源,决定虚拟机落在哪个计算节点。
  • nova-conductor:有状态服务,是nova-compute和数据库之间的中间层,计算节点不直接访问数据库,而是通过conductor。控制节点通常每个节点都跑conductor,多个conductor同时工作。
  • nova-novncproxy:提供VNC控制台访问,通过VIP暴露6080端口,由HAProxy负载均衡到三台控制节点。

n个服务在三个控制节点上全部启用,通过systemctl enable --now逐一启动。配置里最重要的几个点:

[database] connection = mysql+pymysql://nova:密码@10.10.0.10/nova?charset=utf8 [api_database] connection = mysql+pymysql://nova_api:密码@10.10.0.10/nova_api?charset=utf8 [placement] region_name = RegionOne project_domain_name = Default project_name = service username = placement password = 密码 auth_url = http://10.10.0.10:5000/v3 [neutron] url = http://10.10.0.10:9696 auth_url = http://10.10.0.10:5000/v3 service_metadata_proxy = True metadata_proxy_shared_secret = 元数据密钥

数据库连接全部指向Galera的VIP而不是某个节点IP,这样任何控制节点宕机都不影响数据库访问。

Nova初始化数据表后,还需要执行:

nova-manage cell_v2 map_cell_resources

这条命令在计算节点注册到集群之后执行,作用是让控制面知道有哪些计算节点和资源。新加计算节点时也要重新跑一次,否则新节点不会出现在调度候选里。

4.3 Neutron:L3高可用与DHCP/元数据代理的分布

Neutron是OpenStack里拓扑最复杂的服务。控制节点上跑neutron-server,负责API、数据库、插件管理;计算节点上跑neutron-ovs-agent,负责虚拟机网卡和OVS网桥的接入。

网络拓扑层面,我建议用VXLAN作为租户网络类型,mechanism_driversopenvswitch,l2population。L2 population能在VXLAN场景下减少泛洪,实现ARP抑制,性能比默认模式好不少。

浮动IP的实现依赖L3 Agent,三台控制节点都跑l3-agent,开启HA模式:

[DEFAULT] router_distributed = False [agent] ha_enabled = True

三台控制节点的L3 agent共同承载路由器,每个router会选一个节点做master,另外两个做backup。某个控制节点挂掉后,router会自动在存活节点上恢复,浮动IP的连通性基本不中断。DHCP Agent同样在三台控制节点运行,每个子网的dhcp租约由某个特定节点负责,节点挂了会自动重建。

外部网络这块,要在控制节点上把外部网桥br-ex和物理网卡打通。如果外部网是平铺的VLAN网络,配置相对简单;如果是和物理交换机做trunk,需要确认VLAN ID的映射。最容易出错的是neutron-ovs-agent里的bridge_mappingsprovider:br-ex,物理网卡要加入br-ex桥,否则外部网络无法连通。

元数据服务也要格外注意。虚拟机启动时请求的169.254.169.254其实会转发到neutron的metadata agent,再由它转发给nova-api的8775端口。nova.confmetadata_proxy_shared_secret必须和neutron配置里的metadata_proxy_shared_secret完全一致,不一致的话虚拟机内部请求cloud-init元数据会认证失败,表现为虚拟机起来后没有注入主机名、没有注入公钥,或者在虚拟机里curl 169.254.169.254没有响应。这个坑我帮人排查过太多次了。

4.4 Horizon等附加组件的取舍

Horizon是否要装,我的建议是:如果团队主要用OpenStack CLI或Terraform/Ansible管理云平台,可以暂时不装;如果需要给业务方提供一个自助申请资源的界面,那就装。Horizon部署相对独立,三台控制节点各跑一个django应用,通过HAProxy负载均衡到80/443端口。

装Horizon时需要注意ALLOWED_HOSTS要包含VIP地址和各节点hostname,否则访问时会有400错误。Session存储建议用django memcached后端,指向控制节点的Memcached服务。Memcached本身是缓存服务,三台控制节点上都跑就行了,各服务配置里把memcached_servers写成多个地址或都指向VIP,客户端会自动做一致性哈希。

Heat(编排)、Octavia(负载均衡)、Manila(文件共享)这些组件看实际业务需要再上。8节点规模下,如果业务对自服务资源编排没有强需求,可以先不上,减少控制面的复杂度。控制面每多一个组件,故障域就多了一圈,生产环境讲究"够用就好,能跑就行"。

5. Ceph存储怎么接进OpenStack:rbd后端与超融合的坑

5.1 为什么生产环境选Ceph而不是本地盘

OpenStack的虚拟机磁盘存储有两种主流方案:本地盘和分布式存储。本地盘(默认的LVM后端)部署简单,但存在两个致命问题:热迁移时虚拟机磁盘在同一计算节点上无法迁移到其他节点;计算节点宕机后上面的实例无法在其他节点自动恢复。生产高可用集群要求"节点挂了实例还能在其他节点拉起",仅凭这一条,cinder和nova的镜像就不能只放在本地。

Ceph的RBD块设备天然支持多副本、快照、克隆,和OpenStack的Glance、Nova、Cinder三个组件的集成非常成熟。这也是为什么OpenStack生产集群里Ceph几乎是事实标准。超融合方案里,计算节点同时承担OSD角色,好处是省机器,坏处是计算和存储的IO互相抢资源。要缓解这个问题,必须保证OSD盘和系统盘分离,同时存储流量走独立的25GbE网卡,不要和租户VXLAN流量挤在一起。

5.2 搭建Ceph并将三个组件接入RBD

Ceph的部署我推荐用cephadm,比手工部署省太多事。先装ntp,再在c1上执行:

cephadm bootstrap --mon-ip 10.30.0.11

bootstrap完成之后,把c2、c3加入集群作为新的monitor:

ceph orch host add c2 10.30.0.12 ceph orch host add c3 10.30.0.13 ceph orch apply mon c1,c2,c3

计算节点(也是OSD节点)加入并部署OSD:

ceph orch host add cmp1 10.30.0.21 ceph orch host add cmp2 10.30.0.22 ceph orch device zap cmp1 /dev/sdb --force ceph orch apply osd --all-available-devices

apply osd --all-available-devices会自动发现所有未使用的裸盘并创建OSD。如果某台机器有不想被Ceph使用的盘(比如系统盘),先用ceph orch device zap排除,或者在主机标签上做限制。

接下来创建OpenStack需要的存储池:

ceph osd pool create images 128 ceph osd pool create vms 256 ceph osd pool create volumes 256 ceph osd pool create backups 64

池大小建议按角色的不同设置:images池size=2即可,因为镜像丢了从原始文件还能重新上传;vms和volumes池生产环境至少size=3,如果磁盘资源不够,size=2加min_size=1是底线,但要清楚这牺牲了数据安全。

需要为Glance、Nova、Cinder分别创建Ceph认证用户并授权:

ceph auth get-or-create client.glance mon 'allow r' \ osd 'allow class-read object_prefix rbd_children, allow rwx pool=images' ceph auth get-or-create client.cinder mon 'allow r' \ osd 'allow class-read object_prefix rbd_children, allow rwx pool=volumes, allow rwx pool=vms, allow rwx pool=backups' ceph auth get-or-create client.nova mon 'allow r' \ osd 'allow class-read object_prefix rbd_children, allow rwx pool=vms, allow rwx pool=images'

然后分别在三处配置里接入rbd。Glance的glance-api.conf

[DEFAULT] default_store = rbd [glance_store] stores = rbd rbd_store_pool = images rbd_store_user = glance rbd_store_ceph_conf = /etc/ceph/ceph.conf

Nova的nova.conf(每个计算节点上配置):

[libvirt] images_type = rbd images_rbd_pool = vms images_rbd_ceph_conf = /etc/ceph/ceph.conf images_rbd_glance_pool_name = images rbd_user = nova

Cinder的cinder.conf

[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

配置完之后,还要把Ceph的client keyring复制到每台计算节点和glance/cinder运行的控制节点上,并放在/etc/ceph/目录。特别注意Nova的libvirt需要把client.nova的key作为secret注入到libvirt:

cat > /tmp/secret.xml <<EOF <secret ephemeral='no' private='no'> <uuid>具体的UUID</uuid> <usage type='ceph'> <name>client.nova secret</name> </usage> </secret> EOF virsh secret-define --file /tmp/secret.xml virsh secret-set-value --secret 具体的UUID --base64 $(grep key /etc/ceph/ceph.client.nova.keyring | awk '{print $3}')

这个secret如果没配好,虚拟机启动时会报无法连接rbd,错误信息往往只有mapped rbd或者no such file,非常误导。

5.3 CRUSH规则与故障域:副本数是存储安全的生命线

Ceph的CRUSH规则决定了数据副本分布在哪些故障域里。默认规则是把副本分布在不同主机上,这正好符合我们"一台计算节点宕机不影响数据可用性"的诉求。但如果是一台机器上插了多块OSD盘,副本默认不会落在同一台机器的不同盘上,这里不需要额外调整。

倒是PG数量的估算值得记一下。常见公式是:总PG数 = (OSD总数 × 100) / 期望副本数,再取接近的2的幂。比如集群有20个OSD(5节点×4盘),副本数3,20×100/3≈666,靠近的2的幂是1024,也就是说所有池的PG总量接近1024。上面我建了4个池,images 128、vms 256、volumes 256、backups 64,加起来704,其实还可以,但如果后续要加池,整体PG数量要重新算,别让任何一个池的PG数过大,PG太多会拖慢OSD启动恢复。

存储网的带宽也是必须提前规划的。Ceph的OSD副本流量可能非常大,尤其是在坏盘替换、OSD重平衡期间,整个存储网都会被占满。这也是我反复强调存储网要独立网卡甚至独立物理交换机的原因。如果存储网和VXLAN共用交换机,重平衡时租户虚拟机延迟会明显变高,业务侧反馈"云主机变卡",其实是底层存储流量在打架。

6. 故障演练实录:关掉一个控制节点后集群还活着吗

6.1 演练场景与判定标准

高可用集群不是配完就算完事,必须通过故障演练验证。上线前的演练,我一般设置三个必测场景:

场景操作预期结果
控制节点API进程故障在c2上kill掉keystone和nova-api进程所有API请求在几秒内恢复,新建实例成功
控制节点整机宕机在c2上systemctl stop network模拟断网VIP切到c1或c3,数据库和消息队列不中断,已运行实例不受影响
计算节点宕机在cmp3上强制关机该节点上的实例标记为ERROR,其他节点正常,Ceph副本保持可用,数据不丢

判定标准不只是"集群没崩",而是业务可恢复性:API要能正常响应、openstack server list不超时、现有虚拟机网络不掉线、新的虚拟机能在其他节点创建成功、块存储卷能正常读写。这些指标都满足,才算过了第一关。

6.2 实测现象与原理分析

我实际跑过这类演练,几次下来最直观的感受是:API层的故障恢复是秒级的,而数据层的故障恢复是分钟级的,两者节奏完全不同

VIP切换那部分,keepalived的advert_int设置为1秒,实际检测到主节点不可用大约1~3秒完成VIP漂移。HAProxy上的既有TCP连接会断开,但OpenStack CLI会自动重连,所以用户感知几乎为零。

数据库这块,拔掉c2网卡后,Galera会因心跳超时把c2从集群中剔除,剩余c1和c3重新组成primary组件继续服务。关键点在于:如果c1和c3之间网络也不通,或者只剩一个节点,Galera会进入non-primary状态,拒绝所有写入。所以控制节点的网络必须坚固,管理网的交换机建议做堆叠,避免单交换机故障把数据库仲裁打没。

RabbitMQ的表现稍微复杂一点。镜像队列在主节点宕机时会从从节点中提升新的主队列,消息不会丢,但部分消息可能重复投递。好在OpenStack各服务的消息处理都做了幂等设计,实际测试中没出现重复创建虚拟机的问题。

计算节点宕机后,Ceph会自动触发PG的peering和恢复,存储数据不丢,但该节点上运行的虚拟机不会自动在别的节点拉起——这是OpenStack默认行为,Nova不支持自动故障迁移,除非你接额外组件。我的建议是:计算节点宕机后,手动或通过运维脚本把实例rescuerebuildevacuate到其他节点。evacuate在共享存储(Ceph)场景下很顺,虚拟机磁盘已经在Ceph里了,新节点只需要重新定义XML并启动,基本是分钟级恢复。

6.3 常见故障的排查链路

把演练中遇到的几个典型问题排出来,供大家遇到类似情况时参考:

  • 访问VIP的API时好时坏:先查ip a确认VIP当前在哪台节点,再在客户端curl -v http://10.10.0.10:5000/v3,看是连接被拒还是超时。连接被拒大概率是HAProxy后端列表里某个节点挂了还留在后端,检查HAProxy的stats页面和健康检查脚本。
  • 数据库状态显示non-primary:登录任何一个节点的MariaDB执行SHOW STATUS LIKE 'wsrep_cluster_status',如果结果是non-primary,说明多数派丢了。恢复方法:找到数据最新的节点,以它为基准执行galera_new_cluster重新引导,其他节点再启动加入。
  • RabbitMQ节点显示down且无法join:先查erlang cookie是否一致,再查两个节点的hostname能否互相解析。如果节点曾经被标记为down,加入时需要先rabbitmqctl forget_cluster_node清理。
  • 虚拟机创建失败,但控制节点都正常:去计算节点看nova-compute日志,常见的是libvirt连不上Ceph。执行ceph status确认集群health状态,如果HEALTH_WARN是因为PG数不合适或down的osd,先解决存储问题再创建虚拟机。

排查过程有个通用经验:日志永远比报错信息靠谱。openstack CLI报的错误信息经常是503 Service Unavailable这种模糊提示,但/var/log/nova/nova-compute.log里会明确写出创建失败的阶段和原因。养成先看日志的习惯,能省大量时间。

7. 上线前的验收清单与后续运维节奏

7.1 功能验收:不只是能创建虚拟机

上线前要把OpenStack的核心功能完整走一遍,任何一个环节出问题都要在生产环境暴露前发现。我习惯按下面的顺序过:

验收项具体操作通过标准
认证openstack token issueopenstack project list三台控制节点均可正常返回
镜像上传一个cirros镜像,openstack image listGlance状态为active
租户网络创建VXLAN网络、子网、路由器网络状态为ACTIVE
虚拟机创建一台带浮动IP的实例实例状态为ACTIVE,能ping通、能SSH
块存储创建卷并挂载到实例卷状态为in-use,实例内能看到盘
快照对实例做快照,从快照创建新实例新实例能正常启动
热迁移对一个正在运行的实例执行openstack server migrate --live迁移成功,实例网络不中断
控制台通过VNC/SPICE访问实例控制台能看到登录界面

热迁移这项很多人会漏掉,但它恰恰是验证Ceph存储是否配好的最好方式。热迁移失败的话,日志里通常能看到operation not supported或者internal error,十有八九是libvirt的Ceph secret没配好。

7.2 监控、日志、备份策略

生产环境没有监控的高可用集群等于裸奔。监控我建议至少覆盖三层:物理层(CPU、内存、磁盘、网卡流量)、OpenStack服务层(各API进程是否存活、RabbitMQ队列堆积量、Galera集群状态)、业务层(虚拟机运行状态、卷状态、网络连通性)。

工具组合可以用Prometheus + node_exporter +openstack-exporter+ceph_exporter。OpenStack的openstack-exporter能暴露各服务的API可访问性,Ceph方面直接用ceph mgr prometheus模块即可。告警规则里优先配置这几个:任何控制节点宕机、任何OSD down超过5分钟、RabbitMQ队列堆积超过阈值、Galerawsrep_cluster_status不是primary、任何OpenStack API的HTTP状态码错误率突增。

备份策略这块,最容易被忽略的是Keystone的Fernet密钥和/etc/下的配置文件。数据库挂了可以从备份恢复,但Fernet密钥丢了等于所有token作废,users/passwords本身不丢,但所有已签发的token全部失效,业务会瞬间崩掉。所以备份清单一定要包含:

  • MariaDB的mariabackup全量 + binlog增量
  • RabbitMQ的definitions导出(rabbitmqctl export_definitions
  • Keystone fernet-keys和credential-keys目录
  • 所有节点的/etc/keystone /etc/nova /etc/neutron /etc/cinder /etc/glance /etc/ceph
  • Ceph的crash和配置快照(ceph orch config dump

备份恢复演练必须做,而且至少半年一次。很多团队备份脚本一直在跑,真到恢复那天才发现备份文件不完整或者恢复流程缺步骤。我见过最惨的一次是数据库备份文件只有控制节点的mysqldump,Galera的binlog阶段全部缺失,恢复时只能回到几小时前,业务丢了不少数据。

7.3 版本升级与补丁节奏

OpenStack的版本升级是大工程,不建议在集群运行期间随意跨版本升级。我的经验是:小版本补丁(比如在同一release内的bugfix)可以先在测试环境验证,然后逐个控制节点滚动更新,每更新一个节点就检查一次集群状态。大版本升级(比如从Yoga到Zed)至少要留出一个完整的维护窗口,而且必须先做数据库schema迁移(nova-manage db syncneutron-db-manage upgrade)。

升级前把yum repo固定到当前release,避免意外拉到不兼容版本。升级过程的顺序是:先数据库(确认Galera三个节点schema一致),再消息队列,再控制面服务,最后计算节点。每升完一个组件,都执行一遍核心API验证(token、image list、server list),确认没问题再继续。

这里还想多说一句关于大版本选择的建议:不要做追新族。OpenStack社区每个release周期很短,但一个release的生命周期和上游支持窗口就那么多。生产环境选一个当前主流且社区资料丰富的版本,比如Yoga或Antelope,稳定用上两三年比频繁升级实在得多。Ceph也一样,Quincy或Reef都是大版本里的稳定分支,别再往上追了。

这个8节点集群从规划到跑通,我前前后后搭过三轮,第一轮失败在基础网络和erlang cookie,第二轮是Ceph接入OpenStack时的认证和secret问题,第三轮才算把整个故障演练完整跑下来。每次踩坑之后我都会更新一版实施笔记,到后来这份笔记几乎成了团队内部的标准操作手册。最后给正在实施的朋友两个建议:第一,任何组件的高可用配置都不要只停留在"装了"的程度,一定要拔一次网线验证它真的能扛住;第二,把八台机器的网络拓扑、VIP地址、服务端口、认证密钥整理成一份文档放在团队Wiki里,别只存在某一个人脑子里。集群本身再可靠,也架不住运维交接时信息断档。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 3:49:56

AIGC技术栈落地指南:弹幕游戏与向量数据库实战解析

1. 项目概述1.1 核心需求解析先把话说在前头&#xff0c;这个标题一看就不是纯粹的学术报告&#xff0c;也不是单独某一个产品的说明书。它把“腾讯云”“AIGC技术栈”“弹幕游戏”“向量数据库”串联在一起&#xff0c;潜台词其实是&#xff1a;AIGC应用要真正落地&#xff0c…

作者头像 李华
网站建设 2026/9/19 3:49:15

信息发布系统软件定制开发技术标撰写要点与实践指南

简介&#xff1a;信息发布系统软件定制开发及设备采购项目的招标投标技术标文档&#xff0c;面向投标方、系统集成商与项目管理人员&#xff0c;完整呈现了从项目背景、建设目标、建设内容到网络系统整体架构、点对点应答、报价要求、付款方式、保修条件、安全保密、现场部署等…

作者头像 李华
网站建设 2026/9/19 3:47:57

Nacos 配置更新延迟?让 Codex 走 TaoToken 查长轮询

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 3:47:54

AI短漫剧全链路制作实战:从成本核算到角色一致性控制

短漫剧这个赛道&#xff0c;今年算是彻底卷起来了。我自己手上就有两个AI漫剧项目在跑&#xff0c;日更压力下&#xff0c;最初一集做下来又慢又贵&#xff0c;后来才慢慢磨出一套能持续出片的流程。正好腾讯云这套AIGC全链路方案公布后&#xff0c;我第一时间把资料翻了个底朝…

作者头像 李华
网站建设 2026/9/19 3:46:56

Spring Boot + LangChain4j + Milvus构建企业级RAG知识库问答系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 3:46:19

前端学Docker:从镜像构建到云服务器部署全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华