自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

第一次,如此清晰脫俗的直解K8S網(wǎng)絡(luò)

原創(chuàng)
網(wǎng)絡(luò) 通信技術(shù) 開發(fā)工具
K8S 網(wǎng)絡(luò)設(shè)計與實現(xiàn)是在學(xué)習(xí) K8S 網(wǎng)絡(luò)過程中總結(jié)的內(nèi)容。本文按照 K8S 網(wǎng)絡(luò)設(shè)計原則、Pod 內(nèi)部網(wǎng)絡(luò)、Pod 之間網(wǎng)絡(luò)等幾個步驟講解 K8S 復(fù)雜的網(wǎng)絡(luò)架構(gòu)。

【51CTO.com原創(chuàng)稿件】 K8S 網(wǎng)絡(luò)設(shè)計與實現(xiàn)是在學(xué)習(xí) K8S 網(wǎng)絡(luò)過程中總結(jié)的內(nèi)容。本文按照 K8S 網(wǎng)絡(luò)設(shè)計原則、Pod 內(nèi)部網(wǎng)絡(luò)、Pod 之間網(wǎng)絡(luò)等幾個步驟講解 K8S 復(fù)雜的網(wǎng)絡(luò)架構(gòu)。

[[273327]]

圖片出自:《你女兒也能看懂的插畫版 Kubernetes 指南》

K8S 網(wǎng)絡(luò)設(shè)計原則

K8S 網(wǎng)絡(luò)設(shè)計原則如下:

  • 每個 Pod 都擁有一個獨立 IP 地址,Pod 內(nèi)所有容器共享該 IP 地址。
  • 集群內(nèi)所有 Pod 都在一個直接連通的扁平網(wǎng)絡(luò)中,可通過 IP 直接訪問。

即:所有容器之間無需 NAT 就可以直接互相訪問;所有 Node 和所有容器之間無需 NAT 就可以直接互相訪問;容器自己看到的 IP 跟其他容器看到的一樣。

K8S 網(wǎng)絡(luò)規(guī)范

CNI 是由 CoreOS 提出的一個容器網(wǎng)絡(luò)規(guī)范。已采納規(guī)范的包括 Apache Mesos,Cloud Foundry,Kubernetes,Kurma 和 RKT。

另外 Contiv Networking,Project Calico 和 Weave 這些項目也為 CNI 提供插件。

CNI 規(guī)定了一個容器 Runtime 和網(wǎng)絡(luò)插件之間的簡單的契約。這個契約通過 JSON 的語法定義了 CNI 插件所需要提供的輸入和輸出。

CNI 插件提供兩個功能:

  • 一個用來將網(wǎng)絡(luò)接口加入到指定網(wǎng)絡(luò)。
  • 另一個用來將其移除。

這兩個接口分別在容器被創(chuàng)建和銷毀的時候被調(diào)用。容器 Runtime 首先需要獲得一個網(wǎng)絡(luò)命名空間以及一個容器 ID,然后連同一些 CNI 配置參數(shù)傳給網(wǎng)絡(luò)驅(qū)動。

接著網(wǎng)絡(luò)驅(qū)動會將該容器連接到網(wǎng)絡(luò)并將分配的 IP 地址以 JSON 的格式返回給容器 Runtime。

K8S 網(wǎng)絡(luò)插件要求

K8S 對網(wǎng)絡(luò)插件的要求總的來講主要有兩個最基本的,分別是:

  • 要能夠為每一個 Node 上的 Pod 分配互相不沖突的 IP 地址。
  • 要所有 Pod 之間能夠互相訪問。

K8S 網(wǎng)絡(luò)實現(xiàn)方案

K8S網(wǎng)絡(luò)實現(xiàn)方案有如下幾種:

隧道方案

隧道方案在 IaaS 層的網(wǎng)絡(luò)中應(yīng)用也比較多,將 Pod 分布在一個大二層的網(wǎng)絡(luò)規(guī)模下。網(wǎng)絡(luò)拓撲簡單,但隨著節(jié)點規(guī)模的增長復(fù)雜度會提升。

代表方案:

  • Weave:UDP 廣播,本機建立新的 BR,通過 PCAP 互通。
  • Open vSwitch:基于 VxLan 和 GRE 協(xié)議,但是性能方面損失比較嚴重。
  • Flannel:UDP 廣播,VxLan。
  • Racher:IPsec。

路由方案

路由方案一般是從 3 層或者 2 層實現(xiàn)隔離和跨主機容器互通的,出了問題也很容易排查。

代表方案:

  • Calico:基于 BGP 協(xié)議的路由方案,支持很細致的 ACL 控制,對混合云親和度比較高。
  • Macvlan:從邏輯和 Kernel 層來看隔離性和性能優(yōu)的方案,基于二層隔離,所以需要二層路由器支持,大多數(shù)云服務(wù)商不支持,所以混合云上比較難以實現(xiàn)。

K8S Pod 的網(wǎng)絡(luò)創(chuàng)建流程

K8S Pod 的網(wǎng)絡(luò)創(chuàng)建流程如下:

  • 每個 Pod 除了創(chuàng)建時指定的容器外,都有一個 Kubelet 啟動時指定的基礎(chǔ)容器。
  • Kubelet 創(chuàng)建基礎(chǔ)容器,生成 Network Namespace。
  • Kubelet 調(diào)用網(wǎng)絡(luò) CNIdriver,根據(jù)配置調(diào)用具體的 CNI 插件。
  • CNI 插件給基礎(chǔ)容器配置網(wǎng)絡(luò)。
  • Pod 中其他的容器共享基礎(chǔ)容器的網(wǎng)絡(luò)。

Pod 中的網(wǎng)絡(luò)

Pod 是 K8S 的最小工作單元。每個 Pod 包含一個或多個容器。K8S 管理的也是 Pod 而不是直接管理容器。Pod 中的容器會作為一個整體被 Master 調(diào)度到一個 Node 上運行。

