DVR介绍

dvr是distributed virtual router的缩写,目的是为了解决openstack neutron部署的扩展问题,分发网络节点的流量负载到计算节点上。如果实例绑定了floating ip,外网流量直接从计算节点出去,不经过网络节点。对于那些没绑定floating ip的实例外网流量还是走snat,要经过网络节点。


DVR配置

这里说明一下,我的controller node和network node在同一台机器上

controller节点
[root@controller-162 ~(keystone_admin)]# vim /etc/neutron/neutron.conf  # 添加如下配置选项
router_distributed = True

[root@controller-162 ~(keystone_admin)]# vim /etc/neutron/plugins/ml2/ml2_conf.ini   # 网络采用ml2+vxlan,配置如下
[ml2]
type_drivers = flat,vxlan,vlan,gre
tenant_network_types = vxlan
mechanism_drivers = openvswitch,l2population
[ml2_type_flat]
[ml2_type_vlan]
[ml2_type_gre]
[ml2_type_vxlan]
vni_ranges = 1:1000
vxlan_group = 239.1.1.1
[agent]
l2_population = True
tunnel_types = vxlan
enable_distributed_routing = True
[ovs]
enable_tunneling = True
tunnel_type = vxlan
integration_bridge = br-int
local_ip = 10.0.0.162
[securitygroup]
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
enable_security_group = True
enable_ipset = True

[root@controller-162 ~(keystone_admin)]# vim /etc/neutron/l3_agent.ini 
[DEFAULT]
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
ovs_use_veth = True
use_namespaces = True
external_network_bridge = br-ex
router_delete_namespaces = True
agent_mode = dvr_snat             # 虚拟机snat上外网走network node 的L3


compute节点
[root@compute-2 ~]# vim /etc/neutron/plugins/ml2/ml2_conf.ini   # 网络采用ml2+vxlan,配置如下
[ml2]
type_drivers = flat,vxlan,vlan,gre
tenant_network_types = vxlan
mechanism_drivers = openvswitch,l2population
[ml2_type_flat]
[ml2_type_vlan]
[ml2_type_gre]
[ml2_type_vxlan]
vni_ranges = 1:1000
vxlan_group = 239.1.1.1
[agent]
l2_population = True
tunnel_types = vxlan
enable_distributed_routing = True
[ovs]
enable_tunneling = True
tunnel_type = vxlan
integration_bridge = br-int
local_ip=10.0.0.2
[securitygroup]
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
enable_security_group = True
enable_ipset = True

[root@compute-2 ~]# vim /etc/neutron/l3_agent.ini  # compute node也要起l3-agent,记住还要add-br br-ex,add-port br-ex eth2这些
[DEFAULT]
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
ovs_use_veth = True
use_namespaces = True
external_network_bridge = br-ex
router_delete_namespaces = True
agent_mode = dvr                     # floating ip直接走compute node的l3 

[root@compute-2 ~]# vim /etc/neutron/metadata_agent.ini  # compute node也起了l3,所以会有找metadata的问题
[DEFAULT]
auth_url = http://controller-162:35357/v2.0
auth_region = regionOne
admin_tenant_name = service
admin_user = neutron
admin_password = neutron
nova_metadata_ip = controller-162                #  controller node的metadata地址(nova-api接管metadata服务)
metadata_proxy_shared_secret = meta_pass


DVR功能

先来看下controller node的namespace

[root@controller-162 ~(keystone_admin)]# ip netns
qdhcp-f8876645-352e-48d2-b96c-304cb8de805f
snat-ac4a4d9b-27c7-492b-824a-ae384710ab2a        # 虚拟机上外网专门的snat,单独出来的namespace
qrouter-ac4a4d9b-27c7-492b-824a-ae384710ab2a
[root@compute-3 ~]# ip netns
qrouter-ac4a4d9b-27c7-492b-824a-ae384710ab2a    #  qrouter-xxxxxxx  跟上面一样的哦,floating ip的dnat规则在这里

# 我在dashboard上面绑定floating ip的时候找不到port,后台命令行可以绑定,这个bug openstack官方已经修复。
# 详情见这里 https://review.openstack.org/#/c/132383/3/openstack_dashboard/api/neutron.py
#           https://ask.openstack.org/en/question/51634/juno-dvr-associate-floating-ip-reported-no-ports-available/

