Kubernetes網絡模型

Kubernetes旨在在一組機器集羣上運行分佈式系統。分佈式系統的本質使網絡成爲Kubernetes部署的核心和必要組成部分,而且瞭解Kubernetes網絡模型將使您可以正確運行,監視和故障排除在Kubernetes上運行的應用程序。html

網絡是一個擁有許多成熟技術的廣闊空間,對於不熟悉該領域的人們來講,這可能會感到不舒服,由於大多數人都對網絡已有先入爲主的概念,而且有不少新舊概念均可以理解並融合在一塊兒。本文包含不少技術點,可能包括網絡名稱空間,虛擬接口,IP轉發和網絡地址轉換等技術。本指南旨在經過討論每種與Kubernetes相關的技術以及如何使用這些技術的說明來揭開Kubernetes網絡神祕面紗,從而理解Kubernetes網絡模型。node

咱們首先討論一些基本的Kubernetes術語,以確保在整個指南中正確使用術語,而後討論Kubernetes的網絡模型以及它所施加的設計和實現決策。隨後是本指南,該指南至關長,分爲幾個部分。本指南中最長,最有趣的部分:深刻討論如何使用幾種不一樣的用例在Kubernetes中路由流量。linux

若是您不熟悉任何網絡術語,則本指南附有網絡術語詞彙表。git

1 Kubernetes 基礎

Kubernetes是基於幾個核心概念構建而成的,這些核心概念被組合在一塊兒並具備愈來愈強大的功能。本節列出了這些概念中的每個,並提供了簡要的概述以幫助促進討論。Kubernetes的功能遠不止此處列出的內容。應該做爲入門,讓讀者能夠在後面的部分中繼續學習。若是您已經熟悉Kubernetes,請隨時跳過本部分。github

1.1 Kubernetes API server

在Kubernetes中,一切都是由Kubernetes API服務器(kube-apiserver)提供服務的API調用。API服務器是etcd數據存儲的網關,可維護您的應用程序集羣的所需狀態。要更新Kubernetes集羣的狀態,您能夠對描述您所需狀態的API服務器進行API調用。docker

1.2 Controllers

控制器是用於構建Kubernetes的核心抽象。一旦您使用API​​服務器聲明瞭集羣的所需狀態,控制器就會經過持續觀察API服務器的狀態並對任何內容作出反應來確保集羣的當前狀態與所需狀態匹配控制器中的更改經過一個簡單的循環進行操做,該循環不斷地根據集羣的所需狀態檢查集羣的當前狀態。若是存在任何差別,控制器將執行使當前狀態與所需狀態匹配的任務。api

while true:
  X = currentState()
  Y = desiredState()

  if X == Y:
    return  # Do nothing
  else:
    do(tasks to get to Y)

例如,當您使用API​​服務器建立新的Pod時,Kubernetes調度程序(一個控制器)會注意到更改並決定將Pod放置在集羣中的位置,而後使用API​​服務器將狀態更改寫入,而後,kubelet(控制器)注意到新的更改並設置了所需的網絡功能,以使Pod在羣集中可訪問。在這裏,兩個單獨的控制器對兩個單獨的狀態更改作出反應,以使羣集的實際狀況匹配用戶的意圖。安全

1.3 Pods

Pod是Kubernetes的原子,Kubernetes是構建應用程序的最小可部署對象。單個Pod表明集羣中正在運行的工做負載,並封裝一個或多個Docker容器,任何須需的存儲以及惟一的IP地址。被設計爲位於同一機器上並位於同一位置。服務器

1.4 Nodes

節點是運行Kubernetes集羣的機器,它們能夠是裸機,虛擬機或其餘任何東西。主機一詞一般與節點互換使用。我會嘗試使用術語一致性節點,但有時會使用虛擬機一詞。根據上下文引用節點。網絡

2 The Kubernetes 網絡模型

Kubernetes對於Pod網絡作出了明智的選擇,尤爲是Kubernetes對任何網絡實現都規定了如下要求:

  • 全部Pod均可以與全部其餘Pod通訊,而無需使用網絡地址轉換(NAT)。
  • 全部節點均可以在沒有NAT的狀況下與全部Pod通訊。
  • Pod看到本身的IP就是其餘人看到的IP。