Pod 的設(shè)計理念是支持多個容器在一個 Pod 中共享網(wǎng)絡(luò)地址和文件系統(tǒng),可以通過進程間通信和文件共享這種簡單高效的方式組合完成服務(wù)。

一個 Pod 中可以包含多個容器,而一個 Pod 只有一個 IP 地址。那么多個容器之間互相訪問和訪問外網(wǎng)是如何使用這一個 IP 地址呢?

答案是:多個容器共享同一個底層的網(wǎng)絡(luò)命名空間 Net(網(wǎng)絡(luò)設(shè)備、網(wǎng)絡(luò)棧、端口等)。

下面以一個小例子說明,創(chuàng)建一個 Pod 包含兩個容器,yaml 文件如下:

  1. apiVersion: apps/v1beta1 
  2. kind: Deployment 
  3. metadata: 
  4.   name: Pod-two-container 
  5. spec: 
  6.   replicas: 1 
  7.   template: 
  8.     metadata: 
  9.       labels: 
  10.         app: nginx 
  11.     spec: 
  12.       containers: 
  13.       - name: busybox 
  14.         image: busybox 
  15.         command: 
  16.         - "/bin/sh" 
  17.         - "-c" 
  18.         - "while true;do echo hello;sleep 1;done" 
  19.       - name: nginx 
  20.         image: nginx 

創(chuàng)建 1 個 Pod 中包含 2 個 Container,實際會創(chuàng)建 3 個 Container。多出的一個是“Pause”容器。

該 Container 是 Pod 的基礎(chǔ)容器,為其他容器提供網(wǎng)絡(luò)功能。

查看 Pause 容器的基礎(chǔ)信息:

使用命令 docker inspect 容器 _ID 查看 Nginx 詳細信息,其網(wǎng)絡(luò)命令空間使用了 Pause 容器的命名空間,同樣還有進程間通信的命名空間。

再查看 Busybox,可以發(fā)現(xiàn)其網(wǎng)絡(luò)命令空間使用了 Pause 容器的命名空間,進程通信的命名空間也是 Pause 容器的命名空間。

實現(xiàn)方式:Nginx 和 Busybox 之所以能夠和 Pause 的命名空間連通是因為 Docker 有一個特性:能夠在創(chuàng)建時使用指定 Docker 的網(wǎng)絡(luò)命名空間。

在 Docker 的官網(wǎng)上有一段描述:

  1. https://docs.docker.com/engine/reference/run/ 

所以如果要手動完成一個上面的 Pod,可以先創(chuàng)建 Pause,再創(chuàng)建 Nginx 和 Busybox,同時將網(wǎng)絡(luò)指定為 Pause 的網(wǎng)絡(luò)命名空間即可。

docker run --name pause mirrorgooglecontainers/pause-amd64:3.1docker run --name=nginx --network=container:pause nginx docker run --name=busybox --network=container:pause busybox

上述步驟由 K8S 幫助我們完成,所以 Pod 命名空間應(yīng)該是這樣的:

講完了 Pod 內(nèi)部的網(wǎng)絡(luò)實現(xiàn),我們主要來看 Pod 如何獲取 IP 地址,以及 Pod 與 Pod 之間的通信是怎么樣的過程?

Flannel 網(wǎng)絡(luò)

Flannel 簡介

Flannel 是 CoreOS 團隊針對 Kubernetes 設(shè)計的一個網(wǎng)絡(luò)規(guī)劃服務(wù),簡單來說,它的功能是讓集群中的不同節(jié)點主機創(chuàng)建的 Docker 容器都具有全集群唯一的虛擬 IP 地址。

在默認的 Docker 配置中,每個節(jié)點上的 Docker 服務(wù)會分別負責所在節(jié)點容器的 IP 分配。這樣導(dǎo)致的一個問題是,不同節(jié)點上容器可能獲得相同的 IP 地址。

Flannel 的設(shè)計目的就是為集群中的所有節(jié)點重新規(guī)劃 IP 地址的使用規(guī)則,從而使得不同節(jié)點上的容器能夠獲得“同屬一個內(nèi)網(wǎng)”且“不重復(fù)的”IP 地址,并讓屬于不同節(jié)點上的容器能夠直接通過內(nèi)網(wǎng) IP 通信。

Flannel 實質(zhì)上是一種“覆蓋網(wǎng)絡(luò)(overlay network)”,也就是將 TCP 數(shù)據(jù)包裝在另一種網(wǎng)絡(luò)包里面進行路由轉(zhuǎn)發(fā)和通信。

目前已經(jīng)支持 UDP、Vxlan、Host-gw、Aws-vpc、Gce 和 Alloc 路由等數(shù)據(jù)轉(zhuǎn)發(fā)方式,默認的節(jié)點間數(shù)據(jù)通信方式是 UDP 轉(zhuǎn)發(fā)。

適用場景:不需要隔離 Pod,集群規(guī)模小。

設(shè)計思想:為每一個 Node 節(jié)點分配 IP 網(wǎng)段,使 Node 之間 IP 不重復(fù),Pod 之間直接使用 IP 訪問。

設(shè)計優(yōu)勢:網(wǎng)絡(luò)模型簡單,安裝配置相對容易,成熟度高,適合大多數(shù)用例的環(huán)境。

Flannel 對網(wǎng)絡(luò)要求提出的解決辦法

互相不沖突的 IP:

  • Flannel 利用 Kubernetes API 或者 etcd 用于存儲整個集群的網(wǎng)絡(luò)配置,根據(jù)配置記錄集群使用的網(wǎng)段。
  • Flannel 在每個主機中運行 Flanneld 作為 Agent,它會為所在主機從集群的網(wǎng)絡(luò)地址空間中,獲取一個小的網(wǎng)段 Subnet,本主機內(nèi)所有容器的 IP 地址都將從中分配。

