Docker系列04—跨主機網路方案(overlay/weave)
在前面詳細講解了幾種網路模式:none,host,bridge,container。他們解決了單個主機間的容器的通訊問題,並不能實現多個主機容器之間的通訊。
跨主機網路方案包括兩大類:
1,docker原生的:overlay和macvlan
2,第三方方案:flannel、weave和calico
overlay
Docker overlay網路需要一個key-value資料庫用於儲存網路狀態資訊,包括Network、Endpoint、IP等。
consul、Etcd、Zookeeper都是Docker支援的key-value軟體,這裡我們使用consul。
在docker主機docker01(10.0.0.11)和docker02(10.0.0.12)上實踐各種跨主機網路方案,在10.0.0.11上部署支援的元件,比如consul。
第一步:啟動路由轉發功能
【兩臺主機都需開啟】
[root@docker01 ~]# echo "1" > /proc/sys/net/ipv4/ip_forward [root@docker02 ~]# echo "1" > /proc/sys/net/ipv4/ip_forward
第二步:執行consul
以容器的方式執行consul
[root@docker01 ~]# systemctl restart docker [root@docker01 ~]# systemctl enable docker [root@docker01 ~]# docker pull progrium/consul Using default tag: latest latest: Pulling from progrium/consul [root@docker01 ~]# docker run -d -p 8500:8500 -h consul --name consul --restart=always progrium/consul -server -bootstrap ### 其中 -h 為指定容器內部的主機名;--restart=always 為docker啟動時,此容器自動啟動;-server -bootstrap 表示當在群集中,加上這兩個選項可以使其以master的身份出現 [root@docker01 ~]# netstat -lntp | grep 8500 tcp6 0 0 :::8500 :::* LISTEN 1576/docker-proxy
第三步:瀏覽器訪問
通過ip+port的方式訪問
第四步:修改docker啟動檔案
需要修改的是docker01和docker02的docker daemon 的配置檔案。
【注】在這裡我們使用的是兩臺。如果是3臺,可以為3臺都設定:表示這3臺準備跨主機;也可以將第一臺設定為只存放consul,2,3臺修改配置檔案即可:表示後兩臺準備跨主機。
【注】只修改[Service]內容即可
[root@docker01 ~]# cat /usr/lib/systemd/system/docker.service ... [Service] Type=notify # the default is not to use systemd for cgroups because the delegate issues still # exists and systemd currently does not support the cgroup feature set required # for containers run by docker ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://10.0.0.11:8500 --cluster-advertise=eth0:2376 # ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always ... ### 各項解釋如下 # /var/run/docker.sock 表示Docker的一個程式設計介面; # '-H tcp://0.0.0.0:2376' 表示使用本機的2376/tcp埠; # '--cluster-store=consul://10.0.0.11:8500' 表示運行了consul的伺服器IP和埠 # '--cluster-advertise=eth0:2376' 表示從本機的eth0網絡卡通過2376埠收集網路資訊,也有可能是ens33。
[root@docker02 ~]# cat /usr/lib/systemd/system/docker.service ... [Service] Type=notify # the default is not to use systemd for cgroups because the delegate issues still # exists and systemd currently does not support the cgroup feature set required # for containers run by docker ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://10.0.0.11:8500 --cluster-advertise=eth0:2376 # ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always ...
重新載入docker daemon,修改了檔案的服務都需要重啟
[root@docker01 ~]# systemctl daemon-reload [root@docker01 ~]# systemctl restart docker
這裡注意,如果consul容器沒有設定為自啟,那麼需要手動啟動
[root@docker02 ~]# systemctl daemon-reload [root@docker02 ~]# systemctl restart docker
第五步:瀏覽器檢視
這時發現兩個主機已經註冊上去了
第六步:建立overlay網路
在docker01上建立網路ov_ken
[root@docker01 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE c8d69c4c3ffe bridge bridge local f5d3339712b4 host host local 93359dad0336 none null local [root@docker01 ~]# docker network create -d overlay ov_ken [root@docker01 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE c8d69c4c3ffe bridge bridge local f5d3339712b4 host host local 93359dad0336 none null local 70c2c8b47ead ov_ken overlay global ### 這個時候docker02上不用新增就會自動新增 [root@docker02 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 7c9560f3b566 bridge bridge local e76394dcf8f8 host host local 4cdde3f7dce2 none null local 70c2c8b47ead ov_ken overlay global ### 因為建立ov_ken時docker01將overlay網路資訊存入了consul,docker02從consul讀取了新網路的資料。
檢視網路資訊
[root@docker01 ~]# docker network inspect ov_ken [ { "Name": "ov_ken", "Id": "70c2c8b47ead8af423a6b562aba42f1106454b58577c27cf47143a9eacdb419a", "Created": "2020-04-13T11:47:08.079686153+08:00", "Scope": "global", "Driver": "overlay", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "10.0.0.0/24", "Gateway": "10.0.0.1" } ] }, ### 由此可以看出docker自動為ov_ken分配的ip地址空間為10.0.0.0/24
在overlay網路中執行容器
執行一個busybox容器並使用overlay網路
[root@docker01 ~]# docker run -d -it --name busybox --network ov_ken busybox:latest 3492931078a8d2cf2a7e77b7a8518c3f89f64c0b803a79ffc9742965581d96fa
6.1 跨主機連通
在docker02上執行新的容器
[root@docker02 ~]# docker run -it -d --name busybox_02 --network ov_ken busybox:latest 53e708b68a31d5f08bce6f949426e64ce333e4ee9f28396271b2a6eb3daad182
檢視容器的網路
[root@docker02 ~]# docker exec busybox_02 ip r default via 172.18.0.1 dev eth1 10.0.0.0/24 dev eth0 scope link src 10.0.0.3 172.18.0.0/16 dev eth1 scope link src 172.18.0.2
測試使用docker01上的容器ping docker02上的容器
[root@docker01 ~]# docker exec busybox ip r default via 172.18.0.1 dev eth1 10.0.0.0/24 dev eth0 scope link src 10.0.0.2 172.18.0.0/16 dev eth1 scope link src 172.18.0.2 [root@docker01 ~]# docker exec busybox ping -c 2 10.0.0.3 PING 10.0.0.3 (10.0.0.3): 56 data bytes 64 bytes from 10.0.0.3: seq=0 ttl=64 time=3.657 ms 64 bytes from 10.0.0.3: seq=1 ttl=64 time=0.351 ms --- 10.0.0.3 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.351/2.004/3.657 ms
至此:overlay容器是可以直接通訊,同時docker也實現了DNS服務。
6.2 overlay網路隔離
不同的overlay網路是相互隔離的。我們建立第二個overlay網路ov_ken2並執行容器
[root@docker01 ~]# docker network create -d overlay ov_ken2 0dd70337a3f1504c9d24891c9e37d74af35abcad0ce3751ac0efa5ad138cb12c [root@docker01 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE c8d69c4c3ffe bridge bridge local 2436e5e8c848 docker_gwbridge bridge local f5d3339712b4 host host local 93359dad0336 none null local 70c2c8b47ead ov_ken overlay global 0dd70337a3f1 ov_ken2 overlay global [root@docker01 ~]# docker run -d -it --name busybox_03 --network ov_ken2 busybox:latest a5963fd6a9b863613269f773069fa99630fc88d7af49a3b355e78c9060858699 [root@docker01 ~]# docker exec busybox_03 ip r default via 172.18.0.1 dev eth1 10.0.1.0/24 dev eth0 scope link src 10.0.1.2 172.18.0.0/16 dev eth1 scope link src 172.18.0.3 ### 在這裡我們能看到docker給第二個overlay分配的ip地址為10.0.1.0/24 [root@docker01 ~]# docker exec busybox_03 ping -c 2 10.0.0.3 PING 10.0.0.3 (10.0.0.3): 56 data bytes --- 10.0.0.3 ping statistics --- 2 packets transmitted, 0 packets received, 100% packet loss ### 在這裡我們發現ov_ken和ov_ken2並不互通
如果要實現busybox_03和busybox_02的互通,可以將busybox_03也連線到ov_ken網路上
[root@docker01 ~]# docker network connect ov_ken busybox_03 ### 意思為,將busybox_03新增到ov_ken網路 [root@docker01 ~]# docker exec busybox_03 ip r default via 172.18.0.1 dev eth1 10.0.0.0/24 dev eth2 scope link src 10.0.0.4 10.0.1.0/24 dev eth0 scope link src 10.0.1.2 172.18.0.0/16 dev eth1 scope link src 172.18.0.3 ### 這個時候會發現busybox_03會被新增一個新的ov_ken的網段IP [root@docker01 ~]# docker exec busybox_03 ping -c 2 10.0.0.3 PING 10.0.0.3 (10.0.0.3): 56 data bytes 64 bytes from 10.0.0.3: seq=0 ttl=64 time=6.571 ms 64 bytes from 10.0.0.3: seq=1 ttl=64 time=0.411 ms --- 10.0.0.3 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.411/3.491/6.571 ms
weave
weave不依賴分散式資料庫(例如etcd和consul)交換網路資訊,每個主機上只需要執行weave元件就能建立起跨主機容器網路。接下來在docker01和docker02上部署weave並實踐weave的各項特性
一、安裝部署weave
weave安裝非常簡單,在docker01和docker02上執行如下命令:
[root@docker01 ~]# curl -L git.io/weave -o /usr/local/bin/weave [root@docker01 ~]# chmod a+x /usr/local/bin/weave [root@docker02 ~]# curl -L git.io/weave -o /usr/local/bin/weave [root@docker02 ~]# chmod a+x /usr/local/bin/weave
在docker01上啟動weave
[root@docker01 ~]# weave launch
注:在執行weave launch命令,啟動weave相關服務。weave所有的元件都是以容器的方式執行的,會自動從docker hub上獲取最新的image並啟動容器
檢視啟動的容器
[root@docker01 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e089485df46f weaveworks/weave:2.6.2 "/home/weave/weaver …" 55 seconds ago Up 54 seconds weave
weave運行了一個容器:
weave是主程式,負責建立weave網路,收發資料,提供DNS服務等
在docker01中啟動容器
[root@docker01 ~]# eval $(weave env) [root@docker01 ~]# docker run -d -it --name busybox_01 --rm busybox:latest a1a4f0931a65b36067f8d27e6474fee584d003ac302e9c7ac4e517f48b0d46a2
注意:在這裡因為是測試,用到了 --rm :關閉即刪除,刪除,刪除 !!
首先執行 eval $(weave env) 很重要,其作用是將後續的docker命令傳送給weave proxy處理,如果要恢復之前的環境,可執行eval $(weave env --restore)。
檢視當前容器busybox_01的網路配置
[root@docker01 ~]# docker exec busybox_01 ip r default via 172.17.0.1 dev eth0 10.32.0.0/12 dev ethwe scope link src 10.32.0.1 172.17.0.0/16 dev eth0 scope link src 172.17.0.2 224.0.0.0/4 dev ethwe scope link ### 由此可以看出,docker給其分配的地址為10.32.0.0/12網段,並且IP地址為10.32.0.1 ### 而且busybox_01有兩個網路介面eth0和ethwe,其中eth0是預設連線的bridge網路,即網橋docker0。分配的IP 10.32.0.1/12 ethwe與weave相關
在當前主機上再執行一個容器
[root@docker01 ~]# docker run -d -it --name busybox_02 --rm busybox:latest 88f208a2ca486eccc346ed7239f44836587796ce7898f48b65e162bfebe522e6 [root@docker01 ~]# docker exec busybox_02 ip r default via 172.17.0.1 dev eth0 10.32.0.0/12 dev ethwe scope link src 10.32.0.2 172.17.0.0/16 dev eth0 scope link src 172.17.0.3 224.0.0.0/4 dev ethwe scope link
測試同一個主機上的busybox_01和busybox_02的連通性
[root@docker01 ~]# docker exec busybox_01 ping -c 2 busybox_02 PING busybox_02 (10.32.0.2): 56 data bytes 64 bytes from 10.32.0.2: seq=0 ttl=64 time=0.051 ms 64 bytes from 10.32.0.2: seq=1 ttl=64 time=0.050 ms --- busybox_02 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.050/0.050/0.051 ms ### 在這裡是可以連通的,並且還可以解析
二、weave跨主機通訊
第一步:再docker02上執行以下命令
[root@docker02 ~]# weave launch 10.0.0.11 ## 格式 weave launch [docker01的ip地址]
這裡必須指定docker01的ip地址,這樣docker01和docker02才能加入到同一個weave網路。
第二步:開啟路由轉發功能
[root@docker01 ~]# echo "1">/proc/sys/net/ipv4/ip_forward [root@docker02 ~]# echo "1">/proc/sys/net/ipv4/ip_forward
第三步:啟動容器
[root@docker02 ~]# docker run -d -it --name busybox_03 --rm busybox:latest 82503c97ee984d5a330f635eeca825edc795c7ef96a8fc592da9dc8598764594
第四步:測試連通性
[root@docker02 ~]# docker exec busybox_03 ping -c 2 busybox_02 PING busybox_02 (10.32.0.2): 56 data bytes 64 bytes from 10.32.0.2: seq=0 ttl=64 time=1.477 ms 64 bytes from 10.32.0.2: seq=1 ttl=64 time=1.187 ms --- busybox_02 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 1.187/1.332/1.477 ms ### 可以發現主機docker02上執行的容器可以與docker01上的容器通訊,而且可以解析主機名
三、weave網路隔離
預設配置下,weave使用一個大subnet(例如10.32.0.0/12),所有的主機的容器都是從這個地址空間中分配IP,因為同屬一個subnet,容器可以直接通訊。如果要實現網路隔離,可以通過環境變數WEAVE_CIDR為容器分配不同的subnet的IP,舉例如下:
[root@docker02 ~]# docker run -d -it -e WEAVE_CIDR=net:10.32.2.0/24 --name busybox_04 --rm busybox:latest d3a4430bbc111c9f7eca1ab9c4b6f432f63d9e45d66ea0d0d66b3dfecfa75eb6
在這裡WEAVE_CIDR=net:10.32.2.0/24的作用是使容器分配到IP 10.32.2.2。由於10.32.0.0/12 與 10.32.2.0/24位於不同的subnet,所以無法ping到busybox_02。
[root@docker02 ~]# docker exec busybox_04 ping -c 2 busybox_02 PING busybox_02 (10.32.0.2): 56 data bytes --- busybox_02 ping statistics --- 2 packets transmitted, 0 packets received, 100% packet loss
當然也無法ping同同主機上的busybox_03
除了subnet,我們還可以直接為容器分配特定的ip:
[root@docker02 ~]# docker run -d -it -e WEAVE_CIDR=ip:10.32.6.6/24 --name busybox_05 busybox:latest b2eccb69e37e5da8558237163103f050a3efc118cf71bf11c62c68b572e2b8a6 [root@docker02 ~]# docker exec busybox_05 ip r default via 172.17.0.1 dev eth0 10.32.6.0/24 dev ethwe scope link src 10.32.6.6 172.17.0.0/16 dev eth0 scope link src 172.17.0.4 224.0.0.0/4 dev ethwe scope link
四、weave與外網的連通性
weave是一個私有的VLAN網路(容器可以訪問外網),預設與外部網路隔離。外部網路如何才能訪問到weave中的容器呢?
答案:
-
首先將主機加入到weave網路。
-
然後把主機當作訪問的閘道器。
第一步:要將主機加入到weave,執行weave expose。
[root@docker02 ~]# weave expose 10.32.2.129
第二步:檢視ip
這個10.32.2.129會被配置到host2的weave網橋上。
[root@docker02 ~]# ip a
...
13: weave: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue state UP qlen 1000
link/ether c6:77:0c:f6:e2:29 brd ff:ff:ff:ff:ff:ff
inet 10.32.2.129/12 brd 10.47.255.255 scope global weave
valid_lft forever preferred_lft forever
inet6 fe80::c477:cff:fef6:e229/64 scope link
valid_lft forever preferred_lft forever
第三步:測試連通性
ping同一主機的busybox_03
[root@docker02 ~]# docker exec busybox_03 ip r default via 172.17.0.1 dev eth0 10.32.0.0/12 dev ethwe scope link src 10.44.0.0 172.17.0.0/16 dev eth0 scope link src 172.17.0.2 224.0.0.0/4 dev ethwe scope link [root@docker02 ~]# ping -c 2 10.44.0.0 PING 10.44.0.0 (10.44.0.0) 56(84) bytes of data. 64 bytes from 10.44.0.0: icmp_seq=1 ttl=64 time=0.123 ms 64 bytes from 10.44.0.0: icmp_seq=2 ttl=64 time=0.048 ms --- 10.44.0.0 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.048/0.085/0.123/0.038 ms
ping docker01上的busybox_01
[root@docker01 ~]# docker exec busybox_01 ip r default via 172.17.0.1 dev eth0 10.32.0.0/12 dev ethwe scope link src 10.32.0.1 172.17.0.0/16 dev eth0 scope link src 172.17.0.2 224.0.0.0/4 dev ethwe scope link [root@docker02 ~]# ping -c 2 10.32.0.1 PING 10.32.0.1 (10.32.0.1) 56(84) bytes of data. 64 bytes from 10.32.0.1: icmp_seq=1 ttl=64 time=2.16 ms 64 bytes from 10.32.0.1: icmp_seq=2 ttl=64 time=0.337 ms --- 10.32.0.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 0.337/1.252/2.168/0.916 ms
接下來要讓其他非weave主機訪問到busybox_01和busybox_03,只需要將閘道器指向docker01。例如在新的主機docker03上新增如下路由:
[root@docker03 ~]# ip route add 10.32.0.0/12 via 10.0.0.11 [root@docker03 ~]# ping -c 2 10.32.0.1 PING 10.32.0.1 (10.32.0.1) 56(84) bytes of data. 64 bytes from 10.32.0.1: icmp_seq=1 ttl=63 time=1.45 ms 64 bytes from 10.32.0.1: icmp_seq=2 ttl=63 time=2.25 ms --- 10.32.0.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 1.450/1.852/2.254/0.402 ms
注意:10.32.0.0/12是weave網路使用的預設subnet,如果此地址空間與現有IP衝突,可以通過--ipalloc-range 分配特定的subnet。
weave launch --ipalloc-range 10.2.0.0/16
不過需要確保所有的host都使用相同的subnet
【注意】如果出現以下情況
[root@docker02 ~]# docker ps Cannot connect to the Docker daemon at unix:///var/run/weave/weave.sock. Is the docker daemon running?
需要執行
[root@docker02 ~]# eval $(weave env --restore)