1. 程式人生 > >OpenStack DVR 原理深入分析

OpenStack DVR 原理深入分析

一、DVR實驗環境

一套vlan模式的openstack環境,interface_driver使用openvswitch,並在計算節點新增br-ex,用於計算節點虛擬機器出外網。

二、DVR配置

1、控制節點

a、編輯/etc/neutron/neutron.conf
[DEFAULT]
router_distributed = True

b、重啟neutron-server服務

2、網路節點

a、編輯/etc/neutron/l3_agent.ini
[DEFAULT]
agent_mode = dvr_snat

b、編輯
/etc/neutron/plugins/ml2/openvswitch_agent.ini
[agent]
enable_distributed_routing = True

c、重啟neutron-l3-agent和neutron-openvswitch-agent服務

3、計算節點

a、編輯/etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0

b、執行命令sysctl –p

c、編輯/etc/neutron/l3_agent.ini
[DEFAULT]
interface_driver=neutron.agent.linux.interface.OVSInterfaceDriver
external_network_bridge =
agent_mode = dvr

d、編輯
/etc/neutron/plugins/ml2/openvswitch_agent.ini
[agent]
enable_distributed_routing = True

e、重啟neutron-l3-agent和neutron-openvswitch-agent服務

三、啟用dhcp實現metadata功能

1、預設情況下,metadata功能通過l3實現,在dvr模式下,如果使用l3實現的話,需要額外配置metadata agent,為了簡化,該實驗啟用dhcp agent來實現metadata功能。

a、在網路節點上編輯/etc/neutron/dhcp_agent.ini
[DEFAULT]
force_metadata = True

b、重啟neutron-dhcp-agent服務。

四、DVR到閘道器流表分析

1、建立router,關聯到test1網路(閘道器192.168.1.1),並在test1網路內建立instance(192.168.1.9),網路模型如下:

OpenStack DVR 原理深入分析

執行上述操作之後,neutron會在網路節點和計算節點(有instance執行)上都建立一個router的namespace,且配置完全一樣。

也就是說,平臺中會出現多個相同的router namespace,那麼neutron如何實現虛擬機器到閘道器的流量只到本地的router namespace呢?答案是flow table

2、舉個例子:

a、在test1內ping閘道器(192.168.1.1),虛擬機器會先發送arp請求去學習閘道器的mac地址,arp報文會從qvo-xxx埠進入br-int的table0,匹配arp和in_port,根據流表項,resubmit到table24。

b、在table24中匹配arp、in_port和arp_spa,命中之後,resubmit到table25。

c、在table25中匹配in_port和dl_src,命中之後,resubmit到table60。

d、在table60中,命中table-miss flow entry,根據action執行NORMAL。

e、閘道器地址是配置在router namespace中的qr-xxx上,而qr-xxx是br-int上的。

埠,所以qr-xxx會收到arp請求,並進行相應,arp相應報文會從qr-xxx埠再次進入br-int table0,命中table-miss flow entry,從而進行NORMAL轉發,將報文轉發給虛擬機器的qvo-xxx。

f、虛擬機器學到閘道器的mac地址之後,將icmp報文通過流表,轉發給閘道器,ping流程完成。

3、現在分析neutron如何通過flow table 實現虛擬機器到閘道器的流量只到本地的router namespace。

在上述的d步驟中,命中table-miss flow entry,根據action執行NORMAL,報文可能通過正常轉發,到達br-vlan。

a、報文到達br-vlan後,會進入table=0,匹配in_port,命中後,resubmit到table1

b、在table1中,匹配dl_vlan、arp_tpa(arp報文)或者dl_dst,從而把到閘道器的報文,全部drop。

c、通過上述流表,保證到達閘道器的報文全部終結在宿主機本地。

五、虛擬機器內網通訊分析

DVR模式下,虛擬機器的內網通訊一般有四種場景:同網路同宿主機,同網路不同宿主機,不同網路同宿主機,不同網路不同宿主機,下面將對這四種場景逐一進行分析:

1、同網路同宿主機,不需要通過router,實驗模型如下:

OpenStack DVR 原理深入分析

test1和test2執行在同一臺宿主上,執行test1 ping test2。

a、test1通過arp學習到test2的mac地址,流表匹配過程和步驟4(DVR到閘道器流表分析)中arp學習相同,然後封裝icmp報文,從qvo-xxx port進入br-int的table0,匹配in_port,命中後,resubmit到table25。