如測試環(huán)境中 IP 分配:

①Master 節(jié)點

②Node1

③Node2

在 Flannel Network 中,每個 Pod 都會被分配唯一的 IP 地址,且每個 K8S Node 的 Subnet 各不重疊,沒有交集。

Pod 之間互相訪問:

  • Flanneld 將本主機獲取的 Subnet 以及用于主機間通信的 Public IP 通過 etcd 存儲起來,需要時發(fā)送給相應(yīng)模塊。
  • Flannel 利用各種 Backend 機制,例如 UDP,Vxlan 等等,跨主機轉(zhuǎn)發(fā)容器間的網(wǎng)絡(luò)流量,完成容器間的跨主機通信。

Flannel 架構(gòu)原理

Flannel 架構(gòu)圖:

各個組件的解釋如下:

Cni0:網(wǎng)橋設(shè)備,每創(chuàng)建一個 Pod 都會創(chuàng)建一對 Veth Pair。其中一端是 Pod 中的 eth0,另一端是 cni0 網(wǎng)橋中的端口(網(wǎng)卡)。

Pod 中從網(wǎng)卡 eth0 發(fā)出的流量都會發(fā)送到 cni0 網(wǎng)橋設(shè)備的端口(網(wǎng)卡)上。

注:cni0 設(shè)備獲得的 IP 地址是該節(jié)點分配到的網(wǎng)段的第一個地址。

Flannel.1:Overlay 網(wǎng)絡(luò)的設(shè)備,用來進行 Vxlan 報文的處理(封包和解包)。不同 Node 之間的 Pod 數(shù)據(jù)流量都從 Overlay 設(shè)備以隧道的形式發(fā)送到對端。

Flanneld:Flannel 在每個主機中運行 Flanneld 作為 Agent,它會為所在主機從集群的網(wǎng)絡(luò)地址空間中,獲取一個小的網(wǎng)段 Subnet,本主機內(nèi)所有容器的 IP 地址都將從中分配。

同時 Flanneld 監(jiān)聽 K8S 集群數(shù)據(jù)庫,為 Flannel.1 設(shè)備提供封裝數(shù)據(jù)時必要的 Mac,IP 等網(wǎng)絡(luò)數(shù)據(jù)信息。

不同 Node 上的 Pod 的通信流程:

  • Pod 中產(chǎn)生數(shù)據(jù),根據(jù) Pod 的路由信息,將數(shù)據(jù)發(fā)送到 cni0。
  • cni0 根據(jù)節(jié)點的路由表,將數(shù)據(jù)發(fā)送到隧道設(shè)備 Flannel.1。
  • Flannel.1 查看數(shù)據(jù)包的目的 IP,從 Flanneld 獲得對端隧道設(shè)備的必要信息,封裝數(shù)據(jù)包。
  • Flannel.1 將數(shù)據(jù)包發(fā)送到對端設(shè)備。節(jié)點的網(wǎng)卡接收到數(shù)據(jù)包,發(fā)現(xiàn)數(shù)據(jù)包為 Overlay 數(shù)據(jù)包,解開外層封裝,并發(fā)送內(nèi)層封裝到 Flannel.1 設(shè)備。
  • Flannel.1 設(shè)備查看數(shù)據(jù)包,根據(jù)路由表匹配,將數(shù)據(jù)發(fā)送給 cni0 設(shè)備。
  • cni0 匹配路由表,發(fā)送數(shù)據(jù)給網(wǎng)橋上對應(yīng)的端口。

通信流程

①Pod1 中的容器到 cni0

Pod1 與 Pod3 能夠互相 Ping 通:

Ping 包的 Dst IP 為 192.20.1.43,根據(jù)路由匹配到最后一條路由表項,去往 192.20.0.0/12 的包都轉(zhuǎn)發(fā)給 192.20.0.1。

192.20.0.1 為 cni0 的 IP 地址。

②cni0 到 Flannel1.1

當 Icmp 包達到 cni0 之后,cni0 發(fā)現(xiàn) Dst 為 192.20.1.43,CNI 根據(jù)主機路由表來查找匹配項。

根據(jù)最小匹配原則,匹配到圖上的一條路由表項。去往 192.20.1.0/24 網(wǎng)段的包,發(fā)送 192.20.1.0 網(wǎng)關(guān),網(wǎng)關(guān)設(shè)備是 Flannel.1。

③Flannel.1

內(nèi)層封裝:Flannel.1 為 Vxlan 隧道端點,當數(shù)據(jù)包來到 Flannel.1 時,需要將數(shù)據(jù)包封裝起來。此時:

  • 源 IP src ip 為 192.20.0.51。
  • 目的 IP dst ip 為 192.20.1.43。

數(shù)據(jù)包繼續(xù)封裝需要知道目的 IP 192.20.1.43,IP 地址對應(yīng)的 Mac 地址。此時,F(xiàn)lannel.1 不會發(fā)送 ARP 請求去獲得目的 IP 的 Mac 地址,而是將請求發(fā)送到用戶空間的 Flanned 程序。

Flanned 程序收到內(nèi)核的請求事件之后,從 etcd 查找能夠匹配該地址的子網(wǎng)的 Flannel.1 設(shè)備的 Mac 地址,即發(fā)往的 Pod 所在 Host 中 Flannel.1 設(shè)備的 Mac 地址。

Flannel 在為 Node 節(jié)點分配 IP 網(wǎng)段時記錄了所有的網(wǎng)段和 Mac 等信息。該過程交互流程如下圖所示:

Flanned 將查詢到的信息放入 Master 節(jié)點的 ARP Cache 表中:

到這里,Vxlan 的內(nèi)層數(shù)據(jù)包就完成了封裝。格式是這樣的:

簡單總結(jié)這個流程:

  • 數(shù)據(jù)包到達 Flannel.1,通過查找路由表,知道數(shù)據(jù)包要通過 Flannel.1 發(fā)往 192.20.1.0。
  • 通過 ARP Cache 表,知道了目的 IP 192.20.1.0 的 Mac 地址。

