新聞中心
問題背景
在云原生技術的廣泛普及和實施過程中,筆者接觸到的很多用戶需求里都涉及到對云原生集群的可觀測性要求。實現(xiàn)集群的可觀測性,是進行集群安全防護的前提條件。而在可觀測性的需求中,集群中容器和容器之間網絡流量的可觀測性需求是其中一個比較重要的部分。對于容器網絡的流量采集,其實施難度是大于傳統(tǒng)主機網絡的流量采集的。

創(chuàng)新互聯(lián)公司是一家專業(yè)提供海湖新企業(yè)網站建設,專注與成都網站設計、網站建設、外貿網站建設、html5、小程序制作等業(yè)務。10年已為海湖新眾多企業(yè)、政府機構等服務。創(chuàng)新互聯(lián)專業(yè)的建站公司優(yōu)惠進行中。
那么容器網絡的復雜度到底在哪里?如何更好的去適配容器網絡?這里筆者結合在工作實踐中的一些積累,在本文中給出一些關于云原生集群網絡流量可觀測性的一點思考,希望能起到拋磚引玉的效果。
CNI 插件
目前在云隙(自適應微隔離)產品云原生場景適配的過程中,已經遇到過如下的一些 CNI 插件:
Flannel—— 默認為 Vxlan 的分布式網關模式,可選擇 host-gw 模式,也可以選擇 udp 模式(早已被淘汰的一種模式)
Calico—— 默認的 BGP 模式,使用 IPIP 隧道進行跨節(jié)點容器間數(shù)據(jù)的轉發(fā),當然也可以不用 IPIP 隧道模式(類似于 Flannel 的 host-gw 模式)
Openshift-SDN—— 基于 Openvswitch 技術,是一套基于 SDN 技術的網絡方案
OVN-Kubernetes—— 基于 Openvswitch 中的 OVN 方案,其實和 Openshift-SDN 是差不多類似的體系,只是在架構和細節(jié)上做了更多的云原生優(yōu)化
現(xiàn)有問題
上述幾類插件是大多數(shù)云原生環(huán)境中常見的 CNI 插件,并且它們本身也涵蓋了容器間網絡所使用的大部分技術。而在對以這幾類 CNI 插件基礎的容器網絡進行流量信息采集的過程中,筆者發(fā)現(xiàn)并不能用一種模式完成所有的采集功能。例如在有的 CNI 插件中,我們需要把宿主機當作一個網絡中轉設備,在主機上利用旁路的方式檢測容器網絡流量的變化情況;而在有的 CNI 插件中,我們沒法在宿主機上直接觀察到任何容器網絡的流量信息,需要進入到容器的網絡命名空間中去完成采集工作;甚至在有的 CNI 插件中,我們無法抓到兩個容器之間的直接訪問關系,必須要配合這個 CNI 插件本身實現(xiàn)的技術原理,通過更多的分析來完成對訪問關系的確定。
所以,在進行容器網絡流量的可觀測性方案實施之前,需要對相關 CNI 插件做進一步的分析,來幫助理解為什么不同的 CNI 插件兼容適配的要求會有不同。
插件分析
Flannel 插件的原理
Flannel 是 CoreOS 團隊針對 Kubernetes 設計的一個覆蓋網絡(Overlay Network)CNI 插件。它可以配置為很多種工作模式,目前默認的工作模式是 Vxlan,是一個虛擬的二層網絡。
組件概述
圖1
Flannel 是以 DaemonSet 的方式部署在 Kubernetes 集群中。一個完整的 Flannel 架構中包含了如下的一些組件:
etcd—— 這是 Flannel 所依賴的配置中心,每個節(jié)點上的 flanneld 都會依賴這個 etcd 組件來實現(xiàn)協(xié)調和同步。在一般的部署方案中,這個 etcd 是直接復用的 Kubernetes 控制層平面的 etcd 組件,所以一般也沒有單獨部署。
flanneld—— 每一個宿主機節(jié)點之上都會啟動一個 flanneld 服務,目前默認是基于 Vxlan 的配置工作模式,在這種模式和 host-gw 模式下,flanneld 都主要承擔了一個旁路配置管理的工作。而在 UDP 模式下,flanneld 還要承擔數(shù)據(jù)的轉發(fā)工作,由于該方案本身有嚴重的性能問題。所以早已被放棄不用。
網絡模式概述
總的來說,F(xiàn)lannel 是一個二層的網絡解決方案。就其默認的 Vxlan 工作模式來說,可以看作是應用 Vxlan 的分布式網關架構組建了一個二層的通信網絡。在這種架構下,宿主機中的虛擬網卡 flannel.1 可以看作是一個作為 Vxlan 二層網關和三層網關的 leaf 節(jié)點,而宿主機本身的網卡則可以看作是用于轉發(fā)的 spine 節(jié)點。
圖2
在這種網絡環(huán)境下,跨界點的容器通信在接收端其實是無法直接抓到來自于發(fā)送端的 IP 地址的,因為在三層轉發(fā)的時候,發(fā)送端的 IP 就已經被替換為了網關的地址。如果從旁路的角度來看,宿主機上也無法直接觀察到容器間流量。如果能觀察到,一般都是節(jié)點自身兩個容器之間的連接,因為它們本身處于一個二層網絡中。同時,在這種環(huán)境中,如果使用 SideCar 模式去容器網絡命名空間下進行觀測,也會發(fā)現(xiàn)由于這個虛擬二層網絡本身存在三層轉發(fā)的網關,我們依然無法直接采集到兩個容器之間的連接關系。
如果是 host-gw 模式,那么宿主機就會被純粹配置一個三層轉發(fā)的網關,雖然不走 Vxlan 這樣的隧道了,但是由于三層轉發(fā)的存在,我們依然無法直接觀測到跨節(jié)點容器通信的網絡關系。
綜上所述,在觀測基于 Flannel 的網絡流量之時,一定要結合 Flannel 的架構本身,將三層網關的轉發(fā)特性考慮到網絡連接關系的梳理過程之中,才能真正地梳理出實際的連接關系。這樣的網絡架構,也是網絡流量觀察的一個難點。
Calico 插件的原理
Calico 是一套開源的網絡和網絡安全方案,用于容器、虛擬機、宿主機之間的網絡連接,可以用在kubernetes、OpenShift、DockerEE、OpenStrack 等 PaaS 或 IaaS 平臺上
組件概述
圖3
Felix—— Calico 的核心組件,運行在每個節(jié)點上。主要的功能有接口管理、路由規(guī)則、ACL 規(guī)則和狀態(tài)報告
ETCD—— 保證數(shù)據(jù)一致性的數(shù)據(jù)庫,存儲集群中節(jié)點的所有路由信息。為保證數(shù)據(jù)的可靠和容錯建議至少三個以上 ETCD 節(jié)點
Orchestrator Plugin—— 協(xié)調器插件負責允許 Kubernetes 或 OpenStack 等原生云平臺方便管理 Calico,可以通過各自的 API 來配置 Calico 網絡實現(xiàn)無縫集成。如 Kubernetes 的 CNI 網絡插件
Bird—— BGP 客戶端,Calico 在每個節(jié)點上的都會部署一個 BGP 客戶端,它的作用是將 Felix 的路由信息讀入內核,并通過 BGP 協(xié)議在集群中分發(fā)。當 Felix 將路由插入到 Linux 內核 FIB 中時,BGP 客戶端將獲取這些路由并將它們分發(fā)到部署中的其他節(jié)點。這可以確保在部署時有效地路由流量
BGP Router Reflector—— 大型網絡僅僅使用 BGP Client 形成 Mesh 全網互聯(lián)的方案就會導致規(guī)模限制,所有節(jié)點需要“N的平方”個連接,為了解決這個規(guī)模問題,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 僅與特定 RR 節(jié)點互聯(lián)并做路由同步,從而大大減少連接數(shù)
Calicoctl—— Calico 命令行管理工具
網絡模式概述
Calico 使用的是 BGP 協(xié)議來構建容器間網絡,簡單來理解就是將集群間的節(jié)點當作邊界路由來實現(xiàn)整個網絡的互通。BGP 協(xié)議之下,每一個節(jié)點上的所有容器被當作了一個 AS(自治系統(tǒng)),而不同的節(jié)點之間,則通過 BGP 服務來進行路由轉發(fā)實現(xiàn)連通。實際上,Calico 項目提供的 BGP 網絡解決方案,與 Flannel 的 Host-GW 模式幾乎一樣。不同之處在于 Calico 基于路由表實現(xiàn)容器數(shù)據(jù)包轉發(fā),而 Flannel 則使用 flanneld 進程維護路由信息。這里區(qū)別在于 flanneld 會介入到路由的轉發(fā)過程中,導致實際的容器之間通信看起來如同中間會有一個 NAT 服務器的轉換(這樣的情況下,旁路模式無法直接獲取兩個容器之間的流量連接關系,需要做一定的推導)。Calico 則是基于內核自己的 BGP 路由轉發(fā),本質上還是容器之間原始數(shù)據(jù)包的投遞,所以在宿主機節(jié)點上,可以旁路采集到整個容器之間的流量關系。
Calico 為了適配三層網絡上運行容器間網絡,還增加了對 IPIP 隧道模式的支持。這種模式下,BGP 協(xié)議轉發(fā)的容器網絡數(shù)據(jù)包,會通過內核的 IPIP 模塊進行封裝然后進行宿主機網絡的傳送。但是本質上,還是容器和容器 之間的原始通信數(shù)據(jù)包的傳遞,沒有像 Flannel 那樣在跨界點的時候會使用節(jié)點 IP 來替換數(shù)據(jù)包本身發(fā)送端的 IP 地址。
Calico 為了靈活適配不同的集群網絡規(guī)模,提供了全互聯(lián)模式(Node-to-Node Mesh)和路由反射模式(Router Reflection 簡稱 RR)。其中全互聯(lián)模式適用于小規(guī)模集群節(jié)點,其本身結構簡單,易于實現(xiàn)。但是缺點在于 BGP 的連接總數(shù)是 “N的平方” ,其中 N 是節(jié)點數(shù),在節(jié)點增長的情況下,連接數(shù)增長會極快帶來巨大的網絡損耗。而路由反射模式則指定一個或多個 BGP Speaker 為 RouterReflection,這樣就減少了連接總數(shù)。不過這種架構實現(xiàn)起來更加的復雜,同時對于作為 BGP Speaker 的節(jié)點也有更高的要求,適合大型集群的網絡規(guī)劃。
Openshift-SDN 插件的原理
Openshift-SDN 是紅帽推出的一款容器集群網絡方案,是部署 Openshift 時默認使用的網絡方案??梢酝ㄟ^ oc get Network.config.openshift.io cluster -o yaml 命令來查看當前環(huán)境使用 CNI 插件。
組件概述
圖4
一套 Openshift-SDN 包含了管控面和數(shù)據(jù)面:
CTRL—— 管控面,是一套 Deployment,用于自動化地給每個節(jié)點分配網段,并記錄到 CRD 中
Node—— 數(shù)據(jù)面,是一套 DaemonSet,用于根據(jù) CRD 變化,構建節(jié)點網絡數(shù)據(jù)面。包括路由、網卡、流表、IPTABLES 規(guī)則
就具體組件來說,主要由 Controller、Agent 以及 CNI 的幾個部分構成,它們各自負責的主要內容包括:
1. Controller
負責配置集群級別的容器 CIDR,對應 Openshift-SDN 的 CRD :clusterNetwork
給新加入的 Node 分配子段,對應 Openshift-SDN 的 CRD :hostSubnet
觀察k8s集群中 namespace、networkpolicy 等對象的變更,同步地更新 Openshift-SDN 的 CRD :netnamespaces、egressnetworkpolicies(專門針對出站的networkpolicy)
2. Agent
每次啟動時獲取集群 clusterNetwork,與本地流表做對比,當發(fā)現(xiàn)有出入,就會重新配置本地的集群網絡流表、節(jié)點上的路由、以及 IPTABLES 規(guī)則
觀察集群中 Openshift-SDN 的 CRD :hostSubnet 的變化,配置到達其他 Node 的流表
觀察集群中 Openshift-SDN 的 CRD :netnamespaces、egressnetworkpolicies 的變化,配置相應的租戶隔離和出站限制的流表
生成節(jié)點上的 CNI 二進制文件,并提供 IP 分配功能
針對本節(jié)點的每個容器,配置對應的流表
3. CNI
負責被 kubelet 調用,以進行容器網絡的配置和解除
會向 Agent 申請和釋放 IP
會配置容器內部的IP和路由
網絡模式概述
一言蔽之,Openshift-SDN 就是構建了一套容器間的大二層網絡(虛擬二層中沒有三層轉發(fā))。所有容器的 IP 都屬于一個虛擬的 L2 中,他們彼此可以互相通過 ARP 請求確認對方物理地址,并進行正常的網絡發(fā)包。不管是 ARP 包還是普通的 IP 包,都會被 ovs 流處理并進行必要的封裝。
就實際的鏈路來看,在使用 Openshift-SDN 的時候,主要會有如下幾種情況:
- 同節(jié)點的容器與容器訪問 :包從客戶端容器的 Veth,到宿主機的 ovs 網橋,直接到達對端容器的 Veth
- 跨節(jié)點的容器與容器訪問 :包從客戶端容器的 Veth,到宿主機的 ovs 網橋,走 vxlan0 端口封裝后,經過宿主機的協(xié)議棧,從宿主機的物理網卡發(fā)出,到對端容器所在宿主機的物理網卡,被識別為 Vxlan,進入對端機器的 ovs 網橋,然后到對端容器的 Veth
- 容器訪問 Node :包從客戶端容器的 Veth,到宿主機 ovs 網橋,因為 Node 的物理網卡 IP 與容器的網絡不在一個平面,所以直接走內部流表 Table100,然后從 tun0 口發(fā)出,經過宿主機的協(xié)議棧,進行路由轉發(fā),最后走宿主機所在的網絡到達某個 Node 的物理網卡
- Node 訪問本節(jié)點的容器 :根據(jù)宿主機的路由,包從 tun0 發(fā)出,進入宿主機的 ovs 網橋,送達對端容器的Veth
- 容器訪問 Service :包從客戶端容器的 Veth,到宿主機 ovs 網橋,從 tun0 發(fā)出,經過宿主機協(xié)議棧,受 IPTABLES 規(guī)則做了 DNAT 和 MASQUERADE,至此變成了 Node 訪問其他節(jié)點的容器
- Service 的后端回包給容器:因為上一步,容器訪問 Service 時,做了 MASQUERADE,所以 Service 后端會認為是某個 Node 訪問了自己,回包給客戶端容器所在的 Node,Node 上收到后對照 Conntrack 表,確認是之前連接的響應包,于是對包的源地址和目的地址做了修改(對應之前做的 DNAT 和 MASQUERADE),變成了 ServiceIP 訪問客戶端容器的包。根據(jù) Node 上的路由,走 tun0,進入 ovs 網橋后,直接送到容器的 Veth
這里可以看到,Openshift-SDN 設計是實現(xiàn)了純虛擬二層網絡,這個和 Flannel 使用 Vxlan 來實現(xiàn)容器間網絡有一些不一樣。Openshift-SDN 實現(xiàn)的純虛擬二層網絡是一個完整的二層網絡,相對于 flanneld 還要維護一個自定義的路由表帶來的容器之間無法捕獲到完整的連接關系不同,在 Openshift-SDN 中容器之間的通信是完整的原始數(shù)據(jù)包流轉。
但是由于使用隧道網絡協(xié)議,在宿主機上無法通過旁路的方式直接看到隧道內的網絡拓撲關系。所以,這里需要在同步到容器的內部網絡命名空間中進行采集,才能夠有效的完成集群網絡的可觀測性功能的實現(xiàn)。
OVN-Kubernetes 插件的原理
OVN 是基于 OVS 實現(xiàn)到一套網絡方案,可以虛擬出二層和三層網絡。本質來說和 Openshift-SDN 的技術原理是一致的。但是這是 OVS 提供的原生虛擬化網絡方案,旨在解決傳統(tǒng) SDN 架構(比如 Neutron DVR)的性能問題。對于 Openshift 本身來說,也解決了 Openshift-SDN 對 NetworkPolicy 支持不完整的問題。
組件概述
圖5
- northbound database —— 存儲邏輯交換機、路由器、ACL、端口等的信息,目前基于 ovsdb-server,未來可能會支持 etcd v3
- ovn-northd —— 集中式控制器,負責把 northbound database 數(shù)據(jù)分發(fā)到各個 ovn-controller
- ovn-controller —— 運行在每臺機器上的本地 SDN 控制器
- southbound database —— 基于ovsdb-server(未來可能會支持etcd v3),包含三類數(shù)據(jù):物理網絡數(shù)據(jù),比如 VM 的 IP 地址和隧道封裝格式;邏輯網絡數(shù)據(jù),比如報文轉發(fā)方式;物理網絡和邏輯網絡的綁定關系
如果以 Kubernetes 中的部署形式來看,它主要分為如下幾個組件:
- ovnkube-db deployment(包含 nb-ovsdb, sb-ovsdb 兩個容器) —— 顧名思義,部署的是ovn 的兩個 db
- ovnkube-master deployment(包含 ovn-northd, nbctl-daemon, ovnkube-master 三個容器) —— 用來初始化 master 節(jié)點,并監(jiān)聽集群中對象的變化對 ovn 網絡進行相應的配置;運行一個 cni 二進制的 http 服務器,相應 cmdAdd 和 cmdDel
- ovnkube daemonset for nodes(ovs-daemons,ovn-controller,ovnkube-node) —— 每臺 node 上的守護進程,初始化 node
- ovn-k8s-overlay —— CNI plugin 二進制,當 POD 創(chuàng)建/銷毀的時候,會被 kubelet 調用
網絡模式概述
OVN-Kubernetes 主要使用的是 overlay 模式,這種模式下 OVN 通過 logical overlay network 連接所有節(jié)點的容器。
圖6
從本質來說,OVN-Kubernetes 和 Openshift-SDN 的運行原理都是一致的,都是基于 OVS 構建的一個容器的大二層網絡。OVN-Kubernetes 重要的改進點在于其本身對于云原生場景的適配上。重點在于兼容 Kubernetes 以及將容器、Service 網絡全部替換為基于 OVN 體系之上的實現(xiàn)。
- OVN-Kubernetes 使用 Geneve 協(xié)議來作為隧道網絡的通信協(xié)議,這點不同于 Openshift-SDN 使用 VXlan 來在節(jié)點間創(chuàng)建網絡。所以,在使用上還需要注意一些限制:
- OVN-Kubernetes 不支持設置一個 Kubernetes service 為 local 的外部流量策略或內部流量策略。默認值是 cluster。這個限制能影響你當添加一個 LoadBalancer、NodePort 或一個帶有 external IP 的 service
- sessionAffinityConfig.clientIP.timeoutSeconds service 在一個 OVN-Kuberntes 環(huán)境中沒有作用,但是在 Openshift-SDN 中有用。這個是兩個插件之間不兼容的一個地方。
- 對于雙棧網絡的集群,IPV4 和 IPV6 流量必須使用同樣的網絡接口作為默認網關。如果達不到這個要求,ovnkube-node DaemonSet 中的 POD 在這個主機上會進入 CrashLoopBackOff 狀態(tài)。所以必須要配置主機支持雙棧網絡的配置。
總的來說,就流量觀測上 OVN-Kubernetes 和 Openshift-SDN 的方案都是類似的,要直接同步到容器的網絡命名空間中進行觀測,這里也要肯定 SDN 架構確實相對于傳統(tǒng)的虛擬局域網架構進一步簡化虛擬網絡層本身的復雜度,為容器網絡流量的可觀測性掃清了三層轉發(fā)這一攔路虎,有助簡化流量可觀測性的設計思路。
總結
目前,在云原生的場景下,非軟件行業(yè)大型企業(yè)用戶多傾向于選擇功能豐富、有完善技術支持的商業(yè)產品 Openshift 來實現(xiàn)自己的云原生數(shù)據(jù)中心的搭建。這樣的環(huán)境中,容器網絡流量觀測工具要想做到功能的適配,要么是深度對接 OVS 的技術架構,通過其本身的底層實現(xiàn)原理來做數(shù)據(jù)分析,得到網絡拓撲。要么就是拋開宿主機層面的網絡架構復雜性,直接進入到容器的二層網絡中做數(shù)據(jù)的搜集。
在一些偏軟件行業(yè)的企業(yè)用戶中,自研云原生環(huán)境也是有很多的。這類環(huán)境中,大多采用開源的軟件組件構建自己的基礎設施。而在這些環(huán)境中,大多數(shù)企業(yè)會選擇 Calico 來實現(xiàn)自己的容器間網絡。相對于復雜的 OVS 等虛擬化網絡解決方案,Calico 提供的 BGP + IPIP 方案也滿足了 Kubernetes 本身對于容器間網絡的基本連接要求。在夠用的情況下,這類用戶會采用更加簡單的架構來實現(xiàn)自己的環(huán)境,所以 Calico 這類方案也得到了廣泛的應用。類似 Calico 的網絡方案,更多的考慮的是利用主機本身提供的網絡能力,所以在主機上往往可以直接捕獲到容器間的通信流量。可以在主機網絡流量搜集工具的基礎上稍加改造來支持對容器間網絡拓撲關系的采集。
理論來說,類 SideCar 的模式來采集容器網絡幾乎可以適配大部分的網絡插件下容器與容器之間的網絡拓撲采集。但是依然會有一些特例,比如在容器網絡中實現(xiàn)了三層轉發(fā)方案的插件(比如 Flannel,通過配置 Vxlan 的二層轉發(fā)和三層轉發(fā)來實現(xiàn)了一個二層網絡;或者類似于 Calico 不帶 IPIP 隧道模式以及 Flannel 的 host-gw 模式,本質也是類似于將主機直接當作三層轉發(fā)網關實現(xiàn)的二層網絡)。這樣的容器網絡,無論是旁路模式還是 SideCar 模式,都無法直接搜集到兩個容器之間的連接關系,所以在這個基礎上通過合理的適配網絡架構的特點進行相應的網絡流量關系二次分析是可觀測性在這些架構上正確工作的一個重要思路。
當然,隨著 Linux 內核自身可觀測性功能的不斷發(fā)展。相信未來會有更多優(yōu)秀的方案,甚至可能會出現(xiàn)一種更加通用的方案來實現(xiàn)對不同網絡架構下的容器間網絡的流量觀測。
文章題目:對創(chuàng)新互聯(lián)集群網絡流量可觀測性的一點思考
標題網址:http://fisionsoft.com.cn/article/djejdgs.html


咨詢
建站咨詢
