一、Neutron 网络
传统网络vs虚拟网络

网络虚拟化

Neutron架构图:

Neutron 的架构是基于插件的,不同的插件提供不同的网络服务,主要包含一下组件
- Neutron Server: 对外提供网络API,并调用Plugin处理请求
- Plugin:处理Neutron server的请求,维护网络状态,并调用Agent处理请求
- Agent: 处理Plugin的请求,调用底层虚拟或物理网络设备实现各种网络功能



虚拟交换机:
Bridge:
OVS: Open Vswitch
OVN: Open Virtual Network

tap设备:虚拟机虚拟网卡名称,在虚拟机操作系统中网卡eth0,在openstack看来就是一个tap设备
qbr: QEME Bridge 提供安全组规则,目前OpenSwitch 不支持iptables防火墙规则,引入qbr 来实现iptables规则
qvb: Bridge qbr
qvo: OVS qvo
br-int: 内部虚机交换机 集成网桥,所有instance 的虚拟网卡和其他虚拟网络设备都将连接到该网桥
br-tun: 隧道网桥,基于隧道技术的vxlan 和 GRE 网络将使用 该网桥进行通信
metadata agent cloud-init 如果没有该服务,即使安装了cloud-init也无法实现个性化信息,主机名 IP地址 root密码等
Agent: 代理,具体处理业务的存在 L2 Agent 处理真正二层交换数据
L3 Agent 处理路由数据
VM1和VM2 在同一个子网,并且在同一台计算节点上,则VM1访问VM2,直接通过br-int这个内部虚拟交换机来实现,提升访问性能
Neutron 组件-Agent
- Neutron Agent 向虚拟机提供二层和三层的网络连接、完成虚拟网络和物理网络,之间的转换,提供扩展服务
Neutron Agent :L2 Agent 、L3 Agent、DHCP Agent、MetaData Agent
在一个网络中,L2 Agent 可以由Bridge或者OVS 来实现,但是同时只能使用其中之一,所有节点要么是Bridge ,要么是OVS,考虑到业务的多样性,其他公司和其他公司采用不同L2 Agent。
引入ML2 ,支持多种L2 Agent 让我们的环境同时支持多种L2 Agent
==========================================
ML2插件 :
通过TypeManager 和 MechainismManager 实现二层互通
抽象出Plugin中共性代码(DB等)减少厂商新增和维护Plugin的工作量、只需实现driver即可
解决原结构中只支持一个Plugin的问题,同时支持多个Driver
通过l2 polulation 减少overlay网络广播流量
实现异构部署: 每个hypervisor node可使用不同的driver
计算节点运行L2 Agent openstack-openvswitch.service
网络节点运行L3 Agent
neutron-L3-agent.service
查看各个节点运行的网络组件
neutron agent-list
普通用户创建网络时,不能指定类型,使用默认类型
LOCAL :如果Neutron 租户采用该网络,只有同一个计算节点的虚拟机才能通讯,仅主机模式一般不采用
Flat: 扁平网络 不采用VLAN隔离的网络
VLAN: 带vlan tag的网络
VXLAN,GRE 等: 隧道网络
1. FLAT网络
需求一 :改造现有的VXLAN网络为Flat 网络(无Vlan隔离的网络类型)
1.在管理员身份下,创建指定的网络
OVS flat network
flat network 是不带tag的网络,宿主机的物理网卡通过网桥与flat network连接,每个flat网络都会占用一个物理网卡。
在ML2 配置中 enable flat network
在控制节点/etc/neutron/plugins/ml2/ml2_conf.ini 中设置 flat network 相关参数:
[ml2]
tenant_network_types = flat
extension_drivers = port_security
type_drivers = local,flat,vlan,gre,vxlan
memchanism_drivers = openvswitch
tenant_network_types = flat
指定普通用户网络类型为flat
&& flat网络与物理网卡一一对应,一般情况下租户网络不会采用flat
label 是flat网络的标识,在创建flat时会用到,label命名是可以任意字符串,只要确保各个节点ml2_conf.ini中的label命名一致就可以了。各个节点中label与物理网卡的对应可能不一样。
每个节点可以使用不同的物理网卡将instance 连接到flat网络
与linux bridge实现的flat网络不同,ml2中并不会直接指定label与物理网卡的对应关系,而是指定label与ovs bridge的对应关系
[ovs]
bridge_mappings = default-eth1
这里的ovs bridge 是br-eth1,需要提前通过命令ovs-ovctl 命令:
1. 创建br-eth1
1. 将物理网卡eth1 桥接在br-eth1上
如果要创建多个flat网络,需要定义多个label,用逗号隔开,当然也需要用到多个ovs bridge,如下所示:
[ml2_type_flat]
flat_networks = flat1,flat2
[ovs]
bridge_mappings = flat1:br-eth1,flat2:eth2
通过以上步骤控制节点的flat网络就准备好了。计算节点也需要做相同的配置,然后重启所有节点上的neutron服务
controller :
ovs-vsctl add-br br-eth1
ovs-vsctl add-port br-eth1 ens37
compute:
ovs-vsctl add-br br-eth1
ovs-vsctl add-port br-eth1 ens37
controller:
[root@controller ~]# egrep -v ‘^#|^$’ /etc/neutron/plugins/ml2/ml2_conf.ini
[ml2]
type_drivers=geneve,flat,vxlan,vlan
tenant_network_types=flat
mechanism_drivers=openvswitch
extension_drivers=port_security,qos
path_mtu=0[root@controller ~]# egrep -v “^#|^$” /etc/neutron/plugins/ml2/openvswitch_agent.ini
[DEFAULT]
[agent]
tunnel_types=vxlan
vxlan_udp_port=4789
l2_population=False
[dhcp]
[network_log]
[ovs]
local_ip=192.168.132.100
bridge_mappings=default:br-eth1[root@controller ~]# systemctl restart neutron-server.service neutron-openvswitch-agent.service
compute:
[root@compute ~]# egrep -v “^#|^$” /etc/neutron/plugins/ml2/openvswitch_agent.ini
[DEFAULT]
[agent]
tunnel_types=vxlan
vxlan_udp_port=4789
l2_population=False
[dhcp]
[network_log]
[ovs]bridge_mappings=default:br-eth1
local_ip=192.168.132.200
[securitygroup]
firewall_driver=neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
可以创建flat 网络default 创建实例,但是通不了外网
需求二:需要让vm1 可以访问internet,或者与其他网段互通
在网络节点上配置neutron
[root@controller ~]# egrep -v ‘^#|^$’ /etc/neutron/plugins/ml2/ml2_conf.ini
[DEFAULT]
[ml2]
type_drivers=geneve,flat,vxlan,vlan
tenant_network_types=flat
mechanism_drivers=openvswitch
extension_drivers=port_security,qos
path_mtu=0
[ml2_type_flat]
flat_networks=default,extnet
[ml2_type_geneve]
vni_ranges=10:100
max_header_size=38
[ml2_type_gre]
[ml2_type_vlan]
network_vlan_ranges=
[ml2_type_vxlan]
vni_ranges=10:100
vxlan_group=224.0.0.1
[ovs_driver]
[securitygroup]
enable_security_group=True
[sriov_driver]
[root@controller ~]# egrep -v “^#|^$” /etc/neutron/plugins/ml2/openvswitch_agent.ini
[DEFAULT]
[agent]
tunnel_types=vxlan
vxlan_udp_port=4789
l2_population=False
[dhcp]
[network_log]
[ovs]
local_ip=192.168.132.100
bridge_mappings=default:br-eth1,exnet:br-ex
[root@controller ~]# systemctl restart neutron-server.service neutron-openvswitch-agent.service
admin用户 创建其他 flat网络 外部
租户创建路由器使用外部网路 关联内部网络
租户的云主机可通网关可通外网
云主机重启获得主机名 主机名和路由器有关