外層封裝:此時內(nèi)層封裝已經(jīng)準備好,需要找到 Vxlan 的外層封裝。Kernel 需要查看 Node 上的 FDB(forwarding database)以獲得內(nèi)層封包中目的 Vtep 設(shè)備所在的 Node 地址。

因為已經(jīng)從 ARP Table 中查到目的設(shè)備 Mac 地址為 52:77:71:e6:4f:58,同時在 FDB 中存在該 Mac 地址對應(yīng)的 Node 節(jié)點的 IP 地址。

如果 FDB 中沒有這個信息,那么 Kernel 會向用戶空間的 Flanned 程序發(fā)起“L2 MISS”事件。Flanneld 收到該事件后,會查詢 etcd,獲取該 Vtep 設(shè)備對應(yīng)的 Node 的“Public IP”,并將信息注冊到 FDB 中。

當內(nèi)核獲得了發(fā)往機器的 IP 地址后,ARP 得到 Mac 地址,之后就能完成 Vxlan 的外層封裝。

④對端 Flannel.1

Node 節(jié)點的 eth0 網(wǎng)卡接收到 Vxlan 設(shè)備包,Kernal 將識別出這是一個 Vxlan 包,將包拆開之后轉(zhuǎn)給節(jié)點上的 Flannel.1 設(shè)備。

這樣數(shù)據(jù)包就從發(fā)送節(jié)點到達目的節(jié)點,F(xiàn)lannel.1 設(shè)備將接收到一個如下的數(shù)據(jù)包:

目的地址為 192.20.1.43,F(xiàn)lannel.1 查找自己的路由表,根據(jù)路由表完成轉(zhuǎn)發(fā)。

根據(jù)匹配原則,F(xiàn)lannel.1 將去往 192.20.1.0/24 的流量轉(zhuǎn)發(fā)到 cni0 上去。

⑤cnio 到 Pod

cni0 是一個網(wǎng)橋設(shè)備。當 cni0 拿到數(shù)據(jù)包之后,通過 Veth Pair,將數(shù)據(jù)包發(fā)送給 Pod。查看 Node 節(jié)點中的網(wǎng)橋。

在 Node 節(jié)點上通過 ARP 解析可以開出,192.20.1.43 的 Mac 地址為 66:57:8e:3d:00:85:

該地址為 Pod 的網(wǎng)卡 eth0 的地址。

同時通過 Veth Pair 的配對關(guān)系可以看出,Pod 中的 eth0 是 Veth Pair 的一端,另一端在 Node 節(jié)點行上,對應(yīng)的網(wǎng)卡是 vethd356ffc1@if3:

所以,在 cni0 網(wǎng)橋上掛載的 Pod 的 Veth Pair 為 vethd356ffc1,即:

eth0@if50 和 vethd356ffc1@if3 組成的一對 Veth Pair。其效果相當于將 Pod 中的 eth0 直接插在到 cni0 上。

簡單總結(jié) cni0 轉(zhuǎn)發(fā)流量的原理:

  • 首先通過 ARP 查找出 IP 地址對應(yīng)的 Mac 地址。
  • 將流量轉(zhuǎn)發(fā)給 Mac 地址所在 eth0 網(wǎng)的對應(yīng)的 Veth Pair 端口。
  • Veth Pair 端口接收到流量,直接將流量注入到 Pod 的 eth0 網(wǎng)卡上。

總結(jié) Flannel 的特點:

  • 使集群中的不同 Node 主機創(chuàng)建的 Docker 容器都具有全集群唯一的虛擬 IP 地址。
  • 建立一個覆蓋網(wǎng)絡(luò)(overlay network),通過這個覆蓋網(wǎng)絡(luò),將數(shù)據(jù)包原封不動的傳遞到目標容器。
  • 創(chuàng)建一個新的虛擬網(wǎng)卡 Flannel0 接收 Docker 網(wǎng)橋的數(shù)據(jù),通過維護路由表,對接收到的數(shù)據(jù)進行封包和轉(zhuǎn)發(fā)。
  • etcd 保證了所有 Node 上 Flanned 所看到的配置是一致的。同時每個 Node 上的 Flanned 監(jiān)聽 etcd 上的數(shù)據(jù)變化,實時感知集群中 Node 的變化。

不同后端的封裝

Flannel 可以指定不同的轉(zhuǎn)發(fā)后端網(wǎng)絡(luò),常用的有 Hostgw,UDP,Vxlan 等,上述使用的就是 Vxlan 網(wǎng)絡(luò)。

①Hostgw:是簡單的 Backend,它的原理非常簡單,直接添加路由,將目的主機當做網(wǎng)關(guān),直接路由原始封包。

例如,我們從 etcd 中監(jiān)聽到一個 EventAdded 事件 Subnet 為 10.1.15.0/24 被分配給主機 Public IP 192.168.0.100。

Hostgw 要做的工作就是在本主機上添加一條目的地址為 10.1.15.0/24,網(wǎng)關(guān)地址為 192.168.0.100,輸出設(shè)備為上文中選擇的集群間交互的網(wǎng)卡即可。

優(yōu)點:簡單,直接,效率高。

缺點:要求所有的 Pod 都在一個子網(wǎng)中,如果跨網(wǎng)段就無法通信。

②UDP:如何應(yīng)對 Pod 不在一個子網(wǎng)里的場景呢?將 Pod 的網(wǎng)絡(luò)包作為一個應(yīng)用層的數(shù)據(jù)包,使用 UDP 封裝之后在集群里傳輸,即 Overlay。

上圖來自 Flannel 官方,其中右邊 Packer 的封裝格式就是使用 UDP 完成 Overlay 的格式。

