Docker 網(wǎng)絡(luò)

轉(zhuǎn)自:http://ju.outofmemory.cn/entry/255894

概述
自從docker容器出現(xiàn)以來(lái),容器的網(wǎng)絡(luò)通信就一直是大家關(guān)注的焦點(diǎn),也是生產(chǎn)環(huán)境的迫切需求。而容器的網(wǎng)絡(luò)通信又可以分為兩大方面:?jiǎn)沃鳈C(jī)容器上的相互通信和跨主機(jī)的容器相互通信。而本文將分別針對(duì)這兩方面,對(duì)容器的通信原理進(jìn)行簡(jiǎn)單的分析,幫助大家更好地使用docker。
docker單主機(jī)容器通信
基于對(duì)net namespace的控制,docker可以為在容器創(chuàng)建隔離的網(wǎng)絡(luò)環(huán)境,在隔離的網(wǎng)絡(luò)環(huán)境下,容器具有完全獨(dú)立的網(wǎng)絡(luò)棧,與宿主機(jī)隔離,也可以使容器共享主機(jī)或者其他容器的網(wǎng)絡(luò)命名空間,基本可以滿足開發(fā)者在各種場(chǎng)景下的需要。按docker官方的說法,docker容器的網(wǎng)絡(luò)有五種模式:
bridge:docker默認(rèn)的網(wǎng)絡(luò)模式,為容器創(chuàng)建獨(dú)立的網(wǎng)絡(luò)命名空間,容器具有獨(dú)立的網(wǎng)卡等所有單獨(dú)的網(wǎng)絡(luò)棧,是最常用的使用方式。
host:直接使用容器宿主機(jī)的網(wǎng)絡(luò)命名空間。
none:為容器創(chuàng)建獨(dú)立網(wǎng)絡(luò)命名空間,但不為它做任何網(wǎng)絡(luò)配置,容器中只有l(wèi)o,用戶可以在此基礎(chǔ)上,對(duì)容器網(wǎng)絡(luò)做任意定制。
其他容器:與host模式類似,只是容器將與指定的容器共享網(wǎng)絡(luò)命名空間。
用戶自定義:docker 1.9版本以后新增的特性,允許容器使用第三方的網(wǎng)絡(luò)實(shí)現(xiàn)或者創(chuàng)建單獨(dú)的bridge網(wǎng)絡(luò),提供網(wǎng)絡(luò)隔離能力。

這些網(wǎng)絡(luò)模式在相互網(wǎng)絡(luò)通信方面的對(duì)比如下所示:

南北向通信指容器與宿主機(jī)外界的訪問機(jī)制,東西向流量指同一宿主機(jī)上與其他容器相互訪問的機(jī)制。
host ****模式
由于容器和宿主機(jī)共享同一個(gè)網(wǎng)絡(luò)命名空間,換言之,容器的IP地址即為宿主機(jī)的IP地址。所以容器可以和宿主機(jī)一樣,使用宿主機(jī)的任意網(wǎng)卡,實(shí)現(xiàn)和外界的通信。其網(wǎng)絡(luò)模型可以參照下圖:

docker詳解01

采用host模式的容器,可以直接使用宿主機(jī)的IP地址與外界進(jìn)行通信,若宿主機(jī)具有公有IP,那么容器也擁有這個(gè)公有IP。同時(shí)容器內(nèi)服務(wù)的端口也可以使用宿主機(jī)的端口,無(wú)需額外進(jìn)行NAT轉(zhuǎn)換,而且由于容器通信時(shí),不再需要通過linuxbridge等方式轉(zhuǎn)發(fā)或者數(shù)據(jù)包的拆封,性能上有很大優(yōu)勢(shì)。當(dāng)然,這種模式有優(yōu)勢(shì),也就有劣勢(shì),主要包括以下幾個(gè)方面:
最明顯的就是容器不再擁有隔離、獨(dú)立的網(wǎng)絡(luò)棧。容器會(huì)與宿主機(jī)競(jìng)爭(zhēng)網(wǎng)絡(luò)棧的使用,并且容器的崩潰就可能導(dǎo)致宿主機(jī)崩潰,在生產(chǎn)環(huán)境中,這種問題可能是不被允許的。
容器內(nèi)部將不再擁有所有的端口資源,因?yàn)橐恍┒丝谝呀?jīng)被宿主機(jī)服務(wù)、bridge模式的容器端口綁定等其他服務(wù)占用掉了。