考慮到這些限制,咱們剩下四個不一樣的網絡問題要解決:

  • 容器到容器網絡
  • Pod到Pod的網絡
  • Pod到服務的網絡
  • 互聯網到服務的網絡

本指南的其他部分將依次討論這些問題及其解決方案。

3 容器到容器的網絡

一般,咱們將虛擬機中的網絡通訊視爲直接與以太網設備進行交互,如圖1所示。
eth0.png
實際上,狀況比這更微妙。在Linux中,每一個正在運行的進程都在網絡名稱空間中進行通訊,該名稱空間爲邏輯網絡堆棧提供了本身的路由,防火牆規則和網絡設備。實質上,網絡名稱空間提供了全新的命名空間內全部進程的網絡堆棧。

做爲Linux用戶,可使用ip命令建立網絡名稱空間。例如,如下命令將建立一個名爲ns1的新網絡名稱空間。

$ ip netns add ns1

建立名稱空間後,將在/var/run/netns下建立該名稱的掛載點,即便沒有附加任何進程,名稱空間也能夠保留。

您能夠經過列出/var/run/netns下的全部掛載點,或使用ip命令來列出可用的名稱空間。

$ ls /var/run/netns
ns1
$ ip netns
ns1

默認狀況下,Linux將每一個進程分配給根網絡名稱空間,以提供對外部環境的訪問,如圖2所示。
root-namespace.png
就Docker架構而言,一個Pod被建模爲一組共享網絡名稱空間的Docker容器。一個Pod中的容器都具備相同的IP地址和經過分配給Pod的網絡名稱空間分配的端口空間,而且能夠經過localhost彼此找到。咱們能夠爲虛擬機上的每一個Pod建立一個網絡名稱空間。首先pause容器,能夠理解爲「Pod容器」,使網絡名稱空間保持打開狀態,而後「應用程序容器」加入到該網絡命名空間,對於Docker的話,即經過docker命令 -net = container:函數加入該命名空間。圖3顯示了每一個Pod如何由共享命名空間中的多個Docker容器(ctr*)組成。
pod-namespace.png
Pod中的應用程序還能夠訪問共享卷,共享卷定義爲Pod的一部分,並能夠掛載到每一個應用程序的文件系統中。

4 Pod到Pod的網絡

在Kubernetes中,每一個Pod都有一個真實的IP地址,每一個Pod都使用該IP地址與其餘Pod通訊。當前的任務是瞭解Kubernetes如何使用真實IP啓用Pod到Pod的通訊,不管Pod是否部署在同一主機上,咱們經過考慮調度在同一臺機器上的Pod來開始討論,以免經過內部網絡進行跨節點通訊的複雜性。

從Pod的角度來看,它存在於本身的以太網名稱空間中,該名稱空間須要與同一節點上的其餘網絡名稱空間進行通訊,幸運的是,名稱空間可使用Linux虛擬以太網設備或由兩個虛擬接口組成的veth對鏈接。要鏈接Pod名稱空間,咱們能夠將veth對的一側分配給根網絡名稱空間,另外一側分配給Pod的網絡名稱空間,每一個veth對都像跳線同樣工做,將兩側鏈接起來並容許流量經過它們能夠在咱們的計算機上覆制到儘量多的Pod。圖4顯示了將VM上的每一個Pod鏈接到根名稱空間的veth對。
pod-veth-pairs.png
至此,咱們已經將Pod設置爲每一個都有本身的網絡名稱空間,以便他們相信本身具備本身的以太網設備和IP地址,而且已將它們鏈接到Node的根名稱空間。經過根名稱空間相互通訊,爲此,咱們使用了網橋。

Linux以太網網橋是一種虛擬的第2層網絡設備,用於將兩個或多個網段結合在一塊兒,透明地工做以將兩個網絡鏈接在一塊兒。網橋經過檢查源和目標之間的轉發表並檢查要傳輸的數據包的目標來進行操做,橋接代碼經過查看網絡中每一個以太網設備惟一的MAC地址來決定是橋接數據仍是丟棄數據。