當容器 10.1.15.2/24 要和容器 10.1.20.2/24 通信時:

  • 因為該封包的目的地不在本主機 Subnet 內(nèi),因此封包會首先通過網(wǎng)橋轉(zhuǎn)發(fā)到主機中。
  • 在主機上經(jīng)過路由匹配,進入網(wǎng)卡 Flannel.1。(需要注意的是 Flannel.1 是一個 Tun 設(shè)備,它是一種工作在三層的虛擬網(wǎng)絡(luò)設(shè)備,而 Flanneld 是一個 Proxy,它會監(jiān)聽 Flannel.1 并轉(zhuǎn)發(fā)流量。)
  • 當封包進入 Flannel.1 時,F(xiàn)lanneld 就可以從 Flanne.1 中將封包讀出,由于 Flanne.1 是三層設(shè)備,所以讀出的封包僅僅包含 IP 層的報頭及其負載。
  • 最后 Flanneld 會將獲取的封包作為負載數(shù)據(jù),通過 UDP Socket 發(fā)往目的主機。
  • 在目的主機的 Flanneld 會監(jiān)聽 Public IP 所在的設(shè)備,從中讀取 UDP 封包的負載,并將其放入 Flannel.1 設(shè)備內(nèi)。
  • 容器網(wǎng)絡(luò)封包到達目的主機,之后就可以通過網(wǎng)橋轉(zhuǎn)發(fā)到目的容器了。

優(yōu)點:Pod 能夠跨網(wǎng)段訪問。

缺點:隔離性不夠,UDP 不能隔離兩個網(wǎng)段。

③Vxlan:和上文提到的 udpbackend 的封包結(jié)構(gòu)是非常類似的,不同之處是多了一個 vxlanheader,以及原始報文中多了個二層的報頭。

當初始化集群里,Vxlan 網(wǎng)絡(luò)的初始化工作:主機 B 加入 Flannel 網(wǎng)絡(luò)時,它會將自己的三個信息寫入 etcd 中,分別是:Subnet10.1.16.0/24、Public IP 192.168.0.101、Vtep 設(shè)備 Flannel.1 的 Mac 地址 MAC B。

之后,主機 A 會得到 EventAdded 事件,并從中獲取上文中 B 添加至 etcd 的各種信息。

這個時候,它會在本機上添加三條信息:

  • 路由信息:所有通往目的地址 10.1.16.0/24 的封包都通過 Vtep 設(shè)備 Flannel.1 設(shè)備發(fā)出,發(fā)往的網(wǎng)關(guān)地址為 10.1.16.0,即主機 B 中的 Flannel.1 設(shè)備。
  • FDB 信息:MAC 地址為 MAC B 的封包,都將通過 Vxlan 發(fā)往目的地址 192.168.0.101,即主機 B。
  • ARP 信息:網(wǎng)關(guān)地址 10.1.16.0 的地址為 MAC B。

事實上,F(xiàn)lannel 只使用了 Vxlan 的部分功能,由于 VNI 被固定為 1,本質(zhì)上工作方式和 UDP Backend 是類似的,區(qū)別無非是將 UDP 的 Proxy 換成了內(nèi)核中的 Vxlan 處理模塊。

而原始負載由三層擴展到了二層,但是這對三層網(wǎng)絡(luò)方案 Flannel 是沒有意義的,這么做也僅僅只是為了適配 Vxlan 的模型。

存在問題

存在的問題如下:

  • 不支持 Pod 之間的網(wǎng)絡(luò)隔離。Flannel 設(shè)計思想是將所有的 Pod 都放在一個大的二層網(wǎng)絡(luò)中,所以 Pod 之間沒有隔離策略。
  • 設(shè)備復(fù)雜,效率不高。Flannel 模型下有三種設(shè)備,數(shù)量經(jīng)過多種設(shè)備的封裝、解析,勢必會造成傳輸效率的下降。

[[273330]]

Calico 網(wǎng)絡(luò)

Calico 簡介

Calico 是一種開源網(wǎng)絡(luò)和網(wǎng)絡(luò)安全解決方案,適用于容器,虛擬機和基于主機的本機工作負載。

Calico 支持廣泛的平臺,包括 Kubernetes,OpenShift,Docker EE,OpenStack 和裸機服務(wù)。

在虛擬化平臺中,比如 OpenStack、Docker 等都需要實現(xiàn) Workloads 之間互連,但同時也需要對容器做隔離控制,就像在 Internet 中的服務(wù)僅開放 80 端口、公有云的多租戶一樣,提供隔離和管控機制。

而在多數(shù)的虛擬化平臺實現(xiàn)中,通常都使用二層隔離技術(shù)來實現(xiàn)容器的網(wǎng)絡(luò),這些二層的技術(shù)有一些弊端,比如需要依賴 VLAN、Bridge 和隧道等技術(shù)。

其中 Bridge 帶來了復(fù)雜性,Vlan 隔離和 Tunnel 隧道則消耗更多的資源并對物理環(huán)境有要求,隨著網(wǎng)絡(luò)規(guī)模的增大,整體會變得越加復(fù)雜。

Calico 是一個純?nèi)龑拥姆桨?,把每個 Node 節(jié)點認為是一個路由器,然后把所有的容器認為是連在這個路由器上的網(wǎng)絡(luò)終端,在路由器之間跑標準的路由協(xié)議——BGP 的協(xié)議,然后讓它們自己去學(xué)習(xí)這個網(wǎng)絡(luò)拓撲該如何轉(zhuǎn)發(fā)。

Calico 為每個主機分配了一段子網(wǎng)作為容器可分配的 IP 范圍,這樣就可以根據(jù)子網(wǎng)的 CIDR 為每個主機生成比較固定的路由規(guī)則,Pod 發(fā)送另一個主機的流量能夠根據(jù)路由規(guī)則匹配而被轉(zhuǎn)發(fā)。

適用場景:集群規(guī)模較大,環(huán)境中的 Pod 之間需要隔離。

