成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Kubernetes 網絡的四種場景分析

云計算
本文介紹了Kubernetes網絡的各種場景,包括容器之間、Pod之間、Pod到Service、外部到內部的這4種場景下,不同的通信模式。

本文介紹了Kubernetes網絡的各種場景,包括容器之間、Pod之間、Pod到Service、外部到內部的這4種場景下,不同的通信模式。在設計Kubernetes容器平臺的時候,建議按照這些通信模式,根據具體的場景,逐一比對選擇合適的解決方案。其中,特別需要注意的是外部到內部的訪問。

[[331143]]

顧文俊,某互聯網公司,金融行業架構師。2008年南京郵電大學電路與系統專業研究生畢業,12+年職業生涯主要從事IT基礎設施、云計算、容器、大數據、AI、金融科技相關領域的解決方案工作。

在實際的業務場景中,業務組件之間的關系十分復雜,特別是微服務概念的提出,應用部署的粒度更加細小和靈活。為了支持業務應用組件的通信聯系,Kubernetes網絡的設計主要致力于解決以下場景:

(1)緊密耦合的容器到容器之間的直接通信;

(2)抽象的Pod到Pod之間的通信;

(3)Pod到Service之間的通信;

(4)集群外部與內部組件之間的通信。

1. 容器到容器的通信

在同一個Pod內的容器(Pod內的容器是不會跨宿主機的)共享同一個網絡命名空間,共享同一個Linux協議棧。所以對于網絡的各類操作,就和它們在同一臺機器上一樣,它們甚至可以用localhost地址訪問彼此的端口。這么做的結果是簡單、安全和高效,也能減少將已經存在的程序從物理機或者虛擬機移植到容器的難度。

如下圖中的陰影部分就是Node上運行著的一個Pod實例。容器1和容器2共享了一個網絡的命名空間,共享一個命名空間的結果就是它們好像在一臺機器上運行似的,它們打開的端口不會有沖突,可以直接用Linux的本地IPC進行通信。它們之間互相訪問只需要使用localhost就可以。

 

容器到容器間通信

2. Pod之間的通信

每一個Pod都有一個真實的全局IP地址,同一個Node內的不同Pod之間可以直接采用對房Pod的IP地址通信,而不需要使用其他發現機制,例如DNS、Consul或者etcd。Pod既有可能在同一個Node上運行,也有可能在不用的Node上運行,所以通信也分為兩類:同一個Node內的Pod之間的通信和不同Node上的Pod之間的通信。

1)同一個Node內的Pod之間的通信

如圖,可以看出,Pod1和Pod2都是通過Veth連接在同一個Docker0網橋上的,它們的IP地址IP1、IP2都是從Docker0的網段上自動獲取的,它們和網橋本身的IP3是同一個網段的。另外,在Pod1、Pod2的Linux協議棧上,默認路由都是Docker0的地址,也就是說所有非本地的網絡數據,都會被默認發送到Docker0網橋上,由Docker0網橋直接中轉,它們之間是可以直接通信的。

 

同一個Node內的Pod關系

2)不同Node上的Pod之間的通信

Pod的地址是與Docker0在同一個網段內的,我們知道Docker0網段與宿主機網卡是兩個完全不同的IP網段,并且不同Node之間的通信只能通過宿主機的物理網卡進行,因此要想實現位于不同Node上的Pod容器之間的通信,就必須想辦法通過主機的這個IP地址來進行尋址和通信。另外一方面,這些動態分配且藏在Docker0之后的所謂“私有”IP地址也是可以找到的。Kubernetes會記錄所有正在運行Pod的IP分配信息,并將這些信息保存在etcd中(作為Service的Endpoint)。這些私有IP信息對于Pod到Pod的通信也是十分重要的,因為我們的網絡模型要求Pod到Pod使用私有IP進行通信。之前提到,Kubernetes的網絡對Pod的地址是平面的和直達的,所以這些Pod的IP規劃也很重要,不能有沖突。綜上所述,想要支持不同Node上的Pod之間的通信,就要達到兩個條件:

