<code>在Docker版本1.12之後swarm模式原生支援覆寫網絡(overlay networks),可以先建立一個覆寫網絡,然後啟動容器的時候啟用這個覆寫網絡,</code>
<code>這樣隻要是這個覆寫網絡内的容器,不管在不在同一個主控端上都能互相通信,即跨主機通信!不同覆寫網絡内的容器組之間是互相隔離的(互相</code><code>ping</code><code>不通)。</code>
<code> </code>
<code>swarm模式的覆寫網絡包括以下功能:</code>
<code>1)可以附加多個服務到同一個網絡。</code>
<code>2)預設情況下,service discovery為每個swarm服務配置設定一個虛拟IP位址(vip)和DNS名稱,使得在同一個網絡中容器之間可以使用服務名稱為互相連接配接。</code>
<code>3)可以配置使用DNS輪循而不使用VIP</code>
<code>4)為了可以使用swarm的覆寫網絡,在啟用swarm模式之間你需要在swarm節點之間開放以下端口:</code>
<code>5)TCP</code><code>/UDP</code><code>端口7946 – 用于容器網絡發現</code>
<code>6)UDP端口4789 – 用于容器覆寫網絡</code>
<code>執行個體如下:</code>
<code>-----------在Swarm叢集中建立overlay網絡------------</code>
<code>[root@manager-node ~]</code><code># docker network create --driver overlay --opt encrypted --subnet 10.10.110.0/24 ngx_net</code>
<code>參數解釋:</code>
<code>–opt encrypted 預設情況下swarm中的節點通信是加密的。在不同節點的容器之間,可選的–opt encrypted參數能在它們的vxlan流量啟用附加的加密層。</code>
<code>--subnet 指令行參數指定overlay網絡使用的子網網段。當不指定一個子網時,swarm管理器自動選擇一個子網并配置設定給網絡。</code>
<code>[root@manager-node ~]</code><code># docker network ls</code>
<code>NETWORK ID NAME DRIVER SCOPE</code>
<code>ca221724531c bridge bridge </code><code>local</code>
<code>10d1451ecc8d docker_gwbridge bridge </code><code>local</code>
<code>5764ade8774b host host </code><code>local</code>
<code>50kipkihuwxy ingress overlay swarm </code>
<code>cz4b4ht5refq ngx_net overlay swarm </code>
<code>f2af952cd27a none null </code><code>local</code>
<code>由上可知,Swarm當中擁有2套覆寫網絡。其中</code><code>"ngx_net"</code><code>網絡正是我們在部署容器時所建立的成果。而</code><code>"ingress"</code><code>覆寫網絡則為預設提供。</code>
<code>Swarm 管理節點會利用 ingress 負載均衡以将服務公布至叢集之外。</code>
<code>在将服務連接配接到這個建立的網絡之前,網絡覆寫到manager節點。上面輸出的SCOPE為 swarm 表示将服務部署到Swarm時可以使用此網絡。</code>
<code>在将服務連接配接到這個網絡後,Swarm隻将該網絡擴充到特定的worker節點,這個worker節點被swarm排程器配置設定了運作服務的任務。</code>
<code>在那些沒有運作該服務任務的worker節點上,網絡并不擴充到該節點。</code>
<code>------------------将服務連接配接到overlay網絡-------------------</code>
<code>[root@manager-node ~]</code><code># docker service create --replicas 5 --network ngx_net --name my-test -p 80:80 nginx</code>
<code>上面名為</code><code>"my-test"</code><code>的服務啟動了3個task,用于運作每個任務的容器都可以彼此通過overlay網絡進行通信。Swarm叢集将網絡擴充到所有任務處于Running狀态的節點上。</code>
<code>[root@manager-node ~]</code><code># docker service ls</code>
<code>ID NAME REPLICAS IMAGE COMMAND</code>
<code>9vgixbn6t2ju my-</code><code>test</code> <code>5</code><code>/5</code> <code>nginx </code>
<code>在manager-node節點上,通過下面的指令檢視哪些節點有處于running狀态的任務:</code>
<code>[root@manager-node ~]</code><code># docker service ps my-test</code>
<code>ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR</code>
<code>eh2mo4ei8qah5d9eolx8yapey my-</code><code>test</code><code>.1 nginx manager-node Running Running about a minute ago </code>
<code>7gg40e57rko5frttqdx9x7ae2 my-</code><code>test</code><code>.2 nginx node2 Running Running about a minute ago </code>
<code>1vp1d7cwmn8m6a5k0wtq9xi75 my-</code><code>test</code><code>.3 nginx node1 Running Running about a minute ago </code>
<code>03nb3ev2r7sxcilkwizoetx9w my-</code><code>test</code><code>.4 nginx node1 Running Running about a minute ago </code>
<code>a0ibepz0r80mhy4x5cam7i190 my-</code><code>test</code><code>.5 nginx manager-node Running Running about a minute ago </code>
<code>可見三個節點都有處于running狀态的任務,是以my-network網絡擴充到三個節點上。</code>
<code>可以查詢某個節點上關于my-network的詳細資訊:</code>
<code>[root@manager-node ~]</code><code># docker network inspect ngx_net</code>
<code>[</code>
<code> </code><code>{</code>
<code> </code><code>"Name"</code><code>: </code><code>"ngx_net"</code><code>,</code>
<code> </code><code>"Id"</code><code>: </code><code>"cz4b4ht5refqxelx0mm871ec6"</code><code>,</code>
<code> </code><code>"Scope"</code><code>: </code><code>"swarm"</code><code>,</code>
<code> </code><code>"Driver"</code><code>: </code><code>"overlay"</code><code>,</code>
<code> </code><code>"EnableIPv6"</code><code>: </code><code>false</code><code>,</code>
<code> </code><code>"IPAM"</code><code>: {</code>
<code> </code><code>"Driver"</code><code>: </code><code>"default"</code><code>,</code>
<code> </code><code>"Options"</code><code>: null,</code>
<code> </code><code>"Config"</code><code>: [</code>
<code> </code><code>{</code>
<code> </code><code>"Subnet"</code><code>: </code><code>"10.10.110.0/24"</code><code>,</code>
<code> </code><code>"Gateway"</code><code>: </code><code>"10.10.110.1"</code>
<code> </code><code>}</code>
<code> </code><code>]</code>
<code> </code><code>},</code>
<code> </code><code>"Internal"</code><code>: </code><code>false</code><code>,</code>
<code> </code><code>"Containers"</code><code>: {</code>
<code> </code><code>"aa954b709a30be6eaf48e06a6c7c4a0642b75d76e121707df6fc1479d99c7b22"</code><code>: {</code>
<code> </code><code>"Name"</code><code>: </code><code>"my-test.5.a0ibepz0r80mhy4x5cam7i190"</code><code>,</code>
<code> </code><code>"EndpointID"</code><code>: </code><code>"4841c9c639b876f065d44e0205320f5e990a0678c8d7f4a02e499779af7b5091"</code><code>,</code>
<code> </code><code>"MacAddress"</code><code>: </code><code>"02:42:0a:0a:6e:07"</code><code>,</code>
<code> </code><code>"IPv4Address"</code><code>: </code><code>"10.10.110.7/24"</code><code>,</code>
<code> </code><code>"IPv6Address"</code><code>: </code><code>""</code>
<code> </code><code>},</code>
<code> </code><code>"d7633d4108e88a471e1a1b6759b7c43e3fc09ab64de47e29736de7b9c5031963"</code><code>: {</code>
<code> </code><code>"Name"</code><code>: </code><code>"my-test.1.eh2mo4ei8qah5d9eolx8yapey"</code><code>,</code>
<code> </code><code>"EndpointID"</code><code>: </code><code>"54e814c87ba0e7df159195067a851a2557ee8010e619db9cc4fdfb3dd6357afa"</code><code>,</code>
<code> </code><code>"MacAddress"</code><code>: </code><code>"02:42:0a:0a:6e:03"</code><code>,</code>
<code> </code><code>"IPv4Address"</code><code>: </code><code>"10.10.110.3/24"</code><code>,</code>
<code> </code><code>}</code>
<code> </code><code>"Options"</code><code>: {</code>
<code> </code><code>"com.docker.network.driver.overlay.vxlanid_list"</code><code>: </code><code>"257"</code><code>,</code>
<code> </code><code>"encrypted"</code><code>: </code><code>""</code>
<code> </code><code>"Labels"</code><code>: {}</code>
<code> </code><code>}</code>
<code>]</code>
<code>從上面的資訊可以看出在manager-node節點上,名為my-</code><code>test</code><code>的服務有一個名為my-</code><code>test</code><code>.1.eh2mo4ei8qah5d9eolx8yapey和</code>
<code>my-</code><code>test</code><code>.5.a0ibepz0r80mhy4x5cam7i190的task連接配接到名為ngx_net的網絡上(另外兩個節點node1和node2同樣可以用上面指令檢視)</code>
<code>[root@node1 ~]</code><code># docker network inspect ngx_net</code>
<code> </code><code>"8dd2171caa337b3c42f35cd6e4590d69cf8edd58ee03463194d0792199415607"</code><code>: {</code>
<code> </code><code>"Name"</code><code>: </code><code>"my-test.4.03nb3ev2r7sxcilkwizoetx9w"</code><code>,</code>
<code> </code><code>"EndpointID"</code><code>: </code><code>"dec0675361db102f082798b9e39ed43ca23ae7b795105ae39b90373d42548418"</code><code>,</code>
<code> </code><code>"MacAddress"</code><code>: </code><code>"02:42:0a:0a:6e:06"</code><code>,</code>
<code> </code><code>"IPv4Address"</code><code>: </code><code>"10.10.110.6/24"</code><code>,</code>
<code> </code><code>"f29e274d0709403ea97210ff750cdc32054af6cd963ee838bb695e6268264574"</code><code>: {</code>
<code> </code><code>"Name"</code><code>: </code><code>"my-test.3.1vp1d7cwmn8m6a5k0wtq9xi75"</code><code>,</code>
<code> </code><code>"EndpointID"</code><code>: </code><code>"e4150c1107a6e52998e3f5417d774d31cdc3d0b24c9aa4305b860cbdf8f78929"</code><code>,</code>
<code> </code><code>"MacAddress"</code><code>: </code><code>"02:42:0a:0a:6e:05"</code><code>,</code>
<code> </code><code>"IPv4Address"</code><code>: </code><code>"10.10.110.5/24"</code><code>,</code>
<code>[root@node2 ~]</code><code># docker network inspect ngx_net</code>
<code> </code><code>"fddb6518e2bb8c2c2f9f49f95eb3e054ded2a1eff9ec10732a188166f2a60509"</code><code>: {</code>
<code> </code><code>"Name"</code><code>: </code><code>"my-test.2.7gg40e57rko5frttqdx9x7ae2"</code><code>,</code>
<code> </code><code>"EndpointID"</code><code>: </code><code>"7263888a54f6211649bef9425aa4acc33ecf838da20d8c93853842e1812f0436"</code><code>,</code>
<code> </code><code>"MacAddress"</code><code>: </code><code>"02:42:0a:0a:6e:04"</code><code>,</code>
<code> </code><code>"IPv4Address"</code><code>: </code><code>"10.10.110.4/24"</code><code>,</code>
<code>可以通過查詢服務來獲得服務的虛拟IP位址,如下:</code>
<code>[root@manager-node ~]</code><code># docker service inspect --format='{{json .Endpoint.VirtualIPs}}' my-test</code>
<code>[{</code><code>"NetworkID"</code><code>:</code><code>"50kipkihuwxy5dqf150z7guad"</code><code>,</code><code>"Addr"</code><code>:</code><code>"10.255.0.2/16"</code><code>},{</code><code>"NetworkID"</code><code>:</code><code>"cz4b4ht5refqxelx0mm871ec6"</code><code>,</code><code>"Addr"</code><code>:</code><code>"10.10.110.2/24"</code><code>}]</code>
<code>由上結果可知,10.10.110.2其實就是swarm叢集内部的vip,整個網絡結構如下所示:</code>
加入ngx_net網絡的容器彼此之間可以通過IP位址通信,也可以通過名稱通信。
<code>[root@node2 ~]</code><code># docker ps</code>
<code>CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</code>
<code>fddb6518e2bb nginx:latest </code><code>"nginx -g 'daemon off"</code> <code>5 minutes ago Up 5 minutes 80</code><code>/tcp</code> <code>my-</code><code>test</code><code>.2.7gg40e57rko5frttqdx9x7ae2</code>
<code> </code>
<code>[root@node2 ~]</code><code># docker exec -ti fddb6518e2bb /bin/bash</code>
<code>root@fddb6518e2bb:/</code><code># apt-get update && apt-get install iproute iputils-ping -y</code>
<code>root@fddb6518e2bb:/</code><code># ip addr</code>
<code>1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default </code>
<code> </code><code>link</code><code>/loopback</code> <code>00:00:00:00:00:00 brd 00:00:00:00:00:00</code>
<code> </code><code>inet 127.0.0.1</code><code>/8</code> <code>scope host lo</code>
<code> </code><code>valid_lft forever preferred_lft forever</code>
<code> </code><code>inet6 ::1</code><code>/128</code> <code>scope host </code>
<code>246: eth0@if247: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default </code>
<code> </code><code>link</code><code>/ether</code> <code>02:42:0a:ff:00:07 brd ff:ff:ff:ff:ff:ff link-netnsid 0</code>
<code> </code><code>inet 10.255.0.7</code><code>/16</code> <code>scope global eth0</code>
<code> </code><code>inet 10.255.0.2</code><code>/32</code> <code>scope global eth0</code>
<code> </code><code>inet6 fe80::42:aff:feff:7</code><code>/64</code> <code>scope link </code>
<code>248: eth1@if249: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default </code>
<code> </code><code>link</code><code>/ether</code> <code>02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 1</code>
<code> </code><code>inet 172.18.0.3</code><code>/16</code> <code>scope global eth1</code>
<code> </code><code>inet6 fe80::42:acff:fe12:3</code><code>/64</code> <code>scope link </code>
<code>251: eth2@if252: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1424 qdisc noqueue state UP group default </code>
<code> </code><code>link</code><code>/ether</code> <code>02:42:0a:0a:6e:04 brd ff:ff:ff:ff:ff:ff link-netnsid 2</code>
<code> </code><code>inet 10.10.110.4</code><code>/24</code> <code>scope global eth2</code>
<code> </code><code>inet 10.10.110.2</code><code>/32</code> <code>scope global eth2</code>
<code> </code><code>inet6 fe80::42:aff:fe0a:6e04</code><code>/64</code> <code>scope link </code>
<code>root@fddb6518e2bb:/</code><code># ping 10.10.110.3</code>
<code>PING 10.10.110.3 (10.10.110.3) 56(84) bytes of data.</code>
<code>64 bytes from 10.10.110.3: icmp_seq=1 ttl=64 </code><code>time</code><code>=0.437 ms</code>
<code>64 bytes from 10.10.110.3: icmp_seq=2 ttl=64 </code><code>time</code><code>=0.310 ms</code>
<code>.....</code>
<code>--- 10.10.110.3 </code><code>ping</code> <code>statistics ---</code>
<code>2 packets transmitted, 2 received, 0% packet loss, </code><code>time</code> <code>999ms</code>
<code>rtt min</code><code>/avg/max/mdev</code> <code>= 0.310</code><code>/0</code><code>.373</code><code>/0</code><code>.437</code><code>/0</code><code>.066 ms</code>
<code>root@fddb6518e2bb:/</code><code># ping 10.10.110.5</code>
<code>PING 10.10.110.5 (10.10.110.5) 56(84) bytes of data.</code>
<code>64 bytes from 10.10.110.5: icmp_seq=1 ttl=64 </code><code>time</code><code>=0.438 ms</code>
<code>64 bytes from 10.10.110.5: icmp_seq=2 ttl=64 </code><code>time</code><code>=0.329 ms</code>
<code>64 bytes from 10.10.110.5: icmp_seq=3 ttl=64 </code><code>time</code><code>=0.359 ms</code>
<code>--- 10.10.110.5 </code><code>ping</code> <code>statistics ---</code>
<code>3 packets transmitted, 3 received, 0% packet loss, </code><code>time</code> <code>1999ms</code>
<code>rtt min</code><code>/avg/max/mdev</code> <code>= 0.329</code><code>/0</code><code>.375</code><code>/0</code><code>.438</code><code>/0</code><code>.048 ms</code>
<code>----------------------------使用swarm模式的服務發現--------------------------</code>
<code>預設情況下,當建立了一個服務并連接配接到某個網絡後,swarm會為該服務配置設定一個VIP。此VIP根據服務名映射到DNS。在網絡上的容器共享該服務的DNS映射,</code>
<code>是以網絡上的任意容器可以通過服務名通路服務。</code>
<code>在同一overlay網絡中,不用通過端口映射來使某個服務可以被其它服務通路。Swarm内部的負載均衡器自動将請求發送到服務的VIP上,然後分發到所有的</code>
<code>active的task上。</code>
<code>如下示例:</code>
<code>在同一個網絡中添加了一個centos服務,此服務可以通過名稱my-</code><code>test</code><code>通路前面建立的nginx服務:</code>
<code>[root@manager-node ~]</code><code># docker service create --name my-centos --network ngx_net centos sleep 3000 </code>
<code>查詢centos運作在哪個節點上(上面建立指令執行後,需要一段時間才能完成這個centos服務的建立)</code>
<code>ece4ac2e6cc1 centos:latest </code><code>"sleep 3000"</code> <code>42 seconds ago Up 40 seconds my-centos.1.5qwknsxmtr1zhclx9d0f0fx4m</code>
<code>登入centos運作的節點(由上可知是node2節點),打開centos的互動shell:</code>
<code>CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES</code>
<code>e4554490d891 centos:latest </code><code>"/bin/bash"</code> <code>About an hour ago Up About an hour my-centos.1.9yk5ie28gwk9mw1h1jovb68ki</code>
<code>[root@node2 ~]</code><code># docker exec -it my-centos.1.5qwknsxmtr1zhclx9d0f0fx4m /bin/bash</code>
<code>[root@ece4ac2e6cc1 /]</code><code># yum install bind-utils -y</code>
<code>[root@ece4ac2e6cc1 /]</code><code># nslookup my-test</code>
<code>Server: 127.0.0.11</code>
<code>Address: 127.0.0.11</code><code>#53</code>
<code>Non-authoritative answer:</code>
<code>Name: my-</code><code>test</code>
<code>Address: 10.10.110.2</code>
<code>從centos容器内部,使用特殊查詢 查詢DNS,來找到my-</code><code>test</code><code>服務的所有容器的IP位址:</code>
<code>[root@ece4ac2e6cc1 /]</code><code># nslookup tasks.my-test</code>
<code>Name: tasks.my-</code><code>test</code>
<code>Address: 10.10.110.3</code>
<code>Address: 10.10.110.7</code>
<code>Address: 10.10.110.5</code>
<code>Address: 10.10.110.4</code>
<code>Address: 10.10.110.6</code>
<code>從centos容器内部,通過wget來通路my-</code><code>test</code><code>服務中運作的nginx網頁伺服器</code>
<code>[root@ece4ac2e6cc1 /]</code><code># wget -O- my-test </code>
<code>--2018-02-08 01:57:26-- http:</code><code>//my-test/</code>
<code>Resolving my-</code><code>test</code> <code>(my-</code><code>test</code><code>)... 10.10.110.2</code>
<code>Connecting to my-</code><code>test</code> <code>(my-</code><code>test</code><code>)|10.10.110.2|:80... connected.</code>
<code>HTTP request sent, awaiting response... 200 OK</code>
<code>Length: 612 [text</code><code>/html</code><code>]</code>
<code>Saving to: </code><code>'STDOUT'</code>
<code> </code><code>0% [ ] 0 --.-K</code><code>/s</code> <code><!DOCTYPE html></code>
<code><html></code>
<code><</code><code>head</code><code>></code>
<code><title>Welcome to nginx!<</code><code>/title</code><code>></code>
<code>...</code>
<code>Swarm的負載均衡器自動将HTTP請求路由到VIP上,然後到一個active的task容器上。它根據round-robin選擇算法将後續的請求分發到另一個active的task上。</code>
<code>-----------------------------------為服務使用DNS round-robin-----------------------------</code>
<code>在建立服務時,可以配置服務直接使用DNS round-robin而無需使用VIP。這是通過在建立服務時指定 --endpoint-mode dnsrr 指令行參數實作的。</code>
<code>當你想要使用自己的負載均衡器時可以使用這種方式。</code>
<code>如下示例(注意:使用DNS round-robin方式建立服務,不能直接在指令裡使用-p指定端口)</code>
<code>[root@manager-node ~]</code><code># docker service create --replicas 3 --name my-dnsrr-nginx --network ngx_net --endpoint-mode dnsrr nginx</code>
<code>[root@manager-node ~]</code><code># docker service ps my-dnsrr-nginx</code>
<code>ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR</code>
<code>8ffi3rs8fg3k4obrvbxg4uwiy my-dnsrr-nginx.1 nginx node2 Running Running 7 seconds ago </code>
<code>amgmv0kgdopc70z2dr97vn7qq my-dnsrr-nginx.2 nginx node1 Running Running 7 seconds ago </code>
<code>2p7obdb3h7yicggsbiv5qmvjx my-dnsrr-nginx.3 nginx manager-node Running Running 7 seconds ago </code>
<code>當通過服務名稱查詢DNS時,DNS服務傳回所有任務容器的IP位址:</code>
<code>[root@ece4ac2e6cc1 /]</code><code># nslookup my-dnsrr-nginx</code>
<code>Name: my-dnsrr-nginx</code>
<code>Address: 10.10.110.12</code>
<code>Address: 10.10.110.11</code>
<code>Address: 10.10.110.10</code>
<code>需要注意的是:一定要确認VIP的連通性</code>
<code>通常Docker官方推薦使用</code><code>dig</code><code>,</code><code>nslookup</code><code>或其它DNS查詢工具來查詢通過DNS對服務名的通路。因為VIP是邏輯IP,</code><code>ping</code><code>并不是确認VIP連通性的正确的工具。</code>
本文轉自 dengaosky 51CTO部落格,原文連結:http://blog.51cto.com/dengaosky/2069911,如需轉載請自行聯系原作者