一 docker網絡模式
Docker使用Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離進程,Mount Namespace隔離文件系統,Network Namespace隔離網絡等。
一個Network Namespace提供了一份獨立的網絡環境,包括網卡、路由、Iptable規則等都與其餘的Network Namespace隔離,Docker容器通常會分配一個獨立的Network Namespace。
1.1 四種模式
指定方式:--net=host
指定方式:--net=container:NAME_or_ID
指定方式:--net=none
指定方式:--net=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。
注意:對以上3個文件的修改不會被docker commit保存,即不會保存在鏡像中,重啓容器也會致使修改失效。
四 多節點docker網絡
docker跨主機通訊按原理可經過如下三種方式實現:
- 直接路由方式;
- 橋接方式(如pipework);
- Overlay隧道方式(如flannel、ovs+gre)等。
Docker 多節點Overlay網絡模式能夠分爲兩類:
- 一類是基於 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/24@172.24.8.2
2 root@docker01:~# pipework br0 container02 172.24.8.202/24@172.24.8.2
3 root@docker02:~# pipework br0 container03 172.24.8.203/24@172.24.8.2
4 root@docker02:~# pipework br0 container04 172.24.8.204/24@172.24.8.2
若提示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網橋上。
注意:pipework經過link名字來判斷是bridge仍是ovs switch,br開頭爲網橋, ovs開頭爲openvswitch,因此pipework建立的網卡必須以br開頭。
也可經過如下命令手動提早建立網橋:
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會自動消失,須要從新設置。
4.3 基於etcd Docker原生overlay網絡
見《007.docker etcd分佈式網絡部署》
4.4 基於Flannel的overlay網絡
Overlay網絡指一種網絡架構上疊加的虛擬化技術模式,其大致框架是對基礎網絡不進行大規模修改的狀況下,實現應用在網絡上的承載,並能與其餘網絡業務分離,而且以基於IP的網絡技術爲主。
案例見《008.docker flannel+etcd分佈式網絡部署》