bridge ****模式
bridge模式是docker默認(rèn)的,也是開發(fā)者最常使用的網(wǎng)絡(luò)模式。在這種模式下,docker為容器創(chuàng)建獨(dú)立的網(wǎng)絡(luò)棧,保證容器內(nèi)的進(jìn)程使用獨(dú)立的網(wǎng)絡(luò)環(huán)境,實(shí)現(xiàn)容器之間、容器與宿主機(jī)之間的網(wǎng)絡(luò)棧隔離。同時(shí),通過宿主機(jī)上的docker0網(wǎng)橋,容器可以與宿主機(jī)乃至外界進(jìn)行網(wǎng)絡(luò)通信。其網(wǎng)絡(luò)模型可以參考下圖:

docker詳解02

從該網(wǎng)絡(luò)模型可以看出,容器從原理上是可以與宿主機(jī)乃至外界的其他機(jī)器通信的。同一宿主機(jī)上,容器之間都是連接到docker0這個(gè)網(wǎng)橋上的,它可以作為虛擬交換機(jī)使容器可以相互通信。然而,由于宿主機(jī)的IP地址與容器veth pair的 IP地址均不在同一個(gè)網(wǎng)段,故僅僅依靠veth pair和namespace的技術(shù),還不足以使宿主機(jī)以外的網(wǎng)絡(luò)主動(dòng)發(fā)現(xiàn)容器的存在。為了使外界可以方位容器中的進(jìn)程,docker采用了端口綁定的方式,也就是通過iptables的NAT,將宿主機(jī)上的端口端口流量轉(zhuǎn)發(fā)到容器內(nèi)的端口上。
舉一個(gè)簡(jiǎn)單的例子,使用下面的命令創(chuàng)建容器,并將宿主機(jī)的3306端口綁定到容器的3306端口:
docker run -tid –name db -p 3306:3306 mysql
在宿主機(jī)上,可以通過iptables -t nat -L -n,查到一條DNAT規(guī)則:
DNAT tcp — 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.5:3306
上面的172.17.0.5即為bridge模式下,創(chuàng)建的容器IP。
很明顯,bridge模式的容器與外界通信時(shí),必定會(huì)占用宿主機(jī)上的端口,從而與宿主機(jī)競(jìng)爭(zhēng)端口資源,對(duì)宿主機(jī)端口的管理會(huì)是一個(gè)比較大的問題。同時(shí),由于容器與外界通信是基于三層上iptables NAT,性能和效率上的損耗是可以預(yù)見的。
none ****模式
在這種模式下,容器有獨(dú)立的網(wǎng)絡(luò)棧,但不包含任何網(wǎng)絡(luò)配置,只具有l(wèi)o這個(gè)loopback網(wǎng)卡用于進(jìn)程通信。也就是說,none模式為容器做了最少的網(wǎng)絡(luò)設(shè)置,但是俗話說得好“少即是多”,在沒有網(wǎng)絡(luò)配置的情況下,通過第三方工具或者手工的方式,開發(fā)這任意定制容器的網(wǎng)絡(luò),提供了最高的靈活性。
其他容器模式
其他網(wǎng)絡(luò)模式是docker中一種較為特別的網(wǎng)絡(luò)的模式。在這個(gè)模式下的容器,會(huì)使用其他容器的網(wǎng)絡(luò)命名空間,其網(wǎng)絡(luò)隔離性會(huì)處于bridge橋接模式與host模式之間。當(dāng)容器共享其他容器的網(wǎng)絡(luò)命名空間,則在這兩個(gè)容器之間不存在網(wǎng)絡(luò)隔離,而她們又與宿主機(jī)以及除此之外其他的容器存在網(wǎng)絡(luò)隔離。其網(wǎng)絡(luò)模型可以參考下圖:
docker詳解03

