1. 程式人生 > >Kubernetes網路原理

Kubernetes網路原理

1. kubernetes網路模型

1.1. 基礎原則

  1. 每個Pod都擁有一個獨立的IP地址,而且假定所有Pod都在一個可以直接連通的、扁平的網路空間中,不管是否執行在同一Node上都可以通過Pod的IP來訪問。
  2. k8s中Pod的IP是最小粒度IP。同一個Pod內所有的容器共享一個網路堆疊,該模型稱為IP-per-Pod模型。
  3. Pod由docker0實際分配的IP,Pod內部看到的IP地址和埠與外部保持一致。同一個Pod內的不同容器共享網路,可以通過localhost來訪問對方的埠,類似同一個VM內的不同程序。
  4. IP-per-Pod模型從埠分配、域名解析、服務發現、負載均衡、應用配置等角度看,Pod可以看作是一臺獨立的VM或物理機。

1.2. k8s對叢集的網路要求

  1. 所有容器都可以不用NAT的方式同別的容器通訊。
  2. 所有節點都可以在不同NAT的方式下同所有容器通訊,反之亦然。
  3. 容器的地址和別人看到的地址是同一個地址。

以上的叢集網路要求可以通過第三方開源方案實現,例如flannel。

1.3. 網路架構圖

這裡寫圖片描述

1.4. k8s叢集IP概念彙總

由叢集外部到叢集內部:

IP型別 說明
Proxy-IP 代理層公網地址IP,外部訪問應用的閘道器伺服器。[實際需要關注的IP]
Service-IP Service的固定虛擬IP,Service-IP是內部,外部無法定址到。
Node-IP 容器宿主機的主機IP。
Container-Bridge-IP 容器網橋(docker0)IP,容器的網路都需要通過容器網橋轉發。
Pod-IP Pod的IP,等效於Pod中網路容器的Container-IP。
Container-IP 容器的IP,容器的網路是個隔離的網路空間。

2. Docker的網路基礎

2.1. Network Namespace

不同的網路名稱空間中,協議棧是獨立的,完全隔離,彼此之間無法通訊。同一個網路名稱空間有獨立的路由表和獨立的Iptables/Netfilter來提供包的轉發、NAT、IP包過濾等功能。

2.1.1. 網路名稱空間的實現

將與網路協議棧相關的全域性變數變成一個Net Namespace變數的成員,然後在呼叫協議棧函式中加入一個Namepace引數。

2.1.2. 網路名稱空間的操作

1、建立網路名稱空間

ip netns add

2、在名稱空間內執行命令

ip netns exec

3、進入名稱空間

ip netns exec bash

3. Docker的網路實現

3.1. 容器網路

Docker使用Linux橋接,在宿主機虛擬一個Docker容器網橋(docker0),Docker啟動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱為Container-IP,同時Docker網橋是每個容器的預設閘道器。因為在同一宿主機內的容器都接入同一個網橋,這樣容器之間就能夠通過容器的Container-IP直接通訊。

Docker網橋是宿主機虛擬出來的,並不是真實存在的網路裝置,外部網路是無法定址到的,這也意味著外部網路無法通過直接Container-IP訪問到容器。如果容器希望外部訪問能夠訪問到,可以通過對映容器埠到宿主主機(埠對映),即docker run建立容器時候通過 -p 或 -P 引數來啟用,訪問容器的時候就通過[宿主機IP]:[容器埠]訪問容器。

這裡寫圖片描述

3.2. 4類網路模式

Docker網路模式 配置 說明
host模式 –net=host 容器和宿主機共享Network namespace。
container模式 –net=container:NAME_or_ID 容器和另外一個容器共享Network namespace。 kubernetes中的pod就是多個容器共享一個Network namespace。
none模式 –net=none 容器有獨立的Network namespace,但並沒有對其進行任何網路設定,如分配veth pair 和網橋連線,配置IP等。
bridge模式 –net=bridge(預設為該模式)

3.3. bridge模式

k8s只使用bridge模式。