b、在table25中,匹配in_port和dl_src,命中後,resubmit到table60。

c、在table60,命中table-miss,執行NORMAL轉發。

d、test2的qvo-yyy port也在br-int上,報文通過qvo-yyy傳送到test2,test2回包給test流程和test1到test2相同。ping流程結束。

2、同網路不同宿主機,不需要router,實驗模型如下:

OpenStack DVR 原理深入分析

test1和test2執行在不同宿主上,執行test1 ping test2。

此場景下,步驟a,b,c和同網路同宿主機場景步驟完全相同,報文會在br-int的table60執行NORMAL,此處不再贅述。

d、執行NORMAL後,報文會從phy-br-vlan port進入br-vlan的table0,匹配in_port,命中後,resubmit到table1。

e、在table1中,命中table-miss,resubmit table2。

f、在table2中,匹配in_port和dl_vlan,命中後,修改local vlan 1為全域性vlan 196,然後執行NORMAL,此時報文會離開宿主機,從業務口發出去。

g、報文會被送到執行test2的宿主機業務口,然後進入br-vlan的table0,命中後,resubmit到table3。

h、在table3中,命中後,執行NORMAL,報文被送到br-int。

i、在br-int的table0中,匹配in_port和dl_vlan,命中後,修改全域性vlan 196 為local vlan 1,然後執行NORMAL,報文會從qvo-yyy進入虛擬機器test2。

j、test2回包和test1發包過程相同,至此,ping操作完成。

3、不同網路同宿主機,需要router,實驗模型如下:

OpenStack DVR 原理深入分析

建立router分別連線兩個網路,每個網路上個各建立一臺instance,執行上述操作之後,neutron會在網路節點和計算節點(有instance執行)上都建立一個router的namespace,且配置完全一樣,qr-裝置會被配置上對應閘道器ip地址。

test1和test2執行在同宿主上,執行test1 ping test2。

a、test1 通過計算知道要到達test2需要走三層,它會先發arp請求,學習閘道器的mac地址,然後封裝icmp報文(目的ip是test2的ip,目的mac是閘道器的mac地址),通過預設路由,將報文送到本地的router namespace。
(學習閘道器過程中匹配流表的過程請參考 <4、DVR到閘道器流表分析>章節)。

b、報文從qr-test1進入router的PREROUTING鏈,然後查詢到test2的路由,命中之後,進入POSTROUTING鏈,並從qr-test2重新進入br-int的table0。

c、在table0中,命中table-miss,resubmit到table60。

d、在table60中,命中後,執行NORMAL,將報文從qvo-xxx送到test2。

e、test2回包的過程和test1發包過程相同,至此,ping操作完成。

4、不同網路不同宿主機,需要router,實驗模型如下:

OpenStack DVR 原理深入分析

test1和test2執行在不同宿主上,執行test1 ping test2。

此場景下,步驟a,b,c和不同網路同宿主機場景步驟完全相同,
報文從qr-test2出來之後,在br-int的table60執行NORMAL,此處不再贅述。

d、在c中執行NORMAL之後,報文通過int-br-vlan port進入br-vlan的table0。

e、在table0中,匹配in_port,命中之後,resubmit到table1。

f、在table1中,匹配dl_vlan和dl_src,命中之後,修改源mac地址為neutron分配給宿主機mac,resubmit到table2。

注:開啟DVR之後,neutron會給每個compute節點分配一個唯一的mac地址,避免物理交換機出現mac地址衝突的問題。

g、在table2中,匹配in_port和dl_vlan,命中之後,修改local vlan 2為全域性
vlan 148,執行NORMAL,此時報文會從業務口eth1離開宿主機。

h、報文會進入執行test2的宿主機的業務口eth1進入br-vlan的table0。

i、在table0中,命中之後,resubmit到table3。

j、在table3中,匹配dl_src(neutron分配給宿主機的mac),將報文從phy-br-vlan送出給br-int table0。

k、在br-int的table0中,匹配in_port和dl_src(neturon分配給宿主機的mac),resubmit給table2。

l、在table2中,匹配dl_vlan和dl_dst,修改源mac為test2閘道器的mac,resubmit到table60。

m、在table60中,匹配dl_vlan和dl_dst ,剝去vlan,通過output將報文直接送到test2。

n、test2回包的過程和test1發包過程相同,至此,ping操作完成。

