CNI - Container Network Interface(容器網絡接口)
CNI(Container Network Interface)是CNCF旗下的一個項目,由一組用於配置Linux容器的網絡接口的規范和庫組成,同時還包含了一些插件。CNI僅關心容器創建時的網絡分配,和當容器被刪除時釋放網絡資源。通過此鏈接瀏覽該項目:https://github.com/containernetworking/cni。
Kubernetes源碼的vendor/github.com/containernetworking/cni/libcni
目錄中已經包含了CNI的代碼,也就是說kubernetes中已經內置了CNI。
接口定義
CNI的接口中包括以下幾個方法:
type CNI interface { AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error) DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error }
該接口只有四個方法,添加網絡、刪除網絡、添加網絡列表、刪除網絡列表。
設計考量
CNI設計的時候考慮了以下問題:
- 容器運行時必須在調用任何插件之前為容器創建一個新的網絡命名空間。
- 然后,運行時必須確定這個容器應屬於哪個網絡,並為每個網絡確定哪些插件必須被執行。
- 網絡配置采用JSON格式,可以很容易地存儲在文件中。網絡配置包括必填字段,如
name
和type
以及插件(類型)。網絡配置允許字段在調用之間改變值。為此,有一個可選的字段args
,必須包含不同的信息。 - 容器運行時必須按順序為每個網絡執行相應的插件,將容器添加到每個網絡中。
- 在完成容器生命周期后,運行時必須以相反的順序執行插件(相對於執行添加容器的順序)以將容器與網絡斷開連接。
- 容器運行時不能為同一容器調用並行操作,但可以為不同的容器調用並行操作。
- 容器運行時必須為容器訂閱ADD和DEL操作,這樣ADD后面總是跟着相應的DEL。 DEL可能跟着額外的DEL,但是,插件應該允許處理多個DEL(即插件DEL應該是冪等的)。
- 容器必須由ContainerID唯一標識。存儲狀態的插件應該使用(網絡名稱,容器ID)的主鍵來完成。
- 運行時不能調用同一個網絡名稱或容器ID執行兩次ADD(沒有相應的DEL)。換句話說,給定的容器ID必須只能添加到特定的網絡一次。
CNI插件
CNI插件必須實現一個可執行文件,這個文件可以被容器管理系統(例如rkt或Kubernetes)調用。
CNI插件負責將網絡接口插入容器網絡命名空間(例如,veth對的一端),並在主機上進行任何必要的改變(例如將veth的另一端連接到網橋)。然后將IP分配給接口,並通過調用適當的IPAM插件來設置與“IP地址管理”部分一致的路由。
參數
CNI插件必須支持以下操作:
將容器添加到網絡
參數:
- 版本。調用者正在使用的CNI規范(容器管理系統或調用插件)的版本。
- 容器ID 。由運行時分配的容器的唯一明文標識符。一定不能是空的。
- 網絡命名空間路徑。要添加的網絡名稱空間的路徑,即
/proc/[pid]/ns/net
或綁定掛載/鏈接。 - 網絡配置。描述容器可以加入的網絡的JSON文檔。架構如下所述。
- 額外的參數。這提供了一個替代機制,允許在每個容器上簡單配置CNI插件。
- 容器內接口的名稱。這是應該分配給容器(網絡命名空間)內創建的接口的名稱;因此它必須符合Linux接口名稱上的標准限制。
結果:
- 接口列表。根據插件的不同,這可以包括沙箱(例如容器或管理程序)接口名稱和/或主機接口名稱,每個接口的硬件地址以及接口所在的沙箱(如果有的話)的詳細信息。
- 分配給每個接口的IP配置。分配給沙箱和/或主機接口的IPv4和/或IPv6地址,網關和路由。
- DNS信息。包含nameserver、domain、search domain和option的DNS信息的字典。
從網絡中刪除容器
參數:
- 版本。調用者正在使用的CNI規范(容器管理系統或調用插件)的版本。
- 容器ID ,如上所述。
- 網絡命名空間路徑,如上定義。
- 網絡配置,如上所述。
- 額外的參數,如上所述。
- 上面定義的容器內的接口的名稱。
- 所有參數應與傳遞給相應的添加操作的參數相同。
- 刪除操作應釋放配置的網絡中提供的containerid擁有的所有資源。
報告版本
- 參數:無。
- 結果:插件支持的CNI規范版本信息。
{ “cniVersion”:“0.3.1”,//此輸出使用的CNI規范的版本 “supportedVersions”:[“0.1.0”,“0.2.0”,“0.3.0”,“0.3.1”] //此插件支持的CNI規范版本列表 }
CNI插件的詳細說明請參考:CNI SPEC。
IP分配
作為容器網絡管理的一部分,CNI插件需要為接口分配(並維護)IP地址,並安裝與該接口相關的所有必要路由。這給了CNI插件很大的靈活性,但也給它帶來了很大的負擔。眾多的CNI插件需要編寫相同的代碼來支持用戶需要的多種IP管理方案(例如dhcp、host-local)。
為了減輕負擔,使IP管理策略與CNI插件類型解耦,我們定義了IP地址管理插件(IPAM插件)。CNI插件的職責是在執行時恰當地調用IPAM插件。 IPAM插件必須確定接口IP/subnet,網關和路由,並將此信息返回到“主”插件來應用配置。 IPAM插件可以通過協議(例如dhcp)、存儲在本地文件系統上的數據、網絡配置文件的“ipam”部分或上述的組合來獲得信息。
IPAM插件
像CNI插件一樣,調用IPAM插件的可執行文件。可執行文件位於預定義的路徑列表中,通過CNI_PATH
指示給CNI插件。 IPAM插件必須接收所有傳入CNI插件的相同環境變量。就像CNI插件一樣,IPAM插件通過stdin接收網絡配置。
可用插件
Main:接口創建
- bridge:創建網橋,並添加主機和容器到該網橋
- ipvlan:在容器中添加一個ipvlan接口
- loopback:創建一個回環接口
- macvlan:創建一個新的MAC地址,將所有的流量轉發到容器
- ptp:創建veth對
- vlan:分配一個vlan設備
IPAM:IP地址分配
- dhcp:在主機上運行守護程序,代表容器發出DHCP請求
- host-local:維護分配IP的本地數據庫
Meta:其它插件
- flannel:根據flannel的配置文件創建接口
- tuning:調整現有接口的sysctl參數
- portmap:一個基於iptables的portmapping插件。將端口從主機的地址空間映射到容器。