(1)在整個Kubernetes集群中對Pod分配進行規劃,不能有沖突;

(2)找到一種辦法,將Pod的IP和所在Node的IP關聯起來,通過這個關聯讓Pod可以互相訪問。

根據條件1的要求,我們需要在部署Kubernetes的時候,對Docker0的IP地址進行規劃,保證每一個Node上的Docker0地址沒有沖突。我們可以在規劃后手工分配到每個Node上,或者做一個分配規則,由安裝的程序自己去分配占用。例如Kubernetes的網絡增強開源軟件Flannel就能夠管理資源池的分配。

根據條件2的要求,Pod中的數據在發出時,需要有一個機制能夠知道對方Pod的IP地址掛在哪個具體的Node上。也就是說要先找到Node對應宿主機的IP地址,將數據發送到這個宿主機的網卡上,然后在宿主機上將相應的數據轉到具體的Docker0上。一旦數據到達宿主機Node,則哪個Node內部的Docker0便知道如何將數據發送到Pod。

具體情況,如下圖所示。

 

跨Node的Pod通信

在圖6中,IP1對應的是Pod1,IP2對應的是Pod2。Pod1在訪問Pod2時,首先要將數據從源Node的eth0發送出去,找到并到達Node2的eth0。也就是說先要從IP3到IP4,之后才是IP4到IP2的送達。

3. Pod 到Service之間的通信

為了支持集群的水平擴展、高可用,Kubernetes抽象出Service的概念。Service是對一組Pod的抽象,它會根據訪問策略(LB)來訪問這組Pod。

Kubernetes在創建服務時會為服務分配一個虛擬的IP地址,客戶端通過訪問這個虛擬的IP地址來訪問服務,而服務則負責將請求轉發到后端的Pod上。這個類似于反向代理,但是,和普通的反向代理有一些不同:首先它的IP地址是虛擬的,想從外面訪問需要一些技巧;其次是它的部署和啟停是Kubernetes統一自動管理的。

Service在很多情況下只是一個概念,而真正將Service的作用落實的是背后的kube-proxy服務進程。在Kubernetes集群的每個Node上都會運行一個kube-proxy服務進程,這個進程可以看作Service的透明代理兼負載均衡器,其核心功能是將到某個Service的訪問請求轉發到后端的多個Pod實例上。對每一個TCP類型的Kubernetes Service,kube-proxy都會在本地Node上建立一個SocketServer來負責接收請求,然后均勻發送到后端某個Pod的端口上,這個過程默認采用RoundRobin負載均衡算法。Kube-proxy和后端Pod的通信方式與標準的Pod到Pod的通信方式完全相同。另外,Kubernetes也提供通過修改Service的service.spec.-sessionAffinity參數的值來實現會話保持特性的定向轉發,如果設置的值為“ClientIP”,則將來自同一個ClientIP的請求都轉發到同一個后端Pod上。此外,Service的ClusterIP與NodePort等概念是kube-proxy通過Iptables和NAT轉換實現的,kube-proxy在運行過程中動態創建與Service相關的Iptables規則,這些規則實現了ClusterIP及NodePort的請求流量重定向到kube-proxy進程上對應服務的代理端口的功能。由于Iptables機制針對的是本地的kube-proxy端口,所以如果Pod需要訪問Service,則它所在的那個Node上必須運行kube-proxy,并且在每個Kubernetes的Node上都會運行kube-proxy組件。在Kubernetes集群內部,對Service Cluster IP和Port的訪問可以在任意Node上進行,這個因為每個Node上的kube-proxy針對該Service都設置了相同的轉發規則。

綜上所述,由于kube-proxy的作用,在Service的調用過程中客戶端無需關心后端有幾個Pod,中間過程的通信、負載均衡及故障恢復都是透明的,如下圖所示。

Service的負載均衡轉發

 

訪問Service的請求,不論是用Cluster IP+Target Port的方式,還是用節點機IP+Node Port的方式,都會被節點機的Iptables規則重定向到kube-proxy監聽Service服務代理端口。Kube-proxy接收到Service的訪問請求后,會如何選擇后端Pod?

