盤點Kubernetes網路問題的4種解決方案
Flannel是CoreOS團隊針對Kubernetes設計的一個網路規劃服務,簡單來說,它的功能是讓叢集中的不同節點主機建立的Docker容器都具有全叢集唯一的虛擬IP地址。而且它還能在這些IP地址之間建立一個覆蓋網路(Overlay Network),通過這個覆蓋網路,將資料包原封不動地傳遞到目標容器內。
下面是一張它的網路原理圖:
可以看到,Flannel首先建立了一個名為flannel0的網橋,而且這個網橋的一端連線docker0的網橋,另一端連線一個名為flanneld的服務程序。
Flanneld程序並不簡單,它首先上連etcd,利用etcd來管理可分配的IP地址段資源,同時監控etcd中每個Pod的實際地址,並在記憶體中建立了一個Pod節點路由表;然後下連docker0和物理網路,使用記憶體中的Pod節點路由表,將docker0發給它的資料包包裝起來,利用物理網路的連線將資料包投遞到目標flanneld上,從而完成pod到pod之間的直接的地址通訊。
Flannel之間的底層通訊協議的可選餘地有很多,比如UDP、VXlan、AWS VPC等等。只要能通到對端的Flannel就可以了。源Flannel封包,目標Flannel解包,最終docker0看到的就是原始的資料,非常透明,根本感覺不到中間Flannel的存在。
Flannel的安裝配置網上講的很多,在這裡就不在贅述了。在這裡注意一點,就是flannel使用etcd作為資料庫,所以需要預先安裝好etcd。
下面說說幾個場景:
1. 同一Pod內的網路通訊。在同一個Pod內的容器共享同一個網路名稱空間,共享同一個Linux協議棧。所以對於網路的各類操作,就和它們在同一臺機器上一樣,它們可以用localhost地址直接訪問彼此的埠。其實這和傳統的一組普通程式執行的環境是完全一樣的,傳統的程式不需要針對網路做特別的修改就可以移植了。這樣做的結果是簡單、安全和高效,也能減少將已經存在的程式從物理機或者虛擬機器移植到容器下執行的難度。
2. Pod1到Pod2的網路,分兩種情況。Pod1與Pod2不在同一臺主機與Pod1與Pod2在同一臺主機。
先說Pod1與Pod2不在同一臺主機。Pod的地址是與docker0在同一個網段的,但docker0網段與宿主機網絡卡是兩個完全不同的IP網段,並且不同Node之間的通訊只能通過宿主機的物理網絡卡進行。將Pod的IP和所在Node的IP關聯起來,通過這個關聯讓Pod可以互相訪問。
Pod1與Pod2在同一臺主機。Pod1和Pod2在同一臺主機的話,由Docker0網橋直接轉發請求到Pod2,不需要經過Flannel。
4. Pod到外網。Pod向外網傳送請求,查詢路由表, 轉發資料包到宿主機的網絡卡,宿主網絡卡完成路由選擇後,iptables執行Masquerade,把源IP更改為宿主網絡卡的IP,然後向外網伺服器傳送請求。
5. 叢集外部訪問Pod或Service
由於Pod和Service是Kubernetes叢集範圍內的虛擬概念,所以叢集外的客戶端系統無法通過Pod的IP地址或者Service的虛擬IP地址和虛擬埠號訪問到它們。為了讓外部客戶端可以訪問這些服務,可以將Pod或Service的埠號對映到宿主機,以使得客戶端應用能夠通過物理機訪問容器應用。
總結:Flannel實現了對Kubernetes網路的支援,但是它引入了多個網路元件,在網路通訊時需要轉到flannel0網路介面,再轉到使用者態的flanneld程式,到對端後還需要走這個過程的反過程,所以也會引入一些網路的時延損耗。另外Flannel預設的底層通訊協議是UDP。UDP本身是非可靠協議,雖然兩端的TCP實現了可靠傳輸,但在大流量、高併發應用場景下還需要反覆除錯,確保不會出現傳輸質量的問題。特別是對網路依賴重的應用,需要評估對業務的影響。二、基於Docker Libnetwork的網路定製
二層VLAN網路的解決跨主機通訊的思路是把原先的網路架構改造為互通的大二層網路,通過特定網路裝置直接路由,實現容器點到點的之間通訊。
Overlay網路是指在不改變現有網路基礎設施的前提下,通過某種約定通訊協議,把二層報文封裝在IP報文之上的新的資料格式。
Libnetwork所要實現的網路模型基本是這樣的: 使用者可以建立一個或多個網路(一個網路就是一個網橋或者一個VLAN ),一個容器可以加入一個或多個網路。 同一個網路中容器可以通訊,不同網路中的容器隔離。這才是將網路從docker分離出去的真正含義,即在建立容器之前,我們可以先建立網路(即建立容器與建立網路是分開的),然後決定讓容器加入哪個網路。
Libnetwork實現了5種網路模式:
bridge:Docker預設的容器網路驅動,Container通過一對veth pair連結到docker0網橋上,由Docker為容器動態分配IP及配置路由、防火牆等。
host:容器與主機共享同一Network Namespace。
null:容器內網路配置為空,需要使用者手動為容器配置網路介面及路由。
remote:Docker網路外掛的實現,Remote driver使得Libnetwork可以通過HTTP Resful API 對接第三方的網路方案,類似於SocketPlane的SDN方案只要實現了約定的HTTP URL處理函式以及底層的網路介面配置方法,就可以替代Docker原生的網路實現。
overlay:Docker原生的跨主機多子網網路方案。
Docker自身的網路功能比較簡單,不能滿足很多複雜的應用場景。因此,有很多開源專案用來改善Docker的網路功能,如Pipework、Weave、SocketPlane等。
舉例:網路配置工具Pipework
Pipework是一個簡單易用的Docker容器網路配置工具。由200多行shell指令碼實現。通過使用IP、brctl、ovs-vsctl等命令來為Docker容器配置自定義的網橋、網絡卡、路由等。有如下功能:
支援使用自定義的Linux Bridge、veth pair為容器提供通訊。
支援使用MacVLAN裝置將容器連線到本地網路。
支援DHCP獲取容器的IP。
支援Open vSwitch。
支援VLAN劃分。
OVS跨主機多子網網路方案
OVS的優勢是,作為開源虛擬交換機軟體,它相對成熟和穩定,而且支援各類網路隧道協議,經過了OpenStack等專案的考驗。這個網上很多,就不再贅述了。三、Kubernetes整合CalicoCalico是一個純3層的資料中心網路方案,而且無縫整合像OpenStack這種IaaS雲架構,能夠提供可控的VM、容器、裸機之間的IP通訊。
通過將整個網際網路的可擴充套件IP網路原則壓縮到資料中心級別,Calico在每一個計算節點利用Linux Kernel實現了一個高效的vRouter來負責資料轉發,而每個vRouter通過BGP協議負責把自己上執行的workload的路由資訊像整個Calico網路內傳播——小規模部署可以直接互聯,大規模下可通過指定的BGP route reflector來完成。這樣保證最終所有的workload之間的資料流量都是通過IP路由的方式完成互聯的。
Calico節點組網可以直接利用資料中心的網路結構(無論是L2或者L3),不需要額外的NAT,隧道或者Overlay Network。
Calico基於iptables還提供了豐富而靈活的網路Policy,保證通過各個節點上的ACLs來提供Workload的多租戶隔離、安全組以及其他可達性限制等功能。
Calico有兩種佈署方案,一般叢集都配有SSL證書和非證書的情況。
第一種無HTTPS連線etcd方案,HTTP模式部署即沒有證書,直接連線etcd
第二種HTTPS連線etcd叢集方案,載入etcd https證書模式,有點麻煩
Docker 1.10版本支援指定IP啟動容器,並且由於部分資料庫應用對例項IP固定有需求,有必要研究容器IP固定方案的設計。
在預設的Kubernetes + Contiv的網路環境下,容器Pod的IP網路連線是由Contiv Network Plugin來完成的,Contiv Master只實現了簡單的IP地址分配和回收,每次部署應用時,並不能保證Pod IP不變。所以可以考慮引入新的Pod層面的IPAM(IP地址管理外掛),以保證同一個應用多次發生部署時,Pod IP始終是不變的。
作為Pod層面的IPAM,可以把這一功能直接整合在Kubernetes裡。Pod作為Kubernetes的最小排程單元,原有的Kubernetes Pod Registry(主要負責處理所有與Pod以及Pod subresource相關的請求:Pod的增刪改查,Pod的繫結及狀態更新,exec/attach/log等操作)並不支援在建立Pod時為Pod分配IP,Pod IP是通過獲取Pod Infra Container的IP來獲取的,而Pod Infra Container的IP即為Contiv動態分配得來的。
在原有Kubernetes程式碼基礎上,修改Pod結構(在PodSpec中加入PodIP)並重寫了Pod Registry同時引入了兩個新的資源物件:
Pod IP Allocator:Pod IP Allocator是一個基於etcd的IP地址分配器,主要實現Pod IP的分配與回收。Pod IP Allocator通過點陣圖記錄IP地址的分配情況,並且將該點陣圖持久化到etcd;
Pod IP Recycler:Pod IP Recycler是一個基於etcd的IP地址回收站,也是實現PodConsistent IP的核心。Pod IP Recycler基於RC全名(namespace + RC name)記錄每一個應用曾經使用過的IP地址,並且在下一次部署的時候預先使用處於回收狀態的IP。Pod IP Recycler只會回收通過RC建立的Pod的IP,通過其他controller或者直接建立的Pod的IP並不會記錄,所以通過這種方式建立的Pod的IP並不會保持不變;同時Pod IP Recycle檢測每個已回收IP物件的TTL,目前設定的保留時間為一天。
這裡對kubelet也需要進行改造,主要包括根據Pod Spec中指定IP進行相關的容器建立(docker run加入IP指定)以及Pod刪除時釋放IP操作。
Pod的建立在PaaS裡主要有兩種情形:
應用的第一次部署及擴容,這種情況主要是從IP pool中隨機分配;
應用的重新部署:在重新部署時,已經釋放的IP已根據RC全名存放於IP Recycle列表中,這裡優先從回收列表中獲取IP,從而達到IP固定的效果。
容器IP固定方案已測試評估中,執行基本上沒問題,但穩定性有待提升。主要表現在有時不能在預期時間內停止舊Pod,從而無法釋放IP造成無法複用(初步原因是由於Docker偶爾的卡頓造成無法在規定時間內停止容器),可以手動去修復。但從長期考慮,IP固定方案還需要加強穩定性並根據具體需求進行優化。
總結:目前已有多種支援Kubernetes的網路方案,比如Flannel、Calico、華為的Canal、Weave Net等。因為它們都實現了CNI規範,使用者無論選擇哪種方案,得到的網路模型都一樣,即每個Pod都有獨立的 IP,可以直接通訊。區別在於不同方案的底層實現不同,有的採用基於VXLAN的Overlay實現,有的則是Underlay,效能上有區別,再有就是是否支援Network Policy了。Kubernetes入門與進階實戰培訓本次培訓內容包括:Docker基礎、容器技術、Docker映象、資料共享與持久化、Docker三駕馬車、Docker實踐、Kubernetes基礎、Pod基礎與進階、常用物件操作、服務發現、Helm、Kubernetes核心元件原理分析、Kubernetes服務質量保證、排程詳解與應用場景、網路、基於Kubernetes的CI/CD、基於Kubernetes的配置管理等,點選瞭解具體培訓內容。
6月22日正式上課,點選閱讀原文連結即可報名。