天天看點

聊聊Kubernetes 基于flannel 的叢集網絡

在讨論Kubernetes網絡之前,讓我們先來看一下Docker網絡

一 docker的網絡模式

聊聊Kubernetes 基于flannel 的叢集網絡

安裝完docker的伺服器上使用 docker network ls指令列出網絡

聊聊Kubernetes 基于flannel 的叢集網絡

1) Host

我們在使用docker run建立Docker容器時,可以用 --net=host選項指定容器的網絡模式, 容器将不會獲得一個獨立的Network Namespace,而是和主控端共用一個Network Namespace。容器将不會虛拟出自己的網卡,配置自己的IP等,而是使用主控端的IP和端口,如下圖,将主控端的ip 172.20.128.0的位址和docker0網橋位址也展示出來。

聊聊Kubernetes 基于flannel 的叢集網絡

2) Bridge

預設情況,Docker使用bridge網絡模式, 此模式會為每一個容器配置設定Network Namespace、設定IP等,并将并将一個主機上的Docker容器連接配接到一個名稱為docker0的虛拟網橋上,如下圖所示:

聊聊Kubernetes 基于flannel 的叢集網絡

這樣主機上的所有容器就通過虛拟網橋裝置連在了一個二層網絡中,docker會從定義的網段(可自定義)配置設定一個ip給容器,如下圖為172.17.0.2,網關指向docker0的位址。

3) None

在none模式下,Docker容器擁有自己的Network Namespace,但是,并不為Docker容器進行任何網絡配置。也就是說,這個Docker容器沒有網卡、IP、路由等資訊。需要我們自己為Docker容器添加網卡、配置IP等。使用–net =none模式啟動容器:

聊聊Kubernetes 基于flannel 的叢集網絡

4) Container

這個模式指定新建立的容器和已經存在的一個容器共享一個Network Namespace,而不是和主控端共享。新建立的容器不會建立自己的網卡,配置自己的IP,而是和一個指定的容器共享IP、端口範圍等。同樣,兩個容器除了網絡方面,其他的如檔案系統、程序清單等還是隔離的。兩個容器的程序可以通過lo網卡裝置通信。使用–net =container模式啟動容器:

docker run -itd --name docker-bridge --network=bridge jl890314/centos:7.7

docker run -itd --name docker-container --network=container:07c7efbb26bf jl890314/centos:7.7

聊聊Kubernetes 基于flannel 的叢集網絡

二 k8s的網絡模式

Kubernetes與Docker網絡有些不同。Kubernetes網絡需要解決下面的4個問題:

叢集内:

容器與容器之間的通信

Pod和Pod之間的通信

Pod和服務之間的通信

叢集外:

外部應用與服務之間的通信

是以,Kubernetes假設Pod之間能夠進行通訊,這些Pod可能部署在不同的主控端上。每一個Pod都擁有自己的IP位址,是以能夠将Pod看作為實體主機或者虛拟機,進而能實作端口設定、命名、服務發現、負載均衡、應用配置和遷移。為了滿足上述需求,則需要通過叢集網絡來實作。

在本文主要分析容器與容器之間,以及Pod和Pod之間的通信;Pod和服務之間,以及外部應用與服務之間的通信請參考Kubernetes的Service和Ingress。

1) 同一個pod中容器之間的通訊

這種場景對于Kubernetes來說沒有任何問題,根據Kubernetes的架構設計。Kubernetes建立Pod時,首先會建立一個pause容器,為Pod指派一個唯一的IP位址。然後,以pause的網絡命名空間為基礎,建立同一個Pod内的其它容器(--net=container:xxx)。是以,同一個Pod内的所有容器就會共享同一個網絡命名空間,在同一個Pod之間的容器可以直接使用localhost進行通信

2) 不同pod中容器之間的通訊

對于此場景,情況現對比較複雜一些,這就需要解決Pod間的通信問題。在Kubernetes通過flannel、calic等網絡插件解決Pod間的通信問題。 本文以flannel為例說明在Kubernetes中網絡模型,flannel是kubernetes預設提供網絡插件,規定主控端下各個Pod屬于同一個子網,不同主控端下的Pod屬于不同的子網。為了跟蹤各個子網的配置設定情況,flannel使用etcd來存儲虛拟IP和主機IP之間的映射,各個節點上運作的flanneld守護程序負責監視etcd中的資訊并完成封包路由

