一 Docker網路
1.1 Docker網路型別
標準的Docker支持以下4類網路模式:- host模式:使用--net=host指定,
- container模式:使用--net=container:NAME_or_ID指定,
- none模式:使用--net=none指定,
- bridge模式:使用--net=bridge指定,為默認設定,
二 bridge模式
2.1 bridge模型
在bridge模式下,Docker Daemon第1次啟動時會創建一個虛擬的網橋,默認的名稱是docker0,然后在私有網路空間中給這個網橋分配一個子網,針對由Docker創建的每一個容器,都會創建一個虛擬的以太網設備(Veth設備對),其中一端關聯到網橋上,另一端使用Linux的網路命名空間技術,映射到容器內的eth0設備,然后從網橋的地址段內給eth0介面分配一個IP地址, 如圖所示為Docker的默認橋接網路模型:
其中ip1是網橋的IP地址,Docker Daemon會在幾個備選地址段里給它選一個地址,通常是以172開頭的一個地址,這個地址和主機的IP地址是不重疊的,ip2是Docker在啟動容器時,在這個地址段選擇的一個沒有使用的IP地址分配給容器,相應的MAC地址也根據這個IP地址,在02:42:ac:11:00:00和02:42:ac:11:ff:ff的范圍內生成,這樣做可以確保不會有ARP沖突,
啟動后,Docker還將Veth對的名稱映射到eth0網路介面,ip3就是主機的網卡地址,
通常,ip1、ip2和ip3是不同的IP段,所以在默認不做任何特殊配置的情況下,在外部是看不到ip1和ip2的,
這樣做的結果就是,在同一臺機器內的容器之間可以相互通信,不同主機上的容器不能相互通信,實際上它們甚至有可能在相同的網路地址范圍內(不同主機上的docker0的地址段可能是一樣的),
為了讓它們跨節點互相通信,就必須在主機的地址上分配埠,然后通過這個埠路由或代理到容器上,這種做法顯然意味著一定要在容器之間小心謹慎地協調好埠的分配,或者使用動態埠的分配技術,
在不同應用之間協調好埠分配是十分困難的事情,特別是集群水平擴展時,而動態的埠分配也會帶來高度復雜性,例如:每個應用程式都只能將埠看作一個符號(因為是動態分配的,所以無法提前設定),
而且API Server要在分配完后,將動態埠插入配置的合適位置,服務也必須能互相找到對方等,這些都是Docker的網路模型在跨主機訪問時面臨的問題,
注意:更多跨主機的Docker通信方案,可參考《006.Docker網路管理》,
2.2 網路規則
- 查看Docker啟動后的系統情況
Docker創建了docker0網橋,并添加了iptables規則,docker0網橋和iptables規則都處于root命名空間中,對這些規則的說明如下:
- 在NAT表中有3條記錄,前兩條匹配生效后,都會繼續執行DOCKER鏈,而此時DOCKER鏈為空,所以前兩條只是做了一個框架,并沒有實際效果,
- NAT表第3條的含義是,若本地發出的資料包不是發往docker0的,即是發往主機之外的設備的,則都需要進行動態地址修改(MASQUERADE),將源地址從容器的地址(172段)修改為宿主機網卡的IP地址,之后就可以發送給外面的網路了,
- 在FILTER表中,第1條也是一個框架,因為后繼的DOCKER鏈是空的,
- 在FILTER表中,第3條是說,docker0發出的包,如果需要Forward到非docker0的本地IP地址的設備,則是允許的,這樣,docker0設備的包就可以根據路由規則中轉到宿主機的網卡設備,從而訪問外面的網路,
- FILTER表中,第4條是說,docker0的包還可以被中轉給docker0本身,即連接在docker0網橋上的不同容器之間的通信也是允許的,
- FILTER表中,第2條是說,如果接收到的資料包屬于以前已經建立好的連接,那么允許直接通過,這樣接收到的資料包自然又走回docker0,并中轉到相應的容器,
- 查看容器啟動后的情況(容器無埠映射)
- 宿主機器上的Netfilter和路由表都沒有變化,說明在不進行埠映射時,Docker的默認網路是沒有特殊處理的,相關的NAT和FILTER這兩個Netfilter鏈還是空的,
- 宿主機上的Veth對已經建立,并連接到容器內,
如上默認停止的回環設備lo已經被啟動,外面宿主機連接進來的Veth設備也被命名成了eth0,并且已經配置了地址172.17.0.2,路由資訊表包含一條到docker0的子網路由和一條到docker0的默認路由,
查看容器啟動后的情況(容器有埠映射)
[root@docker ~]# docker run --name register -d -p 1180:5000 registry #帶埠映射啟動registry
[root@docker ~]# iptables-save
如上新增的規則可以看出,Docker服務在NAT和FILTER兩個表內添加的兩個DOCKER子鏈都是給埠映射用的,在本例中我們需要把外面宿主機的1180埠映射到容器的5000埠,
通過分析可知,無論是宿主機接收到的還是宿主機本地協議堆疊發出的,目標地址是本地IP地址的包都會經過NAT表中的DOCKER子鏈,Docker為每一個埠映射都在這個鏈上增加了到實際容器目標地址和目標埠的轉換,經過這個DNAT的規則修改后的IP包,會重新經過路由模塊的判斷進行轉發,由于目標地址和埠已經是容器的地址和埠,所以資料自然就被轉發到docker0上,從而被轉發到對應的容器內部,
當然在Forward時,也需要在DOCKER子鏈中添加一條規則,如果目標埠和地址是指定容器的資料,則允許通過,在Docker按照埠映射的方式啟動容器時,主要的不同就是上述iptables部分,而容器內部的路由和網路設備,都和不做埠映射時一樣,沒有任何變化,
三 Docker網路局限
3.1 Docker的網路局限
從Docker對Linux網路協議堆疊的示例可知,Docker一開始沒有考慮到多主機互聯的網路解決方案,Docker一直以來的理念都是“簡單為美”,通常,虛擬化技術中最為復雜的部分就是虛擬化網路技術, 多主機互聯相關方案有Libnetwork,Libnetwork針對目前Docker的網路實作,Docker使用的Libnetwork組件只是將Docker平臺中的網路子系統模塊化為一個獨立庫的簡單嘗試,離成熟和完善還有一段距離, 提示:更多Docker網路實作方案參考:《007.基于Docker的Etcd分布式部署》、《008.Docker Flannel+Etcd分布式網路部署》,轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/122581.html
標籤:Linux
上一篇:linux下查看系統版本
