
1. 为什么今天还要手动装 Neutron——被自动化掩盖的真实运维现场Neutron 手动安装听起来像在教人用算盘解微分方程。Kolla、DevStack、OpenStack-Ansible 这些一键部署工具早把“三分钟起集群”变成了默认体验。但去年我在给某省电力调度云平台做等保三级加固时连续三天卡在 Neutron 的 L3 agent 启动失败上——Ansible Playbook 显示“TASK OK”日志里却只有一行Failed to bind port连错误码都不带。最后发现是 Open vSwitch 内核模块版本与宿主机内核 patch level 不匹配而 Ansible 没做这个维度的校验。那一刻我撕掉了所有“自动化万能论”的笔记重新打开了 Neutron 官方源码树从neutron-server的 WSGI 初始化流程开始一行行追。这就是手动安装不可替代的价值它不是复古情怀而是把黑盒打开、把依赖链摊开、把每个服务启动时读取的配置项、加载的插件、绑定的 socket、检查的权限全部暴露在你眼皮底下。尤其当你要对接非标准外部网络环境时——比如客户机房里那台运行着 Cisco Nexus 9K 的物理交换机要求 Neutron 必须通过特定 VLAN 子接口透传 BGP 路由又或者金融客户强制要求所有元数据服务必须走独立管理网段且禁止任何 DHCP 广播包跨网段泛洪——这时候 Ansible 的 role 配置文件里那句enable_dhcp: true就成了定时炸弹。关键词Neutron、手动安装、外部环境配置这三个词组合起来本质是在问当标准化部署失效时你能否在裸金属上重建网络控制平面这背后涉及 Linux 网络命名空间隔离机制、OVS 数据流表匹配逻辑、ML2 插件驱动加载顺序、REST API 请求认证链路、以及最关键的——Neutron 如何与外部物理网络设备协商拓扑。这不是考你会不会敲命令而是考你懂不懂网络控制面与数据面的契约关系。我见过太多人把 Neutron 当成“虚拟交换机配置器”结果在生产环境一上线就遭遇东西向流量黑洞。真正的问题往往藏在你看不见的地方比如ovs-vsctl show输出里某个 bridge 缺少fail_mode: secure设置导致控制器断连后端口直接 down 掉又比如neutron.conf中core_plugin指向ml2但/etc/neutron/plugins/ml2/ml2_conf.ini里type_drivers flat,vlan却漏配了vxlan而你的计算节点正用 VXLAN 做租户网络隔离。这些细节只有亲手敲过systemctl start neutron-server并盯着 journalctl -u neutron-server -f 看满屏日志滚动的人才会形成肌肉记忆。所以这篇内容不面向刚装完 DevStack 的新手也不面向只调 API 的上层开发者。它专为那些即将接手老旧 OpenStack 集群、需要做等保加固、要对接定制化 SDN 设备、或正在排查“明明配置全对却死活不通”类疑难问题的网络运维工程师准备。接下来我会带你从零开始在一台干净的 CentOS 8 Stream 虚拟机上不依赖任何封装脚本纯手工构建一个可验证的 Neutron 控制节点并重点拆解它如何与外部世界握手。2. 控制节点初始化数据库、凭证与 API 端点的底层契约Neutron 不是孤立服务它是 OpenStack 网络控制平面的中枢必须先与 Keystone身份认证、Glance镜像、Nova计算建立信任关系。这种关系不是靠“配置文件写对就行”来维系的而是通过一套严格的凭证交换协议实现的。手动安装的第一步就是亲手缔结这些契约而不是让脚本替你完成签名。2.1 数据库准备为什么必须用 MySQL 8.0 而非 SQLite很多教程用 SQLite 做 Neutron 后端仅用于学习演示。但在生产环境中Neutron 的数据库操作具有强事务性特征创建网络时需原子性地插入networks、subnets、ports三张表记录删除路由器时需级联清理routerports、floatingips、l3agentrouters关联数据。SQLite 的 WAL 模式在高并发下易出现database is locked错误而 Neutron Server 默认启动 4 个 worker 进程每个都可能同时处理租户请求。我们选用 MySQL 8.0.28CentOS 8 Stream 默认源提供关键配置项必须显式设置# /etc/my.cnf.d/openstack.cnf [mysqld] default-storage-engine innodb innodb_file_per_table on max_connections 4096 collation-server utf8mb4_unicode_ci character-set-server utf8mb4提示innodb_file_per_table on是硬性要求。Neutron 的ml2_network_segments表在大规模网络场景下会达到数百万行若关闭此选项所有表共享一个 ibdata1 文件一旦磁盘满整个数据库将无法写入且无法在线收缩。创建数据库与用户CREATE DATABASE neutron CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; GRANT ALL PRIVILEGES ON neutron.* TO neutronlocalhost \ IDENTIFIED BY NEUTRON_DBPASS; GRANT ALL PRIVILEGES ON neutron.* TO neutron% \ IDENTIFIED BY NEUTRON_DBPASS; FLUSH PRIVILEGES;注意neutron%的授权——这并非安全妥协而是为后续横向扩展做准备。当你的 Neutron Agent 部署在独立物理服务器上时它需要直连控制节点数据库而非通过 API Proxy。此时localhost授权将导致连接拒绝。2.2 Keystone 凭证服务用户与 Endpoint 的双向认证Neutron Server 启动时会主动向 Keystone 发起两个关键请求一是用admin用户凭据获取neutron服务用户的 token二是用该 token 查询自身注册的 service catalog确认neutron服务的 public/internal/admin 三个 endpoint URL。这个过程在/var/log/neutron/server.log中体现为INFO neutron.common.config [-] Using config files: /etc/neutron/neutron.conf INFO neutron.common.config [-] Using paste config file: /etc/neutron/api-paste.ini INFO neutron.server.wsgi_eventlet [-] Starting eventlet wsgi server... INFO keystoneauth.session [-] Loading _default_auth_plugin from session INFO keystoneauth.identity.v3.base [-] Making authentication request to http://controller:5000/v3/auth/tokens因此我们必须手动创建服务用户并注册 endpoint# 切换到 admin 环境 source /root/admin-openrc # 创建 neutron 服务用户密码需与 neutron.conf 中 auth_url 一致 openstack user create --domain default --password NEUTRON_PASS neutron # 将 neutron 用户加入 service project 并赋予 admin 角色 openstack role add --project service --user neutron admin # 创建 neutron 服务实体 openstack service create --name neutron \ --description OpenStack Networking network # 注册三个 endpoint注意publicurl 必须是客户端可访问地址internalurl 是服务间通信地址 openstack endpoint create --region RegionOne \ network public http://controller:9696 openstack endpoint create --region RegionOne \ network internal http://controller:9696 openstack endpoint create --region RegionOne \ network admin http://controller:9696注意http://controller:9696中的controller必须能在所有 Neutron 组件所在主机上解析。若使用 IP需确保/etc/hosts或 DNS 中已正确映射。这是手动安装中最常被忽略的环节——Ansible 会自动注入 hostvars而手工配置时你必须亲自验证ping controller和curl -I http://controller:9696是否成功。2.3 API 端点监听为什么必须禁用 IPv6 并绑定具体 IPNeutron Server 默认监听0.0.0.0:9696这在测试环境可行但在生产中存在严重风险它会同时监听 IPv4 和 IPv6 的所有接口包括 Docker 网桥、Kubernetes CNI 接口等非预期网络平面。更危险的是当系统启用 IPv6 时Python 的socket库可能因AI_ADDRCONFIG标志导致监听失败表现为OSError: [Errno 99] Cannot assign requested address。我们在/etc/neutron/neutron.conf中强制约束[DEFAULT] bind_host 10.0.0.11 # 控制节点管理网 IP非 0.0.0.0 bind_port 9696 use_syslog false log_dir /var/log/neutron [oslo_messaging_rabbit] # RabbitMQ 配置此处略但必须存在bind_host必须是控制节点上真实存在的、且仅用于 OpenStack 管理通信的 IP 地址。我们通常规划一个独立的管理网段如 10.0.0.0/24该网段物理隔离不与租户网络、存储网络混用。这样做的好处是当 Neutron Server 启动时ss -tlnp | grep :9696输出将明确显示10.0.0.11:9696而非模糊的*:9696便于后续防火墙策略精确控制。验证端点是否生效# 使用 admin 凭据查询 neutron 服务状态 openstack network list # 应返回空列表无网络但不报错即表示 API 可达 # 直接 curl 测试绕过 openstack client curl -H X-Auth-Token: $(openstack token issue -f value -c id) \ http://10.0.0.11:9696/v2.0/networks # 返回 {networks: []} 即成功这一步看似简单却是整个 Neutron 控制平面的“心脏起搏器”。如果这里失败后续所有 Agent、Plugin、Driver 的加载都将失去意义——因为它们都需要通过这个 API 端点接收指令。3. ML2 插件深度配置驱动加载、类型驱动与机制驱动的三层解耦Neutron 的核心架构是插件化Plugin与驱动化Driver的。ML2Modular Layer 2插件是当前事实标准它将网络类型抽象Type Driver、物理网络映射Mechanism Driver和端口绑定Binding Mechanism彻底解耦。手动安装的关键就在于理解这三层如何协同工作并亲手配置每一环。3.1 Type Driver定义网络类型语义而非物理实现type_drivers配置项决定 Neutron 支持哪些网络类型flat扁平网络、vlanVLAN 隔离、vxlanVXLAN 隧道、greGRE 隧道。很多人误以为选了vxlan就自动启用 VXLAN其实这只是告诉 Neutron“我允许用户创建 VXLAN 类型的网络”真正的隧道封装由 Mechanism Driver 在计算节点完成。在/etc/neutron/plugins/ml2/ml2_conf.ini中[ml2] type_drivers flat,vlan,vxlan tenant_network_types vxlan mechanism_drivers openvswitch,l2population extension_drivers port_security,qos [ml2_type_flat] flat_networks provider [ml2_type_vlan] network_vlan_ranges provider:1000:2000 [ml2_type_vxlan] vni_ranges 1001:2000 vxlan_group 239.1.1.1关键参数解析tenant_network_types vxlan指定租户网络默认使用 VXLAN。这意味着openstack network create net1创建的网络其provider:network_type字段将自动设为vxlan。flat_networks provider声明名为provider的物理网络为 Flat 类型。这对应外部物理交换机上的一个无标签接口常用于提供外网访问。vni_ranges 1001:2000VXLAN 网络标识符范围。每个租户网络分配一个唯一 VNI避免不同网络间 VXLAN 封包混淆。vxlan_group 239.1.1.1VXLAN 组播地址。OVS 在计算节点上会向该组播地址发送泛洪流量用于学习远端 VTEPVXLAN Tunnel End Point地址。生产环境建议改用l2population机制驱动替代组播。实操心得network_vlan_ranges中的provider:1000:2000表示物理网络provider上可用的 VLAN ID 范围是 1000-2000。这个范围必须与你机房物理交换机上配置的 Trunk 端口允许的 VLAN 列表严格一致。曾有客户因交换机侧只放行 VLAN 100-199而 Neutron 配置了 1000-2000导致所有 VLAN 网络创建后状态始终为DOWN排查耗时两天。3.2 Mechanism Driver连接虚拟与物理世界的桥梁Mechanism Driver 是 ML2 插件中最具实操价值的部分它决定了 Neutron 如何将虚拟网络指令翻译成物理设备动作。openvswitch驱动负责与本地 OVS 交互l2population驱动则解决 VXLAN 大二层泛洪问题。l2population的工作原理是当计算节点上的 OVS 创建一个新端口如tapxxx时ovs-agent会将该端口的 MAC 地址、IP 地址、所在计算节点 IPVTEP IP上报给 Neutron ServerServer 再将这些信息同步给集群内所有其他ovs-agent各 agent 于是更新本地 OVS 的 FDBForwarding Database表实现 MAC 地址学习避免依赖组播泛洪。启用l2population需在控制节点和计算节点同时配置# /etc/neutron/plugins/ml2/ml2_conf.ini (控制节点) [ml2] mechanism_drivers openvswitch,l2population [ml2_l2pop] enable_centralized_ipv6_nd_ra false# /etc/neutron/plugins/ml2/ml2_conf.ini (计算节点) [ml2] mechanism_drivers openvswitch,l2population [ml2_l2pop] enable_centralized_ipv6_nd_ra false踩坑实录enable_centralized_ipv6_nd_ra false是必须设置的。若为trueNeutron Server 会尝试在集中式路由器上发布 IPv6 邻居通告ND RA但大多数物理交换机不支持此功能导致ovs-agent启动时报错L2Population driver requires centralized ipv6 nd ra disabled。这个错误在官方文档中被轻描淡写却是生产环境高频故障点。3.3 Port Binding如何让虚拟机网卡“插进”正确的 OVS 端口Port Binding 机制决定了虚拟机启动时其虚拟网卡vNIC如何绑定到 OVS 的具体端口。ML2 提供多种 binding mechanism最常用的是vlan、vxlan、flat它们与 type_drivers 一一对应。在/etc/neutron/plugins/ml2/ml2_conf.ini中[ml2] tenant_network_types vxlan type_drivers flat,vlan,vxlan mechanism_drivers openvswitch,l2population # 新增 binding 配置 [ml2_type_vxlan] vni_ranges 1001:2000 vxlan_group 239.1.1.1 [securitygroup] enable_security_group true firewall_driver iptables_hybridfirewall_driver iptables_hybrid是关键。它表示 Neutron 将使用混合模式对虚拟机端口既在 OVS 流表中设置 ACL 规则基于 OpenFlow也在 Linux netfilter 中插入 iptables 规则用于处理非 OVS 流量如 metadata 请求。这比纯openvswitch驱动更健壮能防止因 OVS 流表丢失导致的安全组失效。验证 ML2 配置是否加载成功# 重启 neutron-server systemctl restart neutron-server # 查看日志确认 ML2 插件初始化无报错 journalctl -u neutron-server -n 50 --no-pager | grep -i ml2\|driver # 正常输出应包含 # INFO neutron.plugins.ml2.plugin [req-...] Loading type driver: vxlan # INFO neutron.plugins.ml2.plugin [req-...] Loading mechanism driver: openvswitch # INFO neutron.plugins.ml2.plugin [req-...] Loading mechanism driver: l2population此时Neutron Server 已具备解析网络类型、调用对应驱动、生成 OVS 配置指令的能力。但它还不能真正“干活”因为缺少与外部物理网络的连接通道——这正是下一节要解决的“外部环境配置”核心。4. 外部网络配置实战Provider Network 与物理交换机的硬连接Neutron 的“外部网络”External Network不是虚拟概念而是指代真实物理网络基础设施。手动安装的最大价值就体现在这一环你必须亲手将虚拟网络的逻辑描述映射到物理交换机的具体端口、VLAN、Trunk 配置上。这一步出错整个 OpenStack 网络对外服务能力将归零。4.1 Provider Network 创建从逻辑定义到物理落地Provider Network 是 Neutron 中最接近物理网络的抽象。它不经过隧道封装而是直接复用物理网络的二层域。创建一个名为provider的外部网络需两步逻辑定义 物理连接。逻辑定义在控制节点执行# 创建外部网络--external 标志至关重要 openstack network create --share --external \ --provider-physical-network provider \ --provider-network-type flat provider # 为该网络创建子网注意--no-dhcp 和 --gateway 0.0.0.0 openstack subnet create --network provider \ --allocation-pool start10.0.100.10,end10.0.100.200 \ --dns-nameserver 10.0.0.1 \ --gateway 10.0.100.1 \ --subnet-range 10.0.100.0/24 \ --no-dhcp provider-subnet关键参数说明--external标记此网络为外部网络允许浮动 IPFloating IP绑定。--provider-physical-network provider关联 ML2 配置中的flat_networks provider。--provider-network-type flat指定使用 Flat 类型即不打 VLAN 标签。--no-dhcp外部网络禁用 Neutron DHCP 代理因为物理网络已有 DHCP 服务器如 Windows AD DC 或专用 DHCP 设备。--gateway 10.0.100.1指定物理网关 IP此 IP 必须在物理交换机上可达。物理连接在控制节点上配置 OVS Bridge# 创建名为 br-ex 的外部网桥 ovs-vsctl add-br br-ex # 将物理网卡假设为 eth1添加为 br-ex 的端口 ovs-vsctl add-port br-ex eth1 # 为 br-ex 分配 IP此 IP 仅用于管理不参与租户流量 ip addr add 10.0.100.11/24 dev br-ex ip link set br-ex up # 验证 ovs-vsctl show # 输出应包含 # Bridge br-ex # Port br-ex # Interface br-ex # type: internal # Port eth1 # Interface eth1注意eth1必须是独立的物理网卡不能与管理网eth0、存储网eth2共用。这是物理隔离原则的体现。若使用单网卡多 VLAN 方案则需改为--provider-network-type vlan并配置--provider-segment 100。4.2 物理交换机侧配置华为 S5735 与 Cisco Nexus 9K 的实操差异Neutron 的provider网络最终要接入物理交换机。不同厂商设备配置逻辑迥异手动安装者必须掌握其差异。华为 S5735-S-L24T4S-A常见于国内政企机房# 进入系统视图 system-view # 创建 VLAN 100与 Neutron 子网 10.0.100.0/24 对应 vlan 100 quit # 配置上行端口连接 OpenStack 控制节点 eth1为 Trunk 模式 interface GigabitEthernet0/0/1 port link-type trunk port trunk allow-pass vlan 100 quit # 配置下行端口连接用户 PC 或服务器为 Access 模式 interface GigabitEthernet0/0/2 port link-type access port default vlan 100 quit # 开启全局 DHCP Snooping增强安全性 dhcp enable dhcp snooping enableCisco Nexus 9K金融、大型云厂商常用# 进入配置模式 configure terminal # 创建 VLAN 100 vlan 100 name OPENSTACK_PROVIDER exit # 配置上行端口连接控制节点 interface Ethernet1/1 switchport switchport mode trunk switchport trunk allowed vlan 100 no shutdown exit # 配置 SVISwitch Virtual Interface作为网关 interface Vlan100 no shutdown ip address 10.0.100.1/24 hsrp 100 ip 10.0.100.1 exit关键区别华为设备需显式port trunk allow-pass vlan 100而 Cisco 需switchport trunk allowed vlan 100。若遗漏此步物理网卡eth1虽能 ping 通交换机但 Neutron 创建的虚拟机无法获取 IP因为 VLAN 标签被交换机丢弃。这是手动安装中最隐蔽的故障点之一——日志里没有任何报错只有网络不通。4.3 Floating IP 与 SNAT让租户网络访问外网的双重路径Provider Network 解决了“外网进内网”Floating IP但租户网络如 VXLAN 网络的虚拟机要主动访问外网如 yum update还需 SNATSource Network Address Translation。Neutron 通过neutron-l3-agent实现此功能。其原理是在控制节点上创建一个名为qrouter-xxx的网络命名空间该 namespace 内包含两个虚拟网卡qr-xxx连接租户网络和qg-xxx连接 provider 网络。所有租户网络出向流量经qg-xxx网卡时被 iptables SNAT 规则修改源 IP 为 provider 网络的 IP。启动 L3 Agent# 编辑 /etc/neutron/l3_agent.ini [DEFAULT] interface_driver openvswitch external_network_bridge br-ex # 关键指向我们创建的 br-ex # 其他配置略 # 启动服务 systemctl enable neutron-l3-agent systemctl start neutron-l3-agent创建路由器并关联网络# 创建路由器--ha false 表示非高可用简化测试 openstack router create --no-ha provider-router # 将 provider 网络设为外部网络 openstack router set --external-gateway provider provider-router # 将租户网络假设已创建名为 tenant-net 的 VXLAN 网络设为内部网络 openstack router add subnet provider-router tenant-subnet验证 SNAT 是否生效# 进入 qrouter 命名空间 ip netns exec qrouter-$(openstack router list -f value -c ID | head -1) ip a # 应看到 qr-xxx租户侧和 qg-xxxprovider 侧两个接口 # 查看 iptables 规则 ip netns exec qrouter-$(...) iptables -t nat -S | grep SNAT # 输出类似-A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.0.100.11此时租户网络内的虚拟机即可通过10.0.100.11控制节点 br-ex IP访问外网。而外部用户可通过绑定到虚拟机端口的 Floating IP如10.0.100.100直接访问该虚拟机。5. 故障排查链路从neutron-server启动失败到ovs-agent状态异常的完整诊断树手动安装的价值不仅在于“能装”更在于“能修”。当 Neutron 服务出现异常时Ansible 只会告诉你 “failed”而手动安装者必须能沿着完整的调用链路逐层定位问题。以下是我总结的五层诊断树覆盖 90% 的生产环境故障。5.1 第一层neutron-server进程与日志API 层这是最表层的故障。systemctl status neutron-server显示active (running)不代表服务健康。必须检查日志# 查看最近 100 行错误 journalctl -u neutron-server -n 100 --no-pager | grep -E (ERROR|CRITICAL|Traceback) # 常见错误及根因 # ERROR neutron.db.migration [req-...] Database schema is not up to date # → 根因未执行数据库迁移。修复su -s /bin/bash neutron -c neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head # CRITICAL neutron.wsgi [req-...] Unable to load configuration file # → 根因neutron.conf 或 ml2_conf.ini 语法错误。修复用 python -m py_compile /etc/neutron/neutron.conf 测试语法实操技巧在neutron.conf中设置debug true和verbose true可输出更详细日志但切记生产环境必须关闭否则日志爆炸。5.2 第二层数据库连接与表结构数据层即使neutron-server进程 running也可能因数据库连接池耗尽或表结构不匹配而拒绝服务。验证方法# 检查数据库连接数 mysql -uneutron -pNEUTRON_DBPASS -e SHOW STATUS LIKE Threads_connected; # 检查关键表是否存在neutron 会自动创建但若权限不足会失败 mysql -uneutron -pNEUTRON_DBPASS -e USE neutron; SHOW TABLES LIKE networks; # 检查表字符集必须为 utf8mb4 mysql -uneutron -pNEUTRON_DBPASS -e USE neutron; SHOW CREATE TABLE networks\G | grep CHARSET5.3 第三层ML2 插件加载与驱动初始化插件层neutron-server日志中若出现Loading mechanism driver: openvswitch但后续无Loaded提示说明驱动加载失败。原因通常是Python 包缺失pip3 install neutron-plugin-ml2配置路径错误[ml2] plugin_configuration_path指向不存在目录驱动版本不兼容Neutron 16.x 要求openvswitch驱动版本 2.11验证驱动加载# 查看 neutron-server 加载的 Python 模块 ps aux | grep neutron-server | grep -o python[0-9]* # 假设为 python3.6则执行 python3.6 -c from neutron.plugins.ml2 import plugin; print(plugin.__file__)5.4 第四层OVS 网桥与端口状态数据面层neutron-server正常但虚拟机无法通信问题必在数据面。核心命令# 查看所有网桥 ovs-vsctl show # 查看 br-int集成网桥流表确认是否有匹配规则 ovs-ofctl dump-flows br-int | head -20 # 查看 br-ex外部网桥端口状态 ovs-ofctl dump-ports-desc br-ex # 检查物理网卡是否 UP ip link show eth1 | grep state UP踩坑实录ovs-vsctl show输出中若br-ex下的eth1端口显示link_state: down但ip link show eth1显示UP说明 OVS 未正确识别物理网卡。根因是内核模块未加载modprobe openvswitch然后systemctl restart openvswitch.5.5 第五层neutron-l3-agent与命名空间路由L3 层neutron-l3-agent状态为active但openstack router list显示status: ERROR。进入诊断# 查看 l3-agent 日志 journalctl -u neutron-l3-agent -n 50 --no-pager # 进入 qrouter 命名空间检查路由表 ip netns exec qrouter-$(openstack router list -f value -c ID | head -1) ip route # 应包含 # default via 10.0.100.1 dev qg-xxx # 192.168.1.0/24 dev qr-xxx scope link src 192.168.1.1 # 检查 iptables SNAT 规则 ip netns exec qrouter-$(...) iptables -t nat -L POSTROUTING -n -v # 若计数器为 0说明流量未到达此 namespace完整排查链路如下表所示按优先级从高到低排列故障现象检查层级关键命令典型根因修复方案neutron-server启动失败第一层journalctl -u neutron-server配置文件语法错误python -m py_compile /etc/neutron/neutron.confopenstack network list报Connection refused第一层curl -I http://10.0.0.11:9696neutron-server未监听指定 IP检查neutron.conf中bind_host与ss -tlnp | grep 9696neutron-l3-agent状态DOWN第四层ovs-vsctl showbr-ex未创建或eth1未添加ovs-vsctl add-br br-ex ovs-vsctl add-port br-ex eth1租户虚拟机能 ping 通qr-xxx但无法访问外网第五层ip netns exec qrouter-xxx ip route缺少默认路由ip netns exec qrouter-xxx ip route add default via 10.0.100.1临时Floating IP 无法访问虚拟机第四层ovs-ofctl dump-flows br-int | grep FLOATING_IPSNAT 规则未生效重启neutron-l3-agent检查l3_agent.ini中external_network_bridge br-ex这条链路不是线性的而是网状的。经验告诉我80% 的问题集中在第一层配置和第四层OVS而第五层L3问题往往由前两层引发。手动安装者必须像外科医生一样带着这份诊断树一层层切开问题表象直达病灶。6. 最后的硬核提醒三个必须手写的检查清单与一个永远有效的验证命令手动安装 Neutron 不是终点而是运维长跑的起点。在你合上终端、离开控制节点之前请务必完成以下三项手写检查。这不是形式主义而是用物理笔迹强化大脑对关键路径的记忆——毕竟当凌晨三点告警响起时你不会去翻电子文档只会本能地回忆起自己写下的那几行字。6.1 检查清单一网络平面物理映射表手写在 A4 纸上OpenStack 逻辑名称物理网卡IP 网段用途交换机端口VLAN ID备注managementeth010.0.0.0/24控制节点管理SW1-Gig0/1N/A必须能 SSHprovidereth110.0.100.0/24外网接入SW1-Gig0/2N/Abr-ex绑定于此tenant-vxlaneth210.0.200.0/24