Kubernetes網絡一直是一個很是複雜的主題。本文將介紹Kubernetes實際如何建立網絡以及如何爲Kubernetes集羣設置網絡。node
本文不包括如何設置Kubernetes集羣。這篇文章中的全部例子都將使用Rancher 2.0集羣(其餘平臺也一樣適用)。即便你打算使用其餘的公有云管理Kubernetes服務,也但願你對Kubernetes網絡的工做原理有更好的瞭解。git
許多Kubernetes部署指南中包含了在K8S部署中部署Kubernetes網絡CNI的說明。可是若是你的K8S集羣已經運行,而且還沒有部署任何網絡,那麼部署網絡就像在K8S上運行其提供的配置文件同樣簡單(對於大多數網絡和基本用例而言)。例如,要部署flannel:github
這樣,從網絡的角度來看,K8S已經可使用。爲了測試一切是否正常,咱們建立了兩個Pod。docker
這將建立兩個pod,它們正在使用咱們的驅動器。查看其中一個容器,咱們發現網絡的IP地址範圍爲10.42.0.0/24。數組
在另外一個Pod進行的快速ping測試代表,網絡運行正常。緩存
Kubernetes經過Docker之上的CNI管理網絡,並將設備附加到Docker。儘管有Docker Swarm的Docker也具備本身的聯網功能(例如overlay、macvlan、bridging等),但CNI也提供了相似類型的功能。安全
還有一點十分重要,K8S並不使用docker0(這是Docker的默認網橋),而是建立本身的網橋,名爲cbr0,該網橋須要與docker0區分開來。服務器
諸如vxlan或ipsec之類的overlay網絡能夠將數據包封裝到另外一個數據包中。這使得實體在另外一臺計算機的範圍以外依舊能夠尋址。Overlay網絡的替代方案包括如macvtap(lan)之類的L3解決方案,甚至包括ivtap(lan)之類的L2解決方案,可是這些方案具備必定的侷限性。網絡
L2或L3上的任何解決方案均可以讓pod在網絡上尋址。這意味着pod不只在Docker網絡內部訪問,還能直接從Docker網絡外部訪問。這些是公共IP地址或私有IP地址。架構
然而,在L2上進行通訊比較麻煩,而且你的經驗會由於網絡設備而異。某些交換機須要一些時間來註冊你的Mac地址,而後才能將其實際鏈接到網絡的其他部分。你還可能會遇到一些麻煩,由於系統中其餘主機的neighbor(ARP) table仍在過期的緩存上運行,而且始終須要使用dhcp運行而不是host-local,這樣能夠避免主機之間的ip衝突。Mac地址和neighbor table問題是諸如ipvlan之類的解決方案存在的緣由。這些解決方案不會註冊新的mac地址,而是在現有地址上路由流量(儘管它們也有本身的問題)。
所以,個人建議是,對於大多數用戶而言,將overlay網絡做爲默認解決方案應該足夠了。可是,一旦工做負載變得更加高級並提出了更具體的要求,你將須要考慮其餘的解決方案,如BGP和直接路由。
在Kubernetes中首先要了解的是,pod實際上並不等同於容器,而是容器的集合。在同一集合的容器中共享一個網絡堆棧。Kubernetes經過在暫停容器上設置網絡來進行管理,你能夠在你所建立的每一個pod中找到這些暫停容器。全部其餘pod都鏈接到暫停容器的網絡,該容器自己除了提供網絡外不執行任何操做。所以,也可使一個容器經過localhost與不一樣容器中的服務進行通訊,此時該容器具備相同pod的相同定義。
除了本地通訊以外,pod之間的通訊看起來與Docker網絡中的container-to-container通訊幾乎相同。
我將以兩種場景爲例,詳細地說明如何在Pod之間路由流量。
在兩種狀況下,流量不會離開主機。一是當調用的服務在同一節點上運行,一是單個pod中的同一個容器集合。
若是從第一個pod中的容器1調用localhost:80並在容器2中運行服務,則流量將經過網絡設備並將數據包轉發到其餘目的地。在這種狀況下,路由流量的路線很短。
若是咱們想要與其餘pod進行通訊,時間會更長一些。首先,流量將傳遞到cbr0,接下來cbr0將會注意到咱們在同一個子網通訊,所以它會將流量轉發到目標Pod,過程以下圖所示:
當咱們離開節點時,這將變得更加複雜。如今,cbr0會將流量傳遞到下一個節點,該節點的配置由CNI管理。這些基本上只是以目標主機爲網關的子網路由。而後,目標主機能夠繼續使用本身的cbr0並將流量轉發到目標容器,以下所示:
CNI是Container Networking Interface(容器網絡接口)的縮寫,基本上是一個具備定義明確的外部接口,Kubernetes能夠調用它來提供網絡功能。
你能夠在如下連接中找到維護的參考插件,其中包括容器網絡官方repo中的大多數重要插件:
https://github.com/containernetworking/plugins
CNI 3.1版不是很複雜。它包含三個必需的功能,ADD、DEL和VERSION,這些功能能夠盡其所能管理網絡。有關每一個函數應返回和傳遞的內容的更詳細說明,您能夠在此處閱讀規範:
https://github.com/containernetworking/cni/blob/master/SPEC.md
如下咱們將介紹一些最受歡迎的CNI:
Flannel
Flannel是一個簡單的網絡,而且是overlay網絡最簡單的設置選項。它的功能包括原生網絡,但在多個網絡中使用時會受到限制。對於大多數用戶來講,Flannel是Canal下面的默認網絡,部署起來很是簡單,甚至還有本地網絡功能,如主機網關。可是Flannel有一些限制,包括缺少對網絡安全策略的支持以及沒有多網絡的功能。
Calico
Calico與Flannel採用不一樣的方法,從技術的角度來講,它不是overlay網絡,而是在全部相關係統之間配置路由的系統。爲此,Calico利用邊界網關協議(BGP),它在名爲peering的過程當中用於Internet。其中每方peering交換流量並參與BGP網絡。BGP協議自己會在其ASN下傳播路由,不一樣之處在於它們是私有的,不須要再RIPE中註冊它們。
可是,在某些狀況下,Calico可與overlay網絡配合使用,如IPINIP。當節點位於不一樣網絡上時使用,以便啓動兩個主機之間的流量交換。
Canal
Canal基於Flannel,但有一些Calico本身的組件,例如felix(主機代理),它能夠利用網絡安全策略。這些一般在Flannel中不存在。所以,它基本上經過添加安全策略來擴展Flannel。
Multus
Multus是一個CNI,但實際上它自己並非網絡接口。只是它編排了多個接口,而且沒有配置實際的網絡,於是Pod沒法單獨與Multus通訊。實際上,Multus是多設備和多子網網絡的推進者。下圖顯示了它是如何工做的,Multus自己基本上調用了真正的CNI而不是kubelet,並將結果傳遞迴kubelet。
Kube-Router
一樣值得一提的是kube-router,與Calico同樣,它能夠與BGP和路由而不是overlay網絡一塊兒使用。就像Calico同樣,它在必要的時候可使用IPINIP。它還能利用ipvs進行負載均衡。
若是您須要使用多個網絡,則可能須要Multus。
咱們須要作的第一件事是設置Multus。咱們使用的幾乎是Multus倉庫示例中的配置,但進行了一些重要的調整。請參閱下面的示例。
首先是調整configmap。由於咱們計劃使用Flannel建立默認網絡,因此咱們在Multus配置的delegates數組中定義配置。這裏用紅色標記的一些重要設置是「 masterplugin」:true,用於定義Flannel網絡自己的網橋。你將在接下來的步驟中瞭解爲何咱們須要這樣作。除此以外,還須要添加配置映射的安裝定義,其餘則不須要調整,由於因爲某些緣由,此示例未完成。
關於此configmap的另外一件重要事情是,這一configmap中定義的全部內容都是默認網絡,這些默認網絡會自動安裝到容器,而無需進一步說明。另外,若是要編輯此文件,請注意,你要麼須要終止並從新運行守護進程的容器,要麼從新啓動節點才能使更改生效。
示例yaml文件:
對於主要的Flannel網絡,設置很是簡單。咱們能夠從Multus倉庫中獲取示例,而後進行部署。此處所作的調整是CNI安裝、容差的調整以及對Flannel的CNI設置所作的一些調整。例如,添加「 forceAddress」:true並刪除「 hairpinMode」:true。
這已在使用RKE設置的集羣上進行了測試,可是隻要您從主機正確安裝CNI(在本例中爲/ opt / cni / bin),它就能夠在其餘集羣上工做。
Multus自己並無太大的改變。他們只註釋了initcontainer配置,你能夠刪除它。之因此如此,是由於Multus將創建其delegates,並充當主要的「 CNI」。
這是修改後的Flannel daemonset:
部署了這些樣本以後,咱們已經完成了不少工做,如今應該爲pod分配一個IP地址。讓咱們測試一下:
如你所見,咱們已經成功部署了Pod,並在eth0接口(默認接口)上爲其分配了IP 10.42.2.43。全部其餘接口都將顯示爲netX,即net1。
輔助網絡還須要進行一些調整,這些調整的前提是假設你要部署vxlan。爲了實際服務於輔助overlay,咱們須要更改VXLAN標識符「 VIN」,默認狀況下將其設置爲1,而且咱們的第一個overlay網絡如今已經使用了它。所以,咱們能夠經過在etcd服務器上配置網絡來更改此設置。咱們使用本身的集羣etcd,此處標記爲綠色(而且假設job在運行etcd客戶端的主機上運行),而後從本地主機(在咱們的狀況下,將其存儲在本地主機)中裝入密鑰(此處標記爲紅色),存儲在/ etc / kubernetes / ssl文件夾中。
完整的YAML文件示例:
接下來,咱們能夠實際部署輔助網絡。此設置幾乎與主要網絡設置相同,但有一些關鍵區別。最明顯的是,咱們更改了子網,可是咱們還須要更改其餘一些內容。
首先,咱們須要設置一個不一樣的dataDir,即/ var / lib / cni / flannel2,以及一個不一樣的subnetFile,即/run/flannel/flannel2.env。這十分必要,由於它們已經被咱們的主要網絡佔用。接下來,咱們須要調整網橋,由於主要的Flannel overlay網絡已經使用了kbr0。
其他還需更改的配置包括將其更改成實際針對咱們以前配置的etcd服務器。在主網絡中,這是經過–kube-subnet-mgr flag直接鏈接到K8S API來完成的。可是咱們不能這樣作,由於咱們還須要修改要讀取的前綴。你能夠在下面看到橙色標記的內容,而集羣etcd鏈接的設置則顯示爲紅色。最後一個設置是再次指定子網文件,在示例中以綠色標記。最後一點是,咱們添加了一個網絡定義。其他部分與咱們的主要網絡配置相同。
有關上述步驟,請參見示例配置文件:
完成此操做後,咱們便準備好了輔助網絡。
既然咱們已經準備好輔助網絡,那麼咱們如今須要分配他。爲此,咱們須要先定義一個NetworkAttachmentDefinition
,以後咱們可使用它將網絡分配給容器。基本上,這是在初始化Multus以前,咱們設置的configmap的動態替代方案。這樣,咱們能夠按需安裝所需的網絡。在此定義中,咱們須要指定網絡類型(本例中是Flannel)以及必要的配置。這包括前面提到的subnetFile、dataDir和網橋名稱。
咱們須要肯定的最後一件事是網絡的名稱,咱們將其命名爲flannel2。
如今,咱們終於可使用輔助網絡生成第一個pod。
如今應該使用輔助網絡建立新的Pod,而且咱們將那些附加網絡視爲額外添加的網絡接口。
成功啦,輔助網絡分配10.5.22.4做爲其IP地址。
若是該示例沒有正常工做,你須要查看kubelet的日誌。
一個常見的問題的是缺乏CNI。我第一次測試的時候,遺漏了CNI網橋,由於RKE沒有部署它。可是這個問題十分容易解決。
如今咱們已經創建並運行網絡,接下來咱們要作的是使咱們的應用程序能夠訪問並將其配置爲高可用和可擴展。高可用性和可伸縮性不只能夠經過負載均衡來實現,它還咱們須要具有的關鍵組件。
Kubernetes有四個概念,可使應用程序在外部可用。
Ingress
Ingress基本上就是具備Layer7功能的負載均衡器,特別是HTTP(s)。最經常使用的ingress controller是NGINX ingress。但這主要取決於你的需求以及你的使用場景。例如,你還能夠選擇traefik或HA Proxy。
配置一個ingress十分簡單。在如下例子中,你將瞭解一個連接服務的例子。藍色標註的是指向服務的基本配置。綠色標註的是連接SSL證書所需的配置(須要在此以前安裝這一證書)。最後,你會看到調整了NGINX ingress的一些詳細設置。
Layer 4 負載均衡器
在Kubernetes中,使用type: LoadBalancer定義Layer 4 負載均衡器,這是一個依賴於負載均衡解決方案的服務提供程序。對於本地計算機,大機率會使用HA代理或一個路由解決方案。雲提供商會使用本身的解決方案以及專用硬件,也可使用HA代理或路由解決方案。
最大的區別是第4層負載平衡器不瞭解高級應用程序協議(layer 7),而且僅可以轉發流量。此級別上的大多數負載均衡器還支持SSL終止。這一般須要經過註釋進行配置,而且還沒有標準化。
使用 {host,node} 端口
{host,node} Port基本上等同於docker -p port:port
,尤爲是hostPort。與hostPort不一樣,nodePort在全部節點上可用,而不是僅在運行pod的節點上可用。對於nodePort,Kubernetes首先建立一個clusterIP,而後經過該端口負載均衡流量。nodePort自己只是將端口上的流量轉發到clusterIP的iptable規則。
除了快速測試外,不多使用nodePort,只有在你但願每一個節點公開端口(即用於監視)時纔會在生產中使用nodePort。大多數時候,你須要使用Layer 4負載均衡器。hostPort僅用於測試,或者少數時候,將pod粘貼到特定節點並在指向該節點的特定IP地址下發布。
例如,在容器規範中定義了hostPort,以下所示:
什麼是ClusterIP ?
clusterIP是Kubernetes集羣及其中全部服務的內部可訪問IP。該IP自己將負載均衡流量到與其selector規則匹配的全部Pod。在不少狀況下,例如在指定類型:LoadBalancer服務或設置nodePort時,也會自動生成clusterIP。其背後的緣由是全部負載均衡都是經過clusterIP進行的。
clusterIP做爲一個概念是爲了解決多個可尋址主機以及這些主機的有效更新的問題。具備不變的單個IP比始終經過服務發現針對服務的全部性質從新獲取數據要容易得多。儘管有時在某些狀況下更適合使用服務發現,但若是你想要explicit control,那麼仍是建議使用clusterIP,如在某些微服務環境中。
若是您使用公有云環境並手動設置主機,則您的集羣可能缺乏防火牆規則。例如,在AWS中,您將須要調整安全組,以容許集羣間通訊以及ingress和egress。若是不這樣作,將致使集羣沒法運行。確保始終打開主節點和worker節點之間的必要端口。直接在主機上打開的端口(即hostPort或nodePort)也是如此。
既然咱們已經設置了全部Kubernetes網絡,咱們還須要確保它們具有必定的安全性。保證安全性的最低原則是爲應用程序提供其運行所需的最少訪問量。這能夠在必定程度上確保即便在發生安全漏洞的狀況下,攻擊者也將難以深刻挖掘你的網絡。雖然它不能徹底確保你的安全,但無疑會使攻擊者進行攻擊時變得更加困難和耗時。這很重要,由於它會使你有更多的時間作出反應並防止進一步的破壞。這裏有一個典型的例子,不一樣應用程序的不一樣exploits/漏洞的組合,這使得攻擊者只有從多個維度(例如,網絡、容器、主機)到達任何攻擊面的狀況下,才能進行攻擊。
這裏的選擇要麼是利用網絡策略,要麼是尋求第三方安全解決方案以實現容器網絡安全。有了網絡策略,咱們有堅實的基礎來確保流量僅在流量應流的地方進行,但這僅適用於少數幾個CNI。例如,它們可與Calico和Kube-router一塊兒使用。Flannel不支持它,可是幸運的是,你能夠移至Canal,這使得Flannel可使用Calico的網絡策略功能。對於大多數其餘CNI,則沒有支持,目前還沒有有支持的計劃。
但這不是惟一的問題。問題在於,網絡策略規則只是針對特定端口的防火牆規則,它十分簡單。這意味着你沒法應用任何高級設置。例如,若是你發現某個容器可疑,就不能按需阻止它。進一步來講,網絡規則沒法理解流量,所以你不知道流量的流向,而且僅限於在第3層和第4層上建立規則。最後,它還沒法檢測到基於網絡的威脅或攻擊,例如DDoS,DNS,SQL注入以及即便在受信任的IP地址和端口上也可能發生的其餘破壞性網絡攻擊。
所以,咱們須要專用的容器網絡安全解決方案,它可爲關鍵應用程序(例如財務或合規性驅動的應用程序)提供所需的安全性。我我的喜歡NeuVector。它具備我曾在Arvato / Bertelsmann進行部署的容器防火牆解決方案,並提供了咱們所需的Layer7可見性和保護。
應該注意的是,任何網絡安全解決方案都必須是雲原生的,而且能夠自動擴展和調整。部署新應用程序或擴展Pod時,你無需檢查iptable規則或更新任何內容。也許對於幾個節點上的簡單應用程序堆棧,你能夠手動進行管理,可是對於任何企業而言,部署安全不能減慢CI / CD流水線的速度。
除了安全性和可見性以外,我還發現擁有鏈接和數據包級容器網絡工具備助於在測試和staging期間調試應用程序。藉助Kubernetes網絡,除非您能看到流量,不然您將永遠沒法真正肯定全部數據包的去向以及將哪些Pod路由到其中。
如今已經介紹了Kubernetes網絡和CNI,始終會出現一個大問題:應該選擇哪一種CNI解決方案?我將嘗試提供一些有關如何作出此決定的建議。
每一個項目的第一件事是儘量詳細地定義你須要首先解決的問題。你也許想知道要部署哪一種應用程序以及它們將產生什麼樣的負載。你可能會問本身的一些問題:
個人應用程序:
網絡是否繁忙?
是否對延遲敏感?
是單體架構嗎?
仍是微服務架構服務?
須要在多個網絡上嗎?
這是一個十分重要的問題,由於你須要事先肯定好。若是你如今選擇一種解決方案,之後再進行切換,則須要從新設置網絡並從新部署全部容器。除非你已經擁有Multus之類的東西而且可使用多個網絡,不然這將意味着您的服務會停機。在大多數狀況下,若是你有計劃的維護時段,那麼事情會沒那麼嚴重,可是隨着應用程序的不斷迭代,零停機時間變得更加劇要!
這一狀況在本地安裝中十分常見,實際上,若是你只想將經過專用網絡和公用網絡的流量分開,那麼這須要你設置多個網絡或者有智能的路由。
影響你作決定的另外一件事是,你須要一些特定的功能,在某些CNI中可用,而其餘CNI中不可用。例如,你想使用Weave或但願經過ipvs進行更爲成熟的負載均衡。
若是你的應用程序對延遲敏感或網絡繁忙,那麼你須要避免使用任何overlay網絡。Overlay在性能上並不划算,規模上也是如此。這這種狀況下,提升網絡性能的惟一方法是避免overlay並改用路由之類的網絡實用程序。尋找網絡性能時,你有幾種選擇,例如:
Ipvlan:它有良好的性能,但須要注意,你不能在同一主機上同時使用macv{tap,lan}。
Calico:這個CNI不是對用戶最友好的,但於vxlan相比,它能夠爲你提供更好的性能,而且能夠進行擴展而無需擔憂。
Kube-Router:它經過使用BGP和路由,以及支持LVS/IPVS,來提供更好的性能(這與Calico相似)。但Calico比它更爲成熟。
雲提供商解決方案:一些雲提供商提供了本身的網絡解決方案,這些方案的好壞須要根據具體狀況來肯定,這裏沒法一律而論。值得一提的是,Rancher的一個開源項目Submariner。它支持多個Kubernetes集羣之間的跨集羣網絡鏈接,而且建立了必要的隧道和路徑,能爲部署在須要相互通訊的多個Kubernetes集羣中的微服務提供網絡鏈接。
在這樣的狀況下,推薦使用canal或帶有vxlan的flannel,由於它們十分容易且有效。可是正如我以前所提到的,vxlan速度很慢,隨着應用程序的不斷髮展,它將耗費大量資源。可是對於剛剛起步的項目而言,這絕對是最簡單的方法。
這其實是作出決定而不是根本不作出決定的問題。若是你沒有特定的功能要求,則能夠從Flannel和vxlan開始。若是您已部署到生產環境,稍後須要一些工做以進行遷移,可是從長遠來看,作出錯誤的決定總比徹底不作出決定要好。
有了全部這些信息,我但願您對Kubernetes網絡的工做方式有一些相關的背景和更好的瞭解。
原文連接:
https://dzone.com/articles/how-to-understand-and-setup-kubernetes-networking