Linux虛擬網路:Docker網路知識之基礎篇
我們在工作中應用了docker容器化技術,服務的部署、維護和擴充套件都方便了很多。然而,近期在私有化部署過程中,由於不同伺服器環境的複雜多變,常常遇到網路方面的問題,現象為容器服務執行正常,但宿主機、容器之間網路不通。
本篇部落格旨在總結:
- Linux虛擬網路及docker網路的基礎知識
- 遇到網路問題時排查問題思路
- 常用指令和工具的使用
以上三部分作為之後的參考,本篇文章也將會在日後實踐過程中逐漸補充。本篇為第一篇,主要介紹基礎知識
Linux網路虛擬化基礎
Network Namespace
網路名稱空間,是Linux 2.6.x核心版本之後提供的功能,主要用於資源的隔離。namespace是實現網路虛擬化的重要功能,使用它,一個Linux系統可以抽象出多個網路子系統,各個子系統都有自己獨立的網路卡、路由表、iptables、協議棧等網路資源。不管是虛擬機器器還是容器,執行時彷彿自己都在獨立的網路中。
ip netns
命令用於完成對ns的各種操作,ip netns exec
子命令用於在namespace執行指令。
Veth Pair(Virtual Ethernet Pair)
成對虛擬裝置埠。它總是成對出現,一端連著協議棧,一端彼此連著。從其中一個埠發出的資料包,可以直接出現在與它對應的另一個埠上,即使它們在不同的namespace中。
如上圖,一對veth-pair直接將兩個namespace連線在一起。
- 使用如下圖所示命令,測試veth pair功能
Bridge 網橋
veth pair打破了Network Namespace的限制,實現了不同Network Namespace之間的通訊。但是veth pair的侷限性也很明顯,只能實現兩個網路介面的通訊。
Linux中引入網橋來實現多個網路介面之間的通訊,可以將一臺機器上的若干介面連通起來。在OSI網路模型中,網橋屬於資料鏈路層。
和網橋相關的操作使用命令brctl
,需要先安裝bridge-utils
工具包。安裝指令:
yum install bridge-utils
iptables/Netfilter
Docker網路基礎
Docker支援四種網路模式:host模式,container模式,none模式和bridge模式。預設使用的是橋接模式。
使用docker network ls
指令可以檢視到宿主機上所有的Docker網路:
Bridge 橋接模式
Docker在啟動時,預設會自動建立網橋裝置docker0,Docker在執行時,守護程式通過docker0為docker的容器提供網路通訊服務。
當Docker啟動容器時,會建立一對Veth Pair,並將其中一個veth網路裝置附加到網橋docker0,另一個加入容器的network namespace中。
根據上一節中關於網橋的定義,我們很容易畫出示意圖:
由上圖可得,容器可以通過網橋互相通訊。如果不想使用預設的網橋裝置,也可以在啟動docker daemon的時候使用 --bridge==BRIDGE
引數指定其他網橋。
然而這還不夠,Docker容器還需要與外網進行相互通訊。這裡涉及到NAT相關知識。
- NAT
網路地址轉換,就是替換IP報文頭部的地址資訊。NAT通常部署在一個組織的網路出口位置,通過將內部網路IP地址替換為出口的IP地址,提供公網可達性和上層協議的連結地址。(請參考:NAT相關科普)- SNAT
源地址轉換即內網地址向外訪問時,發起訪問的內網ip地址轉換為指定的ip地址(可指定具體的服務以及相應的埠或埠範圍),這可以使內網中使用保留ip地址的主機訪問外部網路,即內網的多部主機可以通過一個有效的公網ip地址訪問外部網路。
使用iptables -t nat -vnL
指令檢視宿主機NAT表。
檢視規則:
2051 125K MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
這條規則就關係著Docker容器與外界的通訊,含義為將源地址為172.17.0.0/16的資料包(就是docker容器中發出的資料),如果不是從docker0網路卡發出時,做SNAT轉換,將IP包的源地址替換為相應網路卡的地址。
對於外界來說,從docker容器內發出的請求,和宿主機發出的請求相同。
外界想要訪問Docker容器的服務呢?
在啟動docker容器時,我們使用 -p
引數指定埠,這時其實是在iptables中添加了規則,如下圖所示:
DNAT規則,將傳送到宿主機的流量轉發到真正提供服務的容器IP埠上。
host模式
Docker容器與宿主機使用相同的網路環境,直接使用宿主機的IP和埠及其他網路裝置。這樣雖然避免了很多橋接帶來的網路問題,但同時也容易造成網路環境的混淆和衝突,比如埠被佔用等。不推薦。
container
指定與某一容器共享網路。
none
不配置任何網路。
--link
docker容器之間還可以通過--link
闡述進行通訊,當提供服務的容器只希望個別容器能夠訪問時,我們可以使用該指令,提供更為高效、安全的連線方式。
小結
對Linux虛擬網路基礎知識的簡單學習後,有助於理清楚下一步排查問題思路。
下一篇部落格將介紹目前遇到問題時的排查思路和解決方案,並列舉一些常用工具。