設(shè)計思想:Calico 不使用隧道或 NAT 來實現(xiàn)轉(zhuǎn)發(fā),而是巧妙的把所有二三層流量轉(zhuǎn)換成三層流量,并通過 Host 上路由配置完成跨 Host 轉(zhuǎn)發(fā)。

設(shè)計優(yōu)勢如下:

①更優(yōu)的資源利用:二層網(wǎng)絡(luò)通訊需要依賴廣播消息機制,廣播消息的開銷與 Host 的數(shù)量呈指數(shù)級增長,Calico 使用的三層路由方法,則完全抑制了二層廣播,減少了資源開銷。

另外,二層網(wǎng)絡(luò)使用 VLAN 隔離技術(shù),天生有 4096 個規(guī)格限制,即便可以使用 Vxlan 解決,但 Vxlan 又帶來了隧道開銷的新問題。而 Calico 不使用 Vlan 或 Vxlan 技術(shù),使資源利用率更高。

②可擴展性:Calico 使用與 Internet 類似的方案,Internet 的網(wǎng)絡(luò)比任何數(shù)據(jù)中心都大,Calico 同樣天然具有可擴展性。

③簡單而更容易 Debug:因為沒有隧道,意味著 Workloads 之間路徑更短更簡單,配置更少,在 Host 上更容易進行 Debug 調(diào)試。

④更少的依賴:Calico 僅依賴三層路由可達。

⑤可適配性:Calico 較少的依賴性使它能適配所有 VM、Container、白盒或者混合環(huán)境場景。

Calico 架構(gòu)原理

架構(gòu)圖如下:

Calico 網(wǎng)絡(luò)模型主要工作組件:

  • Felix:運行在每一臺 Host 的 Agent 進程,主要負責網(wǎng)絡(luò)接口管理和監(jiān)聽、路由、ARP 管理、ACL 管理和同步、狀態(tài)上報等。
  • etcd:分布式鍵值存儲,主要負責網(wǎng)絡(luò)元數(shù)據(jù)一致性,確保 Calico 網(wǎng)絡(luò)狀態(tài)的準確性,可以與 Kubernetes 共用。
  • BGP Client(BIRD):Calico 為每一臺 Host 部署一個 BGP Client,使用 BIRD 實現(xiàn),BIRD 是一個單獨的持續(xù)發(fā)展的項目,實現(xiàn)了眾多動態(tài)路由協(xié)議比如 BGP、OSPF、RIP 等。

在 Calico 的角色是監(jiān)聽 Host 上由 Felix 注入的路由信息,然后通過 BGP 協(xié)議廣播告訴剩余 Host 節(jié)點,從而實現(xiàn)網(wǎng)絡(luò)互通。

  • BGP Route Reflector(BIRD):在大型網(wǎng)絡(luò)規(guī)模中,如果僅僅使用 BGP Client 形成 Mesh 全網(wǎng)互聯(lián)的方案就會導(dǎo)致規(guī)模限制,因為所有節(jié)點之間倆倆互聯(lián),需要 N^2 個連接。

為了解決這個規(guī)模問題,可以采用 BGP 的 RouterReflector 的方法,使所有 BGPClient 僅與特定 RR 節(jié)點互聯(lián)并做路由同步,從而大大減少連接數(shù)。

Felix:會監(jiān)聽 ectd 中心的存儲,從它獲取事件,比如說用戶在這臺機器上加了一個 IP,或者是創(chuàng)建了一個容器等。

用戶創(chuàng)建 Pod 后,F(xiàn)elix 負責將其網(wǎng)卡、IP、MAC 都設(shè)置好,然后在內(nèi)核的路由表里面寫一條,注明這個 IP 應(yīng)該到這張網(wǎng)卡。

同樣如果用戶制定了隔離策略,F(xiàn)elix 同樣會將該策略創(chuàng)建到 ACL 中,以實現(xiàn)隔離。

BIRD:是一個標準的路由程序,它會從內(nèi)核里面獲取哪一些 IP 的路由發(fā)生了變化,然后通過標準 BGP 的路由協(xié)議擴散到整個其他的宿主機上,讓其他 Node 節(jié)點都知道這個 IP 在這里,生成路由條目就比較方便。

由于 Calico 是一種純?nèi)龑拥膶崿F(xiàn),因此可以避免與二層方案相關(guān)的數(shù)據(jù)包封裝的操作,中間沒有任何的 NAT,沒有任何的 Overlay。

所以它的轉(zhuǎn)發(fā)效率可能是所有方案中最高的,因為它的包直接走原生 TCP/IP 的協(xié)議棧,它的隔離也因為這個棧而變得好做。

因為 TCP/IP 的協(xié)議棧提供了一整套的防火墻的規(guī)則,所以它可以通過 IPTABLES 的規(guī)則達到比較復(fù)雜的隔離邏輯。

Calico 網(wǎng)絡(luò) Node 之間兩種網(wǎng)絡(luò)

IPIP:是把一個 IP 數(shù)據(jù)包放在在一個 IP 包里,即把 IP 層封裝到 IP 層的一個 Tunnel。

它的作用基本上就相當于一個基于 IP 的網(wǎng)橋!一般來說,普通的網(wǎng)橋是基于 Mac 的,根本不需 IP。

而 IPIP 則是通過兩端的路由做一個 Tunnel,把兩個本來不通的網(wǎng)絡(luò)通過點對點連接起來。

BGP:邊界網(wǎng)關(guān)協(xié)議(Border Gateway Protocol, BGP)是互聯(lián)網(wǎng)上一個核心的去中心化自治路由協(xié)議。

它通過維護 IP 路由表或‘前綴’表來實現(xiàn)自治系統(tǒng)(AS)之間的可達性,屬于矢量路由協(xié)議。

BGP 不使用傳統(tǒng)的內(nèi)部網(wǎng)關(guān)協(xié)議(IGP)的指標,而使用基于路徑、網(wǎng)絡(luò)策略或規(guī)則集來決定路由。

