K8s 從懵圈到熟練 – 叢集網路詳解

大濤學長發表於2019-10-14
導讀:阿里雲 K8S 叢集網路目前有兩種方案:一種是 flannel 方案;另外一種是基於 calico 和彈性網路卡 eni 的 terway 方案。Terway 和 flannel 類似,不同的地方在於 terway 支援 Pod 彈性網路卡,以及 NetworkPolicy 功能。本文中,作者基於當前的 1.12.6 版本,以 flannel 為例,深入分析阿里雲 K8S 叢集網路的實現方法。

鳥瞰

總體上來說,阿里雲 K8S 叢集網路配置完成之後,如下圖所示:包括叢集 CIDR、VPC 路由表、節點網路、節點的 podCIDR、節點上的虛擬網橋 cni0、連線 Pod 和網橋的 veth 等部分。

K8s 從懵圈到熟練 – 叢集網路詳解

類似的圖大家可能在很多文章中都看過,但因為其中相關配置過於複雜,比較難理解。這裡我們可以看下這些配置背後的邏輯。
基本上我們可以把這些配置分三種情況來理解:叢集配置,節點配置以及 Pod 配置。與這三種情況對應的,其實是對叢集網路 IP 段的三次劃分:首先是叢集 CIDR,接著是為每個節點分配 podCIDR(即叢集 CIDR 的子網段),最後在 podCIDR 裡為每個 Pod 分配自己的 IP。

K8s 從懵圈到熟練 – 叢集網路詳解

叢集網路搭建

初始階段

叢集的建立,基於雲資源 VPC 和 ECS,在建立完 VPC 和 ECS 之後,我們基本上可以得到如下圖的資源配置。我們得到一個 VPC,這個 VPC 的網段是 192.168.0.0/16,我們得到若干 ECS,他們從 VPC 網段裡分配到 IP 地址。

K8s 從懵圈到熟練 – 叢集網路詳解

叢集階段

在以上出初始資源的基礎上,我們利用叢集建立控制檯得到叢集 CIDR。這個值會以引數的形式傳給叢集節點 provision 指令碼,並被指令碼傳給叢集節點配置工具 kubeadm。kubeadm 最後把這個引數寫入叢集控制器靜態 Pod 的 yaml 檔案 kube-controller-manager.yaml。

K8s 從懵圈到熟練 – 叢集網路詳解

叢集控制器有了這個引數,在節點 kubelet 註冊節點到叢集的時候,叢集控制器會為每個註冊節點,劃分一個子網出來,即為每個節點分配 podCIDR。如上圖,Node B 的子網是 172.16.8.1/25,而 Node A 的子網是 172.16.0.128/25。這個配置會記錄到叢集 node 的 podCIDR 資料項裡。

節點階段

經過以上叢集階段,K8S 有了叢集 CIDR,以及為每個節點劃分的 podCIDR。在此基礎上,叢集會下發 flanneld 到每個階段上,進一步搭建節點上,可以給 Pod 使用的網路框架。這裡主要有兩個操作:
  • 第一個是叢集透過 Cloud Controller Manager 給 VPC 配置路由表項。路由表項對每個節點有一條,每一條的意思是,如果 VPC 路由收到的目的地址是某一個節點 podCIDR 的 IP 地址,那麼路由會把這個網路包轉發到對應的 ECS 上;
  • 第二個是建立虛擬網橋 cni0 以及與 cni0 相關的路由。這些配置的作用是,從階段外部進來的網路包,如果目的 IP 是 podCIDR,則會被節點轉發到 cni0 虛擬區域網裡。
注意:實際實現上,cni0 的建立,是在第一個使用 Pod 網路的 Pod 被排程到節點上的時候,由下一節中 flannal cni 建立的,但是從邏輯上來說,cni0 屬於節點網路,不屬於 Pod 網路,所以在此描述。

K8s 從懵圈到熟練 – 叢集網路詳解

Pod 階段

在前邊的三個階段,叢集實際上已經為 Pod 之間搭建了網路通訊的幹道。這個時候,如果叢集把一個 Pod 排程到節點上,kubelet 會透過 flannel cni 為這個 Pod 本身建立網路名稱空間和 veth 裝置,然後,把其中一個 veth 裝置加入到 cni0 虛擬網橋裡,併為 Pod 內的 veth 裝置配置 IP 地址。這樣 Pod 就和網路通訊的幹道連線在了一起。 這裡需要強調的是,前一節的 flanneld 和這一節的 flannel cni 完全是兩個元件。flanneld 是一個 daemonset 下發到每個節點的 pod,它的作用是搭建網路(幹道),而 flannel cni 是節點建立的時候,透過 kubernetes-cni 這個 rpm 包安裝的 cni 外掛,其被 kubelet 呼叫,用來為具體的 pod 建立網路(分枝)。理解這兩者的區別,有助於我們理解 flanneld 和 flannel cni 相關的配置檔案的用途。比如 /run/flannel/subnet.env,是 flanneld 建立的,為 flannel cni 提供輸入的一個環境變數檔案;又比如 /etc/cni/net.d/10-flannel.conf,也是 flanneld pod(準確的說,是 pod 裡的指令碼 install-cni)從 pod 裡複製到節點目錄,給 flannel cni 使用的子網配置檔案。

K8s 從懵圈到熟練 – 叢集網路詳解

通訊

以上完成 Pod 網路環境搭建。基於以上的網路環境,Pod 可以完成四種通訊:本地通訊;同節點 Pod 通訊;跨節點 Pod 通訊;以及 Pod 和 Pod 網路之外的實體通訊。

K8s 從懵圈到熟練 – 叢集網路詳解

其中本地通訊,說的是 Pod 內部,不同容器之間的通訊。因為 Pod 內網容器之間共享一個網路協議棧,所以他們之間的通訊,可以透過 loopback 裝置完成。
同節點 Pod 之間的通訊,是 cni0 虛擬網橋內部的通訊,這相當於一個二層區域網內部裝置通訊。
跨節點 Pod 通訊略微複雜一點,但也很直觀,傳送端資料包,透過 cni0 網橋的閘道器,流轉到節點上,然後經過節點 eth0 傳送給 VPC 路由。這裡不會經過任何封包操作。當 VPC 路由收到資料包時,它透過查詢路由表,確認資料包目的地,並把資料包傳送給對應的 ECS 節點。而進去節點之後,因為 flanneld 在節點上建立了 cni0 的路由,所以資料包會被髮送到目的地的 cni0 區域網,再到目的地 Pod。
最後一種情況,Pod 與非 Pod 網路的實體通訊,需要經過節點上 iptables 規則做 SNAT,而此規則就是 flanneld 依據命令列 --ip-masq 選項做的配置。

總結

以上是阿里雲 K8S 叢集網路的搭建和通訊原理。我們主要透過網路搭建和通訊兩個角度去分析 K8S 叢集網路。其中網路搭建包括初始階段、叢集階段、節點階段以及 Pod 階段,這麼分類有助於我們理解這些複雜的配置。而理解了各個配置,叢集通訊原理就比較容易理解了。
本文作者:聲東 阿里雲售後技術專家
本文為雲棲社群原創內容,未經允許不得轉載。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69947441/viewspace-2659898/,如需轉載,請註明出處,否則將追究法律責任。

相關文章