[root@controller-162 ~(keystone_admin)]# nova floating-ip-associate test-5 172.16.101.2   # 绑定floating ip,出现了下面这个东东
[root@compute-3 ~]# ip netns
fip-53f6877e-2f46-43e3-93b7-7e22786cacb2    # 绑定floating ip后,多出来这个namespace
qrouter-ac4a4d9b-27c7-492b-824a-ae384710ab2a中rfp接口和fip-53f6877e-2f46-43e3-93b7-7e22786cacb2中的fpr接口是一对veth,打通两个namespace

[root@compute-3 ~]# route -n   
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.101.254  0.0.0.0         UG    0      0        0 fg-d7d8b46c-14       #  外网的网关在这里
169.254.30.174  0.0.0.0         255.255.255.254 U     0      0        0 fpr-02fa05dc-3
169.254.31.184  0.0.0.0         255.255.255.254 U     0      0        0 fpr-30e06cb3-7
169.254.31.224  0.0.0.0         255.255.255.254 U     0      0        0 fpr-1eaac5a6-2
172.16.101.0    0.0.0.0         255.255.255.0   U     0      0        0 fg-f57ba4c0-e1
172.16.101.0    0.0.0.0         255.255.255.0   U     0      0        0 fg-d7d8b46c-14
172.16.101.24   169.254.31.184  255.255.255.255 UGH   0      0        0 fpr-30e06cb3-7
172.16.101.70   169.254.31.224  255.255.255.255 UGH   0      0        0 fpr-1eaac5a6-2
172.16.101.71   169.254.31.224  255.255.255.255 UGH   0      0        0 fpr-1eaac5a6-2
172.16.101.72   169.254.31.224  255.255.255.255 UGH   0      0        0 fpr-1eaac5a6-2

Trouble Shooting

问题:
ERROR neutron.agent.linux.utils [req-adef3886-1fdd-4904-a442-0f5d43d70d1b None]
Command: ['sudo', 'neutron-rootwrap', '/etc/neutron/rootwrap.conf', 'ip', 'netns', 'exec', 'qrouter-02fa05dc-355f-42fb-8608-6b5d920ece6a', 'ip', '-4', 'neigh', 'del', '10.0.0.38', 'lladdr', 'fa:16:3e:b8:6d:15', 'dev', 'qr-55a5ec64-31']
Exit code: 2
Stdout: ''
Stderr: 'RTNETLINK answers: No such file or directory\n'
# neutron/agent/l3_agent.py中没有判断这个device是否存在,这个bug官方已修。

解决方法:
vim /usr/lib/python2.7/site-packages/neutron/agent/l3_agent.py # 编辑l3_agent.py文件
 
             int_dev = ip_wrapper.add_veth(rtr_2_fip_name,             # 查找这些代码所在位置
                                      fip_2_rtr_name, fip_ns_name)
             self.internal_ns_interface_added(str(rtr_2_fip),
                                         rtr_2_fip_name, ri.ns_name)
             self.internal_ns_interface_added(str(fip_2_rtr),
                                         fip_2_rtr_name, fip_ns_name)
             int_dev[0].link.set_up()
             int_dev[1].link.set_up()
 
# 在这些代码前面,加个判断 
 
             if not ip_lib.device_exists(rtr_2_fip_name,self.root_helper,
                                      namespace=ri.ns_name):
                 int_dev = ip_wrapper.add_veth(rtr_2_fip_name,
                                      fip_2_rtr_name, fip_ns_name)
                 self.internal_ns_interface_added(str(rtr_2_fip),
                                         rtr_2_fip_name, ri.ns_name)
                 self.internal_ns_interface_added(str(fip_2_rtr),
                                         fip_2_rtr_name, fip_ns_name)
                 int_dev[0].link.set_up()
                 int_dev[1].link.set_up()

参考链接

https://wiki.openstack.org/wiki/Neutron/DVR/HowTo

https://wiki.openstack.org/wiki/Neutron/DVR#Juno_and_Distributed_Routing

http://www.openstack.cn/p2510.html

DistributedVirtualRouter-East-WestNorthSouthwithServices.pdf