在這種模式下的容器可以通過localhost來(lái)同一網(wǎng)絡(luò)命名空間下的其他容器,傳輸效率較高。而且這種模式還節(jié)約了一定數(shù)量的網(wǎng)絡(luò)資源,但它并沒有改變?nèi)萜髋c外界通信的方式。在一些特殊的場(chǎng)景中非常有用,例如,kubernetes的pod,kubernetes為pod創(chuàng)建一個(gè)基礎(chǔ)設(shè)施容器,同一pod下的其他容器都以其他容器模式共享這個(gè)基礎(chǔ)設(shè)施容器的網(wǎng)絡(luò)命名空間,相互之間以localhost訪問,構(gòu)成一個(gè)統(tǒng)一的整體。
用戶定義網(wǎng)絡(luò)模式
在用戶定義網(wǎng)絡(luò)模式下,開發(fā)者可以使用任何docker支持的第三方網(wǎng)絡(luò)driver來(lái)定制容器的網(wǎng)絡(luò)。并且,docker 1.9以上的版本默認(rèn)自帶了bridge和overlay兩種類型的自定義網(wǎng)絡(luò)driver??梢杂糜诩蒫alico、weave、openvswitch等第三方廠商的網(wǎng)絡(luò)實(shí)現(xiàn)。
除了docker自帶的bridge driver,其他的幾種driver都可以實(shí)現(xiàn)容器的跨主機(jī)通信。而基于bdrige driver的網(wǎng)絡(luò),docker會(huì)自動(dòng)為其創(chuàng)建iptables規(guī)則,保證與其他網(wǎng)絡(luò)之間、與docker0之間的網(wǎng)絡(luò)隔離。例如,使用下面的命令創(chuàng)建一個(gè)基于bridge driver的自定義網(wǎng)絡(luò):
docker network create bri1
則docker會(huì)自動(dòng)生成如下的iptables規(guī)則,保證不同網(wǎng)絡(luò)上的容器無(wú)法互相通信。
-A DOCKER-ISOLATION -i br-8dba6df70456 -o docker0 -j DROP -A DOCKER-ISOLATION -i docker0 -o br-8dba6df70456 -j DROP
除此之外,bridge driver的所有行為都和默認(rèn)的bridge模式完全一致。而overlay及其他driver,則可以實(shí)現(xiàn)容器的跨主機(jī)通信。
docker ****跨主機(jī)容器通信
早期大家的跨主機(jī)通信方案主要有以下幾種:
容器使用host模式:容器直接使用宿主機(jī)的網(wǎng)絡(luò),這樣天生就可以支持跨主機(jī)通信。雖然可以解決跨主機(jī)通信問題,但這種方式應(yīng)用場(chǎng)景很有限,容易出現(xiàn)端口沖突,也無(wú)法做到隔離網(wǎng)絡(luò)環(huán)境,一個(gè)容器崩潰很可能引起整個(gè)宿主機(jī)的崩潰。
端口綁定:通過綁定容器端口到宿主機(jī)端口,跨主機(jī)通信時(shí),使用主機(jī)IP+端口的方式訪問容器中的服務(wù)。顯而易見,這種方式僅能支持網(wǎng)絡(luò)棧的四層及以上的應(yīng)用,并且容器與宿主機(jī)緊耦合,很難靈活的處理,可擴(kuò)展性不佳。
docker外定制容器網(wǎng)絡(luò):在容器通過docker創(chuàng)建完成后,然后再通過修改容器的網(wǎng)絡(luò)命名空間來(lái)定義容器網(wǎng)絡(luò)。典型的就是很久以前的pipework,容器以none模式創(chuàng)建,pipework通過進(jìn)入容器的網(wǎng)絡(luò)命名空間為容器重新配置網(wǎng)絡(luò),這樣容器網(wǎng)絡(luò)可以是靜態(tài)IP、vxlan網(wǎng)絡(luò)等各種方式,非常靈活,容器啟動(dòng)的一段時(shí)間內(nèi)會(huì)沒有IP,明顯無(wú)法在大規(guī)模場(chǎng)景下使用,只能在實(shí)驗(yàn)室中測(cè)試使用。
第三方SDN定義容器網(wǎng)絡(luò):使用Open vSwitch或Flannel等第三方SDN工具,為容器構(gòu)建可以跨主機(jī)通信的網(wǎng)絡(luò)環(huán)境。這些方案一般要求各個(gè)主機(jī)上的docker0網(wǎng)橋的cidr不同,以避免出現(xiàn)IP沖突的問題,限制了容器在宿主機(jī)上的可獲取IP范圍。并且在容器需要對(duì)集群外提供服務(wù)時(shí),需要比較復(fù)雜的配置,對(duì)部署實(shí)施人員的網(wǎng)絡(luò)技能要求比較高。

