简介:这份文档面向企业云计算架构师与运维工程师,聚焦OpenStack高可用集群的落地实施,提炼自某企业私有云项目的真实部署经验。内容围绕规划与部署、网络分区、存储选型、控制节点HA策略、SDN集成开发及硬件兼容性等关键环节展开,涵盖PXE LiveCD、定制安装盘与脚本安装三种部署路径的取舍,以及Ceph、Glusterfs等分布式存储与Pacemaker、corosync高可用工具的实践思路,适合具备一定Linux与虚拟化基础、需要搭建稳定云平台的读者参考。资源包内含1个docx文档,约460KB,以方法论述为主、细节描述为辅,便于快速理解整体架构与实施脉络。目前已有155人学习。读者可从中获取网络规划分区、存储与计算超融合部署、SDN应用开发及运维减负等具体经验,并借鉴作者在兼容性测试与客户沟通方面的实操建议,为自身项目提供可复用的参考框架。
1. OpenStack 高可用集群:从"能跑起来"到"敢上生产"的那道坎
很多团队第一次搭 OpenStack,单控制节点跑得挺欢,虚拟机创建、镜像上传、网络打通都没问题。可一旦这套环境要承载真实业务,问题就来了——控制节点一重启,整个云平台 API 全挂,已经跑着的虚拟机虽然没死,但没人能管它们了。这就是单点故障的典型翻车现场。OpenStack 高可用集群要解决的核心问题就一个:让控制平面的每一个组件都没有单点,任意一台机器挂了,API 照常响应,数据库照常读写,消息队列照常投递。这套方案适合已经会用 Kolla-Ansible 部署单节点 OpenStack、准备把环境推向生产、或者正在做私有云高可用改造的工程师。下面我从架构选型一路讲到参数调优和踩坑记录,都是实际部署中验证过的路径。
2. 控制平面高可用架构:哪些组件必须做冗余,哪些可以缓一缓
2.1 三个控制节点起步的架构逻辑
OpenStack 控制平面包含的组件很多:Keystone(认证)、Nova API(计算接口)、Neutron Server(网络接口)、Glance API(镜像)、Placement(资源调度)、Horizon(面板),再加上底层的 MariaDB(数据库)、RabbitMQ(消息队列)、Memcached(缓存)。这些组件的高可用策略并不完全一样。
我一般建议最少三个控制节点。为什么不是两个?因为 MariaDB 的 Galera 集群和 RabbitMQ 的镜像队列都需要多数派(quorum)来防止脑裂。三个节点允许挂一个,集群仍能正常仲裁;两个节点挂一个就只剩单节点,失去多数派,数据库会拒绝写入。这是硬性约束,不是拍脑袋定的。
三个控制节点之上,还需要至少两个计算节点来跑实际业务虚拟机。网络节点的高可用取决于你用的是 Linux Bridge 还是 OVS,以及是否用了 DVR(分布式虚拟路由)。如果规模不大,网络组件跟控制节点混布也可以,但生产环境建议独立。
存储方面,Ceph 是 OpenStack 高可用集群里最常见的后端选择,因为它本身自带多副本和自愈能力。Glance 镜像存储、Nova 虚拟机磁盘、Cinder 块存储都可以统一走 Ceph。这样就不需要为每个存储服务单独做 HA。
2.2 各组件的高可用实现方式对比
不同组件的高可用机制差异很大,选错了方案后面会非常痛苦。下面这张表是我在实际项目中总结的对照:
| 组件 | 高可用方式 | 关键依赖 | 注意事项 |
|---|---|---|---|
| MariaDB | Galera Cluster 多主复制 | wsrep 协议、多数派仲裁 | 至少 3 节点,避免大事务 |
| RabbitMQ | 镜像队列 + HAProxy | Erlang Cookie 一致 | 队列策略要设 ha-mode: all |
| Memcached | 多实例并行 | 无状态 | 各节点独立,客户端轮询 |
| HAProxy | Keepalived VIP 漂移 | VRRP 协议 | 主备模式,VIP 绑定 |
| Keystone | 无状态多实例 | 后端数据库 | 通过 HAProxy 负载均衡 |
| Nova API | 无状态多实例 | 数据库 + MQ | 同上 |
| Neutron Server | 无状态多实例 | 数据库 + MQ | 注意 ML2 插件配置一致 |
| Glance API | 无状态多实例 | 数据库 + 存储后端 | 存储后端建议用 Ceph |
| Horizon | 无状态多实例 | 数据库 + Memcached | Session 存 Memcached |
从表里能看出来,真正有状态、需要特殊处理的就是 MariaDB 和 RabbitMQ。其他 API 服务都是无状态的,多起几个实例挂在 HAProxy 后面就行。这也是 Kolla-Ansible 部署高可用集群时的基本思路——它用 HAProxy + Keepalived 做入口 VIP,后端所有 API 服务在三个控制节点上各起一个容器实例。
2.3 用 Kolla-Ansible 规划高可用集群的 inventory
Kolla-Ansible 是目前部署 OpenStack 高可用集群最成熟的方式之一。它把每个服务都容器化,通过 Ansible 编排到多台主机上。核心配置文件是两个:/etc/kolla/globals.yml和/etc/kolla/inventory。
先看 inventory 怎么写。假设三台控制节点 IP 分别是 10.0.0.11、10.0.0.12、10.0.0.13,两台计算节点是 10.0.0.21、10.0.0.22:
[control] 10.0.0.11 10.0.0.12 10.0.0.13 [network] 10.0.0.11 10.0.0.12 10.0.0.13 [compute] 10.0.0.21 10.0.0.22 [monitoring] 10.0.0.11 [storage] 10.0.0.11 10.0.0.12 10.0.0.13 [deployment] localhost ansible_connection=local这里把网络组件跟控制节点混布了,小规模环境够用。如果网络流量大,建议把[network]拆到独立节点。[monitoring]只放一台是因为 Prometheus + Grafana 对高可用要求不高,挂了不影响业务。
再看globals.yml里跟高可用直接相关的关键参数:
# 高可用开关,必须设为 yes enable_haproxy: "yes" enable_keepalived: "yes" # 内部 API 的 VIP,所有控制节点共享 kolla_internal_vip_address: "10.0.0.10" kolla_external_vip_address: "10.0.0.10" # 网卡名要对,写错了 VIP 起不来 api_interface: "ens3" tunnel_interface: "ens4" network_interface: "ens3" # 启用多控制节点 enable_rabbitmq: "yes" enable_mariadb: "yes" enable_memcached: "yes" # 数据库集群 enable_galera: "yes" # 存储后端选 Ceph enable_ceph: "yes" ceph_backend: "rbd"kolla_internal_vip_address是 HAProxy 对外暴露的虚拟 IP,Keepalived 负责在三个控制节点之间漂移这个 VIP。api_interface必须写实际承载 API 流量的网卡名,写错了 Keepalived 起不来,VIP 不会绑定,整个集群的 API 入口就没了。这个参数看起来简单,但我见过至少三次因为网卡名写错导致部署后 VIP ping 不通的情况。
3. 从零部署一套三节点高可用集群:命令、参数与验证
3.1 基础环境准备与 Docker 安装
Kolla-Ansible 要求所有节点时间同步、主机名可解析、Docker 版本一致。先在三台控制节点和两台计算节点上都执行:
# 设置主机名(每台机器不同) hostnamectl set-hostname ctrl01 # 配置 /etc/hosts,所有节点都要加 cat >> /etc/hosts <<EOF 10.0.0.11 ctrl01 10.0.0.12 ctrl02 10.0.0.13 ctrl03 10.0.0.21 compute01 10.0.0.22 compute02 EOF # 时间同步 timedatectl set-timezone Asia/Shanghai systemctl enable --now chronyd # 关闭防火墙和 SELinux(内网环境,生产需按需开放端口) systemctl stop firewalld && systemctl disable firewalld setenforce 0 sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config时间同步是基础中的基础。Galera 集群对节点间时间偏差很敏感,偏差超过一定阈值会导致节点被踢出集群。RabbitMQ 的 Erlang 分布式通信也依赖时间一致。我一般要求所有节点 chronyd 同步偏差在 100ms 以内。
Docker 安装用官方源:
# 所有节点执行 yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io # 配置 Docker 镜像加速和存储驱动 mkdir -p /etc/docker cat > /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": {"max-size": "100m", "max-file": "3"}, "storage-driver": "overlay2", "insecure-registries": ["10.0.0.10:4000"] } EOF systemctl enable --now dockerinsecure-registries指向 Kolla 的本地 registry,因为 Kolla 部署时会先把镜像推到本地 registry 再分发到各节点。log-opts限制日志大小很关键,OpenStack 容器日志量很大,不限制的话磁盘很快被写满。
3.2 Kolla-Ansible 安装与镜像构建
在部署节点(通常是第一台控制节点)上安装 Kolla-Ansible:
# 安装 Python 依赖 yum install -y python3-devel libffi-devel gcc openssl-devel python3-libs # 创建虚拟环境 python3 -m venv /opt/kolla-venv source /opt/kolla-venv/bin/activate # 安装指定版本的 Kolla-Ansible pip install -U pip pip install kolla-ansible==15.4.1 # 复制配置文件 mkdir -p /etc/kolla cp -r /opt/kolla-venv/share/kolla-ansible/etc_examples/kolla/* /etc/kolla/ cp /opt/kolla-venv/share/kolla-ansible/ansible/inventory/* /etc/kolla/版本选择上,Kolla-Ansible 15.x 对应 OpenStack Wallaby 版本,比较稳定。如果要用更新的版本,需要确认跟操作系统和 Docker 版本的兼容性。我一般不会追最新版,选一个社区验证充分的稳定版更省心。
安装 Ansible Galaxy 依赖:
kolla-ansible install-deps生成密码文件:
kolla-genpwd这个命令会生成/etc/kolla/passwords.yml,里面包含所有服务的密码。生成后不要随便改,改了要重新跑kolla-genpwd并重新部署。
构建镜像(这一步耗时较长,取决于网络和机器性能):
kolla-ansible -i /etc/kolla/inventory bootstrap-servers kolla-ansible -i /etc/kolla/inventory prechecks kolla-ansible -i /etc/kolla/inventory pullbootstrap-servers会在所有节点上安装基础依赖、配置 Docker。prechecks做部署前检查,会验证端口占用、磁盘空间、网络连通性等。pull拉取所有需要的容器镜像。这三步任何一步报错都要先解决再往下走,不要跳过。
3.3 执行部署与高可用验证
确认 prechecks 全部通过后,执行正式部署:
kolla-ansible -i /etc/kolla/inventory deploy部署完成后,生成 admin 的 openrc 文件:
kolla-ansible post-deploy source /etc/kolla/admin-openrc.sh验证高可用是否真正生效,不能只看部署有没有报错。我一般按下面几个维度逐一确认:
# 1. 检查 VIP 是否正常绑定 ip addr show ens3 | grep 10.0.0.10 # 2. 检查 HAProxy 后端状态 docker exec -it haproxy bash echo "show stat" | socat /var/run/haproxy.sock stdio | grep -i down # 3. 检查 Galera 集群状态 docker exec -it mariadb bash mysql -uroot -p$DB_ROOT_PASSWORD -e "show status like 'wsrep_cluster_size';" # 期望输出:wsrep_cluster_size = 3 # 4. 检查 RabbitMQ 集群状态 docker exec -it rabbitmq rabbitmqctl cluster_status # 5. 创建一台测试虚拟机验证全链路 openstack server create --flavor m1.tiny --image cirros --nic net-id=$(openstack network show private -f value -c id) test-vmwsrep_cluster_size返回 3 说明三个数据库节点都正常加入了 Galera 集群。如果返回 2 或 1,说明有节点掉队了,需要查/var/log/kolla/mariadb/mariadb.log里的 wsrep 相关报错。HAProxy 的show stat输出里如果看到某个后端状态是 DOWN,说明对应服务在某个节点上没起来,要去看那个节点的容器日志。
4. 高可用集群最容易翻车的五个地方:避坑与排查
4.1 VIP 漂移后 API 不可达
现象:Keepalived 检测到主节点故障,VIP 漂移到备节点,但客户端访问 API 报连接超时。
原因:备节点上的 HAProxy 配置没有正确加载,或者备节点的网络接口没有开启net.ipv4.ip_nonlocal_bind,导致 HAProxy 无法监听 VIP 地址。
解决:在所有控制节点上设置net.ipv4.ip_nonlocal_bind=1,写入/etc/sysctl.d/99-kolla.conf并执行sysctl -p。同时检查 HAProxy 容器是否正常运行,docker logs haproxy看有没有绑定失败的错误。
4.2 Galera 集群节点频繁掉线
现象:MariaDB 的wsrep_cluster_size在 2 和 3 之间反复跳动,数据库写入偶尔超时。
原因:通常是节点间网络延迟过大,或者某个节点上有大事务导致流控(flow control)触发。也可能是wsrep_sync_wait参数设置过于激进。
解决:先检查节点间网络延迟,ping和tcpdump确认没有丢包。然后看 MariaDB 日志里有没有Flow control相关记录。如果有,说明某个节点写入压力太大,其他节点跟不上。可以适当调大wsrep_slave_threads(建议设为 CPU 核数的 2 倍),并避免在 OpenStack 数据库上跑大批量操作。
4.3 RabbitMQ 队列未镜像导致消息丢失
现象:某个控制节点宕机后,部分 OpenStack 操作卡住,Nova 调度失败。
原因:RabbitMQ 默认不开启队列镜像,队列只存在于创建它的节点上。节点挂了,队列就没了。
解决:设置镜像队列策略:
docker exec -it rabbitmq rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'这条命令把所有队列设为镜像到所有节点,ha-sync-mode设为automatic让新节点加入时自动同步。注意镜像队列会增加网络开销,队列数量多的时候要评估性能影响。
4.4 容器时间不同步导致 Keystone Token 校验失败
现象:用户认证偶尔失败,报 Token 过期或签名无效,但重新登录又能用。
原因:各节点容器内时间不一致,Keystone 签发 Token 和校验 Token 的时间偏差超过允许范围。
解决:确保所有宿主机 chronyd 正常运行,并且容器使用宿主机时间(Kolla 默认挂载/etc/localtime)。检查docker exec keystone date和宿主机date是否一致。如果不一致,检查容器的时区挂载配置。
4.5 部署完成后 Horizon 登录报 500
现象:Horizon 页面能打开,但登录时报 500 错误,日志显示 Memcached 连接失败。
原因:Horizon 的 Session 存在 Memcached 里,如果 Memcached 服务没起来或者 HAProxy 后端配置有误,Session 无法读写。
解决:检查 Memcached 容器状态docker ps | grep memcached,确认三个节点上都有实例在跑。然后检查 HAProxy 配置里 Memcached 的后端是否包含所有节点。如果某个节点 Memcached 挂了,HAProxy 健康检查应该把它摘掉,但如果检查间隔太长,期间登录就会失败。可以把 HAProxy 的inter和fall参数调小,加快故障检测。
5. 高可用集群的进阶调优与日常巡检习惯
部署完成只是起点,真正让集群稳定运行靠的是日常巡检和参数调优。我分享几个实际工作中验证有效的做法。
HAProxy 健康检查参数调优。默认的健康检查间隔可能太长,故障发现不及时。在/etc/kolla/haproxy/haproxy.cfg里可以调整:
defaults timeout connect 5s timeout client 30s timeout server 30s option httpchk GET /healthcheck default-server inter 3s fall 2 rise 2inter 3s表示每 3 秒检查一次,fall 2表示连续失败 2 次标记为 DOWN,rise 2表示连续成功 2 次标记为 UP。这样故障发现时间在 6 秒左右,比默认的几十秒快很多。改完配置后docker restart haproxy生效。
Galera 的流控参数。如果数据库写入量大,流控会频繁触发。可以在/etc/kolla/mariadb/galera.cnf里调整:
wsrep_slave_threads = 8 wsrep_provider_options = "gcs.fc_limit=256; gcs.fc_factor=0.8"gcs.fc_limit控制流控触发的队列长度阈值,gcs.fc_factor控制恢复比例。调大这些值可以减少流控触发频率,但会增加节点间数据不一致的窗口。需要根据实际负载权衡。
日常巡检清单。我每天早上会花五分钟跑一遍这些检查:
# 集群整体状态 openstack compute service list openstack network agent list openstack volume service list # 数据库集群 docker exec mariadb mysql -uroot -p$DB_ROOT_PASSWORD -e "show status like 'wsrep_cluster_size'; show status like 'wsrep_ready';" # RabbitMQ docker exec rabbitmq rabbitmqctl cluster_status | grep -E "running_nodes|partitions" # Ceph(如果用了) ceph -sopenstack compute service list里所有服务应该是up状态,如果有down的要立即查。wsrep_ready必须是ON,如果是OFF说明该节点没有准备好接受写入。RabbitMQ 的partitions如果出现网络分区,要尽快处理,否则可能出现数据不一致。
升级和变更的习惯。高可用集群最怕的是变更操作。我的习惯是:任何配置变更先在测试环境验证,然后一次只改一个节点,观察至少 24 小时再改下一个。Kolla-Ansible 支持滚动升级,kolla-ansible -i inventory upgrade会逐个节点更新容器,但升级前一定要备份数据库和配置文件。我吃过亏——有一次升级 MariaDB 镜像版本,Galera 的 SST 方式不兼容,导致节点无法重新加入集群,最后只能从备份恢复。从那以后,任何涉及数据库的变更我都会先mysqldump全量备份。
希望这些经验帮到你,少走一些我踩过的弯路。
本文还有配套的精品资源,点击获取