在bridge模式下,Docker Daemon首次啟動時會建立一個虛擬網橋docker0,地址通常為172.x.x.x開頭,在私有的網路空間中給這個網路分配一個子網。由Docker建立處理的每個容器,都會建立一個虛擬以太裝置(Veth裝置對),一端關聯到網橋,另一端使用Namespace技術對映到容器內的eth0裝置,然後從網橋的地址段內給eth0介面分配一個IP地址。

這裡寫圖片描述

一般情況,宿主機IP與docker0 IP、容器IP是不同的IP段,預設情況,外部看不到docker0和容器IP,對於外部來說相當於docker0和容器的IP為內網IP。

4. kubernetes的網路實現

k8s網路場景

  1. 容器與容器之間的直接通訊。
  2. Pod與Pod之間的通訊。
  3. Pod到Service之間的通訊。
  4. 叢集外部與內部元件之間的通訊。

4.1. Pod網路

Pod作為kubernetes的最小排程單元,Pod是容器的集合,是一個邏輯概念,Pod包含的容器都執行在同一個宿主機上,這些容器將擁有同樣的網路空間,容器之間能夠互相通訊,它們能夠在本地訪問其它容器的埠。 實際上Pod都包含一個網路容器,它不做任何事情,只是用來接管Pod的網路,業務容器通過加入網路容器的網路從而實現網路共享。Pod網路本質上還是容器網路,所以Pod-IP就是網路容器的Container-IP。

一般將容器雲平臺的網路模型打造成一個扁平化網路平面,在這個網路平面內,Pod作為一個網路單元同Kubernetes Node的網路處於同一層級

4.2. 容器之間的通訊

同一個Pod之間的不同容器因為共享同一個網路名稱空間,所以可以直接通過localhost直接通訊。

4.3. Pod之間的通訊

4.3.1. 同Node的Pod之間的通訊

同一個Node內,不同的Pod都有一個全域性IP,可以直接通過Pod的IP進行通訊。Pod地址和docker0在同一個網段。

4.3.2. 不同Node的Pod之間的通訊

不同的Node之間,Node的IP相當於外網IP,可以直接訪問,而Node內的docker0和Pod的IP則是內網IP,無法直接跨Node訪問。需要通過Node的網絡卡進行轉發。

所以不同Node之間的通訊需要達到兩個條件:

  1. 對整個叢集中的Pod-IP分配進行規劃,不能有衝突(可以通過第三方開源工具來管理,例如flannel)。
  2. 將Node-IP與該Node上的Pod-IP關聯起來,通過Node-IP再轉發到Pod-IP。

這裡寫圖片描述

1. Pod間實現通訊

例如:Pod1和Pod2(同主機),Pod1和Pod3(跨主機)能夠通訊

實現:因為Pod的Pod-IP是Docker網橋分配的,Pod-IP是同Node下全域性唯一的。所以將不同Kubernetes Node的 Docker網橋配置成不同的IP網段即可。

2. Node與Pod間實現通訊

例如:Node1和Pod1/ Pod2(同主機),Pod3(跨主機)能夠通訊

實現:在容器叢集中建立一個覆蓋網路(Overlay Network),聯通各個節點,目前可以通過第三方網路外掛來建立覆蓋網路,比如Flannel和Open vSwitch等。

4.4. Service網路

Service的就是在Pod之間起到服務代理的作用,對外表現為一個單一訪問介面,將請求轉發給Pod,Service的網路轉發是Kubernetes實現服務編排的關鍵一環。Service都會生成一個虛擬IP,稱為Service-IP, Kuberenetes Porxy元件負責實現Service-IP路由和轉發,在容器覆蓋網路之上又實現了虛擬轉發網路。

Kubernetes Porxy實現了以下功能:

  1. 轉發訪問Service的Service-IP的請求到Endpoints(即Pod-IP)。
  2. 監控Service和Endpoints的變化,實時重新整理轉發規則。
  3. 負載均衡能力。

5. 開源的網路元件

5.1. Flannel

參考《Kubernetes權威指南》