網橋實施ARP協議以發現與給定IP地址關聯的鏈路層MAC地址。當網橋接收到數據幀時,網橋將幀廣播到全部鏈接的設備(原始發送方除外)和具備相同IP地址的未來流量將使用查找表來發現正確的MAC地址,以將數據包轉發到該地址。
pods-connected-by-bridge.png

4.1 同一節點,不一樣Pod的數據包傳輸

有了將每一個Pod隔離到其本身的網絡堆棧的網絡名稱空間,將每一個名稱空間鏈接到根名稱空間的虛擬以太網設備以及將名稱空間鏈接在一塊兒的網橋,咱們終於能夠在同一節點上的Pod之間發送流量了。如圖6所示。
pod-to-pod-same-node.gif
在圖6中,Pod 1向其本身的以太網設備eth0發送一個數據包,該設備可做爲Pod的默認設備使用。對於Pod 1,eth0經過虛擬以太網設備鏈接到根名稱空間veth0(1)。數據包到達網橋後,網橋將使用ARP協議(3)解析正確的網絡段以將數據包發送至— veth1。當數據包到達虛擬設備veth1時,將爲br配上veth0併爲其鏈接一個網段。它將直接轉發到Pod 2的名稱空間和該名稱空間中的eth0設備(4)。在此通訊流中,每一個Pod僅與localhost上的eth0通訊,並將通訊路由到正確的Pod。是開發人員指望的默認行爲。

Kubernetes的網絡模型規定Pod必須經過其跨節點的IP地址能夠訪問,也就是說,Pod的IP地址對於網絡中的其餘Pod始終可見,而且每一個Pod都將本身的IP地址視爲與其餘Pod相同Pod看到了,咱們如今轉向在不一樣節點上的Pod之間路由流量的問題。

4.1 不一樣節點,Pod到Pod的數據包傳輸

在肯定了如何在同一節點上的Pod之間路由數據包以後,咱們繼續在不一樣節點上的Pod之間路由流量。Kubernetes網絡模型要求Pod IP在整個網絡上都是可訪問的,但並未指定必須如何實現。實際上,這是特定於網絡的,可是已經創建了一些模式來簡化此過程。

一般,爲羣集中的每一個節點分配一個CIDR塊,以指定該節點上運行的Pod可用的IP地址。目的地爲CIDR塊的流量一旦到達該節點,則該節點負責將流量轉發到正確的Pod。假設網絡能夠將CIDR塊中的流量路由到正確的節點,則這是兩個節點之間的流量。
pod-to-pod-different-nodes.gif
圖7以與圖6相同的請求開頭,除了此次,目標Pod(以綠色突出顯示)與源Pod(以藍色突出顯示)位於不一樣的節點上。該數據包首先經過Pod 1的以太網設備發送它與根名稱空間中的虛擬以太網設備配對(1)。最終,數據包最終到達根名稱空間的網絡橋接器(2)。ARP將在橋接器處失敗,由於沒有設備鏈接到具備正確名稱的網橋數據包的MAC地址。若是發生故障,網橋會將數據包發送到默認路由-根名稱空間的eth0設備。這時,該路由離開Node進入網絡(3)。咱們如今假設網絡能夠路由根據分配給節點(4)的CIDR塊將數據包發送到正確的節點。數據包進入目標節點的根名稱空間(VM 2上的eth0),而後經過網橋將其路由到正確的虛擬以太網設備( 5)。最後,路線com經過流過Pod 4的命名空間(6)中的虛擬以太網設備對來完成。通常來講,每一個節點都知道如何將數據包傳遞到其中運行的Pod。一旦數據包到達目標節點,數據包的流動方式與它們相同在同一節點上的Pod之間路由流量。

咱們方便地迴避瞭如何配置網絡以將Pod IP的流量路由到負責這些IP的正確節點的過程。這是特定於網絡的,可是查看特定示例將提供一些有關問題的看法,例如,藉助AWS,亞馬遜爲Kubernetes維護了一個容器網絡插件,該容器插件可以使用容器網絡接口(CNI)插件 在Amazon VPC環境中運行節點到節點網絡。

