一 docker網路模式 Docker使用Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離進程,Mount Namespace隔離文件系統,Network Namespace隔離網路等。 一個Network Namespace提供了一份獨立的網路環境,包括網卡、路 ...
一 docker網路模式
Docker使用Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離進程,Mount Namespace隔離文件系統,Network Namespace隔離網路等。 一個Network Namespace提供了一份獨立的網路環境,包括網卡、路由、Iptable規則等都與其他的Network Namespace隔離,Docker容器一般會分配一個獨立的Network Namespace。1.1 四種模式
- host模式
- container模式
- none模式
- bridge模式
1 root@docker:~# docker network ls #預設已經創建好三種模式,且無法刪除 2 NETWORK ID NAME DRIVER SCOPE 3 4237839afd99 bridge bridge local 4 c7a14aafc3b5 host host local 5 3cc2eba3eb5f none null local
1.2 host模式
容器網路指定為host模式,則容器將不會獲得獨立的Network Namespace,該模式下宿主機共用一個Network Namespace。容器將不會虛擬出自己的網卡,不會配置獨有的IP等,而是使用宿主機的IP和埠。 其具有以下特點:- host模式下的容器沒有隔離的 network namespace;
- 容器的 IP 地址同 Docker host 的 IP 地址;
- 需要註意容器中服務的埠號不能與 Docker host 上已經使用的埠號相衝突;
- host 模式能夠和其它模式共存。
1 root@docker:~# docker run -d --name docker_host1 --network host training/webapp python app.py 2 root@docker:~# docker exec -it docker_host1 /bin/bash 3 root@docker:/opt/webapp# ifconfig -a宿主機172.24.8.90/24上使用host模式啟動一個容器,則查看的網卡信息為宿主機信息,容器中的應用對外直接採用宿主機IP地址提供服務,無任何NAT轉換。 註意:除網路外,容器的其他方面,如文件系統、進程列表等還是和宿主機隔離的,同時採用host模式,埠無法做映射,無需指定,否則會出現warning告警。
1.3 container模式
Container 網路模式是 Docker 中一種較為特別的網路的模式,處於container模式下的 Docker 容器會共用其他容器的網路環境,因此,兩個或以上的容器之間不存在網路隔離,而配置container模式的容器又與宿主機以及除此之外其他的容器存在網路隔離。1 root@docker:~# docker run -dit --name docker_host2 centos7-xhy /bin/bash 2 root@docker:~# docker run -dit --name docker_host3 --network container:docker_host2 centos7-xhy /bin/bash 3 root@docker:~# docker exec -it docker_host2 /bin/bash 4 [root@c9b51e88f75a /]# ifconfig -a
1 root@docker:~# docker exec -it docker_host3 /bin/bash 2 [root@c9b51e88f75a /]# ifconfig -a註意:因為此時兩個容器要共用一個 network namespace,因此需要註意埠衝突情況,否則第二個容器將無法被啟動,以上docker_host3因為埠原因,無法正常啟動。
1.4 none模式
none模式下,Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網路配置和構造任何網路環境。 Docker 容器採用了none 網路模式,那麼容器內部就只能使用loopback網路設備,不會再有其他的網路資源。Docker Container的none網路模式意味著不給該容器創建任何網路環境,容器只能使用127.0.0.1的本機網路。1 root@docker:~# docker run -dit --name docker_host4 --network none centos7-xhy /bin/bash 2 root@docker:~# docker exec -it docker_host4 /bin/bash
1.5 bridge模式
見二。二 bridge模式
2.1 bridge模式簡介
bridge模式是Docker預設的網路設置,此模式會為每一個容器分配Network Namespace、設置IP等,並將該宿主機上的Docker容器連接到一個虛擬網橋上。 使用docker run -p時,docker會在iptables寫入DNAT規則,實現埠轉發功能。可使用以下命令查看。 1 root@docker:~# iptables -t nat -vnL
當Docker server啟動時,會在主機上創建一個名為docker0的虛擬網橋,此主機上啟動的Docker容器會連接到此虛擬網橋上,因此所有連接到此網橋的容器預設能互相通信。
虛擬網橋會使該宿主機上所有容器就通過交換機連在了一個二層網路中,宿主機會選擇一個和宿主機不同的IP地址和子網分配給docker0,連接到docker0的容器就從此子網中選擇一個未占用的IP使用。
2.2 bridge模式特點
- 使用一個 linux bridge,預設為 docker0;
- 使用 veth 對,一端在容器的網路 namespace 中,另一端在 docker0 上;
- 該模式下Docker Container不具有一個公有IP,因為宿主機的IP地址與veth pair的 IP地址不在同一個網段內;
- Docker採用 NAT 方式,將容器內部的服務監聽的埠與宿主機的某一個埠port 進行“綁定”,使得宿主機以外的網路可以主動將網路報文發送至容器內部;
- 外界訪問容器內的服務時,需要訪問宿主機的 IP 以及宿主機的埠 port;
- NAT 模式基於三層網路上的實現方式,故肯定會影響網路的傳輸效率;
- 容器擁有獨立、隔離的網路棧,以便於使得容器和宿主機以外的網路通過NAT建立通信;
1 root@docker:~# docker run -dit --name docker_host5 -p 5005:80 training/webapp python app.py 2 root@docker:~# docker exec -it docker_host5 /bin/bash 3 root@951e6cd51cd0:/opt/webapp# ifconfig -a
1 root@docker:~# iptables -t nat -vnL #查看埠映射
1 root@docker:~# iptables-save 2 …… 3 -A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 80 -j MASQUERADE 4 …… 5 -A DOCKER ! -i docker0 -p tcp -m tcp --dport 5005 -j DNAT --to-destination 172.17.0.3:80解釋: -s :源地址172.17.0.0/16 -o:指定數據報文流出介面為docker0 -j :動作為MASQUERADE(地址偽裝) iptables規則中nat、filter的Docker鏈中分別增加了一條規則,這兩條規則將訪問宿主機5005埠的流量轉發到了172.17.0.3的80埠上,即真正提供服務的Docker容器IP和埠,因此外界訪問Docker容器是通過iptables做DNAT(目的地址轉換)實現。
三 docker容器的DNS和主機名
3.1 DNS和主機名配置文件
同一個Docker鏡像可以啟動很多Docker容器,但各自容器的主機名並不一樣,即主機名並非是被寫入鏡像中。 通過在容器中運行mount命令可以查看/etc/目錄下有3個文件,即容器啟動後被虛擬文件覆蓋的,分別是/etc/hostname、/etc/hosts、/etc/resolv.conf:1 root@docker:~# docker run -dit --name docker_host6 centos7-xhy /bin/bash 2 root@docker:~# docker exec -it docker_host6 /bin/bash 3 [root@12ac200c6a4c /]# mount 4 ... 5 /dev/sda4 on /etc/resolv.conf type ext4 (rw,relatime,data=ordered) 6 /dev/sda4 on /etc/hostname type ext4 (rw,relatime,data=ordered) 7 /dev/sda4 on /etc/hosts type ext4 (rw,relatime,data=ordered) 8 ...提示:此方式能解決主機名的問題,同時也能讓DNS及時更新(改變resolv.conf)。由於這些文件的維護方法隨著Docker版本演進而不斷變化,因此儘量不修改這些文件。
3.2 修改dns和主機名
docker容器的dns和主機名配置可通過Docker提供的參數進行相關設置,配置方式如下:- -h HOSTNAME 或 --hostname=HOSTNAME:設置容器的主機名,此名稱會寫入/etc/hostname和/etc/hosts文件中,也會在容器的bash提示符看到。但是在外部,容器的主機名是無法查看的,不會出現在其他容器的hosts文件中,即使使用docker ps命令也無法查看。此參數是docker run命令的參數,而非docker daemon的啟動參數。
- --dns=IP_ADDRESS...:為容器配置DNS,寫入/etc/resolv.conf中。該參數可以在docker daemon 啟動的時候設置,也可以在docker run時設置,預設為8.8.8.8或8.8.4.4。
四 多節點docker網路
docker跨主機通信按原理可通過以下三種方式實現:- 直接路由方式;
- 橋接方式(如pipework);
- Overlay隧道方式(如flannel、ovs+gre)等。
- 一類是基於 VxLAN ,對跨節點網路的原生支持;
- 另一種是通過插件(plugin)方式引入的第三方實現方案,比如 Flannel,Calico 等等。
4.1 直接路由方式
在docker所在的不同宿主機上採用靜態路由方式實現。4.2 橋接-pipework方式
當兩台網路已聯通的宿主機01和02都存在多個容器組成的集群時,需要相互訪問容器應用時,可通過靜態指定容器IP為宿主機IP同一個網路的形式,即可實現。1 root@docker01:~# apt-get install bridge-utils #兩台docker宿主機都建議安裝此工具 2 root@docker02:~# apt-get install bridge-utils #兩台docker宿主機都建議安裝此工具 3 root@docker01:~# docker run -dit --name container01 --net=none centos:7 /bin/bash 4 root@docker01:~# docker run -dit --name container02 --net=none centos:7 /bin/bash 5 root@docker02:~# docker run -dit --name container03 --net=none centos:7 /bin/bash 6 root@docker02:~# docker run -dit --name container04 --net=none centos:7 /bin/bash 7 8 root@docker01:~# git clone https://github.com/jpetazzo/pipework 9 root@docker02:~# git clone https://github.com/jpetazzo/pipework 10 root@docker01:~# cp pipework/pipework /usr/local/bin/ 11 root@docker02:~# cp pipework/pipework /usr/local/bin/ 12 root@docker01:~# chmod u+x /usr/local/bin/pipework 13 root@docker01:~# brctl show #查看當前預設的橋接網卡
1 root@docker01:~# pipework br0 container01 172.24.8.201/[email protected] 2 root@docker01:~# pipework br0 container02 172.24.8.202/[email protected] 3 root@docker02:~# pipework br0 container03 172.24.8.203/[email protected] 4 root@docker02:~# pipework br0 container04 172.24.8.204/[email protected]若提示Warning: arping not found,可採用以下方式安裝:apt-get -y install arping
1 root@docker01:~# brctl show
1 root@docker02:~# brctl show
提示:
pipework通過network namespace,veth pair以及linux bridge完成容器網路的設置,執行過程大概如下:
- 查看主機是否包含br0(可以自定義)網橋,如果不存在就創建;
- 向容器實例添加一塊網卡(可以設置網卡名),並配置相應的固定IP;
- 若容器實例已經有預設的路由,則刪除掉,將@後面的IP設置為預設路由的網關;
- 將容器實例連接到創建的br0網橋上。
1 root@docker01:~# docker network create --driver bridge --subnet 172.24.8.0/24 --gateway 172.24.8.2 br1 2 root@docker:~# docker network inspect br1
1 root@docker01:~# ip addr add 172.24.8.90/24 dev br0;\ 2 ip addr del 172.24.8.90/24 dev eth0;\ 3 brctl addif br0 eth0;\ 4 ip route del default;\ 5 ip route add default via 172.24.8.2 dev br0 6 root@docker02:~# ip addr add 172.24.8.91/24 dev br0 ;\ 7 ip addr del 172.24.8.91/24 dev eth0;\ 8 brctl addif br0 eth0;\ 9 ip route del default;\ 10 ip route add default via 172.24.8.2 dev br0提示:將兩台宿主機eth0橋接到br0上,並把eth0的IP配置在br0上。
1 root@docker01:~# ping 172.24.8.201
註意:pipework設置固定IP的情況下,容器重啟後IP會自動消失,需要重新設置。