作者:閆興安
1.4 代碼流程分析
1.4.1 dhcp port如何進行bind_port
plugin中,在創建port時會進行bind_port。所謂bind是指端口id、主機名、網絡屬性進行綁定。
其中網絡屬性包括:網絡ID、網絡類型、物理網絡名稱、網絡segment-id。
bind_port的過程:
1) 按序遍歷所有mech_driver,挨個進行bind_port。
2) 如果某個mech_driver報異常,記log,然後繼續進行下一個mech driver的bind。
3) 如果某個mech_driver沒有進行綁定,繼續進行下一個mech driver的bind。
4) 只要有一個mech_driver bind成功,就返回。(ovs driver不支持多層bind)
5) 如果所有的mech_driver都綁定失敗,記vif_type爲binding_failed。
我們的環境中mech_driver只有openvswitch,所以來看下ovs driver的binding:
1) 遍歷所有agent,如果是down的,不進行綁定,記Log;如果是active的,執行下面步驟。
2) 檢查agent的上報過來的配置。包括:網絡類型是否在agent的配置文件中配置;如果是flat和vlan類型的網絡,還檢查物理網絡名稱是否在agent的配置文件中配置;
3) 如果上述檢查不通過,不進行綁定;如果檢查通過,進行綁定。
4) 只要有一個agent綁定成功,就返回,表示ovs driver綁定成功。
5) 如果所有的agent都沒有進行綁定,就會出現binding_failed。
1.4.2 dhcp-agent與plugin的同步
dhcp-agent主動同步過程:
1) 啓動時,首先從namespace名字中獲取網絡信息,記錄到cache(內存)中。後續從plugin獲取的所有信息都記錄在cache裏。之後進行同步時依據的就是這個cache。
2) 可以同步指定的網絡列表,或者同步所有的網絡。
3) 開始同步,打印INFO Synchronizing state。
4) 從plugin中獲取全部網絡,和cache對比,刪除多餘的本地網絡的dhcp,使能本地缺失的網絡的dhcp。使能動作在geen pool裏進行,默認4個thread。
5) 等待步驟4全部完成,打印INFO Synchronizing state complete。
plugin主動下發配置:
1) ml2 plugin通過mech driver發送網絡、子網、端口事件給dhcp-agent。
2) 包括創建、修改、刪除網絡、子網、端口。
3) dhcp-agent收到事件後,立即進行相應處理,見下面cache的處理過程。
同步時間:
1) 第一次report state之後立即進行同步。然後起個定時器,當有reason時進行同步。reason爲需要進行同步的網絡ID,或者全部網絡。週期同步時間默認爲5秒。
2) agent狀態剛剛從down變爲active的時候,標記reason爲全部網絡,等待週期同步。
3) 當啓動dnsmasq進程失敗時,標記reason爲失敗的網絡。
4) 同步時,刪除dnsmasq進程失敗時,標記reason爲失敗的網絡。
5) agent的狀態變化時,同步全部網絡。
dnsmasq driver包括如下幾種接口:
1) enable,生成配置文件、創建namespace和端口、啓動dnsmaq進程。如果dnsmasq進程存在,參考下面的reload。
2) disable,關閉dnsmasq進程、刪除namespace和端口、刪除配置文件。
3) reload,重新生成lease文件,然後給dnsmasq進程發送HUP信號,進程會重新加載配置文件。如果dnsmasq進程不存在,會啓動進程。
4) restart,相當於先執行disable,然後執行enable,此過程不刪除namespace和端口。
從上面的同步過程可以看出,同步的關鍵在於cache裏network信息的維護:
1) 啓動時,首先從namespace名字中獲取網絡信息,記錄到cache(內存)中。
2) plugin發來創建網絡消息時,執行driver的enable接口。如果dnsmasq driver返回成功,將網絡記錄到cache中。如果不成功,標記該網絡重新進行同步,同時driver內部會進行回退處理,保證沒有資源殘留。
3) plugin發來刪除網絡消息時,執行driver的disable接口。如果dnsmasqdriver返回成功,將網絡從cache中刪除。如果不成功,標記該網絡重新進行同步,同時driver內部會進行回退處理,保證沒有資源殘留。
4) plugin發來更新網絡消息時,如果admin_state_up修改爲up,參考步驟2,否則參考步驟3。
5) plugin發來創建、刪除、更新子網消息時,根據前後子網內容的變化,執行disable、restart、reload。這裏,disable和restart執行成功才記錄cache。reload時是無條件記錄cache。
6) plugin發來創建、更新端口消息時,如果端口是本地的IP,並且端口IP發生變化時,執行restart,否則reload。restart和reload無條件記錄cache。
7) plugin發來刪除端口消息時,執行reload。無條件清除cache。
這裏存在的問題:
有些地方沒有判斷driver是否成功,所以可能存在cache與底層不一致的情況。
1.4.3 tap口如何創建
先來看下interface driver:
dhcp agent先通過plugin創建dhcp port,plugin返回Port詳情,包括port ID,mac地址,IP地址等信息。
然後通過interface driver先ovs-vsctl add-port 創建一個internal的tap口,然後加入到br-int中。然後創建namespace,將tap加入namespace,在tap口上配置IP地址。
從下面的debug日誌可以看出dhcp agent創建底層端口的過程。
1.4.4 dhcp-agent日誌分析
1) Unable to sync network state
當出現mysql失聯等原因,導致plugin無法處理同步請求時報此錯誤。
2) Unable to enable dhcp for XXX
需要結合traceback分析。
agent請求某個網絡的詳情,plugin因某種原因(比如mysql失聯),未能正確返回數據時。
當執行底層命令失敗時也會出現此錯誤。
3) Unable to disable dhcp for XXX
同enable。
4) [req-XXX ] Network XXX infocall failed.
當agent向plugin請求某個網絡時出現異常,也需要結合traceback分析。
1.1.5 測試plugin是否主動調度網絡
將dhcp-agent中self.periodic_resync()代碼注掉,重啓dhcp-agent。
創建網絡,看能否創建dhcp-port。
可以創建。
這說明創建網絡時的調度並不依賴於週期同步。
1.4.6 網絡DHCP調度
首先,網絡調度都是由Agent觸發的,只要agent請求某個網絡,或者全部網絡時,就會觸發網絡的調度。調度動作是針對某個agent的,會找出該agent可以承載的網絡。
auto_schedule網絡調度算法:
1) 首先找到該主機上承載的狀態爲admin_up的dhcp-agent(只有一個)。
2) 然後遍歷所有的網絡,執行3-6
3) 對於每個網絡,找到正在承載此網絡的agent列表。
4) 如果“正在承載此網絡的agent”數目與agents_per_network一致,說明該網絡已經成功被完全調度,跳過該網絡。否則繼續。
5) 判斷當前agent是否在“正在承成此網絡的agent”裏面,如果是,說明該網絡被自己調度過了,跳過該網絡。否則繼續。
6) 將當前agent與該網絡進行綁定。
7) 最終返回該agent新綁定的網絡列表。
簡單描述就是:網絡等待被調度,agent按照先來後到的順序領取網絡,一個網絡可以被領指定次數,如果領了網絡的agent失聯了,將網絡分給其他agent。
查找某個網絡“正在承載此網絡的agent”:
1) 在agent與網絡的綁定這個table中,根據網絡網絡ID進行查找。
2) 排除狀態是down的agent。但是包含剛剛啓動的agent。
從上面的調度可以看出,只要有dhcp agent狀態down了,網絡重新調度時就會排除此agent。
如果agent狀態又up了,又會網絡調度到此agent。
1.4.7 是否可以修改每個網絡的agent數目?
從上面的DHCP調度算法可以看出,只要開啓了autoschedule,承載網絡的數目就一定是agents_per_network的數目。而且網絡所在的Agent無法手動指定(即使手動指定,agent down/up一切換,就會重新調度)。
參數 |
默認值 |
用途 |
network_auto_schedule |
True |
自動爲網絡分配agent。 |