IPIP 工作模式

①測試環(huán)境

一個 Msater 節(jié)點,IP 172.171.5.95,一個 Node 節(jié)點 IP 172.171.5.96:

創(chuàng)建一個 Daemonset 的應(yīng)用,Pod1 落在 Master 節(jié)點上 IP 地址為 192.168.236.3,Pod2 落在 Node 節(jié)點上 IP 地址為 192.168.190.203:

Pod1 Ping Pod2:

②Ping 包旅程

Pod1 上的路由信息:

根據(jù)路由信息,Ping 192.168.190.203,會匹配到第一條。第一條路由的意思是:去往任何網(wǎng)段的數(shù)據(jù)包都發(fā)往網(wǎng)管 169.254.1.1,然后從 eth0 網(wǎng)卡發(fā)送出去。

路由表中 Flags 標志的含義:

  • U:UP 表示當前為啟動狀態(tài)。
  • H:Host 表示該路由為一個主機,多為達到數(shù)據(jù)包的路由。
  • G:Gateway 表示該路由是一個網(wǎng)關(guān),如果沒有說明目的地是直連的。
  • D:Dynamicaly 表示該路由是重定向報文修改。
  • M:表示該路由已被重定向報文修改。

Master 節(jié)點上的路由信息:

當 Ping 包來到 Master 節(jié)點上,會匹配到路由 tunl0。該路由的意思是:去往 192.169.190.192/26 的網(wǎng)段的數(shù)據(jù)包都發(fā)往網(wǎng)關(guān) 172.171.5.96。

因為 Pod1 在 5.95,Pod2 在 5.96。所以數(shù)據(jù)包就通過該路由發(fā)往到 Node 節(jié)點上。

Node 節(jié)點上路由信息:

當 Node 節(jié)點網(wǎng)卡收到數(shù)據(jù)包之后,發(fā)現(xiàn)發(fā)往的目的 IP 為 192.168.190.203,于是匹配到紅線的路由(綠線是 Node 結(jié)點對應(yīng)的發(fā)往 Master 的路由)。

該路由的意思是:192.168.190.203 是本機直連設(shè)備,去往設(shè)備的數(shù)據(jù)包發(fā)往 caliadce112d250。這個設(shè)備就是 Pod2 的 Veth Pair 的一端。

在創(chuàng)建 Pod2 時 Calico 會給 Pod2 創(chuàng)建一個 Veth Pair 設(shè)備。一端是 Pod2 的網(wǎng)卡,另一端就是我們看到的 caliadce112d250。

可以通過如下方式驗證:在 Pod2 中安裝 ethtool 工具,然后使用 ethtool-S eth0,查看 Veth Pair 另一端的設(shè)備號。

Pod2 網(wǎng)卡另一端的設(shè)備編號是 18,在 Node 上查看編號為 18 的網(wǎng)絡(luò)設(shè)備,可以發(fā)現(xiàn)該網(wǎng)絡(luò)設(shè)備就是 caliadce112d250。

所以,Node 上的路由,發(fā)送 caliadce112d250 的數(shù)據(jù)其實就是發(fā)送到 Pod2 的網(wǎng)卡中。Ping 包的旅行到這里就到了目的地。

查看一下 Pod2 中的路由信息,發(fā)現(xiàn)該路由信息和 Pod1 中是一樣的。

顧名思義,IPIP 網(wǎng)絡(luò)就是將 IP 網(wǎng)絡(luò)封裝在 IP 網(wǎng)絡(luò)里。IPIP 網(wǎng)絡(luò)的特點是所有 Pod 的數(shù)據(jù)流量都從隧道 tunl0 發(fā)送,并且在 tunl0 這增加了一層傳輸層的封包。

在 Master 網(wǎng)卡上抓包分析該過程:

打開 ICMP 285,Pod1 Ping Pod2 的數(shù)據(jù)包,能夠看到該數(shù)據(jù)包一共 5 層,其中 IP 所在的網(wǎng)絡(luò)層有兩個,分別是 Pod 之間的網(wǎng)絡(luò)和主機之間的網(wǎng)絡(luò)封裝。

根據(jù)數(shù)據(jù)包的封裝順序,應(yīng)該是在 Pod1 Ping Pod2 的 ICMP 包外面多封裝了一層主機之間的數(shù)據(jù)包。

之所以要這樣做是因為 tunl0 是一個隧道端點設(shè)備,在數(shù)據(jù)到達時要加上一層封裝,便于跨網(wǎng)段訪問。

兩層 IP 封裝的具體內(nèi)容:

IPIP 的連接方式:

BGP 工作模式

①修改配置

在安裝 Calico 網(wǎng)絡(luò)時,默認安裝是 IPIP 網(wǎng)絡(luò)。calico.yaml 文件中,將 CALICO_IPV4POOL_IPIP 的值修改成"off",就能夠替換成 BGP 網(wǎng)絡(luò)。

②對比

BGP 網(wǎng)絡(luò)相比較 IPIP 網(wǎng)絡(luò),最大的不同之處就是沒有了隧道設(shè)備 tunl0,且不通過隧道設(shè)備發(fā)送流量。

前面介紹過 IPIP 網(wǎng)絡(luò) Pod 之間的流量發(fā)送 tunl0,然后 tunl0 發(fā)送對端設(shè)備。BGP 網(wǎng)絡(luò)中,Pod 之間的流量直接從網(wǎng)卡發(fā)送目的地,減少了 tunl0 這個環(huán)境。

Master 節(jié)點上路由信息。從路由信息來看,沒有 tunl0 設(shè)備。

同樣創(chuàng)建一個 Daemonset,Pod1 在 Master 節(jié)點上,Pod2 在 Node 節(jié)點上。

③Ping 包旅程

Pod1 Ping Pod2:

