利用Net Namespace可以為Docker容器創(chuàng)建隔離的網(wǎng)絡(luò)環(huán)境,容器具有完全獨立的網(wǎng)絡(luò)棧,與宿主機隔離。也可以使Docker容器共享主機或者其他容器的網(wǎng)絡(luò)命名空間,基本可以滿足開發(fā)者在各種場景下的需要。
Docker網(wǎng)絡(luò)模式
Docker支持4種網(wǎng)絡(luò)模式:
1)host模式,--net=host指定,不支持多主機。
2)container模式,--net = container : name_or_id指定,不支持多主機。
3)none模式,--net=none指定,不支持多主機。
4)bridge模式,--net=bridge指定,默認設(shè)置,不支持多主機。
Host模式:除網(wǎng)絡(luò)命名空間外是隔離的
啟動容器的時候使用Host模式,那么該容器與宿主機共用一個Network Namespace,因此容器將不會虛擬自己的網(wǎng)卡、配置自己的IP等,而是使用宿主機的IP和端口。
采用Host模式的容器,可以直接使用宿主機的IP地址與外界進行通信,無需額外進行NAT轉(zhuǎn)換。由于容器通信時,不再需要通過Linux Bridge等方式轉(zhuǎn)發(fā)或者數(shù)據(jù)包的拆封,性能上有很大優(yōu)勢。當(dāng)然,Host模式有利也有弊,主要包括以下缺點:
1)容器沒有隔離、獨立的網(wǎng)絡(luò)棧。容器因與宿主機共用網(wǎng)絡(luò)棧而爭搶網(wǎng)絡(luò)資源,并且容器崩潰也可能導(dǎo)致宿主機崩潰,這在生產(chǎn)環(huán)境中是不允許發(fā)生的。
2)容器不再擁有所有的端口資源,因為一些端口已經(jīng)被宿主機服務(wù)、Bridge模式的容器端口綁定等其他服務(wù)占用了。
需要補充說明的是,Host模式下的容器僅僅是網(wǎng)絡(luò)命名空間與主機相同,但容器的文件系統(tǒng)、進程列表等還是和與宿主機隔離的。
Container模式:擁有相同命名空間的一組容器
Container模式是一種特殊的網(wǎng)絡(luò)模式。該模式下的容器使用其他容器的網(wǎng)絡(luò)命名空間,網(wǎng)絡(luò)隔離性會處于Bridge模式與Host模式之間。當(dāng)容器與其他容器共享網(wǎng)絡(luò)命名空間時,這兩個容器間不存在網(wǎng)絡(luò)隔離,但它們與宿主機及其他容器又存在網(wǎng)絡(luò)隔離。

在Kubernetes體系架構(gòu)下引入Pod概念,Kubernetes為Pod創(chuàng)建一個基礎(chǔ)設(shè)施容器,同一Pod下的其他容器都以Container模式共享這個基礎(chǔ)設(shè)施容器的網(wǎng)絡(luò)命名空間,相互之間以localhost訪問,構(gòu)成一個統(tǒng)一的整體。
None模式
與前兩種不同,None模式的Docker容器擁有自己的Network Namespace,但并不為Docker容器進行網(wǎng)絡(luò)配置。該Docker容器沒有網(wǎng)卡、IP、路由等信息。需要用戶為Docker容器添加網(wǎng)卡、配置IP等。
Bridge模式
Bridge模式是Docker默認的網(wǎng)絡(luò)模式,也是開發(fā)者最常使用的網(wǎng)絡(luò)模式。在這種模式下,Docker為容器創(chuàng)建獨立的網(wǎng)絡(luò)棧,保證容器內(nèi)的進程使用獨立的網(wǎng)絡(luò)環(huán)境,實現(xiàn)容器之間、容器與宿主機之間的網(wǎng)絡(luò)棧隔離。同時,通過宿主機上的Docker0網(wǎng)橋,容器可以與宿主機乃至外界進行網(wǎng)絡(luò)通信。

同一宿主機上,容器之間都是連接在Docker0這個網(wǎng)橋上,Docker0作為虛擬交換機使容器間相互通信。但是,由于宿主機的IP地址與容器veth pair的IP地址均不在同一個網(wǎng)段,故僅僅依靠veth pair和NameSpace的技術(shù)并不足以使宿主機以外的網(wǎng)絡(luò)主動發(fā)現(xiàn)容器的存在。Docker采用了端口綁定的方式(通過iptables的NAT),將宿主機上的端口流量轉(zhuǎn)發(fā)到容器內(nèi)的端口上,這樣一來,外界就可以與容器中的進程進行通信。iptables的介紹,請點我點我。
創(chuàng)建容器,并將宿主機的3306端口綁定到容器的3306端口:docker run -tid --name db -p 3306:3306 mysql
在宿主機上,可以通過“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
Bridge模式的容器與外界通信時,必定會占用宿主機上的端口,從而與宿主機競爭端口資源,這會造成對宿主機端口管理很復(fù)雜。同時,由于容器與外界通信是基于三層上iptables NAT,性能和效率損耗是顯而易見的。
NAT將地址空間分段的做法引入了額外的復(fù)雜度。比如容器中應(yīng)用所見的IP并不是對外暴露的IP,因為網(wǎng)絡(luò)隔離,容器中的應(yīng)用實際上只能檢測到容器的IP,但是需要對外宣稱的則是宿主機的IP,這種信息的不對稱將帶來諸如破壞自注冊機制等問題。
摘抄自陸平的《基于Kubernetes的容器云平臺實戰(zhàn)》一書的第10章Kubernetes網(wǎng)絡(luò)