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.28(CentOS 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 'neutron'@'localhost' \ 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 并绑定具体 IP?
Neutron 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)的。ML2(Modular Layer 2)插件是当前事实标准,它将网络类型抽象(Type Driver)、物理网络映射(Mechanism Driver)和端口绑定(Binding Mechanism)彻底解耦。手动安装的关键,就在于理解这三层如何协同工作,并亲手配置每一环。
3.1 Type Driver:定义网络类型语义,而非物理实现
type_drivers配置项决定 Neutron 支持哪些网络类型:flat(扁平网络)、vlan(VLAN 隔离)、vxlan(VXLAN 隧道)、gre(GRE 隧道)。很多人误以为选了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:2000:VXLAN 网络标识符范围。每个租户网络分配一个唯一 VNI,避免不同网络间 VXLAN 封包混淆。vxlan_group = 239.1.1.1:VXLAN 组播地址。OVS 在计算节点上会向该组播地址发送泛洪流量,用于学习远端 VTEP(VXLAN 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 地址、所在计算节点 IP(VTEP IP)上报给 Neutron Server;Server 再将这些信息同步给集群内所有其他ovs-agent;各 agent 于是更新本地 OVS 的 FDB(Forwarding 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是必须设置的。若为true,Neutron 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 start=10.0.100.10,end=10.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:标记此网络为外部网络,允许浮动 IP(Floating 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 # 配置 SVI(Switch 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),还需 SNAT(Source 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-xxx(provider 侧)两个接口 # 查看 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.conf |
openstack network list报Connection refused | 第一层 | curl -I http://10.0.0.11:9696 | neutron-server未监听指定 IP | 检查neutron.conf中bind_host与ss -tlnp | grep 9696 |
neutron-l3-agent状态DOWN | 第四层 | ovs-vsctl show | br-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_IP> | SNAT 规则未生效 | 重启neutron-l3-agent,检查l3_agent.ini中external_network_bridge = br-ex |
这条链路不是线性的,而是网状的。经验告诉我,80% 的问题集中在第一层(配置)和第四层(OVS),而第五层(L3)问题往往由前两层引发。手动安装者必须像外科医生一样,带着这份诊断树,一层层切开问题表象,直达病灶。
6. 最后的硬核提醒:三个必须手写的检查清单与一个永远有效的验证命令
手动安装 Neutron 不是终点,而是运维长跑的起点。在你合上终端、离开控制节点之前,请务必完成以下三项手写检查。这不是形式主义,而是用物理笔迹强化大脑对关键路径的记忆——毕竟,当凌晨三点告警响起时,你不会去翻电子文档,只会本能地回忆起自己写下的那几行字。
6.1 检查清单一:网络平面物理映射表(手写在 A4 纸上)
| OpenStack 逻辑名称 | 物理网卡 | IP 网段 | 用途 | 交换机端口 | VLAN ID | 备注 |
|---|---|---|---|---|---|---|
| management | eth0 | 10.0.0.0/24 | 控制节点管理 | SW1-Gig0/1 | N/A | 必须能 SSH |
| provider | eth1 | 10.0.100.0/24 | 外网接入 | SW1-Gig0/2 | N/A | br-ex绑定于此 |
| tenant-vxlan | eth2 | 10.0.200.0/24 |