上面這些方案有各種各樣的缺陷,同時(shí)也因?yàn)榭缰鳈C(jī)通信的迫切需求,docker 1.9版本時(shí),官方提出了基于vxlan的overlay網(wǎng)絡(luò)實(shí)現(xiàn),原生支持容器的跨主機(jī)通信。同時(shí),還支持通過libnetwork的plugin機(jī)制擴(kuò)展各種第三方實(shí)現(xiàn),從而以不同的方式實(shí)現(xiàn)跨主機(jī)通信。就目前社區(qū)比較流行的方案來(lái)說,跨主機(jī)通信的基本實(shí)現(xiàn)方案有以下幾種:
基于隧道的overlay網(wǎng)絡(luò):按隧道類型來(lái)說,不同的公司或者組織有不同的實(shí)現(xiàn)方案。docker原生的overlay網(wǎng)絡(luò)就是基于vxlan隧道實(shí)現(xiàn)的。 ovn 則需要通過geneve或者stt隧道來(lái)實(shí)現(xiàn)的。 flannel 最新版本也開始默認(rèn)基于vxlan實(shí)現(xiàn)overlay網(wǎng)絡(luò)。
基于包封裝的overlay網(wǎng)絡(luò):基于UDP封裝等數(shù)據(jù)包包裝方式,在docker集群上實(shí)現(xiàn)跨主機(jī)網(wǎng)絡(luò)。典型實(shí)現(xiàn)方案有 weave 、 flannel 的早期版本。
基于三層實(shí)現(xiàn)SDN網(wǎng)絡(luò):基于三層協(xié)議和路由,直接在三層上實(shí)現(xiàn)跨主機(jī)網(wǎng)絡(luò),并且通過iptables實(shí)現(xiàn)網(wǎng)絡(luò)的安全隔離。典型的方案為Project Calico 。同時(shí)對(duì)不支持三層路由的環(huán)境,Project Calico還提供了基于IPIP封裝的跨主機(jī)網(wǎng)絡(luò)實(shí)現(xiàn)。

下面,本從網(wǎng)絡(luò)通信模型的角度,對(duì)這些方案的通信原理做一個(gè)簡(jiǎn)單的比較,從中可以窺見各種方案在性能上的本質(zhì)差別。
docker ****容器的 ****CNM ****模型
首先,科普下docker容器的CNM網(wǎng)絡(luò)模型,calico、weave等第三方實(shí)現(xiàn)都是基于CNM模型與docker集成的。CNM網(wǎng)絡(luò)模型的結(jié)構(gòu)如下圖所示:

docker詳解04

在上面的圖中:
Sandbox代表容器的網(wǎng)絡(luò)命名空間,包含了容器的完整網(wǎng)絡(luò)棧,不同的容器之間可以完全隔離。在宿主機(jī)上,就表現(xiàn)為獨(dú)立的網(wǎng)絡(luò)命名空間。
Endpoint代表容器接入網(wǎng)絡(luò)的端點(diǎn),可以形象地認(rèn)為一個(gè)Endpoint對(duì)容器來(lái)說,就是一張物理網(wǎng)卡。
Network代表一組可以直接相互通信的Endpoint集合,可以基于LinuxBridge或者VLAN實(shí)現(xiàn)。在宿主機(jī)上,每個(gè)網(wǎng)絡(luò)都是一個(gè)獨(dú)立的網(wǎng)絡(luò)命名空間,宿主機(jī)上同一網(wǎng)絡(luò)的的容器,都通過veth pair鏈接到這個(gè)網(wǎng)絡(luò)命名空間上。

