最近公司sdn項目在控制器開發過程中,需要運用到Neutron liberty版本中比較新的ML2分層端口綁定(Hierarchical Port Binding),使用此技術主要目的是為了解決基於硬件SDN交換機在使用OpenFlow協議實現租戶網絡隔離使用VLAN協議時,還是會受到VLAN 4096的限制,造成租戶網絡容量無法突破4096。使用分層端口綁定技術可以很好的,在neutron架構下的實現突破4096的限制。為學習分層端口綁定技術首先就需要先仔細閱讀neutron-specs/specs/kilo/ml2-hierarchical-port-binding.rst此篇文章,周末抽時間仔細閱讀粗略翻譯了一下,供大家學習參考。以下是部分原文翻譯:
ML2分層端口綁定(ML2 Hierarchical Port Binding)
在Openstack Neutron的liberty版本ML2機制driver已經支持分層網絡拓撲,每一層級網絡拓撲都有各自的網絡segment id。例如一個機制driver可以綁定一個靜態的網絡VXLAN segment id值,因為與ToR交換機相連的計算節點需要動態的分配VLAN id,因此另一個機制driver,例如OVS,就可以綁定計算節點到需要的動態VLAN上。
問題描述
傳統的ML2插件不完全支持分層網絡拓撲技術。在一個分層的虛擬網絡中使用不同的網絡segment,在不同的網絡級別可能存在不同的網絡類型(VLAN、VXLAN、GRE等等其他)。它可能是由一個或多個top-level靜態網絡段與在較低的水平動態分配的網絡段組成。例如,ToR和核心交換機可以使用VXLAN段封裝在虛擬的網絡流量,而TOR交換機和計算節點之間的那些同一個的虛擬網絡的流量可以使用動態分配的VLAN段。