容器網絡接口(CNI)提供了用於將容器鏈接到外部網絡的通用API。做爲開發人員,咱們想知道Pod可使用IP地址與網絡進行通訊,而且咱們但願此操做的機制透明。由AWS開發的CNI插件試圖知足這些需求,同時經過AWS提供的現有VPC,IAM和安全組功能提供安全和可管理的環境,解決方案是使用彈性網絡接口。

在EC2中,每一個實例都綁定到一個彈性網絡接口(ENI),而且全部ENI都在VPC內鏈接— ENI能夠相互訪問,而無需付出額外的努力。默認狀況下,每一個EC2實例都部署有單個ENI,可是您能夠自由建立多個ENI並將其部署到您認爲合適的EC2實例。Kubernetes的AWS CNI插件經過爲部署到節點的每一個Pod建立一個新的ENI來利用這種靈活性。由於VPC中的ENI已在現有內部鏈接在AWS基礎設施上,這使得每一個Pod的IP地址均可以在VPC內本地尋址。當CNI插件部署到集羣時,每一個Node(EC2實例)都會建立多個彈性網絡接口併爲這些實例分配IP地址,從而造成CIDR塊部署Pods時,做爲DaemonSet部署到Kubernetes集羣的小型二進制文件會收到來自Nodes本地kubelet進程的將Pod添加到網絡的任何請求。從節點的可用ENI池中得到可用的IP地址,並經過鏈接虛擬以太網設備和Linux內核中的網橋,將其分配給Pod,如在同一節點內將Pod聯網時所描述的那樣。

5 Pod到Service的網絡

咱們已經展現瞭如何在Pod及其關聯的IP地址之間路由流量,這在咱們須要處理更改以前很是有用。Pod IP地址不是持久性的,而且會隨着規模的擴大或縮小,應用程序崩潰或出現而消失節點重啓。這些事件中的每個均可以使Pod IP地址更改而不會發出警告。Kubernetes中內置了服務來解決此問題。

Kubernetes服務管理一組Pod的狀態,使您能夠跟蹤隨時間動態變化的Pod IP地址集。服務充當Pod的抽象,併爲一組Pod IP地址分配一個虛擬IP地址尋址到服務虛擬IP的任何流量都將被路由到與虛擬IP關聯的Pod集合。這容許與服務關聯的Pod集合隨時更改-客戶端只須要知道服務的虛擬IP,不會更改。

建立新的Kubernetes服務時,將表明您建立一個新的虛擬IP(也稱爲集羣IP)。在集羣中的任何位置,尋址到該虛擬IP的流量將負載均衡到與該虛擬IP相關聯的一組支持Pod。服務實際上,Kubernetes會自動建立並維護一個分佈式集羣內負載均衡器,該負載均衡器將流量分配給與服務相關聯的健康Pod,讓咱們仔細看看它是如何工做的。

5.1 netfilter 和 iptables

爲了在羣集內執行負載平衡,Kubernetes依賴於Linux內置的網絡框架netfilter; Netfilter是Linux提供的框架,它容許以自定義處理程序的形式實現與網絡相關的各類操做。數據包篩選,網絡地址轉換和端口轉換的操做,提供了經過網絡引導數據包所需的功能,並提供了禁止數據包到達計算機網絡內敏感位置的功能。

iptables是一個用戶空間程序,它提供了一個基於表的系統,用於定義使用netfilter框架處理和轉換數據包的規則。在Kubernetes中,iptables規則由kube-proxy控制器配置,該控制器監視Kubernetes API服務器的更改。更改成服務或Pod會更新服務的虛擬IP地址或Pod的IP地址,更新iptables規則以將定向到服務的流量正確路由到後備Pod。iptables規則監視發往服務虛擬的流量IP,並從一組可用的Pod中隨機選擇一個Pod IP地址,而且iptables規則將數據包的目標IP地址從服務的虛擬IP更改成所選Pod的IP。換句話說,iptables已在計算機上完成了負載平衡,以將定向到服務IP的流量變爲實際流量。iptables規則集已更新以反映集羣狀態的變化。

在返回路徑上,該IP地址來自目標Pod。在這種狀況下,iptables再次重寫IP標頭,用服務的IP替換Pod IP,以便Pod認爲它一直在與服務的IP進行通訊。

5.2 IPVS

Kubernetes的最新版本(1.11)包括用於集羣內負載均衡的第二個選項:IPVS。IPVS(IP虛擬服務器)也基於netfilter構建,並做爲Linux內核的一部分實現傳輸層負載均衡。集成到LVS(Linux虛擬服務器)中,它在主機上運行,​​並充當真實服務器羣集以前的負載均衡器。IPVS能夠將對基於TCP和UDP的服務的請求定向到真實服務器,並進行真實服務器的服務在單個IP地址上顯示爲虛擬服務,這使得IPVS天然適合Kubernetes Services。

聲明Kubernetes服務時,您能夠指定是否要使用iptables或IPVS完成集羣內負載均衡。IPVS專爲負載均衡而設計,並使用更高效的數據結構(哈希表),幾乎能夠無限擴展建立使用IPVS均衡的服務負載時,會發生三件事:在節點上建立虛擬IPVS接口,將服務的IP地址綁定到虛擬IPVS接口,併爲每一個服務IP地址建立IPVS服務器。

未來,IPVS有但願成爲集羣內負載均衡的默認方法。此更改僅會影響羣集內負載均衡,在本指南的其他部分中,您能夠安全地用IPVS替換iptables以實現集羣內負載均衡影響剩下的討論。如今讓咱們來看一看集羣內負載均衡服務的數據包傳輸。

5.3 Pod到Service的數據包傳輸

pod-to-service.gif
在Pod和Service之間路由數據包時,過程以與之前相同的方式開始。數據包首先經過鏈接到Pod網絡名稱空間(1)的eth0接口離開Pod,而後經過虛擬以太網設備到達網橋(2)。網橋上運行的ARP協議不瞭解服務,所以它經過默認路由eth0(3)將數據包傳輸出去,這裏發生了一些變化。在eth0接受以前,數據包是收到數據包後,iptables使用kube-proxy響應服務或Pod事件使用在節點上安裝的規則,將數據包的目標從服務IP重寫到特定的Pod IP(4)。如今註定要到達Pod 4而非服務的虛擬IP。iptables充分利用了Linux內核的conntrack實用程序,以記住作出的Pod選擇,以便未來的流量被路由到相同的Pod(除非有任何擴展事件)。本質上,iptables直接在節點上完成了集羣內負載均衡,而後使用咱們已經研究過的Pod到Pod路由將流量流到Pod。

5.4 Service到Pod的數據包傳輸

service-to-pod.gif
接收到該數據包的Pod會作出響應,將源IP標識爲本身的IP,將目標IP標識爲最初發送該數據包的Pod(1)。進入節點後,數據包流經iptables,後者使用conntrack來記住此處先前已作出選擇,並將數據包的源重寫爲服務的IP而不是Pod的IP(2)。今後處,數據包經過網橋流到與Pod的命名空間(3)配對的虛擬以太網設備,併到達如咱們以前所見(4)。

5.5 使用DNS

Kubernetes能夠選擇使用DNS以免將服務的羣集IP地址硬編碼到您的應用程序中。Kubernetes DNS做爲在羣集上部署的常規Kubernetes服務運行,它配置在每一個Node上運行的kubelet,以便容器使用DNS服務的IP地址以解析DNS名稱。羣集中定義的每一個服務(包括DNS服務器自己)都分配有DNS名稱。DNS記錄根據須要將DNS名稱解析爲服務的羣集IP或POD的IP。 SRV記錄用於指定運行服務的特定命名端口。

CoreDNS與kubedns的工做原理類似,但使用的插件體系結構使其更加靈活。從Kubernetes 1.11開始,CoreDNS是Kubernetes的默認DNS實現。

6 互聯網到Service網絡

到目前爲止,咱們已經研究瞭如何在Kubernetes集羣中路由流量。在某些時候,您但願將服務公開給外部流量。此需求突出了兩個相關的問題:(1)將Kubernetes服務的流量發送到Internet,以及(2)將Internet的流量發送到Kubernetes服務。