首先,目前kube-proxy的負載均衡只支持Round Robin算法。該算法按照成員列表逐個選取成員,如果一輪循環完,便從頭開始下一輪,如此循環往復。Kube-proxy的負載均衡器在Round Robin算法的基礎上還支持Session保持。如果Service在定義中指定了Session保持,則kube-proxy接收請求時會從本地內存中查找是否存在來自該請求IP的affinityState對象,如果存在該對象,且Session沒有超時,則kube-proxy將請求轉向該affinityState所指向的后端Pod。如果本地存在沒有來自該請求IP的affinityState對象,記錄請求的IP和指向的Endpoint。后面的請求就會粘連到這個創建好的affinityState對象上,這就實現了客戶端IP會話保持的功能。

接下來我們深入分析kube-proxy的實現細節。kube-proxy進程為每個Service都建立了一個“服務代理對象”,服務代理對象是kube-proxy程序內部的一種數據結構,它包括一個用于監聽此服務請求的Socket-Server,SocketServer的端口是隨機選擇的一個本地空閑端口。此外,kube-proxy內部也建立了一個“負載均衡器組件”,用來實現SocketServer上收到的連接到后端多個Pod連接之間的負載均衡和會話保持能力。

kube-proxy通過查詢和監聽API Server中Service與Endpoint的變化來實現其主要功能,包括為新創建的Service打開一個本地代理對象(代理對象是kube-proxy程序內部的一種數據結構,一個Service端口是一個代理對象,包括一個用于監聽的服務請求的SocketServer),接收請求,針對發生變化的Service列表,kube-proxy會逐個處理。下面是具體的處理流程:

(1)如果該Service沒有設置集群IP(ClusterIP),則不做任何處理,否則,獲取該Service的所有端口定義列表(spec.ports域)

(2)逐個讀取服務端口定義列表中的端口信息,根據端口名稱、Service名稱和Namespace判斷本地是否已經存在對應的服務代理對象,如果不存在就新建,如果存在且Service端口被修改過,則先刪除Iptables中和該Service相關的的規則,關閉服務代理對象,然后走新建流程,即為該Service端口分配服務代理對象并為該Service創建相關的Iptables規則。

(3)更新負載均衡器組件中對應Service的轉發地址表,對于新建的Service,確定轉發時的會話保持策略。

(4)對于已經刪除的Service則進行清理。

 

Kube-proxy與APIServer的交互過程

4. 外部到內部的訪問

Pod作為基本的資源對象,除了會被集群內部的Pod訪問,也會被外部使用。服務是對一組功能相同Pod的抽象,以它為單位對外提供服務是最合適的粒度。

由于Service對象在Cluster IP Range池中分配到的IP只能在內部訪問,所以其他Pod都可以無障礙地訪問到它。但如果這個Service作為前端服務,準備為集群外的客戶端提供服務,就需要外部能夠看到它。

Kubernetes支持兩種對外服務的Service的Type定義:NodePort和LoadBalancer。

(1)NodePort

在定義Service時指定spec.type=NodePort,并指定spec.ports.nodePort的值,系統就會在Kubernetes集群中的每個Node上打開一個主機上的真實端口號。這樣,能夠訪問Node的客戶端就能通過這個端口號訪問到內部的Service了。

(2)LoadBalancer

如果云服務商支持外接負載均衡器,則可以通過spec.type=LoadBalancer定義Service,同時需要指定負載均衡器的IP地址。使用這種類型需要指定Service的NodePort和ClusterIP。

對于這個Service的訪問請求將會通過LoadBalancer轉發到后端Pod上去,負載分發的實現方式依賴于云服務商提供的LoadBalancer的實現機制。

(3)外部訪問內部Service原理

