Kubernetes 中的 pod 如何獲取 IP 地址

筆記。 翻譯。:這篇文章由 LinkedIn 的 SRE 工程師撰寫,詳細介紹了 Kubernetes 的內在魔力 - 更準確地說,是 CRI、CNI 和 kube-apiserver 的交互 - 當下一個 pod 需要分配 IP 位址時會發生這種交互。

基本要求之一 Kubernetes 網路模型 每個 Pod 必須有自己的 IP 位址,並且叢集中的任何其他 Pod 都必須能夠透過該位址聯繫它。 有許多網路「提供者」(Flannel、Calico、Canal 等)可以幫助實現這種網路模型。

當我第一次開始使用 Kubernetes 時,我並不完全清楚 Pod 到底是如何取得其 IP 位址的。 即使了解各個組件的工作原理,也很難想像它們協同工作。 例如,我知道 CNI 插件的用途,但我不知道它們到底是如何被呼叫的。 因此,我決定寫這篇文章來分享有關各種網路元件以及它們如何在 Kubernetes 叢集中協同工作的知識,這允許每個 pod 獲得自己唯一的 IP 位址。

在 Kubernetes 中組織網路有不同的方法,就像容器有不同的執行時間選項一樣。 本出版品將使用 絨布 在叢集中組織網路並作為可執行環境 - 貨櫃。 我還假設您知道容器之間的網路是如何運作的,因此我將簡要介紹它,僅供參考。

一些基本概念

容器與網路:簡要概述

網路上有許多優秀的出版品解釋容器如何透過網路相互溝通。 因此,我只會對基本概念進行一般性概述,並且僅限於一種方法,即建立 Linux 橋接器和封裝套件。 詳細資訊被省略,因為容器網路主題本身值得單獨撰寫一篇文章。 以下將提供一些特別有洞察力和教育性出版物的連結。

一台主機上的容器

在同一主機上運行的容器之間透過 IP 位址組織通訊的一種方法是建立 Linux 橋接器。 為此,在 Kubernetes(和 Docker)中建立虛擬設備 veth(虛擬乙太網路)。 veth 裝置的一端連接到容器的網路命名空間,另一端連接到 Linux橋 在主機網路上。

同一台主機上的所有容器都有 veth 的一端連接到網橋,透過網橋它們可以透過 IP 位址相互通訊。 Linux 橋接器還有一個 IP 位址,並充當從 pod 發送到其他節點的出口流量的閘道。

Kubernetes 中的 pod 如何獲取 IP 地址

不同主機上的容器

封包封裝是一種允許不同節點上的容器使用 IP 位址相互通訊的方法。 在 Flannel,科技為這個機會負責。 虛擬區域網,它將原始資料包「打包」成UDP資料包,然後將其發送到目的地。

在 Kubernetes 叢集中,Flannel 會建立一個 vxlan 設備並相應地更新每個節點上的路由表。 每個發送到不同主機上的容器的封包都會經過 vxlan 設備並封裝在 UDP 封包中。 在目的地,嵌套資料包被提取並轉發到所需的 Pod。

Kubernetes 中的 pod 如何獲取 IP 地址
注意:這只是組織容器之間網路通訊的一種方法。

什麼是 CRI?

CRI(容器運行時介面) 是一個允許 kubelet 使用不同容器執行時間環境的插件。 CRI API 內建於各種執行時間中,因此使用者可以選擇自己喜歡的執行時間。

什麼是CNI?

CNI項目 它代表 規格 為 Linux 容器組織通用網路解決方案。 此外,它還包括 插件,負責設定 Pod 網路時的各種功能。 CNI插件是一個符合規範的可執行檔(我們將在下面討論一些插件)。

為節點指派子網,以便為 Pod 指派 IP 位址

由於叢集中的每個 Pod 都必須有一個 IP 位址,因此確保該位址的唯一性非常重要。 這是透過為每個節點分配一個唯一的子網路來實現的,然後從該子網路為該節點上的 Pod 分配 IP 位址。

節點 IPAM 控制器

何時 nodeipam 作為標誌參數傳遞 --controllers kube 控制器管理器,它從叢集 CIDR(即叢集網路的 IP 位址範圍)中為每個節點分配一個單獨的子網路 (podCIDR)。 由於這些 podCIDR 不重疊,因此可以為每個 pod 指派唯一的 IP 位址。

Kubernetes 節點最初在叢集中註冊時會被指派一個 podCIDR。 若要變更節點的 podCIDR,您需要取消註冊它們,然後重新註冊它們,其間對 Kubernetes 控制層配置進行適當的變更。 您可以使用以下命令顯示節點的 podCIDR:

$ kubectl get no <nodeName> -o json | jq '.spec.podCIDR'
10.244.0.0/24

Kubelet、容器運行時和 CNI 插件:它是如何運作的

為每個節點調度一個 Pod 涉及許多準備步驟。 在本節中,我將只關注與設定 Pod 網路直接相關的內容。

將 pod 調度到某個節點會觸發以下事件鏈:

Kubernetes 中的 pod 如何獲取 IP 地址

說明: Containerd CRI 外掛的架構.

容器運行時和 CNI 插件之間的交互

每個網路供應商都有自己的 CNI 插件。 容器的運行時運行它來在 pod 啟動時配置網路。 以containerd為例,CNI插件是由插件啟動的 容器 CRI.

此外,每個提供者都有自己的代理商。 它安裝在所有 Kubernetes 節點上,負責 pod 的網路設定。 該代理程式要么包含在 CNI 配置中,要么在節點上獨立建立。 此配置幫助 CRI 插件設定要呼叫的 CNI 插件。