6.1 Egress — 路由流量到Internet

從節點到公共Internet的流量路由是特定於網絡的,而且實際上取決於將網絡配置爲發佈流量的方式。爲了使本節更具體,我將使用AWS VPC討論任何特定的細節。

在AWS中,Kubernetes集羣在VPC內運行,其中爲每一個節點分配了一個私有IP地址,該IP地址可從Kubernetes集羣內訪問。要使從集羣外的訪問變得可行,請將Internet網關鏈接到VPC。有兩個目的:在VPC路由表中爲可路由到Internet的流量提供目標,並對已分配了公共IP地址的任何實例執行網絡地址轉換(NAT)。NAT轉換負責更改節點的IP地址。集羣專用的內部IP地址到公用Internet上可用的外部IP地址。

有了Internet網關後,VM能夠自由地將流量路由到Internet。不幸的是,存在一個小問題:Pod擁有本身的IP地址,該IP地址與託管Pod的節點的IP地址不一樣。 Internet網關上的NAT轉換僅適用於VM IP地址,由於它不瞭解哪些Pod在哪些VM上運行-網關不支持容器。讓咱們看看Kubernetes如何使用iptables解決這個問題(再次)。

6.1.1 Node到Internet的數據包傳輸

在下圖中,數據包起源於Pod的名稱空間(1),並通過鏈接到根名稱空間(2)的veth對。一旦在根名稱空間中,因爲IP爲IP,數據包從網橋移動到默認設備。在到達根名稱空間的以太網設備(3)以前,iptables會處理數據包(3)。在這種狀況下,數據包的源IP地址是Pod,若是將源保持爲Pod,Internet網關將拒絕它,由於網關NAT僅瞭解鏈接到VM的IP地址。解決方案是讓iptables執行源NAT(更改數據包源),以便數據包彷佛即將到來從虛擬機而不是Pod。有了正確的源IP,數據包如今能夠離開虛擬機(4)到達Internet網關(5)。Internet網關將執行另外一個NAT,從VM內部重寫源IP IP到外部IP。一般,數據包將到達公共Internet(6)。在回程中,數據包遵循相同的路徑,而且任何源IP處理都將被撤消,以便系統的每一層都接收其可以理解的IP地址:VM-internal位於節點或VM級別,以及Pod名稱空間中的Pod IP。
pod-to-internet.gif

6.2 Ingress — 路由Internet流量到Kubernetes

Ingress(將流量傳入您的集羣)是一個很是棘手的問題,一樣,它特定於您所運行的網絡,但總的來講,Ingress分爲兩種解決方案,它們可在網絡堆棧的不一樣部分工做:(1 )Service LoadBalancer和(2)Ingress controller。

6.2.1 4層: LoadBalancer

建立Kubernetes服務時,能夠選擇指定一個LoadBalancer來配合使用。LoadBalancer的實現由知道如何爲服務建立負載平衡器的雲控制器提供。建立服務後,它將發佈負載平衡器的IP地址。做爲最終用戶,您能夠開始將流量定向到負載平衡器,以開始與服務進行通訊。

藉助AWS,負載均衡器能夠了解其目標組中的節點,並將平衡羣集中全部節點上的流量。一旦流量到達節點,先前在整個羣集中爲您的服務安裝的iptables規則將確保流量到達Pod您感興趣的服務。

6.2.2 LoadBalancer到Service數據包傳輸

讓咱們看一下它是如何工做的。一旦部署了服務,您正在使用的雲提供商將爲您建立一個新的負載均衡器(1)。因爲負載均衡器不支持容器,所以一旦流量達到負載-balancer,它分佈在組成羣集的全部VM中(2)。每一個VM上的iptables規則會未來自負載均衡器的傳入流量定向到正確的Pod(3)-這些是與IP規則相同的規則在服務建立過程當中(前面已經討論過)。從Pod到客戶端的響應將返回Pod的IP,可是客戶端須要具備負載均衡器的IP地址.iptables和conntrack用於在返回路徑上正確地重寫IP,例如咱們以前看到了。