docker ****原生 ****overlay ****的網(wǎng)絡(luò)通信模型
docker官方文檔的示例中,overlay網(wǎng)絡(luò)是在swarm集群中配置的,但實(shí)際上,overlay網(wǎng)絡(luò)可以獨(dú)立于swarm集群實(shí)現(xiàn),只需要滿足以下前提條件即可。
有consul或者etcd,zookeeper的集群key-value存儲(chǔ)服務(wù);
組成集群的所有主機(jī)的主機(jī)名不允許重復(fù),因?yàn)閐ocker守護(hù)進(jìn)程與consul通信時(shí),以主機(jī)名相互區(qū)分;
所有主機(jī)都可以訪問集群key-value的服務(wù)端口,按具體類型需要打開進(jìn)行配置。例如docker daemon啟動(dòng)時(shí)增加參數(shù) –cluster-store=etcd://<ETCD-IP>:4001 – -cluster-advertise=eth0:2376
overlay網(wǎng)絡(luò)依賴宿主機(jī)三層網(wǎng)絡(luò)的組播實(shí)現(xiàn),需要在所有宿主機(jī)的防火墻上打開下列端口

滿足以上條件后,就可以通過docker network命令來(lái)創(chuàng)建跨主機(jī)的overlay網(wǎng)絡(luò)了,例如: docker network create -d overlay overlaynet 在集群的不同主機(jī)上,使用overlaynet這個(gè)網(wǎng)絡(luò)創(chuàng)建容器,形成如下圖所示的網(wǎng)絡(luò)拓?fù)洌?br>

docker詳解05

由于容器和overlay的網(wǎng)絡(luò)的網(wǎng)絡(luò)命名空間文件不再操作系統(tǒng)默認(rèn)的/var/run/netns下,只能手動(dòng)通過軟連接的方式查看。
ln -s /var/run/docker/netns /var/run/netns
這樣就可以通過ip netns查看到容器和網(wǎng)絡(luò)的網(wǎng)絡(luò)命名空間了。
容器的網(wǎng)絡(luò)命名空間名稱可以通過docker inspect -f ‘{{.NetworkSettings.SandboxKey}}’ <容器ID>方式查看到。網(wǎng)絡(luò)的網(wǎng)絡(luò)命名空間則是通過docker network ls查看到的網(wǎng)絡(luò)短ID。
有時(shí)候網(wǎng)絡(luò)的網(wǎng)絡(luò)命名空間名稱前面會(huì)帶上1-、2-等序號(hào),有時(shí)候不帶。但不影響網(wǎng)絡(luò)的通信和操作。
從這個(gè)通信過程中來(lái)看,跨主機(jī)通信過程中的步驟如下:
容器的網(wǎng)絡(luò)命名空間與overlay網(wǎng)絡(luò)的網(wǎng)絡(luò)命名空間通過一對(duì)veth pair連接起來(lái),當(dāng)容器對(duì)外通信時(shí),veth pair起到網(wǎng)線的作用,將流量發(fā)送到overlay網(wǎng)絡(luò)的網(wǎng)絡(luò)命名空間中。
容器的veth pair對(duì)端eth2與vxlan設(shè)備通過br0這個(gè)Linux bridge橋接在一起,br0在同一宿主機(jī)上起到虛擬機(jī)交換機(jī)的作用,如果目標(biāo)地址在同一宿主機(jī)上,則直接通信,如果不再則通過設(shè)置在vxlan1這個(gè)vxlan設(shè)備進(jìn)行跨主機(jī)通信。
vxlan1設(shè)備上會(huì)在創(chuàng)建時(shí),由docker daemon為其分配vxlan隧道ID,起到網(wǎng)絡(luò)隔離的作用。
docker主機(jī)集群通過key/value存儲(chǔ)共享數(shù)據(jù),在7946端口上,相互之間通過gossip協(xié)議學(xué)習(xí)各個(gè)宿主機(jī)上運(yùn)行了哪些容器。守護(hù)進(jìn)程根據(jù)這些數(shù)據(jù)來(lái)在vxlan1設(shè)備上生成靜態(tài)MAC轉(zhuǎn)發(fā)表。
根據(jù)靜態(tài)MAC轉(zhuǎn)發(fā)表的設(shè)置,通過UDP端口4789,將流量轉(zhuǎn)發(fā)到對(duì)端宿主機(jī)的網(wǎng)卡上。
根據(jù)流量包中的vxlan隧道ID,將流量轉(zhuǎn)發(fā)到對(duì)端宿主機(jī)的overlay網(wǎng)絡(luò)的網(wǎng)絡(luò)命名空間中。
對(duì)端宿主機(jī)的overlay網(wǎng)絡(luò)的網(wǎng)絡(luò)命名空間中br0網(wǎng)橋,起到虛擬交換機(jī)的作用,將流量根據(jù)MAC地址轉(zhuǎn)發(fā)到對(duì)應(yīng)容器內(nèi)部。