CNI配置的位置可以自訂; 預設情況下它位於 /etc/cni/net.d/<config-file>。 叢集管理員也負責在每個叢集節點上安裝 CNI 插件。 它們的位置也是可客製化的; 預設目錄 - /opt/cni/bin.

使用containerd時,可以在 部分中設定插件配置和二進位檔案的路徑 [plugins.«io.containerd.grpc.v1.cri».cni] в 容器設定檔.

由於我們使用 Flannel 作為我們的網路供應商,我們來談談如何設定它:

  • Flanneld(Flannel 的守護程序)通常會以 DaemonSet 安裝在叢集中 install-cni 作為一個 初始化容器.
  • Install-cni 創造 CNI設定檔 (/etc/cni/net.d/10-flannel.conflist)在每個節點上。
  • Flaneld 建立一個 vxlan 設備,從 API 伺服器擷取網路元數據,並監控 pod 更新。 創建它們時,它將路由分發到整個叢集中的所有 Pod。
  • 這些路由允許 Pod 透過 IP 位址相互通訊。

有關 Flannel 工作的更多詳細信息,我建議使用文章末尾的連結。

下面是 Containerd CRI 外掛和 CNI 外掛之間的互動圖:

Kubernetes 中的 pod 如何獲取 IP 地址

如上所示,kubelet 呼叫 Containerd CRI 外掛程式來建立 pod,然後呼叫 CNI 外掛程式來設定 pod 的網路。 在此過程中,網路提供者的 CNI 插件會呼叫其他核心 CNI 插件來配置網路的各個方面。

CNI插件之間的交互

有各種 CNI 插件,其作用是幫助在主機上的容器之間建立網路通訊。 本文將討論其中的三個。

CNI 插件 Flannel

當使用 Flannel 作為網路提供者時,Containerd CRI 元件會呼叫 CNI 插件 Flannel使用 CNI 設定檔 /etc/cni/net.d/10-flannel.conflist.

$ cat /etc/cni/net.d/10-flannel.conflist
{
  "name": "cni0",
  "plugins": [
    {
      "type": "flannel",
      "delegate": {
         "ipMasq": false,
        "hairpinMode": true,
        "isDefaultGateway": true
      }
    }
  ]
}

Flannel CNI 外掛可與 Flanneld 搭配使用。 在啟動過程中,Flanneld 從 API 伺服器檢索 podCIDR 和其他與網路相關的詳細信息,並將它們保存到文件中 /run/flannel/subnet.env.

FLANNEL_NETWORK=10.244.0.0/16 
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450 
FLANNEL_IPMASQ=false

Flannel CNI 外掛程式使用來自 /run/flannel/subnet.env 配置和呼叫 CNI 橋接插件。

CNI 插件橋

使用以下配置呼叫該插件:

{
  "name": "cni0",
  "type": "bridge",
  "mtu": 1450,
  "ipMasq": false,
  "isGateway": true,
  "ipam": {
    "type": "host-local",
    "subnet": "10.244.0.0/24"
  }
}

第一次呼叫時,它會建立一個 Linux 橋 «name»: «cni0»,這在配置中指出。 然後為每個 pod 建立一個 veth 對。 它的一端連接到容器的網路命名空間,另一端包含在主機網路上的 Linux 橋中。 CNI 插件橋 將所有主機容器連接到主機網路上的 Linux 橋接器。

完成 veth 對的設定後,Bridge 插件將呼叫主機本地 IPAM CNI 插件。 IPAM 插件類型可以在 CRI 插件用來呼叫 Flannel CNI 插件的 CNI 配置中進行設定。

主機本機 IPAM CNI 插件

橋接 CNI 呼叫 主機本機 IPAM 外掛程式 CNI 具有以下配置:

{
  "name": "cni0",
  "ipam": {
    "type": "host-local",
    "subnet": "10.244.0.0/24",
    "dataDir": "/var/lib/cni/networks"
  }
}

主機本機 IPAM 插件 (IP A地址的 M管理 - IP 位址管理) 從子網路傳回容器的 IP 位址,並將主機上指派的 IP 儲存在本節中指定的目錄中 dataDir - /var/lib/cni/networks/<network-name=cni0>/<ip>。 此檔案包含指派此 IP 位址的容器的 ID。

當呼叫主機本機IPAM插件時,它會傳回下列資料:

{
  "ip4": {
    "ip": "10.244.4.2",
    "gateway": "10.244.4.3"
  },
  "dns": {}
}

總結

Kube-controller-manager為每個節點分配一個podCIDR。 每個節點的 Pod 從指派的 podCIDR 範圍內的位址空間接收 IP 位址。 由於節點的 podCIDR 不重疊,因此所有 pod 都會收到唯一的 IP 位址。

Kubernetes 叢集管理員配置並安裝 kubelet、容器執行時間、網路供應商代理,並將 CNI 外掛程式複製到每個節點。 在啟動期間,網路提供者代理程式會產生 CNI 配置。 當 pod 被調度到節點時,kubelet 會呼叫 CRI 插件來建立它。 接下來,如果使用containerd,Containerd CRI插件會呼叫CNI配置中指定的CNI插件來設定pod的網路。 結果,Pod 收到一個 IP 位址。

我花了一些時間才理解所有這些互動的所有微妙之處和細微差別。 我希望這次經驗能幫助您更能理解 Kubernetes 的工作原理。 如果我有任何錯誤,請與我聯繫 Twitter 或在地址 [電子郵件保護]。 如果您想討論本文的某些方面或其他任何內容,請隨時與我們聯繫。 我很想跟你聊天!

引用

容器和網路

法蘭絨的工作原理是什麼?

CRI 和 CNI

譯者PS

另請閱讀我們的博客:

來源: www.habr.com

添加評論