六、虛擬機器出外網原理分析

1、建立一個router,並繫結內部網路test1,設定路由器的閘道器外網為external,在內網,外網上各建立一臺虛擬機器,用於測試,實驗模型如下:

OpenStack DVR 原理深入分析

執行上述操作之後,neutron會在網路節點建立三個namespace:qrouter-xxx、fip-yyy、snat-xxx。

計算節點(instance執行)建立qrouter-xxx、fip-yyy。

ps:各節點的namespace會在接下來的分析中說明其作用。

2、虛擬機器test1的報文被送到本宿主機router namespace的qr-xxx裝置上(上述已經說明,此處不再贅述),進入PREROUTING鏈(未命中,不做任何修改),檢視策略路由,使用預設路由準備進行轉發,然後進入POSTROUTING鏈(未命中),報文從qr-xxx發出,送往192.168.1.11進行處理(流表全部命中NORMAL)。

3、可能有人會有疑問,這裡的192.168.1.11是啥?

事實上這個ip地址是neutron分配給snap-yyy namespace的一個ip,被配置在sg-zzz上,snap-yyy namespace在網路節點上,neutron通過策略路由和sg-zzz port將計算節點router namespace中的報文,轉發到網路節點的snat-yyy中。

4、此時報文到達網路節點的snat-yyy namespace中的sg-zzz port上,在路由之前報文會進入PREROUTING鏈(未命中),然後查詢路由。

隨後進入POSTROUTING鏈,進行snat,並做連線跟蹤,之後報文進行轉發。

5、經過上述操作,虛擬機器通過snat-yyy中的qg-裝置出外網,通過連線跟蹤返回(流表命中NORMAL)。

七、Floating ip原理分析

1、在章節6的基礎上,從外網分配一個floating ip(10.100.0.7),並關聯到虛擬機器test1(192.168.1.9)上,並需要自行配置br-ex,用於虛擬機器出外網,實驗模型如下:

OpenStack DVR 原理深入分析

執行上述操作之後,neutron會在對應的namespace裡面新增若干策略,下面的分析中會逐一說明:

1、虛擬機器test1的報文被送到本宿主機router namespace的qr-xxx裝置上(上述已經說明,此處不再贅述),進入PREROUTING鏈(未命中,不做任何修改),檢視策略路由。

通過策略路由,將報文通過rfp-6347c62b-2轉發給169.254.109.47處理,隨後進入POSTROUTING鏈,做snat修改。

2、到這裡,大家可能會有一個疑問,這個rfp-6347c62b-2裝置是啥?
事實上這個是veth pair的一端,它的另一端在fip-xxx namespace裡面

neutron 使用這對veth pair,將報文從router的namespace裡面,通過策略路由,轉發到fip-yyy的namespace裡。

3、至此,報文到達fip-yyy namespace,進入PREROUTING鏈(未命中),檢視路由。

再進入POSTROUTING鏈(未命中),從而將報文從fg-7ec56cee-b5裝置轉發到外網。

4、至此,報文順利從fg port傳送到外網(流表命中NORMAL)。

5、現在開始分析外網裝置通過floating ip進入虛擬機器的情況。

假設存在一臺外網裝置external(10.100.0.14)去ping floating ip(10.100.0.7),外網裝置首先會通過arp學習10.100.0.7的mac地址,而上述描述中,neutron並沒有配置10.100.0.7的ip地址在任何裝置上,也就是說,10.100.0.7並不存在,那報文是如何準確的送到fg口的呢?

事實上,neutron在fg port上開啟了arp_haproxy功能,相當於進行了arp欺騙,這樣,外網裝置就將fg的mac地址學習成10.100.0.7的mac,並更新到自己的mac表中。

6、外網報文到達fg口之後,進入PREROUTING鏈(未命中),檢視route表,準備將目的ip為floating ip的報文從fpr-6347c62b-2傳送169.254.109.46。

隨後進入POSTROUTING鏈(未命中),報文轉發到router的namespace中。

7、報文到達router的namespace中的rfp-6347c62b-2裝置,進入PREROUTING鏈,進行dnat操作。將目的ip從floating ip轉換成內部fix ip(192.168.1.9)

隨後檢視route,準備將報文從qr-xxx port轉發。

然後進入POSTROUTING鏈(未命中),將報文從qr- port轉發到虛擬機器test1。

8、至此,實現外網裝置到內部ip的轉發完成。