1. 从单节点到高可用集群为什么以及如何规划很多朋友在刚开始接触OpenStack私有云的时候都是从单控制节点、单计算节点起步的。我自己最早也是这么干的一台机器跑所有控制服务再加一两台机器跑计算能创建虚拟机、能上网就觉得大功告成了。这种架构在学习和测试阶段完全没问题上手快配置也简单。但一旦你想把它用到生产环境比如给公司内部开发测试用或者跑一些不那么核心的业务单点故障的问题就会像一颗定时炸弹。想象一下如果你的那台唯一的控制节点因为硬件故障、系统更新或者一个误操作重启了会发生什么整个云平台的管理面会瞬间瘫痪。用户无法登录Dashboard无法创建新的虚拟机甚至正在运行的虚拟机都可能因为网络、存储服务的中断而受到影响。这绝对不是我们想要的生产级环境。所以高可用High Availability, HA的核心目标很简单消除单点故障确保关键服务在某个组件失效时依然能持续对外提供服务。对于OpenStack来说高可用主要围绕几个核心层面展开控制节点本身、数据库、消息队列和网络服务。我们今天要做的就是在国产的openEuler操作系统上把这些层面的高可用都构建起来打造一个真正“稳”的私有云。在动手之前规划至关重要。一个清晰的多节点规划能让你在后续的配置中少走很多弯路。我建议至少采用三个控制节点的集群架构。为什么是三个这是为了在保证高可用的同时避免“脑裂”问题。两个节点时一旦网络分区双方都认为对方挂了会争着当主节点导致数据混乱。三个节点或更多奇数个可以通过投票机制比如PacemakerCorosync来确保只有一个主节点存活。这里给出一个我常用的基础规划示例你可以根据实际硬件资源调整节点角色主机名管理网络IP (ens33)集群通信/存储网络IP (ens37)虚拟机隧道网络IP (ens38)主要服务控制节点1controller01192.168.100.1110.10.10.11172.16.10.11API服务、调度器、数据库集群节点、消息队列节点控制节点2controller02192.168.100.1210.10.10.12172.16.10.12API服务、调度器、数据库集群节点、消息队列节点控制节点3controller03192.168.100.1310.10.10.13172.16.10.13API服务、调度器、数据库集群节点、消息队列节点计算节点1compute01192.168.100.2110.10.10.21172.16.10.21Nova-compute, Neutron-agent计算节点2compute02192.168.100.2210.10.10.22172.16.10.22Nova-compute, Neutron-agent存储节点可选storage01192.168.100.3110.10.10.31-Cinder-volume, Swift/Object Storage网络分离是另一个关键点。把管理流量、集群内部同步流量、虚拟机数据流量分开能极大提升稳定性和性能。比如MariaDB Galera集群节点间同步数据量很大如果和管理流量挤在一起一旦管理面操作频繁比如批量创建云主机就可能导致数据库同步延迟甚至失败进而引发集群问题。所以务必为集群通信准备一张独立的网卡。在openEuler上网卡命名可能是eth0,ens33,enp0s3等等用ip a命令看清楚再配置。所有节点的时间同步NTP/Chrony也必须配置一致这是分布式系统协同工作的基础差几秒钟都可能让认证失败或者集群状态异常。先用dnf install -y chrony安装在所有节点指向同一个可靠的时间源比如控制节点01然后启动并启用服务。2. 核心服务高可用部署数据库与消息队列OpenStack的各个服务如Nova, Neutron, Cinder本身是无状态的它们的高可用可以通过负载均衡器如HAProxy代理多个节点的API服务来实现。真正的状态数据也就是整个云的“记忆”存储在数据库和消息队列里。因此MariaDB数据库和RabbitMQ消息队列的高可用是整个OpenStack高可用集群的基石必须最先搭建稳固。2.1 构建MariaDB Galera多主集群MariaDB Galera Cluster是一个同步的多主集群任何节点上的写操作都会同步到其他所有节点任何一个节点都可以处理读写请求这比传统的主从复制模式更符合高可用需求。我们在三个控制节点上部署它。首先在所有三个控制节点上安装MariaDB Galera软件包和必要的依赖。openEuler的仓库里通常包含了这些包。# 在 controller01, controller02, controller03 上分别执行 dnf install -y mariadb-server-galera mariadb-server mariadb-backup galera-4安装完成后先别急着启动服务。我们需要为每个节点编写独立的配置文件/etc/my.cnf.d/galera.cnf。下面以controller01为例注意wsrep_node_address要设置为该节点的集群通信IP也就是上面规划里的ens37的IPwsrep_cluster_name可以自定义一个名字。# 在 controller01 上编辑 /etc/my.cnf.d/galera.cnf [mysqld] binlog_formatROW default-storage-engineinnodb innodb_autoinc_lock_mode2 innodb_flush_log_at_trx_commit0 innodb_buffer_pool_size4G # 绑定地址允许其他节点连接 bind-address0.0.0.0 # Galera 配置 wsrep_onON wsrep_provider/usr/lib64/galera-4/libgalera_smm.so # 集群节点地址用逗号分隔 wsrep_cluster_addressgcomm://10.10.10.11,10.10.10.12,10.10.10.13 wsrep_cluster_nameopenstack_cluster # 当前节点地址 wsrep_node_address10.10.10.11 wsrep_node_namecontroller01 wsrep_sst_methodrsynccontroller02和controller03的配置基本相同只需要修改wsrep_node_address和wsrep_node_name为各自的信息。配置好后启动顺序有讲究。我们需要在一个节点上初始化集群其他节点再加入。在第一个节点比如controller01上以引导模式启动服务# 仅在 controller01 上执行 systemctl start mariadb --wsrep-new-cluster这个--wsrep-new-cluster参数告诉Galera“我是新集群的起点”。启动后可以用mysql -u root登录初始密码可能为空具体查看openEuler文档执行SHOW STATUS LIKE wsrep_cluster_size;应该看到值为1。然后在controller02和controller03上正常启动MariaDB服务即可# 在 controller02 和 controller03 上执行 systemctl start mariadb systemctl enable mariadb它们会自动探测到controller01上的集群并加入。此时再回到controller01上查看wsrep_cluster_size应该会变成3。这就意味着三节点的数据库集群已经搭建成功。你可以尝试在任意一个节点上创建一个数据库然后在其他节点上检查会发现已经同步过去了。2.2 配置RabbitMQ镜像队列OpenStack服务之间通过消息队列RabbitMQ进行异步通信比如创建虚拟机的请求就是由API服务发出消息调度器和计算节点消费消息来执行的。如果RabbitMQ单点故障整个云平台的任务流就会中断。RabbitMQ通过镜像队列来实现高可用将一个队列的内容复制到集群中的其他节点上即使一个节点挂了队列依然可用。首先在所有三个控制节点上安装RabbitMQ。openEuler的仓库通常提供的是比较新的版本。# 在三个控制节点上执行 dnf install -y rabbitmq-server安装完成后我们需要让三个节点的RabbitMQ实例组成一个集群。这里有一个小技巧RabbitMQ集群依赖于一个共同的.erlang.cookie文件。我们可以在第一个节点生成后把它复制到其他节点。# 1. 在 controller01 上启动 RabbitMQ 并获取 cookie systemctl start rabbitmq-server systemctl enable rabbitmq-server # 查看 cookie 文件路径通常是 /var/lib/rabbitmq/.erlang.cookie cat /var/lib/rabbitmq/.erlang.cookie # 2. 将 controller01 的 cookie 复制到 controller02 和 controller03 # 首先停止目标节点的服务如果已启动 scp /var/lib/rabbitmq/.erlang.cookie rootcontroller02:/var/lib/rabbitmq/ scp /var/lib/rabbitmq/.erlang.cookie rootcontroller03:/var/lib/rabbitmq/ # 复制后务必确保 cookie 文件的权限是 400属主是 rabbitmq chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie chmod 400 /var/lib/rabbitmq/.erlang.cookie接下来将controller02和controller03加入到controller01的集群中。在controller02上执行# 在 controller02 上执行 systemctl stop rabbitmq-server rabbitmqctl reset # 重置节点状态如果是全新安装此步可省略 rabbitmqctl join_cluster rabbitcontroller01 systemctl start rabbitmq-server在controller03上重复类似操作。之后在任意节点执行rabbitmqctl cluster_status应该能看到三个节点都在运行中。集群建好了但默认的队列还不是镜像的。我们需要设置一个策略让所有队列都自动镜像到所有节点。在任意一个节点执行rabbitmqctl set_policy ha-all ^ {ha-mode:all}这个命令创建了一个名为ha-all的策略匹配所有队列^模式是all即镜像到集群中的所有节点。这样任何一个节点宕机队列和消息都不会丢失。最后别忘了为OpenStack创建一个用户并设置权限rabbitmqctl add_user openstack 你的强密码 rabbitmqctl set_user_tags openstack administrator rabbitmqctl set_permissions openstack .* .* .*这个用户名和密码在后面配置各个OpenStack服务时会用到。3. 控制节点集群与负载均衡数据库和消息队列高可用搞定后我们就可以让OpenStack的各种API服务Keystone, Nova-api, Glance-api等跑在多个控制节点上并通过一个负载均衡器对外提供统一的访问入口。这样即使某个控制节点的某个服务挂掉请求会被自动转发到其他健康的节点。3.1 使用HAProxy实现四层负载均衡负载均衡器本身也不能是单点不过为了简化初始部署我们可以先在一台独立的机器上部署HAProxy或者干脆就在三个控制节点中的某一个上部署。在生产环境中负载均衡器本身也需要高可用通常会用KeepalivedHAProxy的方案这里我们先聚焦HAProxy的配置。假设我们在controller01上安装和配置HAProxy作为负载均衡器VIP虚拟IP为192.168.100.100。用户将通过这个VIP访问OpenStack Dashboard和API。# 在作为负载均衡器的节点上执行如 controller01 dnf install -y haproxy编辑HAProxy的配置文件/etc/haproxy/haproxy.cfg我们需要为几个关键服务配置后端池。这里以Keystone认证服务和HorizonDashboard为例global log /dev/log local0 maxconn 10000 user haproxy group haproxy daemon defaults log global mode http option httplog option dontlognull timeout connect 5000ms timeout client 50000ms timeout server 50000ms # 监控页面可以通过 http://VIP:8404/stats 查看 listen stats bind *:8404 stats enable stats uri /stats stats refresh 30s stats auth admin:你的监控密码 # 前端Keystone API (端口5000) frontend keystone_front bind 192.168.100.100:5000 default_backend keystone_back # 后端三个控制节点的Keystone服务 backend keystone_back balance source option httpchk GET /v3 HTTP/1.0 server controller01 192.168.100.11:5000 check inter 10s rise 2 fall 3 server controller02 192.168.100.12:5000 check inter 10s rise 2 fall 3 server controller03 192.168.100.13:5000 check inter 10s rise 2 fall 3 # 前端Horizon Dashboard (端口80) frontend horizon_front bind 192.168.100.100:80 default_backend horizon_back # 后端三个控制节点的Apache服务 backend horizon_back balance roundrobin option httpchk GET /dashboard HTTP/1.0 server controller01 192.168.100.11:80 check inter 10s rise 2 fall 3 server controller02 192.168.100.12:80 check inter 10s rise 2 fall 3 server controller03 192.168.100.13:80 check inter 10s rise 2 fall 3 # 类似地你还需要为 Nova-api (8774), Glance-api (9292), Neutron-server (9696) 等添加 frontend 和 backend 配置配置中option httpchk是健康检查HAProxy会定期向后端发送HTTP请求如果失败则认为该节点不健康不再转发流量给它。balance source表示基于源IP进行会话保持这样同一个用户的请求会固定发往同一个后端在某些场景下更合适。保存配置后启动并启用HAProxysystemctl enable --now haproxy。用ss -tlnp | grep haproxy检查端口是否监听。现在你访问http://192.168.100.100/dashboard就应该能看到登录页面了流量会被均匀分配到三个控制节点的Horizon服务上。3.2 在多控制节点上部署OpenStack服务现在我们需要在三个控制节点上安装和配置完全相同的OpenStack服务。以Keystone为例在所有三个节点上安装dnf install -y openstack-keystone httpd mod_wsgi关键的一步是修改Keystone的配置文件/etc/keystone/keystone.conf将数据库连接和RabbitMQ连接指向我们刚刚搭建的高可用集群。[database] # 连接字符串指向MariaDB Galera集群中的任意一个节点即可 connection mysqlpymysql://keystone:你的密码192.168.100.11/keystone?charsetutf8 # 也可以写成多个节点用逗号分隔驱动会尝试连接 # connection mysqlpymysql://keystone:密码192.168.100.11,192.168.100.12,192.168.100.13/keystone?charsetutf8 [oslo_messaging_rabbit] # RabbitMQ连接地址列出所有集群节点 rabbit_hosts 192.168.100.11:5672,192.168.100.12:5672,192.168.100.13:5672 rabbit_userid openstack rabbit_password 你的RabbitMQ密码 rabbit_ha_queues true # 启用高可用队列支持注意rabbit_ha_queues true这个选项很重要它让OpenStack服务知道RabbitMQ是集群模式并能正确处理队列故障转移。其他服务如Nova, Glance, Neutron的配置方式类似都需要修改[database]和[oslo_messaging_rabbit]部分指向集群地址。配置完成后在每个节点上初始化数据库只需要在一个节点上运行keystone-manage db_sync即可因为Galera是多主同步的然后启动服务。记得将每个服务的API通过Apache或本身绑定到所有接口0.0.0.0以便HAProxy能够访问。4. 网络服务Neutron的高可用与性能调优网络是云的血管Neutron服务的高可用直接影响到虚拟机的网络连通性。Neutron的高可用主要涉及neutron-server提供API和各个Agent如L3 Agent, DHCP Agent, Metadata Agent。neutron-server可以像其他API服务一样部署在多个控制节点上通过HAProxy负载均衡。而Agent的高可用则需要通过分布式虚拟路由DVR或L3 Agent高可用模式HA Router来实现。4.1 配置Neutron Server集群与L3高可用首先在三个控制节点上安装neutron-server和相关插件包这里以Linux Bridge为例dnf install -y openstack-neutron openstack-neutron-linuxbridge openstack-neutron-ml2编辑/etc/neutron/neutron.conf配置数据库和RabbitMQ集群连接和前面Keystone的做法一样。然后配置/etc/neutron/plugins/ml2/ml2_conf.ini启用必要的机制驱动和类型驱动。对于L3路由服务传统部署是集中在一个或几个网络节点上这成了单点。OpenStack提供了两种解决方案分布式虚拟路由DVR将路由功能分散到每个计算节点上。东-西向流量和带有浮动IP的南-北向流量直接在计算节点本地路由性能好但配置稍复杂。L3 Agent高可用HA Router多个网络节点运行L3 Agent通过VRRP类似Keepalived协议选举出一个主节点来承载路由器。主节点故障时备用节点自动接管。对于中小规模集群我更喜欢用L3 Agent高可用因为它对现有网络架构改动小更接近传统网络思维。配置起来也不难。首先在至少两个控制节点或独立的网络节点上安装并配置L3 Agent。dnf install -y openstack-neutron-l3-agent编辑/etc/neutron/l3_agent.ini[DEFAULT] interface_driver linuxbridge ha_vrrp_auth_type PASS ha_vrrp_auth_password 一个安全的VRRP密码然后在Neutron中创建一个高可用路由器时需要指定高可用参数。通过Dashboard创建时选择“高可用”选项或者用命令行openstack router create --ha my_ha_routerNeutron会自动在配置了L3 Agent的节点中选举主备并为路由器的每个子网接口创建一对VRRP虚拟IP。这样即使主L3 Agent节点宕机备用节点能在秒级内接管虚拟机的外网访问几乎无感知。4.2 结合openEuler系统特性的网络与存储优化openEuler作为一款高性能的服务器操作系统在内核和基础组件上做了很多优化我们可以利用这些特性来提升OpenStack的网络和存储性能。网络优化调整内核参数编辑/etc/sysctl.conf增加以下参数优化TCP性能和连接数这对于处理大量虚拟机网络连接很有帮助。net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_fin_timeout 30 net.ipv4.tcp_max_syn_backlog 8192 net.ipv4.ip_local_port_range 10000 65000 net.core.somaxconn 65535 net.core.netdev_max_backlog 5000执行sysctl -p使配置生效。使用更高效的内核转发确保net.ipv4.ip_forward 1和net.ipv4.conf.all.rp_filter 0针对某些Overlay网络场景已设置。存储优化 如果你的计算节点使用本地存储如Ceph的RBD后端是更好的生产选择但本地盘更简单可以对文件系统进行优化。openEuler默认的XFS或EXT4性能都不错但挂载时可以加上一些优化选项。对于虚拟机镜像存储的目录比如/var/lib/nova/instances在/etc/fstab中可以考虑这样配置/dev/sdb1 /var/lib/nova/instances xfs defaults,noatime,nodiratime,inode64 0 0noatime和nodiratime可以减少不必要的磁盘写操作提升IO性能。另外对于QEMU/KVM可以调整I/O调度器。在openEuler上对于NVMe SSD通常使用none即noop调度器对于SATA/SAS硬盘使用deadline或mq-deadline可能更合适。可以通过cat /sys/block/sda/queue/scheduler查看当前调度器使用echo deadline /sys/block/sda/queue/scheduler临时修改。5. 集群故障诊断与恢复实战即使搭建了高可用集群运维过程中也难免会遇到问题。掌握一套清晰的诊断和恢复流程能让你在问题发生时从容应对。下面我分享几个最常见的故障场景和排查思路。5.1 脑裂Split-Brain与集群状态异常场景MariaDB Galera集群中部分节点无法写入数据或者wsrep_cluster_size显示节点数不对。诊断登录各个节点检查MariaDB服务状态systemctl status mariadb。登录MySQL查看集群状态SHOW STATUS LIKE wsrep%;。重点关注wsrep_cluster_size集群当前认为的成员数量。wsrep_cluster_status节点状态Primary表示正常Non-Primary或Disconnected表示有问题。wsrep_ready是否为ON表示节点是否可以处理查询。wsrep_connected网络连接是否正常。检查集群通信网络ens37是否通畅用ping测试节点间连通性。检查防火墙是否放行了Galera所需的端口通常是4567, 4568, 4444。恢复 如果出现脑裂比如网络分区导致形成两个独立集群需要人工干预确定哪个分区保留数据并重启另一个分区。选择一个你认为数据最新的分区比如包含原主节点controller01的分区在该分区的每个节点上确保wsrep_cluster_status是Primary。在另一个“失联”的分区节点上停止MariaDB服务systemctl stop mariadb。在要保留的分区的一个节点上如果集群状态不健康可能需要重新引导。先停止该节点服务然后以引导模式启动systemctl start mariadb --wsrep-new-cluster。将保留分区内的其他节点正常启动加入。对于失联分区的节点清空Galera缓存和数据目录危险操作确保数据已丢失或可从主分区同步然后修改配置文件将wsrep_cluster_address指向当前健康集群的任意节点地址再正常启动服务它会作为一个新节点从主集群同步全量数据。5.2 服务失联与负载均衡排查场景用户无法登录Dashboard或者API调用失败。诊断检查VIP和负载均衡器首先ping一下VIP192.168.100.100是否可达。然后访问HAProxy的监控页面http://VIP:8404/stats查看后端各个服务的状态。红色或DOWN状态的后端节点就是有问题的。检查具体后端服务登录被标记为DOWN的节点检查对应的OpenStack服务是否运行。例如Keystone API是否在监听5000端口ss -tlnp | grep :5000。检查服务日志journalctl -u httpd -f如果Keystone通过Apache运行或journalctl -u openstack-keystone -f。检查依赖服务如果服务本身在运行但功能异常检查其依赖。最常见的是数据库和消息队列。在控制节点上尝试连接数据库集群mysql -h 192.168.100.11 -u keystone -p。检查RabbitMQ集群状态rabbitmqctl cluster_status。检查防火墙这是最容易被忽略的。确保控制节点之间、负载均衡器与后端节点之间开放了必要的端口如Keystone的5000MySQL的3306RabbitMQ的5672等等。openEuler默认的防火墙工具可能是firewalld用firewall-cmd --list-all查看规则。恢复 根据诊断结果对症下药。如果是服务进程挂了重启服务systemctl restart openstack-keystone。如果是数据库连接失败按5.1节检查数据库集群。如果是消息队列连接失败检查RabbitMQ服务状态和网络。如果是防火墙问题添加规则firewall-cmd --permanent --add-port5000/tcp firewall-cmd --reload。5.3 虚拟机实例启动失败场景在Dashboard上创建虚拟机状态长时间卡在“构建中”最后变成“错误”。诊断查看失败详情在Dashboard的“管理员”-“计算”-“实例”中点击失败实例查看错误信息。常见的错误有“No valid host was found”找不到合适的主机、“Build of instance ... aborted”实例构建中止。查看计算节点日志登录到计算节点查看Nova-compute日志journalctl -u openstack-nova-compute -f | tail -100。这里通常有最详细的失败原因比如资源不足、镜像下载失败、网络配置错误等。检查调度器日志在控制节点查看Nova-scheduler日志journalctl -u openstack-nova-scheduler -f看它为什么没有选择某个计算节点。检查Hypervisor资源在计算节点上用virsh list --all查看Libvirt管理的虚拟机状态。用free -h和df -h检查内存和磁盘空间是否充足。恢复资源不足扩容计算节点或迁移部分虚拟机。镜像问题检查Glance服务确认镜像状态为active并且计算节点能通过网络访问Glance的API通常是9292端口。网络问题检查计算节点上的Neutron Linux Bridge Agent日志journalctl -u neutron-linuxbridge-agent -f。确认网桥如brqXXXX已创建并且虚拟机的tap设备已正确接入。配置错误仔细核对计算节点的/etc/nova/nova.conf和/etc/neutron/plugins/ml2/linuxbridge_agent.ini确保物理网卡映射、防火墙驱动等配置正确。搭建和维护一个高可用的OpenStack集群确实比单节点复杂但带来的稳定性和可靠性提升是巨大的。这套架构足以支撑起一个中小型企业的生产环境需求。在实际操作中最花时间的往往不是安装配置而是遇到问题时的排查。我的经验是一定要善用日志OpenStack各组件的日志非常详细绝大多数问题都能在日志里找到线索。另外做好关键配置文件的备份在每次重大变更前在测试环境先验证一遍能帮你避开很多坑。
实战指南:在openEuler上构建高可用OpenStack私有云集群(含配置优化与故障排查)
1. 从单节点到高可用集群为什么以及如何规划很多朋友在刚开始接触OpenStack私有云的时候都是从单控制节点、单计算节点起步的。我自己最早也是这么干的一台机器跑所有控制服务再加一两台机器跑计算能创建虚拟机、能上网就觉得大功告成了。这种架构在学习和测试阶段完全没问题上手快配置也简单。但一旦你想把它用到生产环境比如给公司内部开发测试用或者跑一些不那么核心的业务单点故障的问题就会像一颗定时炸弹。想象一下如果你的那台唯一的控制节点因为硬件故障、系统更新或者一个误操作重启了会发生什么整个云平台的管理面会瞬间瘫痪。用户无法登录Dashboard无法创建新的虚拟机甚至正在运行的虚拟机都可能因为网络、存储服务的中断而受到影响。这绝对不是我们想要的生产级环境。所以高可用High Availability, HA的核心目标很简单消除单点故障确保关键服务在某个组件失效时依然能持续对外提供服务。对于OpenStack来说高可用主要围绕几个核心层面展开控制节点本身、数据库、消息队列和网络服务。我们今天要做的就是在国产的openEuler操作系统上把这些层面的高可用都构建起来打造一个真正“稳”的私有云。在动手之前规划至关重要。一个清晰的多节点规划能让你在后续的配置中少走很多弯路。我建议至少采用三个控制节点的集群架构。为什么是三个这是为了在保证高可用的同时避免“脑裂”问题。两个节点时一旦网络分区双方都认为对方挂了会争着当主节点导致数据混乱。三个节点或更多奇数个可以通过投票机制比如PacemakerCorosync来确保只有一个主节点存活。这里给出一个我常用的基础规划示例你可以根据实际硬件资源调整节点角色主机名管理网络IP (ens33)集群通信/存储网络IP (ens37)虚拟机隧道网络IP (ens38)主要服务控制节点1controller01192.168.100.1110.10.10.11172.16.10.11API服务、调度器、数据库集群节点、消息队列节点控制节点2controller02192.168.100.1210.10.10.12172.16.10.12API服务、调度器、数据库集群节点、消息队列节点控制节点3controller03192.168.100.1310.10.10.13172.16.10.13API服务、调度器、数据库集群节点、消息队列节点计算节点1compute01192.168.100.2110.10.10.21172.16.10.21Nova-compute, Neutron-agent计算节点2compute02192.168.100.2210.10.10.22172.16.10.22Nova-compute, Neutron-agent存储节点可选storage01192.168.100.3110.10.10.31-Cinder-volume, Swift/Object Storage网络分离是另一个关键点。把管理流量、集群内部同步流量、虚拟机数据流量分开能极大提升稳定性和性能。比如MariaDB Galera集群节点间同步数据量很大如果和管理流量挤在一起一旦管理面操作频繁比如批量创建云主机就可能导致数据库同步延迟甚至失败进而引发集群问题。所以务必为集群通信准备一张独立的网卡。在openEuler上网卡命名可能是eth0,ens33,enp0s3等等用ip a命令看清楚再配置。所有节点的时间同步NTP/Chrony也必须配置一致这是分布式系统协同工作的基础差几秒钟都可能让认证失败或者集群状态异常。先用dnf install -y chrony安装在所有节点指向同一个可靠的时间源比如控制节点01然后启动并启用服务。2. 核心服务高可用部署数据库与消息队列OpenStack的各个服务如Nova, Neutron, Cinder本身是无状态的它们的高可用可以通过负载均衡器如HAProxy代理多个节点的API服务来实现。真正的状态数据也就是整个云的“记忆”存储在数据库和消息队列里。因此MariaDB数据库和RabbitMQ消息队列的高可用是整个OpenStack高可用集群的基石必须最先搭建稳固。2.1 构建MariaDB Galera多主集群MariaDB Galera Cluster是一个同步的多主集群任何节点上的写操作都会同步到其他所有节点任何一个节点都可以处理读写请求这比传统的主从复制模式更符合高可用需求。我们在三个控制节点上部署它。首先在所有三个控制节点上安装MariaDB Galera软件包和必要的依赖。openEuler的仓库里通常包含了这些包。# 在 controller01, controller02, controller03 上分别执行 dnf install -y mariadb-server-galera mariadb-server mariadb-backup galera-4安装完成后先别急着启动服务。我们需要为每个节点编写独立的配置文件/etc/my.cnf.d/galera.cnf。下面以controller01为例注意wsrep_node_address要设置为该节点的集群通信IP也就是上面规划里的ens37的IPwsrep_cluster_name可以自定义一个名字。# 在 controller01 上编辑 /etc/my.cnf.d/galera.cnf [mysqld] binlog_formatROW default-storage-engineinnodb innodb_autoinc_lock_mode2 innodb_flush_log_at_trx_commit0 innodb_buffer_pool_size4G # 绑定地址允许其他节点连接 bind-address0.0.0.0 # Galera 配置 wsrep_onON wsrep_provider/usr/lib64/galera-4/libgalera_smm.so # 集群节点地址用逗号分隔 wsrep_cluster_addressgcomm://10.10.10.11,10.10.10.12,10.10.10.13 wsrep_cluster_nameopenstack_cluster # 当前节点地址 wsrep_node_address10.10.10.11 wsrep_node_namecontroller01 wsrep_sst_methodrsynccontroller02和controller03的配置基本相同只需要修改wsrep_node_address和wsrep_node_name为各自的信息。配置好后启动顺序有讲究。我们需要在一个节点上初始化集群其他节点再加入。在第一个节点比如controller01上以引导模式启动服务# 仅在 controller01 上执行 systemctl start mariadb --wsrep-new-cluster这个--wsrep-new-cluster参数告诉Galera“我是新集群的起点”。启动后可以用mysql -u root登录初始密码可能为空具体查看openEuler文档执行SHOW STATUS LIKE wsrep_cluster_size;应该看到值为1。然后在controller02和controller03上正常启动MariaDB服务即可# 在 controller02 和 controller03 上执行 systemctl start mariadb systemctl enable mariadb它们会自动探测到controller01上的集群并加入。此时再回到controller01上查看wsrep_cluster_size应该会变成3。这就意味着三节点的数据库集群已经搭建成功。你可以尝试在任意一个节点上创建一个数据库然后在其他节点上检查会发现已经同步过去了。2.2 配置RabbitMQ镜像队列OpenStack服务之间通过消息队列RabbitMQ进行异步通信比如创建虚拟机的请求就是由API服务发出消息调度器和计算节点消费消息来执行的。如果RabbitMQ单点故障整个云平台的任务流就会中断。RabbitMQ通过镜像队列来实现高可用将一个队列的内容复制到集群中的其他节点上即使一个节点挂了队列依然可用。首先在所有三个控制节点上安装RabbitMQ。openEuler的仓库通常提供的是比较新的版本。# 在三个控制节点上执行 dnf install -y rabbitmq-server安装完成后我们需要让三个节点的RabbitMQ实例组成一个集群。这里有一个小技巧RabbitMQ集群依赖于一个共同的.erlang.cookie文件。我们可以在第一个节点生成后把它复制到其他节点。# 1. 在 controller01 上启动 RabbitMQ 并获取 cookie systemctl start rabbitmq-server systemctl enable rabbitmq-server # 查看 cookie 文件路径通常是 /var/lib/rabbitmq/.erlang.cookie cat /var/lib/rabbitmq/.erlang.cookie # 2. 将 controller01 的 cookie 复制到 controller02 和 controller03 # 首先停止目标节点的服务如果已启动 scp /var/lib/rabbitmq/.erlang.cookie rootcontroller02:/var/lib/rabbitmq/ scp /var/lib/rabbitmq/.erlang.cookie rootcontroller03:/var/lib/rabbitmq/ # 复制后务必确保 cookie 文件的权限是 400属主是 rabbitmq chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie chmod 400 /var/lib/rabbitmq/.erlang.cookie接下来将controller02和controller03加入到controller01的集群中。在controller02上执行# 在 controller02 上执行 systemctl stop rabbitmq-server rabbitmqctl reset # 重置节点状态如果是全新安装此步可省略 rabbitmqctl join_cluster rabbitcontroller01 systemctl start rabbitmq-server在controller03上重复类似操作。之后在任意节点执行rabbitmqctl cluster_status应该能看到三个节点都在运行中。集群建好了但默认的队列还不是镜像的。我们需要设置一个策略让所有队列都自动镜像到所有节点。在任意一个节点执行rabbitmqctl set_policy ha-all ^ {ha-mode:all}这个命令创建了一个名为ha-all的策略匹配所有队列^模式是all即镜像到集群中的所有节点。这样任何一个节点宕机队列和消息都不会丢失。最后别忘了为OpenStack创建一个用户并设置权限rabbitmqctl add_user openstack 你的强密码 rabbitmqctl set_user_tags openstack administrator rabbitmqctl set_permissions openstack .* .* .*这个用户名和密码在后面配置各个OpenStack服务时会用到。3. 控制节点集群与负载均衡数据库和消息队列高可用搞定后我们就可以让OpenStack的各种API服务Keystone, Nova-api, Glance-api等跑在多个控制节点上并通过一个负载均衡器对外提供统一的访问入口。这样即使某个控制节点的某个服务挂掉请求会被自动转发到其他健康的节点。3.1 使用HAProxy实现四层负载均衡负载均衡器本身也不能是单点不过为了简化初始部署我们可以先在一台独立的机器上部署HAProxy或者干脆就在三个控制节点中的某一个上部署。在生产环境中负载均衡器本身也需要高可用通常会用KeepalivedHAProxy的方案这里我们先聚焦HAProxy的配置。假设我们在controller01上安装和配置HAProxy作为负载均衡器VIP虚拟IP为192.168.100.100。用户将通过这个VIP访问OpenStack Dashboard和API。# 在作为负载均衡器的节点上执行如 controller01 dnf install -y haproxy编辑HAProxy的配置文件/etc/haproxy/haproxy.cfg我们需要为几个关键服务配置后端池。这里以Keystone认证服务和HorizonDashboard为例global log /dev/log local0 maxconn 10000 user haproxy group haproxy daemon defaults log global mode http option httplog option dontlognull timeout connect 5000ms timeout client 50000ms timeout server 50000ms # 监控页面可以通过 http://VIP:8404/stats 查看 listen stats bind *:8404 stats enable stats uri /stats stats refresh 30s stats auth admin:你的监控密码 # 前端Keystone API (端口5000) frontend keystone_front bind 192.168.100.100:5000 default_backend keystone_back # 后端三个控制节点的Keystone服务 backend keystone_back balance source option httpchk GET /v3 HTTP/1.0 server controller01 192.168.100.11:5000 check inter 10s rise 2 fall 3 server controller02 192.168.100.12:5000 check inter 10s rise 2 fall 3 server controller03 192.168.100.13:5000 check inter 10s rise 2 fall 3 # 前端Horizon Dashboard (端口80) frontend horizon_front bind 192.168.100.100:80 default_backend horizon_back # 后端三个控制节点的Apache服务 backend horizon_back balance roundrobin option httpchk GET /dashboard HTTP/1.0 server controller01 192.168.100.11:80 check inter 10s rise 2 fall 3 server controller02 192.168.100.12:80 check inter 10s rise 2 fall 3 server controller03 192.168.100.13:80 check inter 10s rise 2 fall 3 # 类似地你还需要为 Nova-api (8774), Glance-api (9292), Neutron-server (9696) 等添加 frontend 和 backend 配置配置中option httpchk是健康检查HAProxy会定期向后端发送HTTP请求如果失败则认为该节点不健康不再转发流量给它。balance source表示基于源IP进行会话保持这样同一个用户的请求会固定发往同一个后端在某些场景下更合适。保存配置后启动并启用HAProxysystemctl enable --now haproxy。用ss -tlnp | grep haproxy检查端口是否监听。现在你访问http://192.168.100.100/dashboard就应该能看到登录页面了流量会被均匀分配到三个控制节点的Horizon服务上。3.2 在多控制节点上部署OpenStack服务现在我们需要在三个控制节点上安装和配置完全相同的OpenStack服务。以Keystone为例在所有三个节点上安装dnf install -y openstack-keystone httpd mod_wsgi关键的一步是修改Keystone的配置文件/etc/keystone/keystone.conf将数据库连接和RabbitMQ连接指向我们刚刚搭建的高可用集群。[database] # 连接字符串指向MariaDB Galera集群中的任意一个节点即可 connection mysqlpymysql://keystone:你的密码192.168.100.11/keystone?charsetutf8 # 也可以写成多个节点用逗号分隔驱动会尝试连接 # connection mysqlpymysql://keystone:密码192.168.100.11,192.168.100.12,192.168.100.13/keystone?charsetutf8 [oslo_messaging_rabbit] # RabbitMQ连接地址列出所有集群节点 rabbit_hosts 192.168.100.11:5672,192.168.100.12:5672,192.168.100.13:5672 rabbit_userid openstack rabbit_password 你的RabbitMQ密码 rabbit_ha_queues true # 启用高可用队列支持注意rabbit_ha_queues true这个选项很重要它让OpenStack服务知道RabbitMQ是集群模式并能正确处理队列故障转移。其他服务如Nova, Glance, Neutron的配置方式类似都需要修改[database]和[oslo_messaging_rabbit]部分指向集群地址。配置完成后在每个节点上初始化数据库只需要在一个节点上运行keystone-manage db_sync即可因为Galera是多主同步的然后启动服务。记得将每个服务的API通过Apache或本身绑定到所有接口0.0.0.0以便HAProxy能够访问。4. 网络服务Neutron的高可用与性能调优网络是云的血管Neutron服务的高可用直接影响到虚拟机的网络连通性。Neutron的高可用主要涉及neutron-server提供API和各个Agent如L3 Agent, DHCP Agent, Metadata Agent。neutron-server可以像其他API服务一样部署在多个控制节点上通过HAProxy负载均衡。而Agent的高可用则需要通过分布式虚拟路由DVR或L3 Agent高可用模式HA Router来实现。4.1 配置Neutron Server集群与L3高可用首先在三个控制节点上安装neutron-server和相关插件包这里以Linux Bridge为例dnf install -y openstack-neutron openstack-neutron-linuxbridge openstack-neutron-ml2编辑/etc/neutron/neutron.conf配置数据库和RabbitMQ集群连接和前面Keystone的做法一样。然后配置/etc/neutron/plugins/ml2/ml2_conf.ini启用必要的机制驱动和类型驱动。对于L3路由服务传统部署是集中在一个或几个网络节点上这成了单点。OpenStack提供了两种解决方案分布式虚拟路由DVR将路由功能分散到每个计算节点上。东-西向流量和带有浮动IP的南-北向流量直接在计算节点本地路由性能好但配置稍复杂。L3 Agent高可用HA Router多个网络节点运行L3 Agent通过VRRP类似Keepalived协议选举出一个主节点来承载路由器。主节点故障时备用节点自动接管。对于中小规模集群我更喜欢用L3 Agent高可用因为它对现有网络架构改动小更接近传统网络思维。配置起来也不难。首先在至少两个控制节点或独立的网络节点上安装并配置L3 Agent。dnf install -y openstack-neutron-l3-agent编辑/etc/neutron/l3_agent.ini[DEFAULT] interface_driver linuxbridge ha_vrrp_auth_type PASS ha_vrrp_auth_password 一个安全的VRRP密码然后在Neutron中创建一个高可用路由器时需要指定高可用参数。通过Dashboard创建时选择“高可用”选项或者用命令行openstack router create --ha my_ha_routerNeutron会自动在配置了L3 Agent的节点中选举主备并为路由器的每个子网接口创建一对VRRP虚拟IP。这样即使主L3 Agent节点宕机备用节点能在秒级内接管虚拟机的外网访问几乎无感知。4.2 结合openEuler系统特性的网络与存储优化openEuler作为一款高性能的服务器操作系统在内核和基础组件上做了很多优化我们可以利用这些特性来提升OpenStack的网络和存储性能。网络优化调整内核参数编辑/etc/sysctl.conf增加以下参数优化TCP性能和连接数这对于处理大量虚拟机网络连接很有帮助。net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_fin_timeout 30 net.ipv4.tcp_max_syn_backlog 8192 net.ipv4.ip_local_port_range 10000 65000 net.core.somaxconn 65535 net.core.netdev_max_backlog 5000执行sysctl -p使配置生效。使用更高效的内核转发确保net.ipv4.ip_forward 1和net.ipv4.conf.all.rp_filter 0针对某些Overlay网络场景已设置。存储优化 如果你的计算节点使用本地存储如Ceph的RBD后端是更好的生产选择但本地盘更简单可以对文件系统进行优化。openEuler默认的XFS或EXT4性能都不错但挂载时可以加上一些优化选项。对于虚拟机镜像存储的目录比如/var/lib/nova/instances在/etc/fstab中可以考虑这样配置/dev/sdb1 /var/lib/nova/instances xfs defaults,noatime,nodiratime,inode64 0 0noatime和nodiratime可以减少不必要的磁盘写操作提升IO性能。另外对于QEMU/KVM可以调整I/O调度器。在openEuler上对于NVMe SSD通常使用none即noop调度器对于SATA/SAS硬盘使用deadline或mq-deadline可能更合适。可以通过cat /sys/block/sda/queue/scheduler查看当前调度器使用echo deadline /sys/block/sda/queue/scheduler临时修改。5. 集群故障诊断与恢复实战即使搭建了高可用集群运维过程中也难免会遇到问题。掌握一套清晰的诊断和恢复流程能让你在问题发生时从容应对。下面我分享几个最常见的故障场景和排查思路。5.1 脑裂Split-Brain与集群状态异常场景MariaDB Galera集群中部分节点无法写入数据或者wsrep_cluster_size显示节点数不对。诊断登录各个节点检查MariaDB服务状态systemctl status mariadb。登录MySQL查看集群状态SHOW STATUS LIKE wsrep%;。重点关注wsrep_cluster_size集群当前认为的成员数量。wsrep_cluster_status节点状态Primary表示正常Non-Primary或Disconnected表示有问题。wsrep_ready是否为ON表示节点是否可以处理查询。wsrep_connected网络连接是否正常。检查集群通信网络ens37是否通畅用ping测试节点间连通性。检查防火墙是否放行了Galera所需的端口通常是4567, 4568, 4444。恢复 如果出现脑裂比如网络分区导致形成两个独立集群需要人工干预确定哪个分区保留数据并重启另一个分区。选择一个你认为数据最新的分区比如包含原主节点controller01的分区在该分区的每个节点上确保wsrep_cluster_status是Primary。在另一个“失联”的分区节点上停止MariaDB服务systemctl stop mariadb。在要保留的分区的一个节点上如果集群状态不健康可能需要重新引导。先停止该节点服务然后以引导模式启动systemctl start mariadb --wsrep-new-cluster。将保留分区内的其他节点正常启动加入。对于失联分区的节点清空Galera缓存和数据目录危险操作确保数据已丢失或可从主分区同步然后修改配置文件将wsrep_cluster_address指向当前健康集群的任意节点地址再正常启动服务它会作为一个新节点从主集群同步全量数据。5.2 服务失联与负载均衡排查场景用户无法登录Dashboard或者API调用失败。诊断检查VIP和负载均衡器首先ping一下VIP192.168.100.100是否可达。然后访问HAProxy的监控页面http://VIP:8404/stats查看后端各个服务的状态。红色或DOWN状态的后端节点就是有问题的。检查具体后端服务登录被标记为DOWN的节点检查对应的OpenStack服务是否运行。例如Keystone API是否在监听5000端口ss -tlnp | grep :5000。检查服务日志journalctl -u httpd -f如果Keystone通过Apache运行或journalctl -u openstack-keystone -f。检查依赖服务如果服务本身在运行但功能异常检查其依赖。最常见的是数据库和消息队列。在控制节点上尝试连接数据库集群mysql -h 192.168.100.11 -u keystone -p。检查RabbitMQ集群状态rabbitmqctl cluster_status。检查防火墙这是最容易被忽略的。确保控制节点之间、负载均衡器与后端节点之间开放了必要的端口如Keystone的5000MySQL的3306RabbitMQ的5672等等。openEuler默认的防火墙工具可能是firewalld用firewall-cmd --list-all查看规则。恢复 根据诊断结果对症下药。如果是服务进程挂了重启服务systemctl restart openstack-keystone。如果是数据库连接失败按5.1节检查数据库集群。如果是消息队列连接失败检查RabbitMQ服务状态和网络。如果是防火墙问题添加规则firewall-cmd --permanent --add-port5000/tcp firewall-cmd --reload。5.3 虚拟机实例启动失败场景在Dashboard上创建虚拟机状态长时间卡在“构建中”最后变成“错误”。诊断查看失败详情在Dashboard的“管理员”-“计算”-“实例”中点击失败实例查看错误信息。常见的错误有“No valid host was found”找不到合适的主机、“Build of instance ... aborted”实例构建中止。查看计算节点日志登录到计算节点查看Nova-compute日志journalctl -u openstack-nova-compute -f | tail -100。这里通常有最详细的失败原因比如资源不足、镜像下载失败、网络配置错误等。检查调度器日志在控制节点查看Nova-scheduler日志journalctl -u openstack-nova-scheduler -f看它为什么没有选择某个计算节点。检查Hypervisor资源在计算节点上用virsh list --all查看Libvirt管理的虚拟机状态。用free -h和df -h检查内存和磁盘空间是否充足。恢复资源不足扩容计算节点或迁移部分虚拟机。镜像问题检查Glance服务确认镜像状态为active并且计算节点能通过网络访问Glance的API通常是9292端口。网络问题检查计算节点上的Neutron Linux Bridge Agent日志journalctl -u neutron-linuxbridge-agent -f。确认网桥如brqXXXX已创建并且虚拟机的tap设备已正确接入。配置错误仔细核对计算节点的/etc/nova/nova.conf和/etc/neutron/plugins/ml2/linuxbridge_agent.ini确保物理网卡映射、防火墙驱动等配置正确。搭建和维护一个高可用的OpenStack集群确实比单节点复杂但带来的稳定性和可靠性提升是巨大的。这套架构足以支撑起一个中小型企业的生产环境需求。在实际操作中最花时间的往往不是安装配置而是遇到问题时的排查。我的经验是一定要善用日志OpenStack各组件的日志非常详细绝大多数问题都能在日志里找到线索。另外做好关键配置文件的备份在每次重大变更前在测试环境先验证一遍能帮你避开很多坑。