我們從集群外部訪問集群內部,最終都是落在具體的Pod上。通過NodePort的方式就是將kube-proxy開放出去,利用Iptables為服務的NodePort設置規則,將對Service的訪問轉到kube-proxy上,這樣kube-proxy就可以使用和內部Pod訪問服務一樣的方式來訪問后端的一組Pod了。這種模式就是利用kube-proxy作為負載均衡器,處理外部到服務進一步到Pod的訪問。而更常用的是外部均衡器模式。通常的實現是使用一個外部的負載均衡器,這些均衡器面向集群內的所有節點。當網絡流量發送到LoadBalancer地址時,它會識別出這是某個服務的一部分,然后路由到合適的后端Pod。

所以從外面訪問內部的Pod資源,就有了很多種不同的組合。

  • 外面沒有負載均衡器,直接訪問內部的Pod
  • 外面沒有負載均衡器,直接通過訪問內部的負載均衡器來訪問Pod
  • 外面有負載均衡器,通過外部負載均衡器直接訪問內部的Pod
  • 外面有負載均衡器,通過訪問內部的負載均衡器來訪問內部的Pod

第一種情況的場景十分少見,只是在特殊的時候才需要。我們在實際的生產項目中需要逐一訪問啟動的Pod,給它們發送一個刷新指令。只有這種情況下才使用這種方式。這需要開發額外的程序,讀取Service下的Endpoint列表,逐一和這些Pod進行通信。通常要避免這種通信方式,例如可以采取每個Pod從集中的數據源拉命令的方式,而不是采取推命令給它的方式來避免。因為具體到每個Pod的啟停本來就是動態的,如果依賴了具體的Pod們就相當于繞開了Kubernetes的Service機制,雖然能夠實現,但是不理想。

第二種情況就是NodePort的方式,外部的應用直接訪問Service的NodePort,并通過Kube-proxy這個負載均衡器訪問內部的Pod。

第三種情況是LoadBalancer模式,因為外部的LoadBalancer是具備Kubernetes知識的負載均衡器,它會去監聽Service的創建,從而知曉后端的Pod啟停變化,所以它有能力和后端的Pod進行通信。但是這里有個問題需要注意,那就是這個負載均衡器需要有辦法直接和Pod進行通信。也就是說要求這個外部的負載均衡器使用和Pod到Pod一樣的通信機制。

第四種情況也很少使用,因為需要經歷兩級的負載均衡設備,而且網絡的調用被兩次隨機負載均衡后,更難跟蹤了。在實際生產環境中出了問題排錯時,很難跟蹤網絡數據的流動過程。

(4)外部硬件負載均衡器模式

在很多實際的生產環境中,由于是在私有云環境中部署Kubernetes集群,所以傳統的負載均衡器都對Service無感知。實際上我們只需要解決兩個問題,就可以將它變成Service可感知的負載均衡器,這也是實際系統中理想的外部訪問Kubernetes集群內部的模式。

  • 通過寫一個程序來監聽Service的變化,將變化按照負載均衡器的通信接口,作為規則寫入負載均衡器。
  • 給負載均衡器提供直接訪問Pod的通信手段。

如下圖,說明了這個過程。

 

自定義外部負載均衡器訪問Service

這里提供了一個Service Agent來實現Service變化的感知。該Agent能夠直接從etcd中或者通過接口調用API Server來監控Service及Endpoint的變化,并將變化寫入外部的硬件負載均衡器中。

同時,每臺Node上都運行著有路由發現協議的軟件,該軟件負責將這個Node上所有的地址通過路由發現協議組播給網絡內的其他主機,當然也包含硬件負載均衡器。這樣硬件負載均衡器就能知道每個Pod實例的IP地址是在哪臺Node上了。通過上述兩個步驟,就建立起一個基于硬件的外部可感知Service的負載均衡器。

具體的案例,可以參見第五章的實踐部分。

5. 總結

本章重點介紹了Kubernetes網絡的各種場景,包括容器之間、Pod之間、Pod到Service、外部到內部的這4種場景下,不同的通信模式。在設計Kubernetes容器平臺的時候,建議按照這些通信模式,根據具體的場景,逐一比對選擇合適的解決方案。其中,需要注意的是外部到內部的訪問,既可以通過NodePort,也可以通過LoadBalancer的方式亦或是Ingress模式,需要按照具體的場景來分析。

