Multi-Network ns在Underlay下的應(yīng)用-妙手篇
大家好,我是二哥。接著上篇《??multi-network ns在Underlay下的應(yīng)用-本手篇??》,我們來聊聊基于 multiple network ns 的妙手級(jí)應(yīng)用:Underlay 。上一篇包含 multi network ns 的基礎(chǔ)概念,建議沒有讀過的小伙伴先看一遍。畢竟高考作文題說了:對(duì)于初學(xué)者而言,應(yīng)該從本手開始,本手的功夫扎實(shí)了,棋力才會(huì)提高。一些初學(xué)者熱衷于追求妙手,而忽視更為常用的本手。本手是基礎(chǔ),妙手是創(chuàng)造。
1、從 multi-VM 到 multi-network ns
為了能顯示出 multi network ns 的重大作用,二哥想借另外一張圖來做個(gè)對(duì)比,讓小伙伴們看看從原先的 multi-VM 進(jìn)化到 multi-network ns 是多么的必要。在圖 1 里,物理機(jī)器上創(chuàng)建了若干個(gè) VM 。由 VMM 向 VM 虛擬出 CPU / Memory / Disk / 網(wǎng)卡等設(shè)備。每個(gè) VM 的 OS 部分會(huì)創(chuàng)建一個(gè) net_device ,它是一個(gè)數(shù)據(jù)結(jié)構(gòu),用來對(duì)這個(gè)VM所擁有的網(wǎng)卡進(jìn)行軟件層次的抽象,盡管這個(gè)網(wǎng)卡本身也是虛擬的,但只要 VM 覺得它是一張實(shí)實(shí)在在的網(wǎng)卡,那就夠了。實(shí)際上這些網(wǎng)卡只是 tap 設(shè)備,它連接到物理機(jī)的 Open vSwitch 上,我們大致可以將 vSwitch 粗略地理解為一個(gè) bridge 。
圖 1:multi-VM
熟悉 ECS 或者在阿里云/騰訊云上購買過云服務(wù)器的同學(xué)一定知道通常一臺(tái) VM 上只會(huì)跑一個(gè)或極少量的應(yīng)用(Workload),大部分情況下這個(gè) VM 上的 CPU / Mem / Disk 等資源都是處于閑置狀態(tài),更別提會(huì)使用多個(gè) network ns 這種技術(shù)來隔離多個(gè)應(yīng)用了。 無論是個(gè)人還是公司,大家的錢都不是天上掉下來的,降本增效是永恒的目標(biāo)。一旦有更節(jié)省資源的方式出現(xiàn),大家一定會(huì)趨之若鶩?;?multi namespace 的 Docker 的出現(xiàn)給云計(jì)算機(jī)市場所帶來的幾乎是顛覆性改變就很好地證明了這一點(diǎn)。圖 2:一個(gè)包含 multi network namespace 的環(huán)境
看過《蟻人2:黃蜂女現(xiàn)身》嗎?皮姆博士瞬間把整棟大樓縮小成了一個(gè)拉杠箱,是不是帥呆了?如果將 圖 1 中的 vSwitch 縮小到圖 2 中 bridge 大小,或者將其放置到 bridge 的位置,那么連接在 vSwitch 上的這些 VM 其實(shí)也就一下子縮小到了連接在 bridge 上的屬于多個(gè) network ns 的 Pod 。也很帥,有沒有?以圖 2 為基礎(chǔ):
- 加上 VTEP 就搭建了 Overlay 的基本盤
- 加上 flanneld 這樣的設(shè)施,搭配下面這樣的路由設(shè)置就改造成 host-gw 了一個(gè) Work Node 上面運(yùn)行有一個(gè) bridge ,每個(gè) bridge 組成一個(gè)子網(wǎng)。在所有 Work Node 的路由表上均添加一條記錄:通往一個(gè)子網(wǎng)(比如:10.244.1.0/24)的 “下一跳”為運(yùn)行有該 bridge 的 Work Node 的 IP 地址。也就是說這臺(tái) “主機(jī)”(Host)會(huì)充當(dāng)通往這條容器通信路徑里的“網(wǎng)關(guān)”(Gateway)。Host-gateway 得名于此。
看起來好像挺不錯(cuò),將 Workload 所用資源從 VM 粒度縮小到 Pod 粒度所節(jié)省的資源確實(shí)非常的感人。按照二哥的經(jīng)驗(yàn),對(duì)于一個(gè)像 Web server 這樣的 I/O 型的 Workload ,原先的 VM 粒度是 2 core + 4 GB Memory 的話,可以縮小到 0.5 core + 200 MB 這樣的 Pod 粒度(假設(shè) Pod 里只有一個(gè) container)。不過好像有哪里不太對(duì)勁:圖 2 中 bridge 是組成了一個(gè)子網(wǎng),但看起來子網(wǎng)內(nèi)每個(gè) Pod 想要訪問子網(wǎng)外的資源,網(wǎng)絡(luò)流量就得從 root ns 走一圈。能不能既保留圖 2 這樣的細(xì)粒度資源虛擬化和分配方式,網(wǎng)絡(luò)流量又能像圖 1 的 VM 那樣大路朝天,各走各邊?
2、Underlay
群眾的呼聲就是容器云產(chǎn)商前進(jìn)的動(dòng)力。這不,以 AWS ENI 為代表的,利用彈性網(wǎng)卡來實(shí)現(xiàn)的 Underlay 完美地解決了圖 2 的弊端。既然圖 2 所示弊端的根源在于所有的 Pod 共享了 VM 所擁有的這一張網(wǎng)卡,那能不能給圖 2 中每個(gè) Pod 配備一張單獨(dú)的網(wǎng)卡呢?比如像圖 3 這樣,去掉 bridge ,人手一個(gè)網(wǎng)卡。豪橫的感覺出來了,有沒有?圖 3:拋掉 bridge ,給每個(gè) Pod 裝上一個(gè)網(wǎng)卡示意圖
(1)新加網(wǎng)卡
這個(gè)想法看起來非常不錯(cuò),但前提是這臺(tái) VM 上得有多余的網(wǎng)卡,另外還能把網(wǎng)卡插入到 Pod 中去。其實(shí)給一個(gè) VM 添加一張新網(wǎng)卡這事,像 VMWare 公司的 vSphere 這樣的工具就可以方便地做到。比如在圖 4 里,二哥用鼠標(biāo)點(diǎn)了幾下就手動(dòng)給一臺(tái) VM 添加了一個(gè)新的網(wǎng)卡。
圖 4:給 VM 手動(dòng)添加一張新網(wǎng)卡
當(dāng)然,我們也可以通過 API 的方式自動(dòng)完成這樣的網(wǎng)卡創(chuàng)建工作。像 AWS / 阿里云都支持通過 API 的方式給 ECS 動(dòng)態(tài)創(chuàng)建彈性網(wǎng)卡(ENI)。但一臺(tái) ECS 所能綁定的 ENI 數(shù)量是有限制的,比如 AWS 上根據(jù) ECS 實(shí)例的配置,最高可以綁定 15 個(gè)彈性網(wǎng)卡,阿里云也有類似的限制。彈性網(wǎng)卡是獨(dú)立的虛擬網(wǎng)卡,可以在多個(gè)云服務(wù)器之間遷移,實(shí)現(xiàn)業(yè)務(wù)的靈活擴(kuò)展和遷移??梢噪S ECS 實(shí)例創(chuàng)建并綁定彈性網(wǎng)卡,也可以單獨(dú)創(chuàng)建輔助彈性網(wǎng)卡再綁定到 ECS 實(shí)例上。彈性網(wǎng)卡具備以下功能特點(diǎn):
- 除了隨 ECS 實(shí)例一起創(chuàng)建的主網(wǎng)卡外,一臺(tái) ECS 實(shí)例支持綁定多個(gè)輔助網(wǎng)卡。這些輔助網(wǎng)卡和 ECS 實(shí)例必須屬于同一專有網(wǎng)絡(luò)VPC和同一可用區(qū),可以分屬于不同虛擬交換機(jī)和不同安全組。
- 每個(gè)彈性網(wǎng)卡根據(jù)隨綁定的實(shí)例規(guī)格不同,可以分配相應(yīng)的多個(gè)輔助私網(wǎng)IP地址。
- 將一個(gè)輔助彈性網(wǎng)卡從一個(gè)實(shí)例解綁,再重新綁定到另一個(gè)實(shí)例時(shí),網(wǎng)卡的屬性不會(huì)發(fā)生變化,網(wǎng)絡(luò)流量將直接切換到新的實(shí)例。
- 彈性網(wǎng)卡支持熱插拔,可以在ECS實(shí)例之間自由遷移,切換彈性網(wǎng)卡綁定的實(shí)例時(shí)無需重啟實(shí)例,不影響實(shí)例上運(yùn)行的業(yè)務(wù)。
(2)將新網(wǎng)卡插入到容器中
Um... NICE. 看起來新建網(wǎng)卡有門路了,那又該如何將其插入到 Pod 里面去呢?二哥以 Docker 來做個(gè)示意吧,將新建的一個(gè)名為 eth10 網(wǎng)卡插入到容器里面。首先啟動(dòng)一個(gè)容器,假如這個(gè)容器的 PID 是 2022。
~# docker run -itd --net none ubuntu:16.04
在宿主機(jī)環(huán)境執(zhí)行下面的命令,將 eth10 放到容器中,并重命名為 eth0 ,上電啟動(dòng)再開啟 DHCP 。
~# mkdir /var/run/netns
~# ln -sf /proc/2022/ns/net /var/run/netns/2022
~# ip link set dev eth10 netns 2022
~# ip netns exec 2022 ip link set eth10 name eth0
~# ip netns exec 2022 ip link set eth0 up
~# ip netns exec 2022 dhclient eth0
一通猛如虎的操作后,宿主機(jī)上就再也看不到這個(gè) eth10 了。而如果在容器內(nèi)執(zhí)行這條命令,你會(huì)發(fā)現(xiàn)它多了一個(gè)網(wǎng)卡。
~# ifconfig -a
其實(shí)準(zhǔn)確地說,上面的操作是將 eth10 插入到容器的 network ns 中去的。一個(gè) Pod 本質(zhì)上是共享相同 network ns 的多個(gè)容器的集合,所以你可以想象得出將這些操作應(yīng)用到 Pod 中發(fā)生了什么。
我們將圖 2 和圖 3 重新整理一下。圖 5 就是我們心心所念的,結(jié)合了圖 1 和圖 2 優(yōu)勢的新方案:既保留圖 2 這樣的細(xì)粒度的資源虛擬化方式,網(wǎng)絡(luò)流量又能像圖 1 的 VM 那樣大路朝天,各向天涯。圖 5:支持 multi NIC 的 Underlay
(3)Performance
二哥在之前的文章中提到過,如以 VM 為 benchmark 來做對(duì)比的話,在傳輸性能方面:
- Overlay 模式的傳輸性能會(huì)有 20-30% 左右的下降。因?yàn)樗淼缼砹私?封裝損耗,另外進(jìn)出 Pod 的 traffic 要穿越兩次網(wǎng)絡(luò)棧(如圖 6 所示,進(jìn)兩次,出也是兩次)。解/封裝的代價(jià)顯而易見,而兩次網(wǎng)絡(luò)棧的穿越所付出的代價(jià)卻很容易讓人忽略。圖 6 中用紅色標(biāo)示出了 "iptables overhead",意思是這部分是額外的工作量,言下之意是其實(shí)這部分工作量可以去掉。
- host-gw 模式大概有 10% 左右的性能損耗。原因是和 Overlay 模式一樣,主機(jī)間路由同樣會(huì)出現(xiàn)兩次穿越網(wǎng)絡(luò)棧的問題。
圖 6:進(jìn)出 Pod 的 traffic 多次穿越網(wǎng)絡(luò)棧
那 Underlay 的性能損耗如何?它和 benchmark 相比,幾乎沒有任何性能損耗。原因也很容易找到:既沒有解/封裝,也不需要兩次網(wǎng)絡(luò)棧的穿越。我們?cè)俳o大家附上一個(gè)性能測試對(duì)比報(bào)告,報(bào)告是阿里云團(tuán)隊(duì)公布在他們的網(wǎng)站上的。報(bào)告鏈接 我放在這里,感興趣的同學(xué)可以自己去研究。
圖 7:performance 對(duì)比
3、總結(jié)
其實(shí) K8s 的 Overlay / host-gw / Underlay 網(wǎng)絡(luò)模式的實(shí)現(xiàn)都離不開 multi network ns 。但 Underlay 對(duì)其利用得更干凈、更直觀、更高效,不過也更貴。周志明老師在《鳳凰架構(gòu)》一書中說:對(duì)于真正的大型數(shù)據(jù)中心、大型系統(tǒng),Underlay 模式才是最有發(fā)展?jié)摿Φ木W(wǎng)絡(luò)模式。這種方案能夠最大限度地利用硬件的能力,往往有著最優(yōu)秀的性能表現(xiàn)。但也是由于它直接依賴于硬件與底層網(wǎng)絡(luò)環(huán)境,必須根據(jù)軟、硬件情況來進(jìn)行部署,難以做到 Overlay 網(wǎng)絡(luò)那樣開箱即用的靈活性。大家看完這兩篇文章,不知道是否對(duì)周老師這番話有了更深刻的理解呢?對(duì)于《?multi-network ns在Underlay下的應(yīng)用-本手篇?》文首所提的 3 個(gè)問題,你是不是有了答案呢?