該篇文章是在《通俗說 Openvswitch》的基礎上再結合我再網上收集的資料進行學習、整理與概括,感謝劉大(公衆號:劉超的通俗雲計算)以及創做者的分享。html
軟件定義有啥好處呢?
想象你有一個大的數據中心,裏面有不少的網絡設備,光交換機就有不少,你但願在交換機上配置一些網絡的策略,例如某個口應該屬於某個 VLAN。
怎麼配置呢?登到這臺交換機上去,敲幾行命令就搞定了。
若是要配置 100 臺交換機呢?頭大了吧,難不成登錄 100 臺?
想不想有一個集中的地方,能看到整個網絡的拓撲圖,統一配置一下,而後一回車,配置的策略就經過管理網絡平面下發到 100 臺交換機上。這樣整個網絡的拓撲結構就不是硬的了,也即不是經過插線,拔線,登錄盒子配置的,而是變成了軟的,也即經過軟件統一控制,這個統一控制的地方咱們稱爲 SDN Controller(控制器),這樣的網絡拓撲結構,咱們稱爲軟件定義的網絡。java
虛擬交換機(vSwitch)就是利用虛擬平臺,經過軟件的方式實現(Software Defined Network,SDN,軟件定義網絡)的交換機部件。跟傳統的物理交換機相比,虛擬交換機具有衆多優勢:一是配置靈活,一臺普通的服務器能夠配置出數十臺甚至上百臺虛擬交換機,且端口數目也能夠靈活選擇。例如,一臺 VMware ESXi 服務器能夠仿真出 248 臺虛擬交換機,且每臺交換機預設虛擬端口便可達 56 個;二是成本低廉,經過虛擬交換一樣能夠得到昂貴的普通交換機才能達到的性能,例如,微軟的 Hyper-V,虛擬機與虛擬交換機之間的聯機速度輕易可達 10Gbps。linux
由於虛擬機的建立,刪除,遷移比物理機靈活的多,因此很難像物理的交換機同樣,用網線將交換機和物理服務器鏈接起來,就不怎麼變了。虛擬機就不同了,因此須要虛擬交換機,也即經過軟件模擬一個交換機,用軟件模擬一根網線,一頭插在虛擬機上,一頭插在虛擬交換機上,一下子建立五個虛擬機,要插到一個交換機上,一下子其中兩個虛擬機遷移到了另外的物理機上,則他們兩個的網口要從上一臺交換機上拔下來,插到新的虛擬交換機上,這樣作沒有問題,由於都是軟件實現的,很靈活。git
OpenFlow is a open standard managed by Open Networking Foundation. It specifies a protocol by which a remote controller can modify the behavior of networking devices through a well-defined 「forwarding instruction set」.github
OpenFlow,一種網上通訊協議,屬於數據鏈路層,可以控制網上交換器或路由器的數據轉發平面(Forwarding Plane),藉此改變網上數據包所通過的網上路徑。簡而言之,OpenFlow 就是 SDN Controller 遠程控制網絡設備的協議,經由網上交換器,決定網上數據包要由何種路徑經過網絡交換機。雖然 OpenFlow 的功能不如各大網絡廠商的自家協議強大,但正因如此,OpenFlow 成爲了一個兼容很是高的功能子集,以致於讓各網絡廠商可以達成了部分的共識。web
OpenFlow 容許從遠程控制網上交換器的數據包轉送表,透過新增、修改、移除數據包控制規則與行動,來改變數據包轉送的路徑。比起用訪問控制表(ACLs)和路由協議,容許更加複雜且靈活的流量管理。同時,OpenFlow 容許不一樣網絡供應商用一個簡單,開源的協議去遠程管理交換機(一般提供專有的接口和描述語言)。OpenFlow 協議用來描述控制器和交換機之間交互所用信息的標準,以及控制器和交換機的接口標準。算法
Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware’s vNetwork distributed vswitch or Cisco’s Nexus 1000V.
– 官方網站數據庫
Open vSwitch(下文簡稱 OvS)就是一個開源的虛擬交換機實現。普遍應用在雲計算行業,爲網絡管理員提供虛擬雲主機之間和以內的流量可見性與可控性。Open vSwitch 旨在用虛擬化方案解決網絡問題,與控制器軟件一塊兒實現分佈式的虛擬交換技術。這意味着,交換機和控制器軟件可以在多個服務器之間建立集羣網絡配置,從而不須要在每一臺雲主機和物理主機上單獨配置網絡。這個交換機還支持 VLAN 中繼,經過 NetFlow、sFlow 和 RSPAN 實現可見性,經過 OpenFlow 協議進行管理。它還有其餘一些特性:嚴格流量控制,它由 OpenFlow 交換協議實現;遠程管理功能,它能經過網絡策略實現更多控制。
json
簡而言之,Open vSwitch 即開放的軟件虛擬交換機,可以達到產品級的質量,也就是說能夠部署一些生產環境使用。它不光支持基本的二層交換,還支持標準的管理機接口和協議(e.g. NetFlow,sFlow,SPAN,RSAPN,CLI,LACP,802.1ag),同時也支持 OpenFlow,能夠很好的與 SDN 體系融合。bootstrap
Open vSwitch 的特性清單:
輕量級的數據庫,用於存儲整個 OvS 的配置信息,包括接口,交換內容,VLAN,虛擬交換機的建立,網卡的添加等信息與操做記錄,都由 ovsdb 保存到一個 conf.db 文件(JSON 格式)裏面,經過 db.sock 提供服務。
OvS 的核心部件,實現交換功能,與 Linux 內核兼容模塊一塊兒實現基於流的交換(Flow-based Switching)。它和上層 Controller 通訊聽從 OpenFlow 協議,它與 ovsdb-server 通訊聽從 OVSDB 協議,它和內核模塊經過 netlink 進行通訊,它支持多個獨立的 Datapath(網橋),它經過更改 Flow Table 實現了 Binding(綁定)和 VLAN 等功能。是真正的虛擬交換機生命週期管理進程。它經過 db.sock 文件從 ovsdb-server 進程讀取 conf.db 的配置信息(e.g. 用戶所建立的虛擬交換機、所添加的網卡等等操做記錄)。
在 OvS 中,給一個交換機,或者說一個橋,用了一個專業的名詞,叫作 DataPath!是一個 Linux Kernel 模塊,監聽網卡接口設備,獲取網絡包並交給 vSwitch 處理,支持數據在內核的交換。當 openvswtich.ko 被加載到了內核,會在網卡上註冊一個鉤子函數,每當有網絡包到達網卡時,這個函數就會被調用,將網絡包開始層層拆包(MAC 層,IP 層,TCP 層等),而後查看有沒有已經定義好的策略來處理網絡包(e.g. 修改 MAC,修改 IP,修改 TCP 端口,從哪一個網卡發出去等等),若是找到了策略,則將網絡包從網卡發出。這個處理過程全在內核完成,因此很是快,稱之爲 Fast Path。
NOTE:然而內核態並無被分配太多內存,因此內核態可以保存的策略不多,每每有新的策略到來,老的策略就被丟棄。若是在內核態找不到策略,則須要到用戶態去查詢,網絡包會經過 netlink(一種內核態與用戶態交互的機制)發送給 vswitchd,vswitchd 有一個監聽線程,當發現有從內核態發過來的包,就進入本身的處理流程。在用戶態相對較慢,故稱值爲 Slow Path。用戶態的 vswtichd 不須要吝嗇內存,它包含了全部策略,這些策略都是 Controller(控制器)經過 OpenFlow 協議下發的。vswtichd 會根據網絡包的信息層層匹配,直到找到一款策略進行處理。若是實在找不到,則通常會採用默認策略,好比丟棄這個包。當最終匹配到了一個策略以後,則會根據 「局部性原理」 再經過 netlink 協議,將這條策略下發到內核態,爲了下一個相同類型的網絡包可以直接從內核匹配到,以此加快執行效率。當這條策略下發給內核時,若是內核的內存空間不足,則會開始淘汰部分老策略。因爲近因效應,接下來的網絡包應該大機率可以匹配這條策略的。例如:傳輸一個文件,同類型的網絡包會源源不斷的到來。
# 查看 OvS Log 級別 ovs-appctl vlog/list # 設置 Log 級別 ovs-appctl vlog/set {module name}:{console, syslog, file}:{off, emer, err, warn, info, dbg} # 以 stp 設置 file 爲 dbg level 爲例 ovs-appctl vlog/set stp:file:dbg # 查看 OvS 版本 ovs-ofctl -V # 查詢指令歷史記錄 ovsdb-tool show-log [-mmm] # 修改 ofport (openflow port number) 爲 100 ovs-vsctl add-port <bridge> <interface> -- set Interface <interface> ofport_request=100 # 設置 interface 爲 internal ovs-vsctl set Interface <interface> type=internal # 開啓指定 Bridge 的 STP ovs-vsctl set bridge <bridge> stp_enable=true # 關閉指定 Bridge 的 STP ovs-vsctl set bridge <bridge> stp_enable=false # 查詢指定 Bridge 的 STP 的配置信息 ovs-vsctl get bridge <bridge> stp_enable # 設置指定 Bridge 的 STP Priority ovs−vsctl set bridge <bridge> other_config:stp-priority=0x7800 # 設置指定 Bridge 的 STP Cost ovs−vsctl set port <bridge> other_config:stp-path-cost=10
要理解 OvS 的工做原理,首先要了解網橋的工做原理。網橋也叫作橋接器,工做在數據鏈路層,將兩個 LAN 鏈接,根據 MAC 地址來轉發數據幀,能夠當作一個 「低層的路由器」。網橋處理數據幀遵循如下幾條規則:
Open vSwitch 的內核模塊(openvswitch.ko)實現了多個 「數據路徑(Datapath)」(相似於網橋),每一個 Datapath 均可以有多個 vPorts(相似於網橋上的端口)。每一個 Datapath 也經過關聯流表(Flow Table)來定義數據流向,一般的操做都是將數據流轉發到指定的 vPort 上。當網絡包到達一個 vPort,內核模塊所作的處理是提取其流的關鍵信息並在流表中查找這些關鍵信息,當有一個匹配的流時,就對該網絡包執行相應的操做;若是沒有匹配,則將網絡包送到用戶空間的處理隊列中,用戶空間可能會定義一個流用於之後碰到相同類型的網絡包能夠在內核中執行操做,這就是所謂的 Slow Path 和 Fast Path。
Open vSwitch 實現的流量控制很大部分上是經過 OpenFlow 交換協議實現的。OpenFlow 使 Controller 可以經過網絡訪問一個交換機或路由器的 Datapath。網管人員能夠在任意一臺計算機(Controller)上遠程控制數據管理,這樣他們就可以進行精細的路由和交換控制,並實現複雜的網絡策略。有了 Open vSwitch 中的這些遠程管理功能,雲計算的集成商和供應商就可以向客戶提供在一臺計算機上持續管理各自虛擬網絡、應用和策略的功能。
NOTE:L2 Switch 鏈接到宿主機的 eth0 一般是一個 Trunk 口,由於虛擬機對應的 vnet 每每會設置 VLAN TAG 來隔離虛擬機的廣播域。因此 eth0 就至關於一個 Trunk 口,而 vnets 就至關於 Access 口。
OS:CentOS7
Step1. 關閉 SELinux,不然 ovsdb-server Manager 沒法正常工做。
[root@localhost ~]# setenforce 0 [root@localhost ~]# cat /etc/selinux/config | grep -v ^# SELINUX=disabled SELINUXTYPE=targeted
Step 2. yum install
yum install openvswitch openvswitch-test
Step 3. 啓動服務
systemctl enable openvswitch systemctl start openvswitch systemctl status openvswitch
查看當前的 OvS 版本:
[root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f ovs_version: "2.0.0"
查看 OvS 服務進程清單:
ovsdb-server /etc/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/var/run/openvswitch/db.sock --private-key=db:Open_vSwitch,SSL,private_key --certificate=db:Open_vSwitch,SSL,certificate --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert --no-chdir --log-file=/var/log/openvswitch/ovsdb-server.log --pidfile=/var/run/openvswitch/ovsdb-server.pid --detach --monitor ovs-vswitchd unix:/var/run/openvswitch/db.sock -vconsole:emer -vsyslog:err -vfile:info --mlockall --no-chdir --log-file=/var/log/openvswitch/ovs-vswitchd.log --pidfile=/var/run/openvswitch/ovs-vswitchd.pid --detach --monitor
查看加載的內核模塊:
[root@localhost ~]# lsmod | grep openvswitch openvswitch 70743 0 vxlan 37584 1 openvswitch gre 13808 1 openvswitch libcrc32c 12644 2 xfs,openvswitch
從架構圖可知,ovsdb-server 與 ovs-vswitchd 能夠經過 UNIX Domain Socket(/var/run/openvswitch/db.sock)進行互相通訊。
ovs-db 在操做系統上的載體是 JSON 文件 /etc/openvswitch/conf.db,經過執行指令 ovsdb-client dump
能夠查看其內容,e.g.
[root@localhost ~]# ovsdb-client dump Bridge table _uuid controller datapath_id datapath_type external_ids fail_mode flood_vlans flow_tables ipfix mirrors name netflow other_config ports protocols sflow status stp_enable ----- ---------- ----------- ------------- ------------ --------- ----------- ----------- ----- ------- ---- ------- ------------ ----- --------- ----- ------ ---------- Controller table _uuid connection_mode controller_burst_limit controller_rate_limit enable_async_messages external_ids inactivity_probe is_connected local_gateway local_ip local_netmask max_backoff other_config role status target ----- --------------- ---------------------- --------------------- --------------------- ------------ ---------------- ------------ ------------- -------- ------------- ----------- ------------ ---- ------ ------ Flow_Sample_Collector_Set table _uuid bridge external_ids id ipfix ----- ------ ------------ -- ----- Flow_Table table _uuid flow_limit groups name overflow_policy ----- ---------- ------ ---- --------------- IPFIX table _uuid cache_active_timeout cache_max_flows external_ids obs_domain_id obs_point_id sampling targets ----- -------------------- --------------- ------------ ------------- ------------ -------- ------- Interface table _uuid admin_state bfd bfd_status cfm_fault cfm_fault_status cfm_health cfm_mpid cfm_remote_mpids cfm_remote_opstate duplex external_ids ifindex ingress_policing_burst ingress_policing_rate lacp_current link_resets link_speed link_state mac mac_in_use mtu name ofport ofport_request options other_config statistics status type ----- ----------- --- ---------- --------- ---------------- ---------- -------- ---------------- ------------------ ------ ------------ ------- ---------------------- --------------------- ------------ ----------- ---------- ---------- --- ---------- --- ---- ------ -------------- ------- ------------ ---------- ------ ---- Manager table _uuid connection_mode external_ids inactivity_probe is_connected max_backoff other_config status target ----- --------------- ------------ ---------------- ------------ ----------- ------------ ------ ------ Mirror table _uuid external_ids name output_port output_vlan select_all select_dst_port select_src_port select_vlan statistics ----- ------------ ---- ----------- ----------- ---------- --------------- --------------- ----------- ---------- NetFlow table _uuid active_timeout add_id_to_interface engine_id engine_type external_ids targets ----- -------------- ------------------- --------- ----------- ------------ ------- Open_vSwitch table _uuid bridges cur_cfg db_version external_ids manager_options next_cfg other_config ovs_version ssl statistics system_type system_version ------------------------------------ ------- ------- ---------- -------------------------------------------------- --------------- -------- ------------ ----------- --- ---------- ----------- -------------- 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f [] 0 "7.3.0" {system-id="257b9b47-87e7-4404-9af8-37f98b04f2bd"} [] 0 {} "2.0.0" [] {} unknown unknown Port table _uuid bond_downdelay bond_fake_iface bond_mode bond_updelay external_ids fake_bridge interfaces lacp mac name other_config qos statistics status tag trunks vlan_mode ----- -------------- --------------- --------- ------------ ------------ ----------- ---------- ---- --- ---- ------------ --- ---------- ------ --- ------ --------- QoS table _uuid external_ids other_config queues type ----- ------------ ------------ ------ ---- Queue table _uuid dscp external_ids other_config ----- ---- ------------ ------------ SSL table _uuid bootstrap_ca_cert ca_cert certificate external_ids private_key ----- ----------------- ------- ----------- ------------ ----------- sFlow table _uuid agent external_ids header polling sampling targets ----- ----- ------------ ------ ------- -------- -------
使用圖形化工具能夠更加友好的查看:
數據庫表之間的關係以下圖所示:
其中 Open_vSwitch 表是 OvS DB 的 root(根)。
它的表結構以下圖,記錄 ovs-vswitchd 的配置信息,e.g.
數據庫結構是一款軟件的資源模型設計的映射,下文主要根據 OvS 的資源模型來依次認識每種資源對象的特性與做用。
Manager 對象都是爲了配置 ovsdb-server 的 Connection,讓 Clients(e.g. ovs-vswitchd、ovs-vsctl、host) 能夠遠程對 ovsdb-server 執行 DB Operation。
從上述架構圖可知,ovsdb-server 是 ovs-db 提供管理的 RPC 接口。加載了 Open_vSwitch 表中的 manager_options 字段值來做爲監聽端口。
Manager 的表結構:
其中最重要的字段是 target,記錄了 ovsdb-server 的監聽參數信息:
Active(主動)database connection methods:
ssl:ip[:port]
:監聽在指定 Remote IP 的 Port 上,協議爲 SSLtcp:ip[:port]
:監聽在指定 Remote IP 的 Port 上,協議爲 TCPunix:FILE
:Unix domain socket named FILEPassive(被動)database connection methods:
pssl:[port][:ip]
:監聽在本機 IP 的指定 Port 上,協議爲 SSLptcp:[port][:ip]
:監聽在本機 IP 的指定 Port 上,協議爲 TCP經過下述指令設置:
ovs-vsctl set-manager TARGET... # set the list of managers to TARGET... # Active Listener ovs-vsctl set-manager tcp:1.2.3.4:6640 # Passive Listener ovs-vsctl set-manager ptcp:6640
NOTE:基於 TCP 的 DB Connection,使得 ovs-vsctl 在遠程機器上也能夠控制 ovsdb-server。
[root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f ovs_version: "2.0.0" [root@localhost ~]# ovs-vsctl set-manager ptcp:8881 [root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" ovs_version: "2.0.0" [root@localhost ~]# ovsdb-client dump ... Manager table _uuid connection_mode external_ids inactivity_probe is_connected max_backoff other_config status target ------------------------------------ --------------- ------------ ---------------- ------------ ----------- ------------ -------------------------------------------------------------------- ----------- 84f0a33c-a798-40fc-a285-ed4d83121d3e [] {} [] false [] {} {bound_port="8881", sec_since_connect="0", sec_since_disconnect="0"} "ptcp:8881"
檢查 Port 是否正常開啓:
[root@localhost ~]# netstat -lpntu | grep 8881 tcp 0 0 0.0.0.0:8881 0.0.0.0:* LISTEN 3024/ovsdb-server
從遠程計算機上執行鏈接:
[root@localhost ~]# ovs-vsctl --db=tcp:192.168.1.109:8881 show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" ovs_version: "2.0.0"
NOTE:注意防火牆的干擾因素。
若是將 Open vSwitch 配置爲經過網絡鏈接到 OpenFlow 控制器(ovs-vswitchd 與 ovs-controller 之間),那麼建議你使用 OpenSSL 來構建安全的網絡通信,雙向的 SSL 互相可確保 OpenFlow 鏈接的完整性和與安全。
想創建 SSL 鏈接,首先要獲取相關的 CA 證書,並將這些證書記錄到 SSL 表中。啓動 ovsdb-server 時,經過選項 --private-key=db:Open_vSwitch,SSL,private_key --certificate=db:Open_vSwitch,SSL,certificate --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert
來指定應用這些參數。
SSL 表結構:
SSL 表屬性:
其中主機(客戶端)的 Public key 包含在 CA 簽發的證書(certificate)內,而後再由 CA 中心的 private key 進行簽名,CA 中心來擔保這個 certificate 是合法的。爲了驗證 CA 簽名,還須要 CA 的 public key,並放到 ca_cert 指向的 CA 證書裏面。而 CA 自己的 public key 也須要被簽名更高級的 CA 或者 CA(根 CA)本身擔保。
SSL 驗證流程:
# 查詢 SSL 鏈接 ovs-vsctl get-ssl # 設置 SSL 證書 ovs-vsctl set-ssl sc-privkey.pem sc-cert.pem cacert.pem # 刪除 SSL 鏈接 ovs-vsctl del-ssl
自簽發 CA 根證書:
mkdir ~/OVS_CA cd ~/OVS_CA openssl genrsa -out caprivate.key 1024
openssl req -key caprivate.key -new -subj "/C=CN/ST=CN/L=CN/O=CN/CN=fanguiju@163.com" -out cacertificate.req
openssl x509 -req -in cacertificate.req -signkey caprivate.key -out cacertificate.pem
PS:自簽發即本身擔保本身,用本身的私鑰對本身的 CSR 進行簽發,因此也稱爲根證書。
簽發客戶端證書:
mkdir ~/ClientCerts cd ~/ClientCerts openssl genrsa -out cliu8private.key 1024
openssl req -key cliu8private.key -new -subj "/C=CN/ST=CN/L=CN/O=CN/CN=cliu8@163.com" -out cliu8certificate.req
cp ~/OVS_CA/caprivate.key ~/OVS_CA/cacertificate.pem ~/ClientCerts openssl x509 -req -in cliu8certificate.req -CA cacertificate.pem -CAkey caprivate.key -out cliu8certificate.pem -CAcreateserial
配置 SSL Connection:
ovs-vsctl del-manager ovs-vsctl set-manager pssl:8881 ovs-vsctl set-ssl /root/ClientCerts/cliu8private.key /root/ClientCerts/cliu8certificate.pem /root/OVS_CA/cacertificate.pem
NOTE:set-ssl 必定要指定絕對路徑,不然沒法正確載入證書文件。
查看修改:
[root@localhost newcerts]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "pssl:8881" ovs_version: "2.0.0" [root@localhost ~]# ovsdb-client dump ... SSL table _uuid bootstrap_ca_cert ca_cert certificate external_ids private_key ------------------------------------ ----------------- -------------------------------- ---------------------------------------- ------------ ------------------------------------ f8d8f0f5-f87b-430b-9d48-123a74a6804f false "/root/OVS_CA/cacertificate.pem" "/root/ClientCerts/cliu8certificate.pem" {} "/root/ClientCerts/cliu8private.key"
驗證:
[root@localhost ~]# ovs-vsctl --db=ssl:192.168.1.109:8881 show 2019-02-23T06:46:26Z|00001|stream_ssl|ERR|Private key must be configured to use SSL 2019-02-23T06:46:26Z|00002|stream_ssl|ERR|Certificate must be configured to use SSL 2019-02-23T06:46:26Z|00003|stream_ssl|ERR|CA certificate must be configured to use SSL 2019-02-23T06:46:26Z|00004|reconnect|WARN|ssl:192.168.1.109:8881: connection attempt failed (Protocol not available) ovs-vsctl: ssl:192.168.1.109:8881: database connection failed (Protocol not available)
scp cliu8private.key cliu8certificate.pem cacertificate.pem root@192.168.1.110:~/certs
[root@localhost certs]# ovs-vsctl --db=ssl:192.168.1.109:8881 --private-key=cliu8private.key --certificate=cliu8certificate.pem --ca-cert=cacertificate.pem show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "pssl:8881" ovs_version: "2.0.0"
NOTE:
PKI configuration (required to use SSL): -p, --private-key=FILE file with private key -c, --certificate=FILE file with certificate for private key -C, --ca-cert=FILE file with peer CA certificate
Bridge 即網橋,但在 Linux 的語義中 Bridge 與 vSwitch 具備相同的含義,可見 Bridge 正式 Open vSwitch 最爲核心的對象與概念。關於 Bridge 的概念再也不多談,更詳細的內容能夠瀏覽《Networking 基本術語/概念》一文。下面主要記錄了 OvS 關於 Bridge 的常見操做。
Bridge commands: add-br BRIDGE create a new bridge named BRIDGE add-br BRIDGE PARENT VLAN create new fake BRIDGE in PARENT on VLAN del-br BRIDGE delete BRIDGE and all of its ports list-br print the names of all the bridges br-exists BRIDGE exit 2 if BRIDGE does not exist br-to-vlan BRIDGE print the VLAN which BRIDGE is on br-to-parent BRIDGE print the parent of BRIDGE br-set-external-id BRIDGE KEY VALUE set KEY on BRIDGE to VALUE br-set-external-id BRIDGE KEY unset KEY on BRIDGE br-get-external-id BRIDGE KEY print value of KEY on BRIDGE br-get-external-id BRIDGE list key-value pairs on BRIDGE # Bridge 管理操做 ovs-vsctl show ovs-vsctl add-br <bridge> ovs-vsctl del-br <bridge> ovs-vsctl --if-exists del-br <bridge> ovs-vsctl add-port <bridge> <port>|<interface> ovs-vsctl del-port <bridge> <port>|<interface> ovs-vsctl list <bridge>|<port>|<interface> ovs-vsctl list bridge <bridge> # 建立 Bridge 的同時爲 Bridge 添加 Port/Interface ovs−vsctl add−br <bridge> -- add−port <bridge> <port>|<interface>
[root@localhost ~]# ovs-vsctl add-br ubuntu_br [root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" Bridge ubuntu_br Port ubuntu_br Interface ubuntu_br type: internal ovs_version: "2.0.0"
[root@localhost ~]# ip link add first_br type veth peer name first_if [root@localhost ~]# ip link add second_br type veth peer name second_if [root@localhost ~]# ip link add third_br type veth peer name third_if
[root@localhost ~]# ip l 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:a2:2e:a4 brd ff:ff:ff:ff:ff:ff 3: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether f6:66:5f:f9:ba:17 brd ff:ff:ff:ff:ff:ff 4: ubuntu_br: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1000 link/ether 46:ca:9f:ed:0b:46 brd ff:ff:ff:ff:ff:ff 5: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT qlen 1000 link/ether 52:54:00:69:fc:47 brd ff:ff:ff:ff:ff:ff 6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN mode DEFAULT qlen 1000 link/ether 52:54:00:69:fc:47 brd ff:ff:ff:ff:ff:ff 7: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT qlen 1000 link/ether fe:54:00:b8:9a:cf brd ff:ff:ff:ff:ff:ff 8: vnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT qlen 1000 link/ether fe:54:00:43:07:06 brd ff:ff:ff:ff:ff:ff 9: vnet2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT qlen 1000 link/ether fe:54:00:ce:e6:40 brd ff:ff:ff:ff:ff:ff 10: first_if@first_br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 46:df:83:a6:66:bc brd ff:ff:ff:ff:ff:ff 11: first_br@file_if: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 72:90:6d:0d:4b:e0 brd ff:ff:ff:ff:ff:ff 12: second_if@second_br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 6a:68:8f:38:86:a2 brd ff:ff:ff:ff:ff:ff 13: second_br@second_if: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 86:8d:e3:32:03:b4 brd ff:ff:ff:ff:ff:ff 14: third_if@third_br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 5e:72:4c:9b:4d:18 brd ff:ff:ff:ff:ff:ff 15: third_br@third_if: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether a2:cf:5f:72:da:23 brd ff:ff:ff:ff:ff:ff
[root@localhost ~]# ovs-vsctl add-port ubuntu_br first_br [root@localhost ~]# ovs-vsctl add-port ubuntu_br second_br [root@localhost ~]# ovs-vsctl add-port ubuntu_br third_br [root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" Bridge ubuntu_br Port ubuntu_br Interface ubuntu_br type: internal Port first_br Interface first_br Port second_br Interface second_br Port third_br Interface third_br ovs_version: "2.0.0"
NOTE:Bridge ubuntu_br 的同名 Port,通常就是 Bridge 的管理端口了,類比物理交換機的管理端口,通常會爲其配置 IP 地址。
OvS 是一個 OpenFlow Switch 實現,能夠經過 OpenFlow Controller(OpenFlow 協議)對全部分佈式的 Bridge 進行統一管理。所謂 「管理」,其實是對 Bridge 的 Flow Table 的管理。SDN Controller 的核心是控制策略的下發,並以此來決策數據的流向。
Controller 有兩種類型:
OvS 爲 Bridge 提供了下列兩種 Fail Mode:
# 查詢 Bridge 的 Fail Mode ovs-vsctl get-fail-mode ovs-br # 設置 Bridge 的 Fail Mode ovs-vsctl set-fail-mode ovs-br standalone ovs-vsctl set-fail-mode ovs-br secure # 移除 Bridge 的 Fail Mode ovs-vsctl del-fail-mode ovs-br # 查看 Bridge 和 Controller 的鏈接模式 ovs-vsctl get controller ovs-br connection-mode # 設置 Out-of-band 鏈接模式 ovs-vsctl set controller ovs-br connection-mode=out-of-band # 設置 In-band (default) 鏈接模式 ovs-vsctl set controller ovs-br connection-mode=in-band # 移除 hidden flow ovs-vsctl set bridge br0 other-config:disable-in-band=true
Controller 表結構:
# 設置 Controller ovs-vsctl set-controller <bridge> tcp:<controller_ip>:6633 # 設置 Multi Controller ovs-vsctl set-controller <bridge> tcp:<controller_ip1>:6633 tcp:<controller_ip2>:6633 # 獲取 Bridge 的 Controller ovs-vsctl get-controller <bridge> # 移除 Controller ovs-vsctl del-controller <bridge>
OpenFlow Controller 的種類繁多,常見有如 OpenDaylight 等等,詳細清單可瀏覽《OpenFlow Controllers in GENI》。本篇以 Floodlight 爲例,感覺 Controller 對 Bridge 的流量控制功能。
官方網站:http://www.projectfloodlight.org/getting-started/
官方部署手冊:https://floodlight.atlassian.net/wiki/spaces/floodlightcontroller/pages/1343544/Installation+Guide
Installing Floodlight:
git clone git://github.com/floodlight/floodlight.git cd floodlight/ git submodule init git submodule update ant sudo mkdir /var/lib/floodlight sudo mkdir /var/log/floodlight sudo chmod 777 /var/lib/floodlight
NOTE: 這裏使用的是 Tag 1.2 版本
Running Floodlight in the Terminal:
nohup java -jar ~/floodlight/target/floodlight.jar > /var/log/floodlight/floodlight.log 2>&1 &
檢查 Controller 的監聽端口:
[root@localhost ~]# cat /var/log/floodlight/floodlight.log | grep "Listening for switch connections" 09:28:16.102 INFO [n.f.c.i.OFSwitchManager:main] Listening for switch connections on /0.0.0.0:6653 [root@localhost ~]# netstat -lpntu | grep 6653 tcp6 0 0 :::6653 :::* LISTEN 20159/java
NOTE:Floodlight 會經過監聽 /0.0.0.0:6653
Socket 來獲取 Bridge 的鏈接。
將 Bridge 鏈接到 Controller:
[root@localhost floodlight-1.2]# ovs-vsctl set-controller ubuntu_br tcp:192.168.1.109:6653 [root@localhost floodlight-1.2]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" Bridge ubuntu_br Controller "tcp:192.168.1.109:6633" Port ubuntu_br Interface ubuntu_br type: internal Port third_br Interface third_br Port first_br Interface first_br Port second_br Interface second_br ovs_version: "2.0.0"
NOTE:Bridge 鏈接到 Controller 以後,Controller 就能夠收集、下發、管理 Bridge 的相關信息了(e.g. Flow Table)。
訪問 Web GUI:
http://192.168.1.109:8080/ui/index.html
將三臺 KVM 虛擬機接入到 Bridge:
[root@localhost ~]# virsh domiflist VM1 Interface Type Source Model MAC ------------------------------------------------------- macvtap1 direct ubuntu_br rtl8139 52:54:00:b8:9a:cf [root@localhost ~]# virsh domiflist VM2 Interface Type Source Model MAC ------------------------------------------------------- macvtap0 direct ubuntu_br rtl8139 52:54:00:43:07:06 [root@localhost ~]# virsh domiflist VM3 Interface Type Source Model MAC ------------------------------------------------------- macvtap2 direct ubuntu_br rtl8139 52:54:00:ce:e6:40
NOTE:VM一、二、3 都鏈接到同一個 Bridge 上,只要三者具備網段的 IP 地址就能夠通訊了。
查看 Floodlight Dashboard:
等待一段時間 Floodlight 就會將會主機上的 Bridges、Bridge 上的 Hosts、Host 的 IP/MAC 地址等信息收集上來。
Floodlight Dashboard 基本上只做爲展現,因此大部分操做依舊須要經過指令行來完成。
curl http://localhost:8080/wm/core/controller/switches/json
curl http://localhost:8080/wm/staticflowentrypusher/list/all/json
curl http://192.168.1.109:8080/wm/core/switch/00:00:46:ca:9f:ed:0b:46/flow/json
curl -d '{"switch": "00:00:00:00:00:00:00:01", "name":"flow-mod-1", "cookie":"0", "priority":"32768", "ingress-port":"1", "active":"true", "actions":"output=2"}' http://localhost:8080/wm/staticflowentrypusher/json
# VM1 curl -d '{"switch": "00:00:46:ca:9f:ed:0b:46", "name":"static-flow2", "cookie":"0", "priority":"32768", "src-mac":"52:54:00:b8:9a:cf","active":"true", "actions":"output=10"}' http://localhost:8080/wm/staticflowentrypusher/json # VM3 curl -d '{"switch": "00:00:46:ca:9f:ed:0b:46", "name":"static-flow1", "cookie":"0", "priority":"32768", "src-mac":"52:54:00:ce:e6:40","active":"true", "actions":"output=12"}' http://localhost:8080/wm/staticflowentrypusher/json
curl -X DELETE -d '{"name":"flow-mod-1"}' http://localhost:8080/wm/staticflowentrypusher/json
curl http://localhost:8080/wm/staticflowentrypusher /clear/<dpid>/json
Mirror 的功能就是配置一個 Bridge 將某些具備特定條件的包發給指定的 Mirrored Ports。
包的條件有如下幾種:
指定的目的 Ports 有如下兩種:
Source (SPAN) port - A port that is monitored with use of the SPAN feature.
Destination (SPAN) port - A port that monitors source ports, usually where a network analyzer is connected.
ovs-vsctl add-br ovs-br ovs-vsctl add-port ovs-br eth0 ovs-vsctl add-port ovs-br eth1 # 設置 SPAN Mirrors,將 ovs-br 上 add-port {eth0,eth1} Mirror 至 tap0 ovs-vsctl add-port ovs-br tap0 \ -- --id=@p get port tap0 \ -- --id=@m create mirror name=m0 select-all=true output-port=@p \ -- set bridge ovs-br mirrors=@m # 刪除 SPAN Mirrors ovs-vsctl clear bridge ovs-br mirrors
Open vSwitch 支持的網卡類型:
netdev:通用網卡設備(e.g. eth0、veth)
internal:虛擬網卡設備
gre device:隧道設備(無論用戶態建立多少個 GRE Tunnel,在內核態有且只有一個 GRE 設備)
Port 的一個重要的特性就是 VLAN Configuration,具備兩種類型:
Trunk Port:
簡而言之,就是物理交換機的 Trunk 口,符合 Trunks 列表的 VLAN ID 可經過。
Access Port:
簡而言之,由 Access Port 接收到的包會被打上 Tag,Access Port 只接收 Untag 包,不然丟棄。具備相同 VLAN ID 的包會給轉發到對應的 Access Port 而後解除 Tag 再發出。
# 添加 Port 並設置 VLAN tag,ID 爲 3 ovs-vsctl add-port <bridge> <vlan_access_interface> tag=3 -- set interface <vlan_access_interface> type=internal # 爲已存在的 Port 設置 VLAN tag,ID 爲 9 ovs-vsctl set port <port> tag=9 # 移除 VLAN tag ovs-vsctl del-port <bridge> <vlan_access_interface> # 查詢 VLAN ifconfig <vlan_access_interface> # 設置 Vlan Trunk ovs-vsctl add-port <bridge> <vlan_trunk_interface> trunk=3,4,5,6 # 添加設置 VLAN 的 Flow,ID 爲 100 ovs-ofctl add-flow <bridge> in_port=1,dl_vlan=0xffff,actions=mod_vlan_vid:100,output:3 ovs-ofctl add-flow <bridge> in_port=1,dl_vlan=0xffff,actions=push_vlan:0x8100,set_field:100-\>vlan_vid,output:3 # 添加摘除 VLAN tag 的 Flow ovs-ofctl add-flow <bridge> in_port=3,dl_vlan=100,actions=strip_vlan,output:1 # ovs-ofctl add-flow pop-vlan ovs-ofctl add-flow ovs-br in_port=3,dl_vlan=0xffff,actions=pop_vlan,output:1
Port 和 Interface 的關係是一對多的關係,由於 OvS 支持 Bond 功能。所謂 Bond 就是將多個 Interface 「捆綁」 在一塊兒造成一個虛擬的鏈接,從而實現高可用性以及高吞吐量的效果。
常見的 bond_mode 有如下幾種:
PS:LACP (Link Aggregation Control Protocol,鏈路聚合控制協議)。
OvS 的 bond 模型:
OvS 中的 Qos 每每是和 Flow Policy 一塊兒使用的。總所周知 QoS 有兩個方向,一個是入方向(Ingress),一個是出方向(Egress)。
在 Linux 上最經常使用的網絡 QoS 就是 TC 工具,其主要是經過 隊列 的方式來實現的。
1.Classless Queuing Disciplines:默認爲 pfifo_fast,是一種不把網絡包分類的技術。pfifo_fast 根據網絡包中的 TOS 對應的數字,在 TOS 的 priomap 中查看對應的 Band,不一樣的 Band 對應的不一樣的隊列。
2. SFQ, Stochastic Fair Queuing:有不少的 FIFO 的隊列,TCP Session 或者 UDP stream 會被分配到某個隊列。包會 RoundRobin 的從各個隊列中取出發送。這樣一個 Session 就不會佔據全部的流量。但不是每個 Session 都具備一個隊列,而是經過 Hash 算法,將大量的 Session 分配到有限的隊列中。這樣兩個或若干個 Session 會共享一個隊列,也有可能互相影響。所以 Hash 函數會常常改變,從而 Session 不會老是相互影響。
3. TBF, Token Bucket Filter:全部的網絡包排成隊列進行發送,但不是到了隊頭就能發送,而是須要拿到 Token 的包才能發送。Token 根據設定的速率(Rate)生成,因此即使隊列很長,也會按照 Rate 進行發送。當沒有包在隊列中時,Token 仍是以既定的速度生成,可是並不是無限累積,而是到 Buckets 放滿爲止,籃子(buckets)的大小經常使用 burst/buffer/maxburst 參數來設定。Buckets 會避免下面這種狀況:當長時間沒有包發送的時候,積累了大量的 Token,忽然來了大量的包,每一個都能獲得 Token,形成瞬間流量大增。
4. Classful Queuing Disciplines:其中典型的爲 HTB, Hierarchical Token Bucket。
# 建立一個 HTB 的 qdisc 在 eth0 上,句柄爲 1:,default 12 表示默認發送給 1:12。 tc qdisc add dev eth0 root handle 1: htb default 12 # 建立一個 root class,而後再建立幾個 sub class。 # 同一個 root class 下的 sub class 能夠相互借流量,若是直接不在 qdisc下面建立一個 root class,而是直接建立三個 class,他們之間是不能相互借流量的。 tc class add dev eth0 parent 1: classid 1:1 htb rate 100kbps ceil 100kbps tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30kbps ceil 100kbps tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10kbps ceil 100kbps tc class add dev eth0 parent 1:1 classid 1:12 htb rate 60kbps ceil 100kbps # 建立葉子 qdisc,分別爲 fifo 和 sfq。 tc qdisc add dev eth0 parent 1:10 handle 20: pfifo limit 5 tc qdisc add dev eth0 parent 1:11 handle 30: pfifo limit 5 tc qdisc add dev eth0 parent 1:12 handle 40: sfq perturb 10 # 設定規則:從 IP 1.2.3.4 來的而且發送給 port 80 的包,從 1:10 走;其餘從 1.2.3.4 發送來的包從 1:11 走;其餘的走默認。 # 實現了限速與分流。 tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 match ip dport 80 0xffff flowid 1:10 tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 flowid 1:11
實際上 OvS 能控制的只有 Egress QoS,經過 Shaping 實現。而 Ingress QoS 是沒法控制的,只能經過 Policy 將指定的包丟棄。
Ingress policy:
ovs-vsctl set Interface tap0 ingress_policing_rate=100000 ovs-vsctl set Interface tap0 ingress_policing_burst=10000
Egress shaping:Port QoS policy 僅支持 HTB。
OvS 支持三種隧道類型,這三種 Tunnel 的原理均在 《Networking 基礎術語/概念》中講過,再也不贅述。
# Instance1 ovs-vsctl add-br testbr ifconfig testbr 10.0.0.1/24 ovs-vsctl add-port testbr gre0 -- set Interface gre0 type=gre options:local_ip=192.168.100.100 options:remote_ip=192.168.100.101 ovs-vsctl add-port testbr vxlan0 -- set Interface vxlan0 type=vxlan options:local_ip=192.168.100.100 options:remote_ip=192.168.100.102 # Instance2 ovs-vsctl add-br testbr ifconfig testbr 10.0.0.2/24 ovs-vsctl add-port testbr gre0 -- set Interface gre0 type=gre options:local_ip=192.168.100.101 options:remote_ip=192.168.100.100 ovs-vsctl add-port testbr ipsec0 -- set Interface ipsec0 type=ipsec_gre options:local_ip=192.168.100.101 options:remote_ip=192.168.100.102 options:psk=password # Instance3 ovs-vsctl add-br testbr ifconfig testbr 10.0.0.3/24 ovs-vsctl add-port testbr vxlan0 -- set Interface vxlan0 type=vxlan options:local_ip=192.168.100.102 options:remote_ip=192.168.100.100 ovs-vsctl add-port testbr ipsec0 -- set Interface ipsec0 type=ipsec_gre options:local_ip=192.168.100.102 options:remote_ip=192.168.100.101 options:psk=password # enable STP,避免環致使的洪泛(Flood) # Spanning Tree Protocol,即經過協議,將一個有環的二層網絡變成一顆樹。 ovs-vsctl set Bridge testbr stp_enable=true
Open vSwitch 定義了一系列的 Flow Table,經過這些 Tables 來控制網絡包的流向和結構。
根據 OpenFlow 協議,一行 Flow Entry 應該由兩部分組成:
若是數據包符合 Match 則執行 Action。
Match Field 對網絡包進行解析,解析的內容涵蓋了 TCP/IP 協議族各層,具備下列字段,看這些字段是否可以匹配某個值。
Action 主要包含下列操做:
OvS 對 Flow Table 的管理,主要經過 ovs-ofctl 工具來完成:
# 查看 Bridge 的流表 ovs-ofctl show <bridge> # 查詢指定 Bridge 的流表 ovs-ofctl dump-flows <bridge> # 添加 Bridge 的流表 ovs-ofctl add−flow <bridge> <flow> # e.g. ovs-ofctl add-flow ovs_br dl_src=02:a2:a2:a2:a2:a2,dl_dst=02:b2:b2:b2:b2:b2,in_port=2,dl_type=0x0800,nw_src=10.0.0.1,nw_dst=10.0.0.2,actions=output:6 # 修改 Bridge 的流表 ovs-ofctl mod−flows <bridge> <flow> # 刪除 Bridge 的指定流表 ovs-ofctl del−flows <bridge> <flow> # e.g. ovs-ofctl del-flows <bridge> dl_src=02:a2:a2:a2:a2:a2,dl_dst=02:b2:b2:b2:b2:b2,in_port=2,dl_type=0x0800,nw_src=10.0.0.1,nw_dst=10.0.0.2 # 刪除 Bridge 的全部流表 ovs-ofctl del-flows <bridge> # This will delete all the flow entries in the flow table
http://www.javashuo.com/article/p-gxyfutsg-nb.html
https://blog.csdn.net/w0823m/article/details/71319973
http://www.javashuo.com/article/p-eoiqiurt-dy.html