雲原生網絡總結
什么是雲原生網絡
容器網絡 對比 物理網路:
容器網絡:集群中node、pod、工作負載、節點數量變化頻率非常高。
物理網絡:機器上架后就不發生大的變動。
容器網絡基本特點:
- 每個pod單獨的ip
- pod之間三層可達
- service、DNS、NetworkPolicy、Ingress等網絡應用
但是,雲原生網絡最好可以實現跨平台,不應該依賴於底層的基礎設施,可以在公有雲、私有雲、物理機隨時遷移。如果網絡和底層綁定(某個公有雲或私有雲),跨平台能力就會弱很多。雲與安生網絡應該是跟平台無關的,可以方便的跨雲進行轉移。
所以,雲原生網絡得具有容器網絡的特性+ Service、DNS、NetworkPolicy、Ingress等,以及跨平台特性,才構成了完整的雲原生網絡。
雲原生網絡的開源實現
- CNI
- 可插拔式容器網絡
- 規定容器和網絡之間的交互協議 ADD/DEL
- 控制平面
- 分布式kv存儲:Flannel、Kube-OVN、Cillium
- 路由協議:Calico、Kube-Router
- 底層物理設備:Macvlan、IPvlan
- Gossip協議:Weave
- 數據平面
- 封裝模式:Flannel Vxlan、Kube-OVN Geneve、Calico IPIP,Cillium Vxlan
- Underlay模式:Flannel hostGateway、Kube-OVN Vlan、Calico BGP
關於開源實現,CNCF(雲原生計算基金會)很早就定義了一個標准——CNI(container network interface),它實際是一個可插拔式的容器網絡協議,Flannel、Clillium、Calico等都是基於CNI協議來做的。它規定了上層調度系統和底層容器網絡之間的一個交互協議,交互協議定義了兩個接口:ADD和DEL。
我們從控制平面和數據平面兩個角度對網絡插件實現進行分類。控制平面是指網絡之間是如何相互發現的,容器網絡相當於在物理機器的網絡上面又加了一層網絡,那么網絡之間是如何相互學習了解的?一個節點的容器是如何發現另一節點的容器?其中的機制是怎樣的?
這種實現機制大致可以分為四類:一種是所有控制信息用分布式kv進行存儲,典型如Flannel、Cillium,把所有的控制信息存到etcd,然后下發到每個節點。靈雀雲開源的Kube-OVN是把所有的控制信息存到OVS DB,也是一個raft協議的分布式存儲。
第二種是不通過物理層面的存儲,直接通過現有網絡層面的路由器或者交換機上的自我發現能力,比如Calico, Kube-Router通過路由協議,有一個協議的Agent,把路由信息發布到外部路由器和交換機,外部硬件的信息就可以通過路由協議把整個控制平台的信息進行轉發。
第三種是用底層物理設備,物理機的控制平面就是交換機,相當於每個機器把網絡接到交換機上之后,交換機就學到了如何進行控制平面的轉發。如果容器能夠直接接入底層物理設備的話,可以試試這種做法,比較典型的是Macvlan,IPvlan。
還有一種比較少見但挺有意思的實現方式,Gossip協議Weave,也叫八卦協議或者流行病協議。就是一個人告訴另一個人,另外一個人再去不斷告訴其他人。
從數據平面角度來看,主要分為兩種:一種封裝模式,比如Flannel Vxlan, Kube-OVN Geneve, CalicoIPIP, Cillium Vxlan,以及跟封裝模式相對的Underlay 模式: Flannel hostGateway, Kube-OVNVlan, Calico BGP 。
雲原生網絡面臨的挑戰
-
功能
- 固定ip
- 多租戶
- 加密
- 集群內外互通
-
監控和故障排查
- 網絡變化復雜
- 微服務化,關系復雜
- 已有技術棧是否兼容
-
安全性
- 支持什么級別的安全策略
- 流量審計,回放
-
性能
- 控制平面的性能
- 數據平面的性能
- 應用所需的性能
雲原生網絡在實際落地時,也面臨着一些挑戰,主要分為四個方面。
第一,功能層面來看,雲原生網絡功能方面的能力比較少,落地時會碰到很多客戶要做的新功能。
比如固定IP,當用戶提出要求,只能要么網絡這邊改,要么應用方面改。多租戶的能力,有的用戶有很大的集群,有很多項目組,希望有租戶管理的功能。租戶不僅指計算資源的隔離,也包括網絡資源的隔離。比如地址空間相對獨立,網絡控制獨立,一些銀行或其他金融機構希望流量經過交換機時是加密的,還有一些客戶並非所有業務都上了K8s,這些應用需要相互之間進行交互,集群內外的網絡互通也是一個問題。
第二,監控和故障排查,這是比功能層面更讓人頭疼的問題,上了容器網絡后會發現大部分時間都是在運維這個網絡,檢查各種各樣的網絡問題。這其中最典型的可能就是網絡不通。而且,如果涉及開發環境,微服務也可能一塊上了,就會導致網絡結構和拓撲變得特別復雜。
還有一個網絡容易出現的問題–與已有技術棧的兼容。有些客戶還有傳統的網絡監控方式,傳統的網絡監控已經很成熟了,但在容器網絡這塊是空缺的,會導致整體監控是缺失的,整體的排查經驗也是缺失的,網絡一旦出現問題,就會是很難解決的問題。
第三,安全性。傳統方式可能采用基於黑白名單,或者基於IP划分的網絡策略,但是容器在K8s上面,如果是用Networkpolicy,很多方式和傳統是不一致的,會帶來很多兼容性的問題。傳統的流量審計流量回放會收集經過集群的所有流量,這種形式如果沒有好的底層基礎設施,很多安全機制相當於被架空了,這些都是落地時會碰到的問題。
第四,性能,提到性能大多數人會關注數據平面的性能。但在我們來看,現階段比較大的問題是,用戶的網絡究竟能撐多大規模的集群,什么時候控制平面的性能會出現明顯的衰減,這是在選型時需着重考慮的。數據平面的性能到實際應用時,很多情況下沒有那么突出。它需要根據應用所需要的性能進行評估,很多情況下最大的極端的性能反而不是最需要的性能。
下面介紹一下靈雀雲開源的Kube-OVN在雲原生實踐方面所做的一些事情,Kube-OVN根據日常實踐中遇到的問題也在不斷改進。
1子網模型
Kube-OVN比較大的改動是對子網模型進行了改進,把Subnet Per Node的模型改成了Subnet Per Namespace。這樣做有幾點好處:首先,子網可以分布在所有節點上,避免了網絡地址和主機地址的綁定。進行網絡擴縮容時,不需要對整個機器集群進行改動,只需要增加或減少子網。
子網跟namespace關聯時,后面會有很多獨立的設置,比如每個namespace可以有獨立的地址空間,對應到用戶那邊可能是某一個項目組,或者某個租戶,這樣的對應就很直接,因為它可能是租戶對應到namespace,租戶對應到子網,是一個緊密關聯的情況。子網跟namespace綁定后,可以根據租戶來定義一些防火牆的策略,網關、NAT策略,子網IPv4還是IPv6,都可以按照這個子網的級別來進行設置,而不會跟節點綁死。
2固定IP
Kube-OVN還對固定IP做了全面支持。
•Pod 支持固定 IP/Mac
•Workload 類型(deployment/statefulset/dae monset/job)可通過 ippool annotation 固定 IP,保證在deployment生命周期內一直在復用IP。
•StatefulSet 支持 IP 復用,生命周期內按名字復用已分配IP 。在創建StatefulSet 時不知道IP是多少,一旦StatefulSet創建完成,pod名字和IP是固定的。
我們對StatefulSet還做了一些額外的支持,在StatefulSet里面實現了默認的固定IP。這一點其實有爭議,有人覺得不該這么應用,但在我們的實踐中,還是把最終的選擇權留給用戶。如果他不需要固定IP的功能,我們完全可以按照隨機分配IP的方式去做。如果用戶一些部門之間存在這樣的問題,需要應用或者底層去做修改,可能應用方面不想改,但是又希望上容器,要用固定IP,我們也能提供這樣的能力。
3Gateway
出網的方式,在實際中會碰到應用一部分在K8s上,一部分不在,或者關聯的一些系統不在K8s上,就涉及到集群內外互訪的需求。我們提供幾種不同的出網方式。默認是分布式網關,它和Flannel、Calico的默認模式類似,pod如果想訪問外部網絡,從所在node節點直接出網。但這種方式不一定能滿足所有場景。
采用這種方式如果你的pod飄移,意味着出網的地址也是飄移的,加白名單或做審計都是很困難的事情,這種情況下要把整個集群所有機器都加白名單。審計時,他也不清楚究竟審計應該從哪個節點過來流量。我們做了一個namespace級別的,這個和前面的子網是綁定的,只要配置子網的網關,就可以配置出網的方式。
每個Namespace可以設置獨立的Gateway節點出網。在這個節點,所有出網的流量都通過一個特定節點,相當於通過一種固定的方式出網。在外部進行審計或加白名單時,對一個節點進行處理就可以。而且這個節點可以做高可用的,現在是主備模式,如果當前的斷掉,或者故障下線,可以自動切換到下一個備用的節點。
除了這兩種出網方式,我們還有一個特殊的設置,pod出網要不要進行NAT,如果進行的話,相當於是以當前主機節點IP的方式出網。如果不做NAT,就相當於集群內外的互通。我們的做法還是把所有的能力都提供出來,交給用戶去選擇。