本文将继续介绍在将Openstack的nova实例连接到外网过程中网络拓扑的变化。
上一篇文《Openstack Neutron网络实验-01》中在Openstack中创建了以下内容:
- 租户网络test-net,包含子网:test-net-subnet,并启用了dhcp。
- 虚机实例test-vm1,并接入网络test-net。
- 路由器router01, 并接入子网test-net-subnet。
0. 准备-宿主机网络介绍
按照《使用vagrant和virtualbox搭建openstack集群》安装完Openstack后,两台宿主机os-ctl1和os-cpu1可通过网口eth0使用NAT访问外部网络,ip是virtualbox自动分配的10.0.2.15/24。而网口eth1则作为两台宿主机之间通信和管理使用,ip由Vagrantfile中的网络配置指定。
本次实验的目的使得虚机实例test-vm1能够访问外部网络,任务是要创建一个External Network将之前创建的租户网络接入到网络节点os-ctl1的网口eth0。
1. 创建外部网络
在Openstack上创建一个外部网络,菜单路径为:Admin -> Network -> Networks -> Create Network。
注意:仅能在Admin菜单下才能创建External Network, Project菜单下只能创建租户内部网络
填入如下参数:
- Name:external-net
- Project:admin
- Provider Network Type: Flat
- Physical Network: extnet,该参数为物理网络的标识,需要和Neutron配置文件中的定义一致,packstack的安装参数文件中默认定义如下,表示extnet这个物理网络实际上由br-ex网桥承载。
- CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS=extnet:br-ex
- CONFIG_NEUTRON_OVS_EXTERNAL_PHYSNET=extnet
- Subnet Name: external-net-subnet
- Network Address: 10.0.2.0/24,该参数应和实际的物理网络情况相符,VirtualBox的NAT网络默认使用10.0.2.0/24。
- Gateway IP: 10.0.2.2,该参数应和实际的物理网络情况相符,VirtualBox的NAT网络默认网关为10.0.2.2。
- Enable DHCP: False,该网络中的IP由实际物理网络决定,不需要Openstack的DHCP agent分配。
创建External Network后,网络节点拓扑没有变化。和test-net不一样,external-net没有启用DHCP, 所以其端口列表为空。
2. 将外部网络接入租户Router
将之前创建的租户router01的网关设置为新创建的外部网络,由于上一篇中这个Router已经连接了内部网络test-net,设置网关后将使得两个网络连通起来。
菜单路径为:Project -> Network -> Routers -> router01 -> Set GateWay。填入如下参数:
- External Network:external-net
- Enable SNAT: True,打开SNAT使得从租户网络出去的数据包的源地址被转换成外部网络地址。
# ovs-vsctl show
...
Bridge br-int
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port int-br-ex
Interface int-br-ex
type: patch
options: {peer=phy-br-ex}
Port "tape68eed07-f5"
tag: 1
Interface "tape68eed07-f5"
type: internal
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port "qg-95f2615e-cd"
tag: 9
Interface "qg-95f2615e-cd"
type: internal
Port br-int
Interface br-int
type: internal
Port "qvo5d07f509-f1"
tag: 1
Interface "qvo5d07f509-f1"
Port "qr-9516320e-52"
tag: 1
Interface "qr-9516320e-52"
type: internal
...
# ip netns exec qrouter-7d360e8e-e392-4def-816b-f92f7e5f9bc5 ip address
1: lo: mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
12: qr-9516320e-52: mtu 1450 qdisc noqueue state UNKNOWN qlen 1000
link/ether fa:16:3e:f6:ec:e8 brd ff:ff:ff:ff:ff:ff
inet 172.16.2.1/24 brd 172.16.2.255 scope global qr-9516320e-52
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fef6:ece8/64 scope link
valid_lft forever preferred_lft forever
24: qg-95f2615e-cd: mtu 1500 qdisc noqueue state UNKNOWN qlen 1000
link/ether fa:16:3e:22:4c:c8 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.10/24 brd 10.0.2.255 scope global qg-95f2615e-cd
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe22:4cc8/64 scope link
valid_lft forever preferred_lft forever
# ip netns exec qrouter-7d360e8e-e392-4def-816b-f92f7e5f9bc5 netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 qg-95f2615e-cd
10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 qg-95f2615e-cd
172.16.2.0 0.0.0.0 255.255.255.0 U 0 0 0 qr-9516320e-52
拓扑图如下:
进入虚机,发现可以ping通网关新增的接口10.0.2.10,但是外部网关没有ping通。
$ ping 10.0.2.10
PING 10.0.2.10 (10.0.2.10): 56 data bytes
64 bytes from 10.0.2.10: seq=0 ttl=64 time=8.391 ms
�
--- 10.0.2.10 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 8.391/8.391/8.391 ms
$ ping 10.0.2.2
PING 10.0.2.2 (10.0.2.2): 56 data bytes
�
--- 10.0.2.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
3. 将访问外部网络的网口eth0加入网桥br-ex中
上述定义的外部网络extnet被映射到了OVS网桥,即Openstack实例将通过网桥br-ex访问外部网络,因此我们需要将网络节点用于访问外部网络的eth0接口加入到br-ex网桥中。
# ovs-vsctl add-port br-ex eth0
# ovs-vsctl show
...
Bridge br-ex
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port "eth0"
Interface "eth0"
Port br-ex
Interface br-ex
type: internal
Port phy-br-ex
Interface phy-br-ex
type: patch
options: {peer=int-br-ex}
...
进入虚机,确认外部网关10.0.2.2已经外网Google DNS IP 8.8.8.8均能ping通。
$ ping 10.0.2.2
PING 10.0.2.2 (10.0.2.2): 56 data bytes
64 bytes from 10.0.2.2: seq=0 ttl=62 time=1.752 ms
�
--- 10.0.2.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 1.752/1.752/1.752 ms
$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=2 ttl=36 time=126.277 ms
�
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 1 packets received, 66% packet loss
round-trip min/avg/max = 126.277/126.277/126.277 ms
4. 配置提供对外访问的网口
eth0加入网桥后,必须将其ip配到网桥br-ex上,否则外部无法访问这个IP,呈现为两个问题:
- floating ip无法访问openstack实例,因为网络节点没有floating ip的路由。
- vagrant ssh无法登陆宿主机。
修改/etc/sysconfig/network-scripts/下的ifcfg-br-ex和ifcfg-eth0文件,内容如下,然后重启网络服务
$ sudo vi /etc/sysconfig/network-scripts/ifcfg-br-ex
$ sudo cat /etc/sysconfig/network-scripts/ifcfg-br-ex
DEVICE=br-ex
OVSBOOTPROTO=dhcp
ONBOOT=yes
NM_CONTROLLED=no
TYPE=OVSBridge
DEVICETYPE=ovs
PERSISTENT_DHCLIENT=yes
OVSDHCPINTERFACES=eth0
$ sudo vi /etc/sysconfig/network-scripts/ifcfg-eth0
$ sudo cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
ONBOOT=yes
NM_CONTROLLED=no
TYPE=OVSPort
DEVICETYPE=ovs
OVS_BRIDGE=br-ex
$ sudo systemctl restart network
上述配置使得eth0在启动时加入到br-ex网桥中,而br-ex网桥通过eth0进行dhcp获取ip,即VirtualBox分配的10.0.2.15/24。
这些配置应该在安装部署Openstack的时候完成,如果使用packstack安装,可以通过设置以下参数指定:
CONFIG_NEUTRON_OVS_BRIDGE_IFACES=br-ex:eth0
5. 分配浮动IP
到此为止,我们已经成功在Openstack中创建了两个网络,并且通过路由器将其连通。当前两个网络如下图显示:
接入外部网络的时候启用了SNAT,因此当数据包由内网发往外网时,路由器会将数据包的源地址转换为外网地址,不同实例的源地址可共享同一个外网地址,即router01的external-net地址10.0.2.10。
但是当数据包由外网发往内网时,则需要使用DNAT协议将目的地址转换为内网地址,此时,每个实例的内网地址均需对应一个外网地址才能供外部访问。
菜单路径为:Project -> Network -> Floating IPs -> Allocate IP to Project。填入如下参数:
- Pool: external-net
分配完成后对该IP点击“Associate”,将其绑定到实例test-vm1中。
绑定完成后,可以看到新分配的外网IP 10.0.2.11被映射到了内网IP 172.16.2.7。
实际上,浮动IP的分配是在router的iptables中添加了一条NAT规则:
# ip netns exec qrouter-7d360e8e-e392-4def-816b-f92f7e5f9bc5 iptables-save -t nat
...
-A neutron-l3-agent-OUTPUT -d 10.0.2.11/32 -j DNAT --to-destination 172.16.2.7
...
5. 修改Security Group
菜单路径为:Project -> Network -> Security Groups -> "default" -> "Manage Rules" -> "Add Rule"。
添加ICMP和SSH两项规则:
- Rule: ALL ICMP
- Rule: SSH
在宿主机上分别使用ping和ssh访问test-vm1实例,均能成功。
# ping 10.0.2.11
PING 10.0.2.11 (10.0.2.11) 56(84) bytes of data.
64 bytes from 10.0.2.11: icmp_seq=1 ttl=63 time=7.74 ms
^C
--- 10.0.2.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 7.747/7.747/7.747/0.000 ms
$ ssh [email protected]
[email protected]'s password:
$ exit
Connection to 10.0.2.11 closed.
实际上,Security Group通过修改网络节点的iptables来实现防火墙功能:
# iptables-save | grep neutron-openvswi
...
-A neutron-openvswi-i5d07f509-f -p icmp -j RETURN
...
-A neutron-openvswi-i5d07f509-f -p tcp -m tcp --dport 22 -j RETURN
...
-A neutron-openvswi-sg-chain -m physdev --physdev-out tap5d07f509-f1 --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-openvswi-i5d07f509-f
-A neutron-openvswi-sg-chain -m physdev --physdev-in tap5d07f509-f1 --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-openvswi-o5d07f509-f
-A neutron-openvswi-sg-chain -j ACCEPT
...
上述规则的意思是指对于在neutron-openvswi-i5d07f509-f链中匹配到了icmp和ssh数据包,返回到其父链neutron-openvswi-sg-chain中继续判断,而父链neutron-openvswi-sg-chain中将接受所有的数据包。
问题:
- 如果把eth0加入到br-int桥,无法访问外网,为什么?