CNI:容器网络接口详解
CNI 簡介
不管是 docker 還是 kubernetes,在網(wǎng)絡(luò)方面目前都沒有一個(gè)完美的、終極的、普適性的解決方案,不同的用戶和企業(yè)因?yàn)楦鞣N原因會(huì)使用不同的網(wǎng)絡(luò)方案。目前存在網(wǎng)絡(luò)方案 flannel、calico、openvswitch、weave、ipvlan等,而且以后一定會(huì)有其他的網(wǎng)絡(luò)方案,這些方案接口和使用方法都不相同,而不同的容器平臺(tái)都需要網(wǎng)絡(luò)功能,它們之間的適配如果沒有統(tǒng)一的標(biāo)準(zhǔn),會(huì)有很大的工作量和重復(fù)勞動(dòng)。
CNI 就是這樣一個(gè)標(biāo)準(zhǔn),它旨在為容器平臺(tái)提供網(wǎng)絡(luò)的標(biāo)準(zhǔn)化。不同的容器平臺(tái)(比如目前的 kubernetes、mesos 和 rkt)能夠通過相同的接口調(diào)用不同的網(wǎng)絡(luò)組件。
CNI(Conteinre Network Interface) 是 google 和 CoreOS 主導(dǎo)制定的容器網(wǎng)絡(luò)標(biāo)準(zhǔn),它 本身并不是實(shí)現(xiàn)或者代碼,可以理解成一個(gè)協(xié)議。這個(gè)標(biāo)準(zhǔn)是在?rkt 網(wǎng)絡(luò)提議?的基礎(chǔ)上發(fā)展起來的,綜合考慮了靈活性、擴(kuò)展性、ip 分配、多網(wǎng)卡等因素。
這個(gè)協(xié)議連接了兩個(gè)組件:容器管理系統(tǒng)和網(wǎng)絡(luò)插件。它們之間通過 JSON 格式的文件進(jìn)行通信,實(shí)現(xiàn)容器的網(wǎng)絡(luò)功能。具體的事情都是插件來實(shí)現(xiàn)的,包括:創(chuàng)建容器網(wǎng)絡(luò)空間(network namespace)、把網(wǎng)絡(luò)接口(interface)放到對(duì)應(yīng)的網(wǎng)絡(luò)空間、給網(wǎng)絡(luò)接口分配 IP 等等。
關(guān)于網(wǎng)絡(luò),docker 也提出了 CNM 標(biāo)準(zhǔn),它要解決的問題和 CNI 是重合的,也就是說目前兩者是競爭關(guān)系。目前 CNM 只能使用在 docker 中,而 CNI 可以使用在任何容器運(yùn)行時(shí)。CNM 主要用來實(shí)現(xiàn) docker 自身的網(wǎng)絡(luò)問題,也就是?docker network?子命令提供的功能。
官方網(wǎng)絡(luò)插件
所有的標(biāo)準(zhǔn)和協(xié)議都要有具體的實(shí)現(xiàn),才能夠被大家使用。CNI 也不例外,目前官方在 github 上維護(hù)了同名的?CNI?代碼庫,里面已經(jīng)有很多可以直接拿來使用的 CNI 插件。
官方提供的插件目前分成三類:main、meta 和 ipam。main 是主要的實(shí)現(xiàn)了某種特定網(wǎng)絡(luò)功能的插件;meta 本身并不會(huì)提供具體的網(wǎng)絡(luò)功能,它會(huì)調(diào)用其他插件,或者單純是為了測試;ipam 是分配 IP 地址的插件。
ipam 并不提供某種網(wǎng)絡(luò)功能,只是為了靈活性把它單獨(dú)抽象出來,這樣不同的網(wǎng)絡(luò)插件可以根據(jù)需求選擇 ipam,或者實(shí)現(xiàn)自己的 ipam。
這些插件的功能說明如下:
- main
- loopback:這個(gè)插件很簡單,負(fù)責(zé)生成?lo?網(wǎng)卡,并配置上?127.0.0.1/8?地址
- bridge:和 docker 默認(rèn)的網(wǎng)絡(luò)模型很像,把所有的容器連接到虛擬交換機(jī)上
- macvlan:使用 macvlan 技術(shù),從某個(gè)物理網(wǎng)卡虛擬出多個(gè)虛擬網(wǎng)卡,它們有獨(dú)立的 ip 和 mac 地址
- ipvlan:和 macvlan 類似,區(qū)別是虛擬網(wǎng)卡有著相同的 mac 地址
- ptp:通過 veth pair 在容器和主機(jī)之間建立通道
- meta
- flannel:結(jié)合 bridge 插件使用,根據(jù) flannel 分配的網(wǎng)段信息,調(diào)用 bridge 插件,保證多主機(jī)情況下容器
- ipam
- host-local:基于本地文件的 ip 分配和管理,把分配的 IP 地址保存在文件中
- dhcp:從已經(jīng)運(yùn)行的 DHCP 服務(wù)器中獲取 ip 地址
接口參數(shù)
網(wǎng)絡(luò)插件是獨(dú)立的可執(zhí)行文件,被上層的容器管理平臺(tái)調(diào)用。網(wǎng)絡(luò)插件只有兩件事情要做:把容器加入到網(wǎng)絡(luò)以及把容器從網(wǎng)絡(luò)中刪除。調(diào)用插件的數(shù)據(jù)通過兩種方式傳遞:環(huán)境變量和標(biāo)準(zhǔn)輸入。一般插件需要三種類型的數(shù)據(jù):容器相關(guān)的信息,比如 ns 的文件、容器 id 等;網(wǎng)絡(luò)配置的信息,包括網(wǎng)段、網(wǎng)關(guān)、DNS 以及插件額外的信息等;還有就是 CNI 本身的信息,比如 CNI 插件的位置、添加網(wǎng)絡(luò)還是刪除網(wǎng)絡(luò)。
我們來看一下為容器添加網(wǎng)絡(luò)是怎么工作的,刪除網(wǎng)絡(luò)和它過程一樣。
把容器加入到網(wǎng)絡(luò)
調(diào)用插件的時(shí)候,這些參數(shù)會(huì)通過環(huán)境變量進(jìn)行傳遞:
- CNI_COMMAND:要執(zhí)行的操作,可以是?ADD(把容器加入到某個(gè)網(wǎng)絡(luò))、DEL(把容器從某個(gè)網(wǎng)絡(luò)中刪除)
- CNI_CONTAINERID:容器的 ID,比如 ipam 會(huì)把容器 ID 和分配的 IP 地址保存下來。可選的參數(shù),但是推薦傳遞過去。需要保證在管理平臺(tái)上是唯一的,如果容器被刪除后可以循環(huán)使用
- CNI_NETNS:容器的 network namespace 文件,訪問這個(gè)文件可以在容器的網(wǎng)絡(luò) namespace 中操作
- CNI_IFNAME:要配置的 interface 名字,比如?eth0
- CNI_ARGS:額外的參數(shù),是由分號(hào);分割的鍵值對(duì),比如 “FOO=BAR;hello=world”
- CNI_PATH:CNI 二進(jìn)制查找的路徑列表,多個(gè)路徑用分隔符?:?分隔
網(wǎng)絡(luò)信息主要通過標(biāo)準(zhǔn)輸入,作為 JSON 字符串傳遞給插件,必須的參數(shù)包括:
- cniVersion:CNI 標(biāo)準(zhǔn)的版本號(hào)。因?yàn)?CNI 在演化過程中,不同的版本有不同的要求
- name:網(wǎng)絡(luò)的名字,在集群中應(yīng)該保持唯一
- type:網(wǎng)絡(luò)插件的類型,也就是 CNI 可執(zhí)行文件的名稱
- args:額外的信息,類型為字典
- ipMasq:是否在主機(jī)上為該網(wǎng)絡(luò)配置 IP masquerade
- ipam:IP 分配相關(guān)的信息,類型為字典
- dns:DNS 相關(guān)的信息,類型為字典
插件接到這些數(shù)據(jù),從輸入和環(huán)境變量解析到需要的信息,根據(jù)這些信息執(zhí)行程序邏輯,然后把結(jié)果返回給調(diào)用者,返回的結(jié)果中一般包括這些參數(shù):
- IPs assigned to the interface:網(wǎng)絡(luò)接口被分配的 ip,可以是 IPv4、IPv6 或者都有
- DNS 信息:包含 nameservers、domain、search domains 和其他選項(xiàng)的字典
CNI 協(xié)議的內(nèi)容還在不斷更新,請(qǐng)到官方文檔獲取當(dāng)前的信息。
CNI 的特性
CNI 作為一個(gè)協(xié)議/標(biāo)準(zhǔn),它有很強(qiáng)的擴(kuò)展性和靈活性。如果用戶對(duì)某個(gè)插件有額外的需求,可以通過輸入中的?args?和環(huán)境變量?CNI_ARGS?傳輸,然后在插件中實(shí)現(xiàn)自定義的功能,這大大增加了它的擴(kuò)展性;CNI 插件把 main 和 ipam 分開,用戶可以自由組合它們,而且一個(gè) CNI 插件也可以直接調(diào)用另外一個(gè) CNI 插件,使用起來非常靈活。
如果要實(shí)現(xiàn)一個(gè)繼承性的 CNI 插件也不復(fù)雜,可以編寫自己的 CNI 插件,根據(jù)傳入的配置調(diào)用 main 中已經(jīng)有的插件,就能讓用戶自由選擇容器的網(wǎng)絡(luò)。
在 kubernetes 中的使用
CNI 目前已經(jīng)在 kubernetes 中開始使用,也是目前官方推薦的網(wǎng)絡(luò)方案,具體的配置方法可以參考kubernetes 官方文檔。
kubernetes 使用了 CNI 網(wǎng)絡(luò)插件之后,工作過程是這樣的:
- kubernetes 先創(chuàng)建 pause 容器生成對(duì)應(yīng)的 network namespace
- 調(diào)用網(wǎng)絡(luò) driver(因?yàn)榕渲玫氖?CNI,所以會(huì)調(diào)用 CNI 相關(guān)代碼)
- CNI driver 根據(jù)配置調(diào)用具體的 cni 插件
- cni 插件給 pause 容器配置正確的網(wǎng)絡(luò)
- pod 中其他的容器都是用 pause 的網(wǎng)絡(luò)
參考資料
- CNI spec 文檔
- Linux Network namespaces and CNI
- The container networking landscape: cni from coreos and cnm from docker
- CNI and OCI
總結(jié)
以上是生活随笔為你收集整理的CNI:容器网络接口详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Go开发gRPC
- 下一篇: 容器技术标准化大统一,首个开放容器标准