在分層網絡的低層級里的動態分配segment值,是特別重要的保證neutron部署超出4k VLAN限制的物理網絡。VLAN的分配管理可以在低級的層級網絡中,允許超過4K的虛擬網絡的存在和計算節點通過VLAN訪問,只要保證從TOR交換機到各個計算節點鏈路不同時大於4K的VLAN的。
支持分配動態segment值功能在Juno版本進入ML2插件。但目前還沒有辦法支持在ToR交換機層上由一個機制driver動態分配segment值,並用不同的機制driver來支持計算節點上的L2 agent。但需要的是一個初始化的機制driver來為虛機網絡的port綁定一個靜態segment值,並且可由不同的機制driver在下一個分層里分配一個動態segment值,並且此種綁定可持續進行,直到綁定功能完成。
上面的圖顯示靜態VXLAN segment連接了ToR和core交換機,但是Neutron server和L2 agent之間通過RPC調用管理的隧道端點很可能已經不是現在vxlan網絡類型。取而代之的是網絡類型在交換機之間封裝格式和隧道端點之間被指定。每個network_type值應該明確定義為的標准的或專有的協議,實現必須的互操作性,並在異構部署共存。
修改提案
ML2將支持分層網絡技術,通過機制drivers綁定端口和在每一個層級為端口分配網絡segment值。例如一個機制driver可以綁定靜態VXLAN segment,從而導致與靜態網絡相連的ToR交換機,在與連接的計算節點之間的鏈路上會分配一個動態的VLAN值。因此第二個機制driver,例如VOS或HyperV driver,將綁定那個動態VLAN值到計算節點。
一個新的功能和特性將加入到PortContext類中,來實現分層端口綁定。
class PortContext(object):
# ...
@abc.abstractmethod
def continue_binding(self, segment_id, next_segments_to_bind):
pass
@abc.abstractproperty
def segments_to_bind(self):
pass
新加入的continue_binding()方法可以通過一個機制driver的bind_port()方法來調用,並替代已經存在的set_binding()方法。按當前的情況,如果一個機制driver能完成綁定,它會調用PortContext.set_binding(segment_id, vif_type, vif_details, status)方法。如果機制driver只能部分建立綁定,它將調用continue_binding(segment_id, next_segments_to_bind)。如果機制driver不能再綁定,它將什么都不調用。
正如set_binding()時,傳遞給continue_binding()的segment_id,將會被continue_binding驅動所綁定。新的new_segments參數指定一組可以通過該端口綁定在下一階段可以使用的網絡segment段。它通常將包含一個動態分配的segment給下一個driver驅動程序,用來繼續或完成綁定。
現在,機制driver是嘗試使用PortContext.network.network_segments的segments屬性值來綁定。這些都是網絡的靜態segment方式。新的PortContext.segments_to_bind將替代所有的drivers。在綁定初始階段,PortContext.segments_to_bind將包含於PortContext.network.network_segments相同的segment。但在后續綁定階段,它將包含由前一級driver的next_segments_to_bind,並傳遞給PortContext.continue_binding()。
ML2插件現在是嘗試使用所有注冊的機制driver,按照mechanism_drivers配置文件的順序進行加載。為了支持分層端口綁定,只需要進行一小點改動,以避免在綁定循環中任何可能的配置錯誤和部署異常。在每個綁定階段,任何已經在高一級綁定的driver,在現在的級別繼續綁定相同的segment是會排除的。這種方法允許相同個driver在分層網絡多個級別使用不同的segment,但是不能使用相同的segment。同樣,如果超過設置的綁定級別數量,綁定將會失敗並記錄錯誤日志。
最后,為了通過機制driver去查看分層綁定的詳細信息,PortContext的bound_segment, original_bound_segment, bound_driver, original_bound_driver屬性將被新的屬性所替換
# ...
@abc.abstractproperty
def binding_levels(self):
@abc.abstractproperty
def original_binding_levels(self):
@abc.abstractproperty
def top_bound_segment(self):
@abc.abstractproperty
def original_top_bound_segment(self):
@abc.abstractproperty
def bottom_bound_segment(self):
@abc.abstractproperty
def original_bottom_bound_segment(self):
如果port已經完全或部分綁定,binding_levels和original_binding_levels屬性返回一個列表字典,描述每個綁定級別。BOUND_DRIVER和BOUND_SEGMENT被定義,並且根據需要附加key在今后版本也可添加。第一條記錄描述top級綁定,通常是port的網絡靜態segment信息。當完全綁定后,最后一條記錄是bottom級綁定信息,將提供port的binding:vif_type和binding:vif_details屬性值。
在分層綁定的存在下,使用舊bound_segment,original_bound_segment,bound_driver,和/或original_bound_driver屬性的一些機制驅動需要訪問top級綁定,同時其他driver需要訪問bottom級綁定。因此,舊的屬性將被新提供訪問的屬性替代。
數據模型的影響
為了給機制driver提供存儲多級綁定信息,修改ML2數據庫是必須的。driver和segment列從ml2_port_bindings and ml2_dvr_port_bindings移到新的ml2_port_binding_levels表。這個表將 包含port_id, host, level列作為主key。不需要單獨的dvr表。
DB遷移將提供現有的綁定數據移動到新表上的升級。數據庫降級將保留現有的單級綁定數據,但保留在降級現有的多層次的綁定還沒有合理的方式。
REST API的影響
neutron的REST API不需要做改變。只有top級別的靜態segment可以訪問。現在還不需要通過REST API暴露動態segment。portbinding擴展方法在未來修改后可以暴露更多的多級綁定信息。
其他部署影響
當部署在非分層網絡不需要做什么改變。但當部署在分層網絡,機制driver將需要做些改變。此外,當VLAN作為低級綁定方式,L2 agent的配置將受到影響。
機制機制需要確定他們是否可以通過NETWORK_TYPE以及任何相關信息綁定到一個網段。例如,如果NETWORK_TYPE是'flat'或'VLAN',L2 agent的機制driver查看physical_network,並使用數據庫的信息,來確保該主機上的L2 agent具有physical_network的segment的映射。這是現有機制的驅動程序是運行方。
在分層端口綁定環境里,ToR交換機是采用動態VLAN segment,並且連接到它的主機使用的是標准L2 agent,主機上的L2 agent配置physical_network名的mapping信息,對應在此physical_network下switch分配動態VLAN。
如果動態VLAN segment在交換機范圍內進行分配,那么每個ToR交換機應該有一個唯一對應的physical_network名稱。switch的機制driver將使用這個physical_network名為其創建部分綁定動態segment。在連接到該交換機的主機在L2 agent必須有一個(橋或接口)的映射到相同physical_network名,從而允許正常的L2 agent機制的驅動來完成綁定。
如果動態VLAN segment在交換機端口范圍進行分配,因此每個交換機端口將有一個相應的唯一physical_network名,只連接到該交換機的端口上的主機應具有該physical_network的mapping映射信息。由於多級的網絡部署可能需要使用一個特定的供應商專有的switch,該供應商應提供的文件和部署工具來幫助管理員。
開發影響
支持分級綁定機制的驅動程序將使用額外的驅動程序API調用。其他驅動只需要一個非常小的更新使用REPortContext.segments_to_bind代替端口Context.network.network_segments,和使用新的屬性用於訪問所述頂級或低級綁定的segment或驅動。
根據以上內容,能對分層端口綁定的概念有了基本了解,結合具體ML2代碼分析研究,才能對此功能有更進一步的認識。
參考資料:
ML2:Hierarchical Port Binding
https://github.com/openstack/neutron-specs/blob/master/specs/kilo/ml2-hierarchical-port-binding.rst
作者簡介:趙俊峰,現為華勝信泰信息產業發展有限公司 雲計算部Openstack開發工程師。主要從事Power和x86混合環境下Openstack相關計算、網絡、存儲相關服務軟件開發和系統架構設計工作。
