docker的網絡-Container network interface(CNI)與Container network model(CNM)


Overview

目前圍繞着docker的網絡,目前有兩種比較主流的聲音,docker主導的Container network model(CNM)和社區主導的Container network interface(CNI)。本文就針對兩者模型進行分別介紹。

Container Networking Interface

概述

Container Networking Interface(CNI)提供了一種linux的應用容器的插件化網絡解決方案。最初是由rkt Networking Proposal發展而來。也就是說,CNI本身並不完全針對docker的容器,而是提供一種普適的容器網絡解決方案。因此他的模型只涉及兩個概念:

  • 容器(container) : 容器是擁有獨立linux網絡命名空間的獨立單元。比如rkt/docker創建出來的容器。

這里很關鍵的是容器需要擁有自己的linux網絡命名空間。這也是加入網絡的必要條件。

  • 網絡(network): 網絡指代了可以相互聯系的一組實體。這些實體擁有各自獨立唯一的ip。這些實體可以是容器,是物理機,或者其他網絡設備(比如路由器)等。

接口及實現

CNI的接口設計的非常簡潔,只有兩個接口ADD/DELETE。

以 ADD接口為例

Add container to network

參數主要包括:

  • Version. CNI版本號
  • Container ID. 這是一個可選的參數,提供容器的id
  • Network namespace path. 容器的命名空間的路徑,比如 /proc/[pid]/ns/net。
  • Network configuration. 這是一個json的文檔,具體可以參看network-configuration
  • Extra arguments. 其他參數
  • Name of the interface inside the container. 容器內的網卡名

返回值:

  • IPs assigned to the interface. ipv4或者ipv6地址
  • DNS information. DNS相關信息

調用實現

CNI的調用方式是通過一個可執行文件進行的。這里以calico為例,說明CNI插件的調用方式。

首先,calico進行插件注冊

mkdir -p /etc/cni/net.d
$ cat >/etc/cni/net.d/10-calico.conf <<EOF
{
    "name": "calico-k8s-network",
    "type": "calico",
    "etcd_authority": "<ETCD_IP>:<ETCD_PORT>",
    "log_level": "info",
    "ipam": {
        "type": "calico-ipam"
    },
    "policy": {
        "type": "k8s"
    }
}
EOF

k8s的DefaultCNIDir/opt/cni/bin。因為注冊的typecalico,所以k8s會從/opt/cni/bin中搜索一個calico的可執行文件,然后進行執行。

執行的時候傳遞參數有兩種方式,一種是通過環境變量進行傳遞,比如上文中的VersionContainer ID等;另外一種是通過執行calico作為執行的參數傳進去,這個主要就是Network configuration的部分,通過json將其打包傳入。

同樣判斷是否執行成功,是通過執行文件的返回值獲取的。0為成功,1為版本版本不匹配,2為存在不符合的字段。如果執行成功,返回值將通過stdout返回。

Container Network Model

概述

相較於CNI,CNM是docker公司力推的網絡模型。其主要模型如下圖:

docker network

Sandbox

Sandbox包含了一個容器的網絡棧。包括了管理容器的網卡,路由表以及DNS設置。一種Sandbox的實現是通過linux的網絡命名空間,一個FreeBSD Jail 或者其他類似的概念。一個Sandbox可以包含多個endpoints。

Endpoint

一個endpoint將Sandbox連接到network上。一個endpoint的實現可以通過veth pair,Open vSwitch internal port 或者其他的方式。一個endpoint只能屬於一個network,也只能屬於一個sandbox。

Network

一個network是一組可以相互通信的endpoints組成。一個network的實現可以是linux bridge,vlan或者其他方式。一個網絡中可以包含很多個endpoints。

接口

CNM的接口相較於CNI模型,較為復雜。其提供了remote plugin的方式,進行插件化開發。remote plugin相較與CNI的命令行,更加友好一些,是通過http請求進行的。remote plugin監聽一個指定的端口,docker daemon直接通過這個端口與remote plugin進行交互。

鑒於CNM的接口較多,這里就不一一展開解釋了。這里主要介紹下在進行docker的操作中,docker daemon是如何同CNM插件繁盛交互。

調用過程

Create Network

這一系列調用發生在使用docker network create的過程中。

  1. /IpamDriver.RequestPool: 創建subnetpool用於分配IP
  2. /IpamDriver.RequestAddress: 為gateway獲取IP
  3. /NetworkDriver.CreateNetwork: 創建neutron network和subnet

Create Container

這一系列調用發生在使用docker run,創建一個contain的過程中。當然,也可以通過docker network connect觸發。

  1. /IpamDriver.RequestAddress: 為容器獲取IP
  2. /NetworkDriver.CreateEndpoint: 創建neutron port
  3. /NetworkDriver.Join: 為容器和port綁定
  4. /NetworkDriver.ProgramExternalConnectivity:
  5. /NetworkDriver.EndpointOperInfo

Delete Container

這一系列調用發生在使用docker delete,刪除一個contain的過程中。當然,也可以通過docker network disconnect觸發。

  1. /NetworkDriver.RevokeExternalConnectivity
  2. /NetworkDriver.Leave: 容器和port解綁
  3. /NetworkDriver.DeleteEndpoint
  4. /IpamDriver.ReleaseAddress: 刪除port並釋放IP

Delete Network

這一系列調用發生在使用docker network delete的過程中。

  1. /NetworkDriver.DeleteNetwork: 刪除network
  2. /IpamDriver.ReleaseAddress: 釋放gateway的IP
  3. /IpamDriver.ReleasePool: 刪除subnetpool

CNI與CNM的轉化

CNI和CNM並非是完全不可調和的兩個模型。二者可以進行轉化。比如calico項目就是直接支持兩種接口模型。

從模型中來看,CNI中的container應與CNM的sandbox概念一致,CNI中的network與CNM中的network一致。在CNI中,CNM中的endpoint被隱含在了ADD/DELETE的操作中。CNI接口更加簡潔,把更多的工作托管給了容器的管理者和網絡的管理者。從這個角度來說,CNI的ADD/DELETE接口其實只是實現了docker network connectdocker network disconnect兩個命令。

kubernetes/contrib項目提供了一種從CNI向CNM轉化的過程。其中原理很簡單,就是直接通過shell腳本執行了docker network connectdocker network disconnect命令,來實現從CNI到CNM的轉化。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM