本文講述下docker容器以及k8s部署環境下,與網絡相關的知識。讀者需要對tcp/ip網絡,交換/路由,網絡虛擬化以及容器技術需要有一定的基礎。
1. 淺談容器網絡
容器container,就是一個被隔離的環境(Namespace)下,同時限制了訪問權限(Cgroup)的進程運行時,它配置了屬於自己的網卡,網絡棧,就像物理機一樣,可以訪問外部網絡,同時外部網絡也可以訪問容器,容器間也可以互相訪問。
1.1 容器怎麼訪問外部網絡
配置了網卡的物理主機,網卡+tcp/ip協議棧就可以訪問網絡了。網卡完成物理層和鏈接層的收發,ip路由,tcp負載傳輸。主機與主機通信,主機訪問互聯網,用網線或者光纖連接主機到交換機,或者兩臺主機網線直連,主機配置IP地址,互相間就可以通信了,中間的網絡,可能是二層,也可能是三層的。
Figure -- 1
如圖Figure -- 1所示,正是veth pair這個設備,把容器“連接”到主機,然後通過主機的路由轉發,虛擬網橋橋接,Vxlan包封裝這些種種技術,容器的packet最終通過物理主機的物理網卡發送或者接收。
這裏用到的一種名叫Veth Pair的虛擬設備,它的特點是:它被創建後,總是以兩張網卡(Veth Peer)的形式成對出現,並且,從其中一個“網卡”發出的數據包,可以直接出現在與它對應的另一張“網卡”上,哪怕這兩個“網卡”在不同的Network Namespace裏。
容器有自己的Network Namespace,TCP/IP網絡棧,報文發送至Veth Pair在容器側的虛擬設備,虛擬Veth設備發送報文,這個過程就是前端(front-end)的處理。報文到達宿主機後,在宿主機的Network Namespace,TCP/IP網絡棧,路由、封裝、轉發,報文最後通過物理網卡發送出去,這個過程就是後端(back-end)的處理。
思考:
- Veth(virtual ethernet)是以太鏈路層設備,承載轉發的是二層mac幀,容器發出的幀到達主機側後,怎麼到達bridge,路由是三層報文轉發,怎麼處理二層mac幀?
- 除了veth pair方式外,容器還可能有別的方式訪問外部網絡嗎?哪種方式性能會好些?
- 容器對比物理主機,網絡性能損耗在哪裏?路由、封裝、轉發,還有哪些處理?
1.2 容器網絡模型
上一節講了容器有獨立的網絡命名空間,通過veth pair訪問外部網絡。可以訪問外部網絡需要具備哪些條件呢?這一節就講講容器創建後,需要創建些啥設備,如何配置,有啥標準的接口和模型?
首先選擇網絡方案(容器網絡第三方插件),創建和配置容器網卡,網絡棧(路由表、iptables、Arp、IP地址、dns等),加入到對應的命名空間,其次創建配置互通和隔離的方式(路由、vxlan、vlan等)。
目前圍繞docker容器,發展出了兩種主流的接口和模型,一種是docker主導的Container network model(CNM)和k8s社區主導的Container network interface(CNI)。
2. 容器間的互通
傳統的網絡是由橋接、交換、路由這些轉發設備,服務器、筆記本、臺式機、各種瘦終端、以及具備收發功能的嵌入式設備,這些林林總總的節點組成。隨着虛擬化,容器,雲計算技術的發展,一方面,出現了虛擬機、容器這樣的虛擬實體,另一方面這些虛擬實體怎麼互相訪問,怎麼通過網絡與物理設備互相訪問,就又出現了新的網絡虛擬化技術(如vxlan,大二層技術等),同時爲了應對新的場景(多租戶,跨機房),更好的提供服務(轉發路由選擇、分類服務、流量控制監控),出現了Software Define Network(SDN)這樣的技術。
2.1 虛擬機場景
Qemu虛擬機是怎麼訪問外部網絡的?與容器有啥區別?
Figure -- 2
如圖Figure -- 2和Figure -- 1所示,虛擬機的虛擬網卡是虛擬化控制器VMM(qemu/kvm)虛擬化出來的,網卡的邏輯控制,數據層面的I/O都是虛擬化控制VMM在參與,說明白些,就是VMM這個軟件程序在模擬,VMM後面將虛擬機的報文發送給tap設備,或者直接socket發送給某個目的地址。
容器與虛擬機網絡的差別:
- 容器通過Veth Pair與外部網絡通信,虛擬機通過虛擬網卡,性能損耗會更大。
- 虛擬機網絡承載的是帶mac地址的以太幀,容器網絡承載的是IP包。
2.2 容器訪問外網
這裏講一下docker容器通過IP與外部網絡進行端對端層面的通信,容器的IP報文與外面網絡是怎麼交互的。
Figure -- 3
容器1的IP地址:172.17.0.2,節點2的IP地址:192.168.0.3,它們之間怎麼互相訪問?如圖Figure -- 3所示,下面用ping舉例說明報文的流向。
1)Ping程序生成ICMP Reuqest報文,通過raw socket發送。
2)Kernel收到報文後查詢路由表,看是否有到達目的地址192.168.0.3的路由。
$ route
Kernel IP routeing table
Destination Gateway Genmak Flags Metric Ref use Iface
default 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
匹配到缺省路由,通過eth0設備發送。
3)Veth Pair的另一端Veth0收到容器發的報文,veth0是bridge設備(docker0)的一個端口。Docker0是個二層的交換設備,虛擬的端口只收發報文,而由docker0轉發。Docker0查看收到的報文時,發現目的mac地址(對應172.17.0.1的mac地址)就是本身的地址,就會把IP報文交給主機網絡協議棧處理,主機查詢路由表,看是否有到達192.168.0.3的路由。
$ route
Kernel IP routeing table
Destination Gateway Genmak Flags Metric Ref use Iface
default 192.168.0.1 0.0.0.0 UG 100 0 0 enp2s0f0
192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 enp2s0f0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
匹配到直連路由(192.168.0.0/24 via enp2s0f0),通過enp2s0f0發送。
4)接下來,容器的ICMP Request報文就通過物理網絡到達目的主機Node2。
2.3 同主機場景
這裏講一下docker容器通過IP與外部網絡進行端對端層面的通信,同一主機的容器之間是怎麼互相訪問的。容器1的IP地址:172.17.0.2,容器2的IP地址:172.17.0.3,它們之間怎麼互相訪問?如圖Figure -- 3所示,過程1)過程2)與上一節是一樣的。
4)docker0這個交換設備,收到veth0報文,查詢到目的MAC地址(對應目的IP:172.17.0.3),發現可以通過端口Veth1發送。
5)Veth Pair在容器2端的一個接口eth0就收到容器1發送的ICMP Request報文了。
2.4 不同主機場景
這一節講述下,不同主機場景下,容器間怎麼互相訪問的?這個問題,就是容器的“跨主通信”問題。在Docker的默認配置下,一臺宿主機上的docker0網橋,和其他宿主機上的docker0網橋,不存在任何關聯,宿主機不把它們打通,它們之間沒有辦法進行訪問。
不過,萬變不離其宗,如圖Figure -- 4所示,如果在主機間通過軟件的方式,構建一個虛擬網絡,連通這些不同宿主機上的容器、網橋,不就可以互相通信了。
Figure -- 4
構建在宿主機物理網絡上面的虛擬網絡,對容器來說就好像是個連通的設備,並且不用去關心是用什麼方式、技術實現的。這個Overlay Network,可以是二層的Vlxlan虛擬網絡,IPinIP的tunnel,也可以是三層之間的路由轉發,甚至是應用層軟件轉發。目前社區裏有不少第三方的網絡插件(Fannel、Calico、Weave等),基於不同的技術實現了Overlay Network,其實主要考量下面幾點:
- 容器的報文通過什麼途徑到插件。
- 網絡插件基於什麼方式構建Overlay Network。
- 原始報文如何封裝、轉發。
2.5 Fannel網絡方案
https://blog.csdn.net/somyjun/article/details/88736599
2.6 Calico網絡方案
https://blog.csdn.net/somyjun/article/details/88739545