雖然上面的網(wǎng)絡(luò)通信模型可以實(shí)現(xiàn)容器的跨主機(jī)通信,但還是有一些缺陷,造成實(shí)際使用上的不便,例如:
由于vxlan網(wǎng)絡(luò)與宿主機(jī)網(wǎng)絡(luò)默認(rèn)不再同一網(wǎng)絡(luò)環(huán)境下,為了解決宿主機(jī)與容器的通信問題,docker為overlay網(wǎng)絡(luò)中的容器額外增加了網(wǎng)卡eth1作為宿主機(jī)與容器通信的通道。這樣在使用容器服務(wù)時(shí),就必須根據(jù)訪問性質(zhì)的不同,選擇不同的網(wǎng)卡地址,造成使用上的不便。
容器對(duì)外暴露服務(wù)仍然只能使用端口綁定的方式,外界無(wú)法簡(jiǎn)單地直接使用容器IP訪問容器服務(wù)。
從上面的通信過程中來(lái)看,原生的overlay網(wǎng)絡(luò)通信必須依賴docker守護(hù)進(jìn)程及key/value存儲(chǔ)來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)通信,約束較多,容器在啟動(dòng)后的一段時(shí)間內(nèi)可能無(wú)法跨主機(jī)通信,這對(duì)一些比較敏感的應(yīng)用來(lái)說是不可靠的。

weave ****網(wǎng)絡(luò)通信模型
weave通過在docker集群的每個(gè)主機(jī)上啟動(dòng)虛擬的路由器,將主機(jī)作為路由器,形成互聯(lián)互通的網(wǎng)絡(luò)拓?fù)?,在此基礎(chǔ)上,實(shí)現(xiàn)容器的跨主機(jī)通信。其主機(jī)網(wǎng)絡(luò)拓?fù)鋮⒁娤聢D:

docker詳解06

如上圖所示,在每一個(gè)部署Docker的主機(jī)(可能是物理機(jī)也可能是虛擬機(jī))上都部署有一個(gè)W(即weave router,它本身也可以以一個(gè)容器的形式部署)。weave網(wǎng)絡(luò)是由這些weave routers組成的對(duì)等端點(diǎn)(peer)構(gòu)成,并且可以通過weave命令行定制網(wǎng)絡(luò)拓?fù)洹?br> 每個(gè)部署了weave router的主機(jī)之間都會(huì)建立TCP和UDP兩個(gè)連接,保證weave router之間控制面流量和數(shù)據(jù)面流量的通過??刂泼嬗蓋eave routers之間建立的TCP連接構(gòu)成,通過它進(jìn)行握手和拓?fù)潢P(guān)系信息的交換通信。控制面的通信可以被配置為加密通信。而數(shù)據(jù)面由weave routers之間建立的UDP連接構(gòu)成,這些連接大部分都會(huì)加密。這些連接都是全雙工的,并且可以穿越防火墻。
當(dāng)容器通過weave進(jìn)行跨主機(jī)通信時(shí),其網(wǎng)絡(luò)通信模型可以參考下圖:
docker詳解07