弹性ip在哪里
ip netns ls
1 | [root@controller ~]# ip netns ls |

# iptables -t nat -A PREROUTING -d 192.168.11.13 -j DNAT –to-dest 192.168.99.195
1 | [root@controller ~(keystone_admin)]# ip netns exec qrouter-9306759e-750f-4001-98c0-cf8cc5c69daf iptables -t nat -nL |
如果云主机绑定了弹性ip,路由器又开启的了SNAT 云主机出去访问是通过SNAT出去,还是弹性ip地址出去?
有弹性ip的优先走弹性ip 没有弹性ip的走路由器SNAT
1 | Chain neutron-l3-agent-float-snat (1 references) |
2. VLAN网络设计与实现
1 | # 所有节点 |
[root@controller ml2(keystone_admin)]# egrep -v ‘^#|^$’ /etc/neutron/plugins/ml2/ml2_conf.ini
[DEFAULT]
[ml2]
type_drivers=geneve,flat,vxlan,vlan
tenant_network_types=vlan
mechanism_drivers=openvswitch
extension_drivers=port_security,qos
path_mtu=0
[ml2_type_flat]
flat_networks=*
[ml2_type_geneve]
vni_ranges=10:100
max_header_size=38
[ml2_type_gre]
[ml2_type_vlan]
network_vlan_ranges=vlannet:100:1000
[ml2_type_vxlan]
vni_ranges=10:100
vxlan_group=224.0.0.1
[ovs_driver]
[securitygroup]
enable_security_group=True
[sriov_driver][root@controller ml2(keystone_admin)]# egrep -v ‘^#|^$’ /etc/neutron/plugins/ml2/openvswitch_agent.ini
[DEFAULT]
[agent]
tunnel_types=vlan
vxlan_udp_port=4789
l2_population=False
[dhcp]
[network_log]
[ovs]
local_ip=192.168.132.100
bridge_mappings=vlannet:br-eth1,extnet:br-ex
[securitygroup]
firewall_driver=neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver[root@compute network-scripts]# egrep -v ‘^#|^$’ /etc/neutron/plugins/ml2/openvswitch_agent.ini
[DEFAULT]
[agent]
tunnel_types=vxlan
vxlan_udp_port=4789
l2_population=False
[dhcp]
[network_log]
[ovs]
tunnel_bridge = br-tun
local_ip=192.168.132.200
bridge_mappings = vlannet:br-eth1
[securitygroup]
firewall_driver=neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
在Openstack web界面上使用admin身份创建网络
租户网络指定不了vlanid


