容器網路模型:CNI vs CNM

liaochangjiang發表於2019-03-18

docker 的出現是革命性的,改變了我們開發以及部署專案的方式。社群一直致力於讓容器技術標準化,這篇文章主要討論的是其中的一個方面:網路。

網路層面:虛擬機器 vs 容器技術

在開始探討不同的容器網路標準模型之前,先來從網路角度對比一下虛擬機器和 docker。

虛擬機器是一整套作業系統層級的虛擬化,它還會虛擬出虛擬網路卡(virtual network interface cards (NIC)),這些虛擬網路卡會和真正的物理機網路卡相連線。

docker 實質上就是一個程式,被 container runtime 統一管理,還會共享一個 Linux kernel。所以,容器有更靈活的網路解決方案:

  • 和宿主機是共享同一個network interface和 network namespace
  • 連線另外的虛擬網路,使用這個虛擬網路的network interface和 network namespace

容器網路設計

早期的容器網路設計把重點放在瞭如何連線一個宿主機上的容器,讓他們可以和外界進行互動。

在"host"模式中,執行在一個宿主機上的容器使用 host 的network namespace,和宿主機一個ip。為了暴露容器,容器會佔用宿主機上的一個埠,通過這個埠和外界通訊。所以,你需要手動維護埠的分配,不要使不同的容器服務執行在一個埠上。

"bridge"模式,在"host"模式的基礎上做了些改進。在該模式裡面,容器被分配到了一個虛擬的區域網裡,在這個network namespace 獲得分配到的 ip 地址,由於 ip 地址是獨立的,就解決了"host"模式中不同容器服務不能執行在同一埠的問題。不過還是有一個問題,如果容器想要和外界通訊的話,還是需要使用 host 的 ip 地址。這時候需要用到 NAT 將 host-ip:port 轉換成 private-ip:port。這一部分的 NAT 規則表示用Linux Iptables 維護的,這會在一定程度上影響效能(雖然不大)。

上述的兩種模式都沒有解決一個問題:多 host 網路解決方案。

CNI 和 CNM 的對比

  • CNM: Docker 公司(docker container runtime 背後的公司)提出。
  • CNI:CoreOS公司提出。

Kubernetes 在處理網路上,沒有選擇自己再獨立創造一個,而是選擇了其中的 CNI作為了自己的網路外掛。(至於為什麼不選擇 CNM,可以看看這篇官方的解釋:Why Kubernetes doesn’t use libnetwork)。不使用 CNM 最關鍵的一點,是 k8s 考慮到CNM 在一定程度上和 container runtime 聯絡相對比較緊密,不好解耦。 有了 k8s 這種巨無霸的選擇之後,後來的很多專案都在 CNM 和 CNI 之間選擇了 CNI。

下面是兩種網路模型的詳細對比:

  1. CNM

CNM 的 api 包含了兩部分:IPAM 外掛和網路外掛。IPAM 外掛負責建立/刪除 address pools、分配網路地址,network 外掛負責建立/刪除 networks、以及分配或收回容器的 ip 地址。事實上,這兩種外掛都可以實現所有的 API,你可以選擇用 IPAM,也可以選擇用 network,或者 BOTH。但是,container runtime 會在不同情況下使用到不同的外掛,這帶來了複雜性。還有就是,CNM 需要使用分散式儲存系統來儲存網路配置資訊,例如 etcd。

  1. CNI

CNI 對外暴露了從一個網路裡面新增和剔除容器的介面。CNI 使用一個 json 配置檔案儲存網路配置資訊。和 CNM 不一樣,CNI 不需要一個額外的分散式儲存引擎。

總結

CNI目前已經獲得了眾多開源專案的青睞,比如 K8S、Memos、Cloud Foundry。同時被Cloud Native Computing Foundation所認可。CNCF 背後有眾多的科技大亨,所以可以預見,CNI 將會成為未來容器網路的標準。

相關文章