從上面的網(wǎng)絡(luò)模型圖中可以看出,對(duì)每一個(gè)weave網(wǎng)絡(luò)中的容器,weave都會(huì)創(chuàng)建一個(gè)網(wǎng)橋,并且在網(wǎng)橋和每個(gè)容器之間創(chuàng)建一個(gè)veth pair,一端作為容器網(wǎng)卡加入到容器的網(wǎng)絡(luò)命名空間中,并為容器網(wǎng)卡配置ip和相應(yīng)的掩碼,一端連接在網(wǎng)橋上,最終通過宿主機(jī)上weave router將流量轉(zhuǎn)發(fā)到對(duì)端主機(jī)上。其基本過程如下:
容器流量通過veth pair到達(dá)宿主機(jī)上weave router網(wǎng)橋上。
weave router在混雜模式下使用pcap在網(wǎng)橋上截獲網(wǎng)絡(luò)數(shù)據(jù)包,并排除由內(nèi)核直接通過網(wǎng)橋轉(zhuǎn)發(fā)的數(shù)據(jù)流量,例如本子網(wǎng)內(nèi)部、本地容器之間的數(shù)據(jù)以及宿主機(jī)和本地容器之間的流量。捕獲的包通過UDP轉(zhuǎn)發(fā)到所其他主機(jī)的weave router端。
在接收端,weave router通過pcap將包注入到網(wǎng)橋上的接口,通過網(wǎng)橋的上的veth pair,將流量分發(fā)到容器的網(wǎng)卡上。

weave默認(rèn)基于UDP承載容器之間的數(shù)據(jù)包,并且可以完全自定義整個(gè)集群的網(wǎng)絡(luò)拓?fù)?,但從性能和使用角度?lái)看,還是有比較大的缺陷的:
weave自定義容器數(shù)據(jù)包的封包解包方式,不夠通用,傳輸效率比較低,性能上的損失也比較大。
集群配置比較負(fù)載,需要通過weave命令行來(lái)手工構(gòu)建網(wǎng)絡(luò)拓?fù)?,在大?guī)模集群的情況下,加重了管理員的負(fù)擔(dān)。

calico ****網(wǎng)絡(luò)通信模型
calico是純?nèi)龑拥腟DN 實(shí)現(xiàn),它基于BPG 協(xié)議和Linux自身的路由轉(zhuǎn)發(fā)機(jī)制,不依賴特殊硬件,容器通信也不依賴iptables NAT或Tunnel 等技術(shù)。能夠方便的部署在物理服務(wù)器、虛擬機(jī)(如 OpenStack)或者容器環(huán)境下。同時(shí)calico自帶的基于iptables的ACL管理組件非常靈活,能夠滿足比較復(fù)雜的安全隔離需求。
在主機(jī)網(wǎng)絡(luò)拓?fù)涞慕M織上,calico的理念與weave類似,都是在主機(jī)上啟動(dòng)虛擬機(jī)路由器,將每個(gè)主機(jī)作為路由器使用,組成互聯(lián)互通的網(wǎng)絡(luò)拓?fù)?。?dāng)安裝了calico的主機(jī)組成集群后,其拓?fù)淙缦聢D所示:

docker詳解08

每個(gè)主機(jī)上都部署了calico/node作為虛擬路由器,并且可以通過calico將宿主機(jī)組織成任意的拓?fù)浼?。?dāng)集群中的容器需要與外界通信時(shí),就可以通過BGP協(xié)議將網(wǎng)關(guān)物理路由器加入到集群中,使外界可以直接訪問容器IP,而不需要做任何NAT之類的復(fù)雜操作。
當(dāng)容器通過calico進(jìn)行跨主機(jī)通信時(shí),其網(wǎng)絡(luò)通信模型如下圖所示:
docker詳解09