没有地址 br-eth1带vlan100的tag

vmnet2 加了vlan100 相当于access vlan 100 但是机器拿不到dhcp的地址
使用user的租户创建两个云主机

查看 oepnstack neutron 的流表
第一条目: 目标vlan 内部br-int tag 2修改成vlan 100
1 | [root@compute ~]# ovs-ofctl dump-flows br-eth1 |
[root@compute ~]# ovs-ofctl dump-flows br-int
cookie=0xb9c421b8d8288c45, duration=3250.291s, table=0, n_packets=0, n_bytes=0, priority=65535,dl_vlan=4095 actions=drop
cookie=0xb9c421b8d8288c45, duration=1264.686s, table=0, n_packets=0, n_bytes=0, priority=10,icmp6,in_port=”qvo61d1e3f4-64”,icmp_type=136 actions=resubmit(,24)
cookie=0xb9c421b8d8288c45, duration=1206.640s, table=0, n_packets=0, n_bytes=0, priority=10,icmp6,in_port=”qvob6c595eb-1e”,icmp_type=136 actions=resubmit(,24)
cookie=0xb9c421b8d8288c45, duration=1264.685s, table=0, n_packets=0, n_bytes=0, priority=10,arp,in_port=”qvo61d1e3f4-64” actions=resubmit(,24)
cookie=0xb9c421b8d8288c45, duration=1206.637s, table=0, n_packets=0, n_bytes=0, priority=10,arp,in_port=”qvob6c595eb-1e” actions=resubmit(,24)
cookie=0xb9c421b8d8288c45, duration=3250.278s, table=0, n_packets=137, n_bytes=20085, priority=2,in_port=”int-br-eth1” actions=drop
cookie=0xb9c421b8d8288c45, duration=1264.689s, table=0, n_packets=45, n_bytes=9578, priority=9,in_port=”qvo61d1e3f4-64” actions=resubmit(,25)
cookie=0xb9c421b8d8288c45, duration=1206.642s, table=0, n_packets=40, n_bytes=8900, priority=9,in_port=”qvob6c595eb-1e” actions=resubmit(,25)
cookie=0xb9c421b8d8288c45, duration=1548.971s, table=0, n_packets=99, n_bytes=15746, priority=3,in_port=”int-br-eth1”,dl_vlan=100 actions=mod_vlan_vid:2,resubmit(,59)
cookie=0xb9c421b8d8288c45, duration=3250.293s, table=0, n_packets=77, n_bytes=7988, priority=0 actions=resubmit(,59)
cookie=0xb9c421b8d8288c45, duration=3250.294s, table=23, n_packets=0, n_bytes=0, priority=0 actions=drop
cookie=0xb9c421b8d8288c45, duration=1264.687s, table=24, n_packets=0, n_bytes=0, priority=2,icmp6,in_port=”qvo61d1e3f4-64”,icmp_type=136,nd_target=fe80::f816:3eff:fe0d:c784 actions=resubmit(,59)
cookie=0xb9c421b8d8288c45, duration=1206.641s, table=24, n_packets=0, n_bytes=0, priority=2,icmp6,in_port=”qvob6c595eb-1e”,icmp_type=136,nd_target=fe80::f816:3eff:fe17:6da0 actions=resubmit(,59)
cookie=0xb9c421b8d8288c45, duration=1264.686s, table=24, n_packets=0, n_bytes=0, priority=2,arp,in_port=”qvo61d1e3f4-64”,arp_spa=192.168.110.8 actions=resubmit(,25)
cookie=0xb9c421b8d8288c45, duration=1206.638s, table=24, n_packets=0, n_bytes=0, priority=2,arp,in_port=”qvob6c595eb-1e”,arp_spa=192.168.110.7 actions=resubmit(,25)
cookie=0xb9c421b8d8288c45, duration=3250.291s, table=24, n_packets=3, n_bytes=126, priority=0 actions=drop
cookie=0xb9c421b8d8288c45, duration=1264.692s, table=25, n_packets=32, n_bytes=8592, priority=2,in_port=”qvo61d1e3f4-64”,dl_src=fa:16:3e:0d:c7:84 actions=resubmit(,30)
cookie=0xb9c421b8d8288c45, duration=1206.644s, table=25, n_packets=31, n_bytes=8250, priority=2,in_port=”qvob6c595eb-1e”,dl_src=fa:16:3e:17:6d:a0 actions=resubmit(,30)
cookie=0xb9c421b8d8288c45, duration=3250.289s, table=30, n_packets=241, n_bytes=42457, priority=0 actions=resubmit(,59)
cookie=0xb9c421b8d8288c45, duration=3250.288s, table=31, n_packets=0, n_bytes=0, priority=0 actions=resubmit(,59)
cookie=0xb9c421b8d8288c45, duration=3250.293s, table=59, n_packets=531, n_bytes=78790, priority=0 actions=resubmit(,60)
cookie=0xb9c421b8d8288c45, duration=3250.292s, table=60, n_packets=531, n_bytes=78790, priority=3 actions=NORMAL
cookie=0xb9c421b8d8288c45, duration=3250.290s, table=62, n_packets=0, n_bytes=0, priority=3 actions=NORMAL
3. VXLAN 的网络设计和实现
解决: 大二层问题,跨数据中心云主机热迁移问题,热迁移只能在二层网络中
VXLAN 实现将二层网络封装在 三层中进行传输,到了对方解封装,实现二层通讯

