本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。QQ郵箱地址:1120746959@qq.com,如有任何學術交流,可隨時聯絡。
1 Dokcer網路模型
2 Kubernetes網路模型
2.1 Flannel如何控制同一水平網路
-
Flannel是如何做到為不同Node上的Pod分配IP且不產生衝突的?因為Flannel使用集中的etcd服務管理這些地址資源資訊,它每次分配的地址段都在同一個公共區域獲取,這樣自然能隨時協調,避免衝突了。在Flannel分配好地址段後,接下來的工作就轉交給Docker完成了。Flannel通過修改Docker的啟動引數將分配給它的地址段傳遞進去。
--bip=172.17.18.1/24 複製程式碼
通過這些操作,Flannel就控制了每個Node節點上的docker0地址段的地址,也能保障所有Pod的IP地址在同一水平的網路中且不產生衝突了
2.1.1 Flannel核心原理
- flannel利用Kubernetes API或者etcd用於儲存整個叢集的網路配置,其中最主要的功能為:設定整個叢集的網路地址空間段。例如,設定整個叢集內所有容器的IP都取自網段“10.1.0.0/16”。
- flannel在每個物理主機中執行flanneld作為agent,它會為所在主機從叢集的網路地址空間中(網段“10.1.0.0/16”),獲取一個小的網段subnet,本主機內所有容器的IP地址都將從中分配(如:分配主機1網段:10.1.1.0/24,主機2網段:10.1.2.0/24)
- flanneld再將本主機獲取的subnet以及用於主機間通訊的Public IP,同樣通過kubernetes API或者etcd儲存起來。
- flannel利用各種backend mechanism,例如udp,vxlan,hostgw等等,跨主機轉發容器間的網路流量,完成容器間的跨主機通訊。
2.1.2 Flannel使用VXLAN協議網路原理
-
每臺物理主機都安裝有flannel,假設k8s定義的flannel網路為10.0.0.0/16,各主機的flannel從這個網路申請一個子網。pod1所在的主機的flannel子網為10.0.13.1/24,pod2所在主機的flannel子網為10.0.14.1/24。
-
每臺主機有cni0和flannel.1虛擬網路卡。cni0為在同一主機pod共用的網橋,當kubelet建立容器時,將為此容器建立虛擬網路卡vethxxx,並橋接到cni0網橋。flannel.1是一個tun虛擬網路卡,接收不在同一主機的POD的資料,然後將收到的資料轉發給flanneld程式。
2.1.3 Pod1與Pod2不在同一臺主機網路傳輸過程資料包流向:
-
- pod1(10.0.14.15)向pod2(10.0.5.150)傳送ping,查詢pod1路由表,把資料包傳送到cni0(10.0.14.1)
-
- cni0查詢host1路由,把資料包轉發到flannel.1
-
- flannel.1虛擬網路卡再把資料包轉發到它的驅動程式flannel
-
- flannel程式使用VXLAN協議封裝這個資料包,向api-server查詢目的IP所在的主機IP,稱為host2(不清楚什麼時候查詢)
-
- flannel向查詢到的host2 IP的UDP埠8472傳輸資料包
-
- host2的flannel收到資料包後,解包,然後轉發給flannel.1虛擬網路卡
-
- flannel.1虛擬網路卡查詢host2路由表,把資料包轉發給cni0網橋,cni0網橋再把資料包轉發給pod2
2.2 Calico 工作原理
-
Calico把每個作業系統的協議棧認為是一個路由器,然後把所有的容器認為是連在這個路由器上的網路終端,在路由器之間跑標準的路由協議——BGP的協議,然後讓它們自己去學習這個網路拓撲該如何轉發。所以Calico方案其實是一個純三層的方案,也就是說讓每臺機器的協議棧的三層去確保兩個容器,跨主機容器之間的三層連通性。
-
對於控制平面,它每個節點上會執行兩個主要的程式,一個是Felix,它會監聽ECTD中心的儲存,從它獲取事件,比如說使用者在這臺機器上加了一個IP,或者是分配了一個容器等。接著會在這臺機器上建立出一個容器,並將其網路卡、IP、MAC都設定好,然後在核心的路由表裡面寫一條,註明這個IP應該到這張網路卡。綠色部分是一個標準的路由程式,它會從核心裡面獲取哪一些IP的路由發生了變化,然後通過標準BGP的路由協議擴散到整個其他的宿主機上,讓外界都知道這個IP在這裡,你們路由的時候得到這裡來。
-
由於Calico是一種純三層的實現,因此可以避免與二層方案相關的資料包封裝的操作,中間沒有任何的NAT,沒有任何的overlay,所以它的轉發效率可能是所有方案中最高的,因為它的包直接走原生TCP/IP的協議棧,它的隔離也因為這個棧而變得好做。因為TCP/IP的協議棧提供了一整套的防火牆的規則,所以它可以通過IPTABLES的規則達到比較複雜的隔離邏輯。
- 每個主機上都部署了calico/node作為虛擬路由器,並且可以通過calico將宿主機組織成任意的拓撲叢集。當叢集中的容器需要與外界通訊時,就可以通過BGP協議將閘道器物理路由器加入到叢集中,使外界可以直接訪問容器IP,而不需要做任何NAT之類的複雜操作。
-
從上圖可以看出,當容器建立時,calico為容器生成veth pair,一端作為容器網路卡加入到容器的網路名稱空間,並設定IP和掩碼,一端直接暴露在宿主機上,並通過設定路由規則,將容器IP暴露到宿主機的通訊路由上。於此同時,calico為每個主機分配了一段子網作為容器可分配的IP範圍,這樣就可以根據子網的CIDR為每個主機生成比較固定的路由規則。
當容器需要跨主機通訊時,主要經過下面的簡單步驟:
- 容器流量通過veth pair到達宿主機的網路名稱空間上。
- 根據容器要訪問的IP所在的子網CIDR和主機上的路由規則,找到下一跳要到達的宿主機IP。 流量到達下一跳的宿主機後,根據當前宿主機上的路由規則,直接到達對端容器的veth pair插在宿主機的一端,最終進入容器。
- 跨主機通訊時,整個通訊路徑完全沒有使用NAT或者UDP封裝,效能上的損耗確實比較低。
-
calico目前只支援TCP、UDP、ICMP、ICMPv6協議,如果使用其他四層協議(例如NetBIOS協議),建議使用weave、原生overlay等其他overlay網路實現。 基於三層實現通訊,在二層上沒有任何加密包裝,因此只能在私有的可靠網路上使用。 流量隔離基於iptables實現,並且從etcd中獲取需要生成的隔離規則,有一些效能上的隱患
總結
Kubernetes網路解決方案為大規模叢集部署提供化多為一的網路,本文結合作者在大規模IOT物聯網大資料支撐平臺的實踐經驗,進行總結,此文尚不完善,請持續關注凱新雲技術社群
秦凱新