下圖顯示了在託管Pods的三個VM以前的網絡負載平衡器,傳入流量(1)定向到Service的負載平衡器。一旦負載平衡器收到數據包(2),它將隨機選擇一個VM。在這種狀況下,咱們從病理上選擇了沒有運行Pod的VM:VM 2(3)。在此,在VM上運行的iptables規則將使用安裝到羣集中的內部負載平衡規則將數據包定向到正確的Pod。 kube-proxy.iptables執行正確的NAT,並將數據包轉發到正確的Pod(4)。
internet-to-service.gif

6.2.3 7層: Ingress Controller

第7層網絡Ingress在網絡堆棧的HTTP/HTTPS協議範圍內運行,而且構建在服務之上。啓用Ingress的第一步是使用Kubernetes中的NodePort服務類型在服務上打開端口。服務的類型字段到NodePort,Kubernetes主服務器將在您指定的範圍內分配一個端口,而且每一個Node都會將該端口(每一個Node上的相同端口號)代理到您的Service中,也就是說,任何定向到Node端口的流量都會服務到Pod的路由遵循了咱們已經在將流量從服務路由到Pod時使用iptables規則轉發到服務時使用的內部集羣負載均衡模式。

若要將Node的端口暴露給Internet,請使用Ingress對象.Ingress是將HTTP請求映射到Kubernetes Services的高級HTTP負載均衡器.Ingress方法將有所不一樣,具體取決於Kubernetes雲提供商控制器如何實現HTTP負載平衡器(像第4層網絡負載平衡器同樣)僅瞭解節點IP(而非Pod IP),所以流量路由一樣利用kube-proxy在每一個節點上安裝的iptables規則提供的內部負載均衡。

在AWS環境中,ALB入口控制器使用Amazon的第7層應用程序負載平衡器提供Kubernetes入口,下圖詳細說明了該控制器建立的AWS組件,還演示了入口流量從ALB到Kubernetes集羣的路線。
ingress-controller-design.png
建立後,(1)Ingress Controller監視來自Kubernetes API服務器的Ingress事件,當發現知足其要求的Ingress資源時,便開始建立AWS資源.AWS使用Application Load Balancer(ALB)(2)負載均衡器與用於將請求路由到一個或多個已註冊節點的目標組協同工做。(3)在AWS中爲入口資源描述的每一個惟一的Kubernetes服務建立了目標組。(4)一個偵聽器是ALB進程使用您配置的協議和端口檢查鏈接請求。Ingress控制器爲Ingress資源註釋中詳細說明的每一個端口建立偵聽器。最後,爲Ingress資源中指定的每一個路徑建立目標組規則。這樣能夠確保將到特定路徑的流量路由到正確的Kubernetes服務(5)。

6.2.4 Ingress到Service數據包傳輸

流經Ingress的數據包的傳輸與LoadBalancer的傳輸很是類似,主要區別在於Ingress知道URL的路徑(容許並能夠根據其路徑將流量路由到服務)以及初始鏈接入口和節點之間的鏈接是經過每一個服務在節點上公開的端口實現的。

讓咱們看一下它在實際中是如何工做的。一旦部署了服務,您正在使用的雲提供商將爲您建立一個新的Ingress負載均衡器(1)。因爲負載均衡器不支持容器,所以一旦流量到達負載均衡器,它經過服務的公告端口分佈在組成羣集(2)的全部VM上。每一個VM上的iptables規則會未來自負載均衡器的傳入流量定向到正確的Pod(3)-如咱們所見從Pod到客戶端的響應將隨Pod的IP返回,可是客戶端須要具備負載均衡器的IP地址。iptables和conntrack用於正確地在返回路徑上重寫IP,如咱們以前所見。
ingress-to-service.gif第7層負載平衡器的優勢之一是它們能夠識別HTTP,所以能夠了解URL和路徑,這使您能夠按URL路徑對服務流量進行細分。它們一般還能夠在X-Forwarded中提供原始客戶端的IP地址。 -對於HTTP請求的標頭。

相關文章
相關標籤/搜索