1. 项目概述:这不是一次简单的环境部署,而是一次对云基础设施底层逻辑的系统性验证
“openstack-iass搭建 二”这个标题看似平淡,甚至带点技术文档式的枯燥感,但它背后指向的,是一个真实、复杂、充满变量的工程实践现场。我接触过太多人把OpenStack当成一个“装完就跑”的黑盒平台——点几下Web界面,开几台虚拟机,就以为自己掌握了IaaS。但真正做过两次以上完整部署的人会明白:第一次是照着文档磕磕绊绊地走通流程,第二次才是开始理解哪些组件真正在协同、哪些配置在静默失效、哪些网络路径在流量洪峰时悄然断裂。这里的“二”,不是版本号,而是实操阶段的分水岭:从“能跑起来”迈向“能稳住、能诊断、能调优”。
这个项目核心解决的是私有云基础设施的可复现性与可观测性问题。它不追求炫酷的UI或新潮的AI集成,而是聚焦在最基础也最关键的环节:如何让一套OpenStack环境,在不同硬件批次、不同内核版本、不同网络拓扑下,都能以确定性的方式完成初始化,并在运行中暴露出真实瓶颈而非掩盖问题。关键词里的“iass”(Infrastructure as Software)是关键提示——它强调基础设施本身必须具备软件工程级别的可测试、可回滚、可版本化能力,而不是一堆手动敲出来的配置文件堆砌。
适合谁来参考?如果你正面临以下任一场景,这篇内容就是为你写的:
- 你刚完成第一次OpenStack部署,但发现节点重启后服务起不来,日志里全是“connection refused”却找不到源头;
- 你的团队在用Ansible或Terraform自动化部署,但每次升级OpenStack版本都得重写80%的playbook;
- 你在排查虚拟机无法获取IP的问题,查了DHCP agent、查了neutron-server、查了ovs流表,最后发现是物理交换机上一个被遗忘的STP端口阻塞;
- 你想知道为什么官方文档推荐用devstack做开发测试,却严禁它出现在生产环境——背后的约束条件到底是什么。
这不是一篇“手把手教你安装”的入门指南,而是一份来自多次踩坑现场的结构化复盘。接下来的内容,将完全围绕“第二次搭建”这一特定情境展开,拆解那些第一次部署时被忽略、但第二次必须直面的核心矛盾。
2. 整体设计思路:为什么必须放弃“一键脚本”,转向分层验证模型
2.1 第一次失败教会我的三件事
第一次搭建openstack-iass时,我用了某社区广为流传的“All-in-One一键脚本”。它确实5分钟就拉起了dashboard,连虚拟机都成功ping通了外网。但两周后,当我在控制节点执行apt upgrade并重启服务时,整个环境彻底瘫痪。排查过程持续了36小时,最终定位到三个根本性问题:
- 时间同步被静默破坏:脚本默认关闭了chrony服务,改用systemd-timesyncd,而后者在虚拟化环境中精度不足。当keystone token校验因时间偏差超5分钟失效时,所有API请求返回401,但日志里没有任何关于时间的警告。
- 数据库连接池配置硬编码:脚本把mysql连接数固定设为32,而实际环境中nova-conductor和neutron-server并发请求远超此值,导致大量连接等待超时,表现为“创建实例卡在building状态”。
- 网络命名空间隔离被绕过:脚本为简化操作,直接在host namespace里配置br-ex桥接,跳过了qrouter命名空间。这导致外部流量能进不能出——因为SNAT规则只存在于qrouter里,而host namespace根本没有该规则。
这三点共同指向一个结论:任何牺牲可观察性换取部署速度的方案,都会在第二次迭代时付出指数级的调试成本。因此,“二”的设计起点,就是建立一套分层验证模型,把基础设施拆解为四个可独立测试、可量化评估的层级:
- L0 硬件与内核层:验证CPU虚拟化支持、内存大页分配、内核模块加载状态;
- L1 网络基础层:验证物理链路连通性、VLAN透传能力、MTU一致性;
- L2 服务依赖层:验证数据库连接池健康度、消息队列吞吐量、证书有效期;
- L3 OpenStack功能层:验证各服务API响应时间、资源配额生效逻辑、镜像上传完整性。
提示:不要试图在单个脚本里完成全部验证。我现在的做法是,每个层级对应一个独立的shell脚本(如
l1-network-check.sh),执行后生成JSON格式的检测报告。这样当问题出现时,我能直接定位到是L1还是L2层先告警,避免无头苍蝇式排查。
2.2 工具链选型:为什么放弃DevStack,选择Kolla-Ansible作为基线
社区常把DevStack称为“OpenStack的Hello World”,但它本质上是个开发调试工具,而非部署框架。它的设计哲学是“最小可行环境”,为此牺牲了三样生产必需品:
- 配置隔离缺失:所有服务共享同一套配置目录,修改一个参数可能意外影响其他服务;
- 无状态假设错误:它假设宿主机是干净的,但现实中服务器往往预装了监控代理、安全加固模块,这些会与DevStack的iptables规则冲突;
- 升级路径不存在:DevStack没有版本迁移机制,从Rocky升级到Stein意味着重装,而你的自定义配置全丢了。
相比之下,Kolla-Ansible采用容器化部署模式,天然具备配置隔离优势。更重要的是,它把OpenStack服务拆分为标准Docker镜像(如kolla/ubuntu-source-nova-api:zed),每个镜像只包含该服务及其最小依赖。这意味着:
- 配置变更通过Ansible变量注入,不会污染镜像;
- 升级只需替换镜像标签并重新部署,旧配置自动继承;
- 故障时可直接进入容器执行
ps aux或netstat -tuln,无需在宿主机上找服务进程。
但Kolla-Ansible也有陷阱:它的默认配置面向大规模集群,对单节点测试环境过于厚重。因此我的“二”版方案做了关键裁剪:
- 关闭所有高可用组件(keepalived、haproxy、etcd);
- 将所有服务容器绑定到localhost(127.0.0.1),避免暴露不必要的端口;
- 使用SQLite替代MySQL作为临时数据库,规避数据库连接池配置难题;
- 用
kolla-build本地构建镜像,而非拉取远程镜像,确保构建环境与运行环境一致。
这种“裁剪式使用”不是妥协,而是对工具本质的尊重——Kolla-Ansible的价值在于其配置管理能力,而非容器编排能力。我们只取其长,避其短。
2.3 网络架构重构:从“能通”到“可知”的质变
第一次搭建时,我满足于“虚拟机能ping通百度”。第二次,我要求网络必须满足三个可观测性指标:
- 路径可追踪:从虚拟机内部traceroute到外网IP,每一跳的设备、端口、VLAN ID必须明确;
- 流量可捕获:在任意网络节点(br-int、br-ex、qrouter)上,能用tcpdump抓到指定虚拟机的原始数据包;
- 策略可验证:安全组规则必须能映射到具体的iptables链和规则序号,且能通过
iptables -C命令实时验证。
为实现这点,我彻底重构了网络拓扑:
- 物理网卡不再直接桥接到br-ex,而是先经过一个Linux bridge(br-phy),再由br-phy连接br-ex;
- 所有OpenStack创建的bridge(br-int、br-ex)均启用STP协议,并设置priority为4096,避免与物理交换机产生环路;
- 在br-phy上配置
tc qdisc add dev br-phy root handle 1: htb default 30,为后续QoS测试预留接口; - 每个qrouter命名空间内,运行
ip link add name veth-debug type veth peer name veth-host,将veth-host接入host namespace,专门用于抓包。
这套设计带来的直接收益是:当虚拟机无法上网时,我不再需要猜“是DHCP没给IP,还是路由没配好,还是NAT没生效”,而是按顺序执行:
ip netns exec qrouter-xxx ip a→ 查看qrouter内网口是否UP;ip netns exec qrouter-xxx tcpdump -i qr-xxx icmp→ 确认ICMP请求是否到达qrouter;tcpdump -i br-ex icmp→ 确认SNAT后的包是否发出;ovs-ofctl dump-flows br-ex | grep "actions=normal"→ 验证br-ex是否正确转发。
注意:很多教程教你在br-ex上直接配置IP,这是危险操作。br-ex应该纯粹作为数据平面,所有控制平面IP(如管理IP、浮动IP)必须配置在qrouter或qdhcp命名空间内。否则,当qrouter重启时,br-ex上的IP会消失,导致管理网络中断。
3. 核心细节解析:L0-L3四层验证的实操要点与参数依据
3.1 L0 硬件与内核层:那些被忽略的底层约束
很多人认为OpenStack对硬件要求宽松,只要CPU支持VT-x即可。但实际部署中,L0层的微小偏差会引发L3层的灾难性故障。以下是我在“二”版中强制验证的七项指标,每项都有明确的量化阈值和失效后果:
| 检测项 | 验证命令 | 合格阈值 | 失效后果 | 实测案例 |
|---|---|---|---|---|
| CPU虚拟化支持 | `egrep -c "(vmx | svm)" /proc/cpuinfo` | ≥1 | nova-compute无法启动,报错"libvirtError: internal error: Unable to initialize network" |
| 内存大页分配 | cat /proc/meminfo | grep HugePages | HugePages_Total > 0且HugePages_Free ≈ HugePages_Total | 虚拟机启动缓慢,内存分配失败率超15% | 默认未启用,需在grub中添加default_hugepagesz=1G hugepagesz=1G hugepages=8 |
| 内核模块加载 | `lsmod | grep -E "(kvm | kvm_intel | vfio | vfio_iommu_type1)"` |
| 网络中断亲和性 | cat /proc/interrupts | grep eth0 | wc -l | ≥2个CPU core处理中断 | 网络吞吐量低于理论值30%,延迟抖动大 | 单core处理所有中断,通过smp_affinity_list绑定到多核 |
| 时间同步精度 | chronyc tracking | grep "Last offset" | Last offset < ±5ms | keystone token频繁失效,API批量请求失败 | NTP服务器响应延迟高,改用chrony pool替代单一NTP源 |
| 文件系统类型 | df -T / | awk 'NR==2 {print $2}' | xfs或ext4(非btrfs/zfs) | glance镜像上传失败,报错"Operation not supported" | 某云厂商默认分配btrfs,需重装系统 |
| SELinux状态 | getenforce | Disabled或Permissive | httpd服务无法绑定80端口,dashboard白屏 | 生产环境常开启Enforcing,需配置seboolsetsebool -P httpd_can_network_connect on |
特别强调内存大页配置的实操细节:OpenStack默认使用2MB大页,但现代服务器普遍支持1GB大页。实测表明,启用1GB大页后,虚拟机内存分配延迟降低67%,且大幅减少TLB miss。配置步骤如下:
- 编辑
/etc/default/grub,在GRUB_CMDLINE_LINUX中添加:default_hugepagesz=1G hugepagesz=1G hugepages=8 - 运行
update-grub && reboot; - 验证:
grep -i huge /proc/meminfo应显示HugePages_Total: 8; - 在nova.conf中配置:
[DEFAULT] mem_stats_interval = 60 [libvirt] hugepages = True hugepage_size = 1GB
实操心得:不要在运行中动态分配大页!
echo 8 > /proc/sys/vm/nr_hugepages看似可行,但会导致内核内存碎片化,后续分配失败。必须在启动时静态预留。
3.2 L1 网络基础层:物理链路的确定性验证
L1层的验证目标是:确保物理网络不引入任何不可控变量。我设计了一套“三步封堵法”,逐层排除物理层干扰:
第一步:链路层隔离验证
在控制节点和计算节点间建立专用测试链路(不经过生产交换机),使用iperf3进行基准测试:
# 控制节点执行 iperf3 -s -p 5201 -i 1 -t 60 # 计算节点执行 iperf3 -c <control_ip> -p 5201 -i 1 -t 60 -P 4合格标准:
- 带宽波动<5%(排除网卡驱动bug);
- 丢包率=0(排除网线/光模块质量问题);
- 延迟抖动<0.5ms(排除交换机QoS策略干扰)。
第二步:VLAN透传验证
OpenStack的provider network依赖VLAN透传。传统方法用vconfig创建子接口测试,但存在兼容性问题。我改用更底层的ip link命令:
# 在控制节点创建VLAN设备 ip link add link eth0 name eth0.100 type vlan id 100 ip addr add 192.168.100.1/24 dev eth0.100 ip link set eth0.100 up # 在计算节点执行相同操作,IP设为192.168.100.2 # 然后测试 ping -c 5 192.168.100.1关键点:必须用ip link而非vconfig,因为后者在较新内核中已被废弃,且不支持802.1ad双层VLAN。
第三步:MTU一致性验证
OpenStack网络链路涉及多个MTU层级:物理网卡→Linux bridge→OVS bridge→qrouter namespace→虚拟机网卡。任一环节MTU不一致,都会导致大包分片失败。我的验证脚本会自动检测所有环节:
# 获取所有网络设备MTU for dev in $(ip -br link show \| awk '{print $1}'); do mtu=$(ip link show $dev \| grep mtu \| awk '{print $5}') echo "$dev: $mtu" done | sort -k2,2n合格标准:所有设备MTU必须严格相等(通常设为1500)。若使用VXLAN,需统一设为1450(减去50字节VXLAN头)。
注意:很多教程建议在br-ex上设置MTU,这是错误的。br-ex是数据平面,不应配置IP,因此无需设置MTU。MTU应配置在qrouter内的qr-xxx接口上,通过neutron port-update命令实现。
3.3 L2 服务依赖层:数据库与消息队列的健康度建模
L2层的核心矛盾是:服务依赖组件的性能拐点,往往早于OpenStack自身瓶颈。例如,当MySQL连接数达到200时,nova-api响应时间开始指数增长,但此时MySQL的CPU使用率仅30%。因此,我建立了服务依赖健康度模型,用三个维度量化:
- 连接池饱和度:
SHOW STATUS LIKE 'Threads_connected'/max_connections; - 查询延迟分布:用
pt-query-digest分析slow log,关注P95延迟; - 消息积压深度:
rabbitmqctl list_queues name messages_ready messages_unacknowledged。
针对MySQL,我放弃了默认的max_connections=151,而是根据公式动态计算:
max_connections = (物理内存GB × 1024) ÷ (每个连接平均内存MB) + 50实测每个nova-api连接平均消耗8MB内存,因此16GB内存服务器应设为:(16 × 1024) ÷ 8 + 50 = 2098。但为防突发流量,我保守设为1500。
更关键的是连接池配置。OpenStack各服务使用不同连接池:
- Nova使用oslo.db,配置在
nova.conf中:[database] max_retries = 10 retry_interval = 1 max_overflow = 50 pool_size = 50 - Neutron使用SQLAlchemy,配置在
neutron.conf中:[database] max_retries = 10 retry_interval = 1 max_overflow = 20 pool_size = 20
这里有个易错点:pool_size是连接池初始大小,max_overflow是超出池大小后允许创建的额外连接数。总连接数上限 =pool_size + max_overflow。若设为pool_size=50, max_overflow=50,则最多100连接,但max_connections需≥100,否则MySQL拒绝新连接。
对于RabbitMQ,我禁用了默认的guest用户,创建专用用户:
rabbitmqctl add_user openstack password123 rabbitmqctl set_permissions openstack ".*" ".*" ".*" rabbitmqctl set_user_tags openstack administrator并配置rabbitmq.conf:
default_user = openstack default_pass = password123 loopback_users.guest = false实操心得:不要在生产环境使用
guest用户!RabbitMQ 3.8+默认禁止guest用户从远程登录,但很多旧教程仍沿用,导致neutron-server启动失败,报错"AMQP connection failed"。
3.4 L3 OpenStack功能层:API响应时间的黄金分割点
L3层的验证不再关注“能否工作”,而是“多快才算正常”。我定义了OpenStack API响应时间的黄金分割点:
- P50 < 200ms:用户无感知延迟;
- P90 < 500ms:可接受的轻微卡顿;
- P95 > 1000ms:必须优化,否则影响用户体验。
为获取真实数据,我编写了api-benchmark.py脚本,模拟典型操作:
import time import requests from concurrent.futures import ThreadPoolExecutor def test_nova_boot(): start = time.time() # 调用nova API创建实例 resp = requests.post( "http://controller:8774/v2.1/servers", headers={"X-Auth-Token": token}, json={"server": {"name": "test", "imageRef": "...", "flavorRef": "..."}} ) return time.time() - start # 并发10个请求,统计P50/P90/P95 with ThreadPoolExecutor(max_workers=10) as executor: times = list(executor.map(test_nova_boot, range(100))) times.sort() print(f"P50: {times[49]:.3f}s, P90: {times[89]:.3f}s, P95: {times[94]:.3f}s")实测发现,影响P95的关键因素是镜像缓存机制。默认情况下,glance将镜像存储在本地文件系统,每次创建实例都要复制镜像到计算节点。我改为启用qemu-img convert的copy-on-write机制:
# 在glance-api.conf中 [glance_store] stores = file,http default_store = file filesystem_store_datadir = /var/lib/glance/images/ # 启用镜像缓存 image_cache_dir = /var/lib/glance/image-cache/并在nova.conf中配置:
[libvirt] images_type = rbd # 若用Ceph,否则用qcow2 images_rbd_pool = images提示:不要盲目启用
rbd后端!若未部署Ceph,nova-compute会启动失败。先确认rbd --version能正常执行,再配置。
4. 实操过程:从零开始的“二”版部署全流程记录
4.1 环境准备:操作系统与基础服务的确定性配置
我选用Ubuntu 22.04 LTS作为基线操作系统,原因有三:
- 内核版本5.15长期支持至2032年,避免频繁升级内核带来的兼容性风险;
- systemd-resolved默认启用,解决DNS解析超时问题(OpenStack服务对DNS延迟极其敏感);
- apt源默认启用
universe仓库,无需额外配置即可安装kolla-ansible。
部署前,执行标准化环境初始化:
# 1. 禁用swap(OpenStack禁止swap) sudo swapoff -a sudo sed -i '/swap/d' /etc/fstab # 2. 配置chrony时间同步(使用国内NTP源) sudo apt install chrony -y sudo tee /etc/chrony/chrony.conf << 'EOF' pool ntp.aliyun.com iburst keyfile /etc/chrony/chrony.keys driftfile /var/lib/chrony/chrony.drift logdir /var/log/chrony EOF sudo systemctl restart chrony # 3. 配置内核参数(优化网络栈) echo 'net.ipv4.ip_forward=1 net.ipv4.conf.all.rp_filter=0 net.ipv4.conf.default.rp_filter=0 net.bridge.bridge-nf-call-iptables=1 net.bridge.bridge-nf-call-ip6tables=1' | sudo tee -a /etc/sysctl.conf sudo sysctl -p # 4. 安装基础依赖 sudo apt update && sudo apt install python3-dev libffi-dev gcc libssl-dev -y关键点在于时间同步配置。很多故障源于NTP服务器响应慢,导致chrony进入burst模式,反而加剧时间漂移。我改用pool指令替代server,让chrony自动选择最优NTP源,并添加iburst参数加速初始同步。
4.2 Kolla-Ansible部署:从镜像构建到服务启动的完整链路
“二”版部署摒弃了kolla-ansible deploy一键式命令,改为分步执行,确保每一步都可验证:
步骤1:安装Kolla-Ansible
# 创建虚拟环境,避免污染系统Python python3 -m venv /opt/kolla-venv source /opt/kolla-venv/bin/activate pip install -U pip pip install kolla-ansible==14.4.0 # Zed版本,稳定可靠步骤2:生成密码文件
kolla-genpwd # 修改admin_password为强密码,确保长度≥12位,含大小写字母+数字+符号步骤3:配置全局变量
编辑/etc/kolla/globals.yml:
kolla_base_distro: "ubuntu" kolla_install_type: "source" openstack_release: "zed" kolla_internal_vip_address: "10.0.0.100" # VIP,用于HA,单节点可设为任意未用IP network_interface: "eth0" neutron_external_interface: "eth1" # 对外网络接口 enable_haproxy: "no" enable_keepalived: "no" enable_etcd: "no" # 数据库使用SQLite(单节点测试) mariadb_enabled: "no" sqlite_enabled: "yes" # 消息队列使用RabbitMQ rabbitmq_enabled: "yes"步骤4:构建本地镜像
# 下载kolla源码 git clone https://opendev.org/openstack/kolla cd kolla # 构建所有服务镜像(耗时约40分钟) kolla-build --registry localhost:4000 --push ubuntu source # 镜像推送到本地registry,避免网络拉取失败步骤5:执行部署
# 预检 kolla-ansible prechecks -i /etc/kolla/inventory/all-in-one # 部署(跳过证书生成,用默认自签名) kolla-ansible deploy -i /etc/kolla/inventory/all-in-one --skip-tags generate_certs # 验证 kolla-ansible post-deploy -i /etc/kolla/inventory/all-in-one部署完成后,关键验证点:
docker ps | grep -E "(nova|neutron|keystone)"应显示所有容器状态为Up;source /etc/kolla/admin-openrc.sh && openstack token issue应返回有效token;openstack image list应返回空列表(说明glance服务正常,只是暂无镜像)。
实操心得:
--skip-tags generate_certs是关键。Kolla-Ansible默认生成的证书有效期仅30天,且证书CN必须匹配VIP。在测试环境中,用自签名证书更可控。生产环境再启用正式CA。
4.3 网络与镜像配置:让虚拟机真正“活”起来
部署完成后,环境只是“通电”,还需赋予它“生命”——即网络和镜像。
网络配置:
# 创建provider网络(flat模式) openstack network create --share --external \ --provider-physical-network provider \ --provider-network-type flat provider-net # 创建子网 openstack subnet create --network provider-net \ --allocation-pool start=10.0.0.100,end=10.0.0.200 \ --dns-nameserver 114.114.114.114 \ --gateway 10.0.0.1 \ provider-subnet # 创建内部网络(self-service) openstack network create selfservice-net openstack subnet create --network selfservice-net \ --subnet-range 172.16.1.0/24 \ --gateway 172.16.1.1 \ selfservice-subnet # 创建路由器并连接 openstack router create provider-router openstack router set --external-gateway provider-net provider-router openstack router add subnet provider-router selfservice-subnet镜像上传:
下载Cirros最小化镜像(30MB,启动快,适合测试):
wget http://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img openstack image create "cirros" \ --file cirros-0.6.2-x86_64-disk.img \ --disk-format qcow2 --container-format bare \ --public安全组配置:
# 允许ICMP和SSH openstack security group rule create --proto icmp default openstack security group rule create --proto tcp --dst-port 22 default此时,执行:
openstack server create --image cirros --flavor m1.tiny \ --network selfservice-net --security-group default test-vm等待约30秒,然后:
openstack server list # 状态应为ACTIVE openstack console url show test-vm # 获取VNC控制台URL注意:若状态卡在BUILD,检查
nova-compute日志:docker logs kolla_nova_compute。常见原因是libvirt未正确配置,需确认/etc/libvirt/qemu.conf中user = "libvirt-qemu"已取消注释。
4.4 四层验证执行:用脚本自动化检测结果
部署完成后,立即执行四层验证脚本validate-openstack.sh:
#!/bin/bash # L0: 硬件层 echo "=== L0 Hardware Validation ===" echo "CPU VT-x: $(egrep -c "(vmx|svm)" /proc/cpuinfo)" echo "HugePages: $(cat /proc/meminfo | grep HugePages_Total | awk '{print $2}')" # L1: 网络层 echo "=== L1 Network Validation ===" echo "br-ex exists: $(ip link show br-ex &>/dev/null && echo YES || echo NO)" echo "qrouter namespace: $(ip netns list | grep qrouter | wc -l)" # L2: 服务层 echo "=== L2 Service Validation ===" echo "MySQL connections: $(mysql -u root -e "SHOW STATUS LIKE 'Threads_connected'" 2>/dev/null | tail -1 | awk '{print $2}')" echo "RabbitMQ queues: $(rabbitmqctl list_queues 2>/dev/null | wc -l)" # L3: 功能层 echo "=== L3 Function Validation ===" source /etc/kolla/admin-openrc.sh echo "Keystone token: $(openstack token issue 2>/dev/null | grep id | wc -l)" echo "Glance images: $(openstack image list 2>/dev/null | wc -l)"执行结果示例:
=== L0 Hardware Validation === CPU VT-x: 8 HugePages: 8 === L1 Network Validation === br-ex exists: YES qrouter namespace: 1 === L2 Service Validation === MySQL connections: 12 RabbitMQ queues: 15 === L3 Function Validation === Keystone token: 1 Glance images: 1所有输出均为预期值,表示环境健康。
5. 常见问题与排查技巧实录:那些文档里不会写的真相
5.1 问题速查表:高频故障的精准定位路径
| 现象 | 可能原因 | 定位命令 | 解决方案 |
|---|---|---|---|
openstack token issue返回401 | Keystone认证失败 | docker logs kolla_keystone | 检查/etc/kolla/config/keystone/keystone.conf中[token] provider是否为fernet,且fernet_keys目录权限正确 |
| 虚拟机状态卡在BUILD | Nova调度失败 | docker logs kolla_nova_scheduler | 检查nova-manage cell_v2 discover_hosts是否执行,确认计算节点已注册到cell |
| 虚拟机无法获取IP | DHCP agent异常 | openstack network agent list | grep dhcp | 重启kolla_neutron_dhcp容器,检查/var/lib/neutron/dhcp/目录是否存在 |
| 浮动IP无法访问 | SNAT规则缺失 | ip netns exec qrouter-xxx iptables -t nat -L POSTROUTING | 检查neutron l3-agent是否运行,确认/etc/neutron/l3_agent.ini中agent_mode = dvr_snat |
| Dashboard白屏 | Horizon静态文件缺失 | docker logs kolla_horizon | 进入容器执行python3 manage.py collectstatic --noinput,确认/usr/share/openstack-dashboard/static/已生成 |
特别提醒浮动IP问题:这是新手最高频的故障。根源在于qrouter命名空间内的SNAT规则未生效。正确排查路径:
openstack router show provider-router→ 获取router_id;ip netns exec qrouter-<router_id> ip a→ 确认qr-xxx接口UP且有IP;ip netns exec qrouter-<router_id> iptables -t nat -L POSTROUTING→ 查看是否有MASQUERADE规则;- 若无规则,执行
neutron router-gateway-clear provider-router再neutron router-gateway-set provider-router provider-net触发规则重建。
5.2 独家避坑技巧:来自血泪教训的三条铁律
铁律一:永远不要在生产环境修改/etc/kolla下的配置文件
Kolla-Ansible的设计哲学是“配置即代码”,所有配置必须通过Ansible变量管理。我曾为快速修复一个SSL问题,直接编辑/etc/kolla/config/horizon/local_settings.py,结果下次kolla-ansible deploy时,该文件被覆盖,导致Horizon彻底崩溃。正确做法是:
- 在
/etc/kolla/config/horizon/下创建local_settings.py.j2模板; - 在
globals.yml中定义变量horizon_custom_settings: {...}; - 通过Jinja2模板渲染生成配置。
铁律二:数据库备份必须包含/var/lib/mysql的完整目录
很多教程教用mysqldump备份,但这只能备份数据,无法恢复表结构权限。OpenStack的MySQL包含大量系统表(如mysql.user),mysqldump不导出它们。正确备份命令:
# 停止所有服务 kolla-ansible stop -i /etc/kolla/inventory/all-in-one # 归档整个目录 tar -czf mysql-backup-$(date +%F).tar.gz /var/lib/mysql # 启动服务 kolla-ansible start -i /etc/kolla/inventory/all-in-one铁律三:网络故障时,第一反应不是查OpenStack,而是查物理交换机
我曾为排查一个“虚拟机无法上网”问题耗时18小时,最终发现是物理交换机上一个端口被管理员手动shutdown。此后,