根據(jù) Pod1 中的路由信息,Ping 包通過 eth0 網(wǎng)卡發(fā)送到 Master 節(jié)點上。

Master 節(jié)點上路由信息。根據(jù)匹配到的 192.168.190.192 路由,該路由的意思是:去往網(wǎng)段 192.168.190.192/26 的數(shù)據(jù)包,發(fā)送網(wǎng)段 172.171.5.96。

而 5.96 就是 Node 節(jié)點。所以,該數(shù)據(jù)包直接發(fā)送了 5.96 機器:

Node 節(jié)點上的路由信息。根據(jù)匹配到的 192.168.190.192 的路由,數(shù)據(jù)將發(fā)送給 cali6fcd7d1702e 設(shè)備,該設(shè)備和上面分析的是一樣,為 Pod2 的 Veth Pair 的一端。數(shù)據(jù)就直接發(fā)送給 Pod2 的網(wǎng)卡。

當 Pod2 對 Ping 包做出回應(yīng)之后,數(shù)據(jù)到達 Node 節(jié)點上,匹配到 192.168.236.0 的路由。

該路由說的是:去往網(wǎng)段 192.168.236.0/26 的數(shù)據(jù),發(fā)送給網(wǎng)關(guān) 172.171.5.95。數(shù)據(jù)包就直接通過網(wǎng)卡 ens160,發(fā)送到 Master 節(jié)點上。

通過在 Master 節(jié)點上抓包,查看經(jīng)過的流量,篩選出 ICMP,找到 Pod1 Ping Pod2 的數(shù)據(jù)包。

可以看到 BGP 網(wǎng)絡(luò)下,沒有使用 IPIP 模式,數(shù)據(jù)包是正常的封裝。

值得注意的是 Mac 地址的封裝。192.168.236.0 是 Pod1 的 IP,192.168.190.198 是 Pod2 的 IP。

而源 Mac 地址是 Master 節(jié)點網(wǎng)卡的 Mac,目的 Mac 是 Node 節(jié)點的網(wǎng)卡的 Mac。

這說明,在 Master 節(jié)點的路由接收到數(shù)據(jù),重新構(gòu)建數(shù)據(jù)包時,使用 ARP 請求,將 Node 節(jié)點的 Mac 拿到,然后封裝到數(shù)據(jù)鏈路層。

BGP 的連接方式如下圖:

網(wǎng)絡(luò)對比

IPIP 網(wǎng)絡(luò):

  • 流量:tunlo 設(shè)備封裝數(shù)據(jù),形成隧道,承載流量。
  • 適用網(wǎng)絡(luò)類型:適用于互相訪問的 Pod 不在同一個網(wǎng)段中,跨網(wǎng)段訪問的場景。外層封裝的 IP 能夠解決跨網(wǎng)段的路由問題。
  • 效率:流量需要 tunl0 設(shè)備封裝,效率略低。

BGP 網(wǎng)絡(luò):

  • 流量:使用路由信息導(dǎo)向流量。
  • 適用網(wǎng)絡(luò)類型:適用于互相訪問的 Pod 在同一個網(wǎng)段,跨網(wǎng)段需要上行交換機或路由器支持。適用于大型網(wǎng)絡(luò)。
  • 效率:原生 HostGW,效率高。

存在問題

①租戶隔離問題

Calico 的三層方案是直接在 Host 上進行路由尋址,那么對于多租戶如果使用同一個 CIDR 網(wǎng)絡(luò)就面臨著地址沖突的問題。

②路由規(guī)模問題

通過路由規(guī)則可以看出,路由規(guī)模和 Pod 分布有關(guān),如果 Pod 離散分布在 Host 集群中,勢必會產(chǎn)生較多的路由項。

③IPtables 規(guī)則規(guī)模問題

1 臺 Host 上可能虛擬化十幾或幾十個容器實例,過多的 IPtables 規(guī)則造成復(fù)雜性和不可調(diào)試性,同時也存在性能損耗。

④跨子網(wǎng)時的網(wǎng)關(guān)路由問題

當對端網(wǎng)絡(luò)不為二層可達時,需要通過三層路由時,需要網(wǎng)關(guān)支持自定義路由配置,即 Pod 的目的地址為本網(wǎng)段的網(wǎng)關(guān)地址,再由網(wǎng)關(guān)進行跨三層轉(zhuǎn)發(fā)。

K8S 網(wǎng)絡(luò)方案對比

以下對比為摘錄內(nèi)容:

http://www.sohu.com/a/256113338_764649

【51CTO原創(chuàng)稿件,合作站點轉(zhuǎn)載請注明原文作者和出處為51CTO.com】

 

責任編輯:武曉燕 來源: 51CTO技術(shù)棧
相關(guān)推薦

2012-04-13 10:11:58

Windows 8泄露

2011-07-21 21:01:37

諾基亞塞班蘋果

2013-06-03 09:28:49

游戲設(shè)計

2017-03-22 15:38:28

代碼架構(gòu)Java

2022-03-16 14:59:28

打包debian模板文件

2012-01-18 11:18:12

Web App

2023-12-05 08:33:44

滴滴故障k8s

2023-09-11 00:14:46

后端團隊項目

2021-08-20 11:35:04

服務(wù)運維 故障

2020-11-02 13:44:56

CentOSK8SLinux

2022-02-23 08:01:04

KubernetesK8sPod

2022-08-15 08:16:56

shiroWeb認證

2013-05-13 11:35:53

獨立開發(fā)開發(fā)經(jīng)驗開發(fā)感悟

2015-10-26 16:38:17

2021-02-05 08:35:21

私活程序員

2022-06-21 09:26:28

開源項目PR

2015-11-02 14:42:12

2013-02-25 09:43:22

LambdasJava8

2017-08-08 12:50:51

Serverless云端數(shù)據(jù)庫

2018-09-11 17:05:12

戴爾
點贊
收藏

51CTO技術(shù)棧公眾號