[root@controller ml2]# egrep -v ‘^#|^$’ /etc/neutron/plugins/ml2/ml2_conf.ini
[DEFAULT]
[ml2]
type_drivers=geneve,flat,vxlan,vlan
tenant_network_types=vxlan
mechanism_drivers=openvswitch
extension_drivers=port_security,qos
path_mtu=0
[ml2_type_flat]
flat_networks=*
[ml2_type_geneve]
vni_ranges=10:100
max_header_size=38
[ml2_type_gre]
[ml2_type_vlan]
network_vlan_ranges=vlannet:100:1000
[ml2_type_vxlan]
vni_ranges=10:100
vxlan_group=224.0.0.1
[ovs_driver]
[securitygroup]
enable_security_group=True
[sriov_driver][root@controller ml2]# egrep -v ‘^#|^$’ /etc/neutron/plugins/ml2/openvswitch_agent.ini
[DEFAULT]
[agent]
tunnel_types=vxlan
vxlan_udp_port=4789
l2_population=False
[dhcp]
[network_log]
[ovs]
integration_bridge = br-int
tunnel_bridge = br-tun
local_ip=192.168.132.100
bridge_mappings=vlannet:br-eth1,extnet:br-ex
[securitygroup]
firewall_driver=neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver[root@controller ml2]# systemctl restart neutron-server
[root@compute ml2]# egrep -v ‘^#|^$’ /etc/neutron/plugins/ml2/openvswitch_agent.ini
[DEFAULT]
[agent]
tunnel_types=vxlan
vxlan_udp_port=4789
l2_population=False
[dhcp]
[network_log]
[ovs]
integration_bridge = br-int
tunnel_bridge = br-tun
local_ip=192.168.132.200
bridge_mappings = vlannet:br-eth1
[securitygroup]
firewall_driver=neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver



