docker 的出現是革命性的,改變了咱們開發以及部署項目的方式。社區一直致力於讓容器技術標準化,這篇文章主要討論的是其中的一個方面:網絡。docker
在開始探討不一樣的容器網絡標準模型以前,先來從網絡角度對比一下虛擬機和 docker。json
虛擬機是一整套操做系統層級的虛擬化,它還會虛擬出虛擬網卡(virtual network interface cards (NIC)),這些虛擬網卡會和真正的物理機網卡相鏈接。api
docker 實質上就是一個進程,被 container runtime 統一管理,還會共享一個 Linux kernel。因此,容器有更靈活的網絡解決方案:網絡
早期的容器網絡設計把重點放在瞭如何鏈接一個宿主機上的容器,讓他們能夠和外界進行交互。分佈式
在"host"模式中,運行在一個宿主機上的容器使用 host 的network namespace,和宿主機一個ip。爲了暴露容器,容器會佔用宿主機上的一個端口,經過這個端口和外界通訊。因此,你須要手動維護端口的分配,不要使不一樣的容器服務運行在一個端口上。性能
"bridge"模式,在"host"模式的基礎上作了些改進。在該模式裏面,容器被分配到了一個虛擬的局域網裏,在這個network namespace 得到分配到的 ip 地址,因爲 ip 地址是獨立的,就解決了"host"模式中不一樣容器服務不能運行在同一端口的問題。不過仍是有一個問題,若是容器想要和外界通訊的話,仍是須要使用 host 的 ip 地址。這時候須要用到 NAT 將 host-ip:port 轉換成 private-ip:port。這一部分的 NAT 規則表示用Linux Iptables 維護的,這會在必定程度上影響性能(雖然不大)。spa
上述的兩種模式都沒有解決一個問題:多 host 網絡解決方案。操作系統
Kubernetes 在處理網絡上,沒有選擇本身再獨立創造一個,而是選擇了其中的 CNI做爲了本身的網絡插件。(至於爲何不選擇 CNM,能夠看看這篇官方的解釋:Why Kubernetes doesn’t use libnetwork)。不使用 CNM 最關鍵的一點,是 k8s 考慮到CNM 在必定程度上和 container runtime 聯繫相對比較緊密,很差解耦。 有了 k8s 這種巨無霸的選擇以後,後來的不少項目都在 CNM 和 CNI 之間選擇了 CNI。插件
CNM 的 api 包含了兩部分:IPAM 插件和網絡插件。IPAM 插件負責建立/刪除 address pools、分配網絡地址,network 插件負責建立/刪除 networks、以及分配或收回容器的 ip 地址。事實上,這兩種插件均可以實現全部的 API,你能夠選擇用 IPAM,也能夠選擇用 network,或者 BOTH。可是,container runtime 會在不一樣狀況下使用到不一樣的插件,這帶來了複雜性。還有就是,CNM 須要使用分佈式存儲系統來保存網絡配置信息,例如 etcd。設計
CNI 對外暴露了從一個網絡裏面添加和剔除容器的接口。CNI 使用一個 json 配置文件保存網絡配置信息。和 CNM 不同,CNI 不須要一個額外的分佈式存儲引擎。
CNI目前已經得到了衆多開源項目的青睞,好比 K8S、Memos、Cloud Foundry。同時被Cloud Native Computing Foundation所承認。CNCF 背後有衆多的科技大亨,因此能夠預見,CNI 將會成爲將來容器網絡的標準。