NodePort服務是暴露服務的最原始方式,會在所有節點上打開特定的端口,并且發送到此端口的任何流量都將轉發到該服務。這種方法有很多缺點:每個端口只能有一個服務;默認只能使用端口30000~32767;如果節點IP地址發生更改,則會帶來問題。由于這些原因,不建議在生產中使用這種方法。如果服務可用性不是特別關注,或者特別關注成本,則這個方案比較合適。

LoadBalancer是服務暴露的標準方式,將會啟動一個網絡負載均衡器,提供一個將所有流量轉發到服務的IP地址。如果直接暴露一個服務,這是默認的方法。指定的端口上所有的流量將被轉發到該服務,沒有過濾、路由等。這就意味著可以發送幾乎任何類型流量,如HTTP、TCP、UDP、Websocket、gRPC或其他。這個方式最大的缺點是,使用LoadBalancer公開的每項服務都將獲得自己的IP地址,并且必須為每個服務使用一個LoadBalancer,這將會付出比較大的代價。

 

Ingress實際上不是一種服務。相反,它位于多個服務之前,充當集群中的“智能路由器”或入口點。默認的Ingress控制器將會啟動一個HTTP(s)負載均衡器。這將可以執行基于路徑和基于子域名的路由到后端服務。Ingress可能是暴露服務最強大的方式了,但也可能是最復雜的。如果希望在相同的IP地址下暴露多個服務,并且這些服務都使用相同的L7協議,則Ingress是最有用的。

 

責任編輯:武曉燕 來源: twt企業IT社區
相關推薦

2020-11-10 10:08:41

Kubernetes容器開發

2021-10-24 08:37:18

網絡監控網絡架構網絡

2023-02-10 11:13:42

網絡功耗無線網絡設備

2012-02-29 09:44:54

MySQL

2019-10-22 14:06:13

Docker軟件Linux

2017-09-01 11:59:59

Android

2023-10-12 11:32:03

網絡分析數字化轉型

2019-10-23 05:08:55

docker網絡模式網絡協議

2020-12-09 11:21:48

大數據數據分析

2020-12-09 10:56:15

業務分析數據分析大數據

2022-03-15 11:01:39

KubernetesLinux平滑升級

2017-08-01 23:44:25

數據分析數據科學數據

2019-10-25 10:35:49

Java用法場景

2017-09-21 13:04:35

數據挖掘分析分析方法數據分析師

2020-12-10 16:15:04

物聯網物聯網分析計算類型

2009-11-05 11:05:19

WCF服務合同

2020-07-16 10:07:57

網絡安全漏洞技術

2013-05-13 09:48:47

網絡接入接入方法綜合布線

2019-10-24 07:42:28

Java引用GC

2017-07-06 15:40:19

DevOps核心能力
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩中文字幕在线视频观看 | 久久久久九九九女人毛片 | 一区二区中文 | 日韩精品一区二区三区在线播放 | 欧美精品久久久久 | 成人性视频在线 | 欧美日韩国产精品一区 | 国产精品毛片一区二区在线看 | 国产一区二区三区四区在线观看 | 黄网站免费在线看 | 亚洲欧美在线视频 | 一二三在线视频 | 一级特黄视频 | 亚洲成人免费视频在线 | 国产女人与拘做受免费视频 | 亚洲精品在线视频 | 欧美久久精品一级黑人c片 91免费在线视频 | 亚洲精品久久久一区二区三区 | 久久伊人在 | 午夜国产一级 | 日日干日日操 | 国产粉嫩尤物极品99综合精品 | 国产免费xxx | 中文字幕一区二区在线观看 | 福利精品| 精品在线免费观看视频 | 久久精品国产一区二区三区 | 天堂色网 | 福利久久 | 91精品国产91久久久久久密臀 | 国产美女精品 | 中文字幕亚洲视频 | 日韩中文字幕在线观看视频 | 一区二区三区网站 | 色综合成人网 | 成人福利 | 波多野结衣先锋影音 | 九九精品在线 | 一级视频黄色 | 久久综合99 | 国产精品国产馆在线真实露脸 |