创建一个空的路由器 关联VPC11

重启实例、或者新建实例
可以获取主机名 ping通网关


Neutron - Metadata(元数据)

Metadata: 用于获取客户自己定义、我们又无法直接传送给虚拟机的数据,目前定义在DHCP上,每个网络有一个metadata,数据只走二层,一个网络有一个metadata_proxy,一个主机有一个metadata_agent,meta_proxy由dhcp_agent拉起。
cloud-init工具
- cloud-init是Linux的一个工具,当系统启动时,cloud-init可从nova metadata服务或者config drive 中获取metadata,完成包括但不限于下面的定制化工作
- 设置default locale
- 设置hostname
- 添加ssh keys 到.ssh、authorized_keys
- 设置用户密码
- 配置网络
- 安装软件包
metadata: nova-metadata neutron-metadata
获取metadata流程
instance 通过预定义的169.254.169.254请求metadata
请求被转发到neutron router
router 将请求转发给neutron-ns-metadata-proxy
再后面就简单了: neutron-ns-metadata-proxy将请求通过unix domain socket 发给neutron-metadata-agent,后者再通过管理网络发送给nova-api-metadata



二、跨主机数据流

1️⃣ 跨主机 + 同子网(VM1 $\rightarrow$ VM2)—— 纯二层走线
- VM1 发出报文 $\rightarrow$
tap$\rightarrow$qbr(安全组) $\rightarrow$br-int(打上内部 VLAN 标签,比如 1) $\rightarrow$br-tun(将内部 VLAN 转为 VXLAN ID,比如 100)。 - 关键一步:
br-tun查 MAC 地址表,发现 VM2 在 Compute 2 上,直接封装隧道外层 IP(源:Compute1 IP,目的:Compute2 IP)。 - 网络传输: 数据包通过物理交换机,直接送到 Compute Node 2。
- 解包入库: Compute 2 的
br-tun剥离 VXLAN 头 $\rightarrow$br-int$\rightarrow$qbr$\rightarrow$ VM2。
💡 总结: 同子网跨主机,数据流呈 一字型(直线) 在两个计算节点间互通,不拐弯,不进网络节点。
🗺️ 正确的数据流向步骤拆解(对应上图):
- VM1 ➔ qbr-XXX (安全组): VM1 发现目标 VM2 的 IP 和自己在同一个网段(比如
192.168.10.0/24),于是直接通过tap设备发出二层以太网帧。经过qbr虚拟网桥时,Neutron 安全组规则(iptables/ovs-firewall)对流量进行安全检查。 - qvo-XXX ➔ br-int (集成网桥): 流量通过
qvb/qvo接口进入br-int。此时br-int会给这个数据包打上一个内部 VLAN Tag(本地有效,用于隔离计算节点上的不同网络)。 - patch-tun ➔ br-tun (隧道网桥): 数据包通过
patch-tun补丁接口到达br-tun。 - 二层核心转换 (VLAN ➔ VXLAN):
br-tun根据内部 VLAN Tag 查表,将其转换为全局唯一的 VXLAN ID (Tunnel ID)。同时,br-tun查找 MAC 地址表,发现 VM2 的 MAC 地址在 Compute Node 2 上。 - 物理网络(直接飞过去):
br-tun为数据包封装外层 IP 头(源 IP: Compute 1 的 VTEP IP,目的 IP: Compute 2 的 VTEP IP)。数据包通过物理网卡ethX出去,直接走物理交换机送达 Compute Node 2。
三、跨主机、跨网络数据流