flannel在每個Node上啟動了一個flanneld的服務,在flanneld啟動後,将從etcd中讀取配置資訊,并請求擷取子網的租約。所有Node上的flanneld都依賴etcd cluster來做集中配置服務,etcd保證了所有node上flanned所看到的配置是一緻的。同時每個node上的flanned監聽etcd上的資料變化,實時感覺叢集中node的變化。flanneld一旦擷取子網租約、配置後端後,會将一些資訊寫入/run/flannel/subnet.env檔案,如下圖的兩個不同的node節點上的資訊,

聊聊Kubernetes 基于flannel 的叢集網絡
聊聊Kubernetes 基于flannel 的叢集網絡

三 flannel的資料傳輸過程

1) 源容器向目标容器發送資料,資料首先發送給docker0網橋.

2) docker0網橋接受到資料後,将其轉交給flannel.1虛拟網卡處理

3) flannel.1接受到資料後,對資料進行封裝,并發給主控端的eth0

flannel.1收到資料後,flannelid會将資料包封裝成二層以太包。

Ethernet Header的資訊:

From:{源容器flannel.1虛拟網卡的MAC位址}

To:{目标容器flannel.1虛拟網卡的MAC位址}

4) 對在flannel路由節點封裝後的資料,進行再封裝後,轉發給目标容器Node的eth0

由于目前的資料包隻是vxlan tunnel上的資料包,是以還不能在實體網絡上進行傳輸。是以,需要将上述資料包再次進行封裝,才能源容器節點傳輸到目标容器節點,這項工作在由linux核心來完成。

Ethernet Header的資訊:

From:{源容器Node節點網卡的MAC位址}

To:{目錄容器Node節點網卡的MAC位址}

IP Header的資訊:

From:{源容器Node節點網卡的IP位址}

To:{目錄容器Node節點網卡的IP位址}

通過此次封裝,就可以通過實體網絡發送資料包。

在目标容器主控端中的資料傳遞過程:

5) 目标容器主控端的eth0接收到資料後,對資料包進行拆封,并轉發給flannel.1虛拟網卡;

6) flannel.1 虛拟網卡接受到資料,将資料發送給docker0網橋;

7) 最後,資料到達目标容器,完成容器之間的資料通信。

四 flannel網絡的幾種模式

1 VxLAN:

Linux核心自3.7.0版本起支援VxLAN, flannel的此種後端意味着使用核心中的VxLAN子產品封裝封包,這也是flannel較為推薦使用的方式 VxLAN,全稱Virtual extensible Local Area Network(虛拟可擴充區域網路),是VLAN擴充方案草案,采用的是MAC in UDP封裝方式,是NVo3(Network Virtualization over Layer3)中的一種網絡虛拟化技術,如圖所示。具體實作方式為:将虛拟網絡的資料幀添加到VxLAN首部後,封裝在實體網絡的UDP封包中,然後以傳統網絡的通信方式傳送該UDP封包,待其到達目的主機後,去掉實體網絡封包的頭部資訊以及VxLAN首部,然後将封包傳遞給目的終端,如圖所示的拓撲結構中,跨節點的Pod間通信即為如此。不過,整個過程中通信雙方對實體網絡無所感覺

聊聊Kubernetes 基于flannel 的叢集網絡

2 host-gw:

Host GateWay,它通過在節點上建立到達目标容器位址的路由直接完成封包轉發,是以這種方式要求各節點本身必須在同一個二層網絡中,故該方式不太适用于較大的網絡規模(大二層網絡除外)。host-gw有着較好的轉發性能,且易于設定,推薦對封包轉發性能要求較高的場景使用

host-gw後端通過添加必要的路由資訊使用節點的二層網絡直接發送Pod的通信封包,其工作方式類似于VxLAN後端中direct routing的功能,但不包括其VxLAN的隧道轉發能力。其工作模型示意圖如圖所示。

聊聊Kubernetes 基于flannel 的叢集網絡

3 UDP:

使用普通UDP封包封裝完成隧道轉發,其性能較前兩種方式要低很多,僅應該在不支援前兩種方式的環境中使用。