從上圖可以看出,當(dāng)容器創(chuàng)建時(shí),calico為容器生成veth pair,一端作為容器網(wǎng)卡加入到容器的網(wǎng)絡(luò)命名空間,并設(shè)置IP和掩碼,一端直接暴露在宿主機(jī)上,并通過設(shè)置路由規(guī)則,將容器IP暴露到宿主機(jī)的通信路由上。于此同時(shí),calico為每個(gè)主機(jī)分配了一段子網(wǎng)作為容器可分配的IP范圍,這樣就可以根據(jù)子網(wǎng)的CIDR為每個(gè)主機(jī)生成比較固定的路由規(guī)則。
當(dāng)容器需要跨主機(jī)通信時(shí),主要經(jīng)過下面的簡(jiǎn)單步驟:
容器流量通過veth pair到達(dá)宿主機(jī)的網(wǎng)絡(luò)命名空間上。
根據(jù)容器要訪問的IP所在的子網(wǎng)CIDR和主機(jī)上的路由規(guī)則,找到下一跳要到達(dá)的宿主機(jī)IP。
流量到達(dá)下一跳的宿主機(jī)后,根據(jù)當(dāng)前宿主機(jī)上的路由規(guī)則,直接到達(dá)對(duì)端容器的veth pair插在宿主機(jī)的一端,最終進(jìn)入容器。

從上面的通信過程來(lái)看,跨主機(jī)通信時(shí),整個(gè)通信路徑完全沒有使用NAT或者UDP封裝,性能上的損耗確實(shí)比較低。但正式由于calico的通信機(jī)制是完全基于三層的,這種機(jī)制也帶來(lái)了一些缺陷,例如:
calico目前只支持TCP、UDP、ICMP、ICMPv6協(xié)議,如果使用其他四層協(xié)議(例如NetBIOS協(xié)議),建議使用weave、原生overlay等其他overlay網(wǎng)絡(luò)實(shí)現(xiàn)。
基于三層實(shí)現(xiàn)通信,在二層上沒有任何加密包裝,因此只能在私有的可靠網(wǎng)絡(luò)上使用。
流量隔離基于iptables實(shí)現(xiàn),并且從etcd中獲取需要生成的隔離規(guī)則,有一些性能上的隱患。

注:文中圖片源自網(wǎng)絡(luò),感謝原作者的貢獻(xiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概述 自從docker容器出現(xiàn)以來(lái),容器的網(wǎng)絡(luò)通信就一直是大家關(guān)注的焦點(diǎn),也是生產(chǎn)環(huán)境的迫切需求。而容器的網(wǎng)絡(luò)通信...
    糙老爺們兒吃什么櫻桃閱讀 3,720評(píng)論 1 5
  • 前言 Weave 作為 Docker 跨主機(jī)集群網(wǎng)絡(luò)解決方案的一種,可以用于連接部署在多臺(tái)主機(jī)上的 Docker ...
    UCloud云計(jì)算閱讀 1,409評(píng)論 0 0
  • 基于對(duì)network namespace的控制,docker可以為在容器創(chuàng)建隔離的網(wǎng)絡(luò)環(huán)境,在隔離的網(wǎng)絡(luò)環(huán)境下,容...
    逑熙閱讀 3,587評(píng)論 0 4
  • 這段時(shí)間趕上了追劇的班車,每天端起小板凳看《急診科醫(yī)生》,作為災(zāi)難率趕超戰(zhàn)爭(zhēng)劇的一部醫(yī)療劇,主演個(gè)個(gè)都是超級(jí)...
    Cicy的竹蜻蜓閱讀 775評(píng)論 0 1
  • 老李頭是李家村的孤老頭,今年快80了。每天他都會(huì)獨(dú)自站在村橋頭發(fā)呆、張望,這一幕都成為了村里一景。今年春節(jié)回去...
    最愛27號(hào)閱讀 314評(píng)論 0 1

友情鏈接更多精彩內(nèi)容