跨主机 + 跨子网(VM1 VM2)—— 三层大拐弯
VM1 发出报文,目的地是 VM2(不同网段),VM1 发现无法直接二层送达,于是将目的 MAC 填为网关(Router 的 qr 接口)的 MAC。
前半程(去网络节点): Compute 1 正常走
br-int$\rightarrow$br-tun(封 VXLAN)。但此时查表发现网关在网络节点上,于是隧道外层目的 IP 填的是 Network Node 的 IP。中转站(网络节点内部剥离与路由):
数据包到达网络节点的
br-tun$\rightarrow$br-int$\rightarrow$ 顺着qr-###接口进入 Router Namespace(虚拟路由器)。三层路由:
路由器摘掉子网 A 的外套,查看路由表,换上子网 B 的外套,从另一个
qr-###接口送回br-int。后半程(去 Compute 2):
网络节点的
br-int$\rightarrow$br-tun(重新封装子网 B 的 VXLAN ID) $\rightarrow$ 此时隧道外层目的 IP 填 Compute Node 2 的 IP。到达终点: 经过物理网络 $\rightarrow$ Compute 2 的
br-tun$\rightarrow$br-int$\rightarrow$ VM2。
💡 总结: 跨子网跨主机,数据流呈 V字型(或三角形)。必须先从 Compute 1 垂直下行到 Network Node 的 Router 换乘,再折返回来到 Compute 2。
四、访问Internet数据流


🛠️ 额外补充:如果是 DVR(分布式路由)呢?
如果你在 OpenStack 里开启了 DVR(Distributed Virtual Router),那么逻辑确实会变得像刚才那张错图一样“差不多”:
- 在 DVR 模式下,每个计算节点上都有路由器的副本。
- VM1 跨子网访问 VM2 时,在 Compute 1 本地就直接由本地路由器完成路由和 VXLAN 转换,然后直接通过隧道发送到 Compute 2。
- 只有当 VM2 需要访问外网(Public Network)或者进行 Floating IP 转换时,才会去和网络节点/网关打交道。