刚接触devstack,可能第一步发愁的就是写 local.conf 了吧。
反正我是在部署前为了让网络的连通性得到保障,根据实际环境在网络规划面前做了考虑。下面是网络方面的部分配置:

1
2
3
4
5
HOST_IP=192.168.100.15  #宿主机接口IP地址
FLOATING_RANGE="192.168.100.0/24" #provide网络CIDR
PUBLIC_NETWORK_GATEWAY="192.168.100.1" #provide网络网关
FIXED_RANGE="192.168.10.0/24" #self-service网络CIDR
NETWORK_GATEWAY="192.168.10.1" #self-service网络网关

当时我为了建立的虚机可以访问外网,特意将 FLOATING_RANGE 设置为和物理机所在网络同一网段。后来证明我是 too young too simple,但是我的这个方案除了后续需要手动修改,比较麻烦,但是也有优势所在,比如分配的 fip 可以被外部主动访问,所以姑且来谈一谈吧。

照这样部署完成后,确实生成了一个 CIDR 为 192.168.100.0/24 的 public 网络,作为 provide 提供外部网络连通。
但仔细观察,网关设置在了 br-ex 这个 port 上,这显然是不合理的,该网络为 provide 网络,和宿主机所在网络同处于一个广播域,该网络网关应该位于 underlay 网络的三层设备上。
因此,为了使 public 可以正常使用,做了以下操作:

  1. 去掉物理机 eth0 上的IP地址(注意会断掉 ssh 连接)
  2. 将 eth0 绑定至 br-ex 桥上,成为 br-ex 桥上的一个 port
  3. 给 br-ex 桥上的 br-ex 这个 port 配上原先物理接口上的IP,配置文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 编辑 /etc/sysconfig/network-scripts/ifcfg-br-ex
# 将原先宿主机接口的 ip 填写在对应区域

DEVICE=br-ex
ONBOOT=yes
HOTPLUG=no
NM_CONTROLLED=no
PEERDNS=no
DEVICETYPE=ovs
TYPE=OVSBridge
BOOTPROTO=static
IPADDR= # 原先宿主机接口网络的地址
NETMASK= # 原先宿主机接口网络的掩码
GATEWAY= # 原先宿主机接口的网关

# 对应的物理网卡配置,例如 eth0 为 external 网桥的物理网卡。编辑 /etc/sysconfig/network-scripts/ifcfg-eth0
# (其实这一步是使用配置文件将把宿主机的 eth0 接口添加至 br-ex 网桥的这个操作固化,以免重启导致 port 掉了)

DEVICE=eth0
ONBOOT=yes
HOTPLUG=no
NM_CONTROLLED=no
PEERDNS=no
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br-ex
BOOTPROTO=none

# 如果部署环境使用 bond,就需要创建 bond-port
# 例如 eth1,eth2 为此 bond port。编辑 /etc/sysconfig/network-scripts/ifcfg-bond1

DEVICE=bond1
ONBOOT=yes
HOTPLUG=no
NM_CONTROLLED=no
PEERDNS=no
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br-ex # ovs 桥的名字
DEVICETYPE=ovs
TYPE=OVSBond
BOND_IFACES="eth1 eth2" # bond 的物理网卡
OVS_OPTIONS="lacp=active bond_mode=balance-slb" # bond 的类型

# 对应的物理网卡 eth1 的配置,编辑 /etc/sysconfig/network-scripts/ifcfg-eth1

DEVICE=eth1
ONBOOT=yes
HOTPLUG=no
NM_CONTROLLED=no
PEERDNS=no
BOOTPROTO=none

# 对应的物理网卡 eth2 的配置,编辑 /etc/sysconfig/network-scripts/ifcfg-eth2

DEVICE=eth2
ONBOOT=yes
HOTPLUG=no
NM_CONTROLLED=no
PEERDNS=no
BOOTPROTO=none
  1. 禁用其他没有使用到的网卡,并重启网络服务是配置生效
1
2
3
4
5
6
# vim /etc/sysconfig/network-scripts/ifcfg-enoX

BOOTPROTO="none"
ONBOOT="no"

# systemctl restart network

至此,使 qrouter 关联该网络后,虚机的南北流量就可以经过 qrouter 路由并进行 snat 后找到该物理网络的正确网关,实现对外网的访问。
需要注意的是,建议使用真实物理机搭建 devstack 环境,而若使用 openstack 环境虚机,再在里面搭建 devstack 环境,还需要一些另外处理。
比如,上文中移动 IP 导致 mac 地址变化,宿主机也需要转发数据,则需要关闭该 port 的安全组和端口安全;此时获取的 fip 是外层 openstack 的 self-service 网络的ip,需要避免冲突和再次进行外层的 fip 映射。


之后不久排查问题,偶然发现在 iptables 的 nat 表里存在这样一条规则:

devstack的自定义public网络利用snat和外部连通

原来 devstack 中的用来连接外部网络的 public 网络是可以自定义的,无需考虑实际环境,之后通过 snat 将原地址转换宿主机物理接口的 ip 与外部网络通信。即虚机的包经过了 qrouter 的 snat ,又再次经过宿主机上的一次 snat 。
显而易见,这样的方案, fip 的作用在 devstack 节点外是不生效的。

另外需要注意的是,filter 表有一条规则会将这样的数据 drop,细节记不太清了,需要把这条规则删除,内部虚机才能正常主动访问外网。