在本實驗中,您將學習如何使用Swarm模式的服務構建,管理和使用覆蓋網絡。
難度:中級
時間:約20分鐘
此次實現包含以下步驟:
第1步-建立新的羣組 第2步-創建覆蓋網絡 第3步-創建服務 第4步-測試網絡 第5步-測試服務發現
先決條件
兩臺基於Linux的Docker主機,暫且叫node1 和node2 主機,它們在引擎模式下運行Docker 1.12或更高版本
步驟1:建立新的羣組
初始化一個新的Swarm,加入一個工作節點,並驗證操作是否有效。
- 在node1執行如下命令
node1$ docker swarm init
Swarm initialized: current node (cw6jpk7pqfg0jkilff5hr8z42) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-3n2iuzpj8jynx0zd8axr0ouoagvy0o75uk5aqjrn0297j4uaz7-63eslya31oza2ob78b88zg5xe \
172.31.34.123:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions
- 複製整個docker swarm join 命令在node2上執行
node2$ docker swarm join \
> --token SWMTKN-1-3n2iuzpj8jynx0zd8axr0ouoagvy0o75uk5aqjrn0297j4uaz7-63eslya31oza2ob78b88zg5xe \
> 172.31.34.123:2377
This node joined a swarm as a worker.
- 在node1上運行 docker node ls ,確認兩臺機器都已經加入swarm集羣了。
node1$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
4nb02fhvhy8sb0ygcvwya9skr ip-172-31-43-74 Ready Active
cw6jpk7pqfg0jkilff5hr8z42 * ip-172-31-34-123 Ready Active Leader
標記了*號的是本機,並且是集羣的leader
步驟2:創建overlay網絡
- node1上執行下面命令,創建一個叫overnet的網絡
node1$ docker network create -d overlay overnet
0cihm9yiolp0s9kcczchqorhb
- 執行 docker network ls命令驗證網絡成功創建
node2$ docker network ls
NETWORK ID NAME DRIVER SCOPE
b76635120433 bridge bridge local
ea13f975a254 docker_gwbridge bridge local
73edc8c0cc70 host host local
8eqnahrmp9lv ingress overlay swarm
c4fb141606ca none null local
請注意,“ overnet”網絡未出現在列表中。 這是因爲Docker主機從網絡上創建的服務運行任務的時候,纔將overlay網絡創建出來。
- node1上執行 docker network inspect 命令查看更多的詳情
node1$ docker network inspect overnet
[
{
"Name": "overnet",
"Id": "0cihm9yiolp0s9kcczchqorhb",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": []
},
"Internal": false,
"Containers": null,
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "257"
},
"Labels": null
}
]
步驟3:創建服務
當前,我們創建了swarm集羣和overlay網絡,下面創建服務
- node1上執行下面的命令創建一個名爲myservice的服務,指定使用overnet網絡,創建2個實例
node1$ docker service create --name myservice \
--network overnet \
--replicas 2 \
ubuntu sleep infinity
e9xu03wsxhub3bij2tqyjey5t
- 驗證服務創建並且2個實例都已啓動
node1$ docker service ls
ID NAME REPLICAS IMAGE COMMAND
e9xu03wsxhub myservice 2/2 ubuntu sleep infinity
- 驗證實例分別在swarm集羣的兩個機器上
node1$ docker service ps myservice
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
5t4wh...fsvz myservice.1 ubuntu node1 Running Running 2 mins
8d9b4...te27 myservice.2 ubuntu node2 Running Running 2 mins
通過node 列可以看到node1 的實例是myservice.1,node2的實例是myservice.2
- 驗證node2節點的任務也在overnet網絡上,在node2上執行下面的命令
node2$ docker network ls
NETWORK ID NAME DRIVER SCOPE
b76635120433 bridge bridge local
ea13f975a254 docker_gwbridge bridge local
73edc8c0cc70 host host local
8eqnahrmp9lv ingress overlay swarm
c4fb141606ca none null local
0cihm9yiolp0 overnet overlay swarm
- 在node2上查看overnet網絡的詳情,並且獲取運行的服務的ip地址
node2$ docker network inspect overnet
[
{
"Name": "overnet",
"Id": "0cihm9yiolp0s9kcczchqorhb",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1"
}
]
},
"Internal": false,
"Containers": {
"286d2e98c764...37f5870c868": {
"Name": "myservice.1.5t4wh7ngrzt9va3zlqxbmfsvz",
"EndpointID": "43590b5453a...4d641c0c913841d657",
"MacAddress": "02:42:0a:00:00:04",
"IPv4Address": "10.0.0.4/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "257"
},
"Labels": {}
}
]
請 注意,在docker1.12版本,docker network inspect 知會顯示當前本機節點上的容器/任務。可以看到當前容器的ipv4地址爲10.0.0.4.
步驟4:網絡測試
- node1上執行下面的命令
node1$ docker network inspect overnet
[
{
"Name": "overnet",
"Id": "0cihm9yiolp0s9kcczchqorhb",
"Scope": "swarm",
"Driver": "overlay",
"Containers": {
"053abaa...e874f82d346c23a7a": {
"Name": "myservice.2.8d9b4i6vnm4hf6gdhxt40te27",
"EndpointID": "25d4d5...faf6abd60dba7ff9b5fff6",
"MacAddress": "02:42:0a:00:00:03",
"IPv4Address": "10.0.0.3/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "257"
},
"Labels": {}
}
]
請注意node1上的容器ip地址爲10.0.0.3,和node2上的不一樣,但是都是處於同一個網絡中。
- node1上執行docker ps 獲取服務容器的id,這樣可以進入容器內部
node1$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
053abaac4f93 ubuntu:latest "sleep infinity" 19 mins ago Up 19 mins myservice.2.8d9b4i6vnm4hf6gdhxt40te27
<Snip>
- 根據容器id進入容器內部
node1$ docker exec -it 053abaac4f93 /bin/bash
root@053abaac4f93:/#
- 安裝ping命令,並且ping 一下node2上的容器地址10.0.0.4
root@053abaac4f93:/# apt-get update && apt-get install iputils-ping
<Snip>
root@053abaac4f93:/#
root@053abaac4f93:/#
root@053abaac4f93:/# ping 10.0.0.4
PING 10.0.0.4 (10.0.0.4) 56(84) bytes of data.
64 bytes from 10.0.0.4: icmp_seq=1 ttl=64 time=0.726 ms
64 bytes from 10.0.0.4: icmp_seq=2 ttl=64 time=0.647 ms
^C
--- 10.0.0.4 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.647/0.686/0.726/0.047 ms
上面的輸出顯示myservice服務的兩個任務都在跨越兩個節點的同一覆蓋網絡上,並且它們可以使用該網絡進行通信。
步驟5:服務發現
如果您還不在node1上的容器內,請使用docker exec命令重新登錄到該容器中。
- 在容器內執行下面命令
root@053abaac4f93:/# cat /etc/resolv.conf
search eu-west-1.compute.internal
nameserver 127.0.0.11
options ndots:0
服務器127.0.0.11 接收所有DNS查詢請求,所有容器的嵌入式DNS解析器都偵聽127.0.0.11:53。
- 在容器內ping myservice
root@053abaac4f93:/# ping myservice
PING myservice (10.0.0.2) 56(84) bytes of data.
64 bytes from ip-10-0-0-2.eu-west-1.compute.internal (10.0.0.2): icmp_seq=1 ttl=64 time=0.020 ms
64 bytes from ip-10-0-0-2.eu-west-1.compute.internal (10.0.0.2): icmp_seq=2 ttl=64 time=0.041 ms
64 bytes from ip-10-0-0-2.eu-west-1.compute.internal (10.0.0.2): icmp_seq=3 ttl=64 time=0.039 ms
^C
--- myservice ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.020/0.033/0.041/0.010 ms
表明容器可以按名稱ping myservice服務。 請注意,返回的IP地址是10.0.0.2。 在接下來的幾個步驟中,我們將驗證該地址是分配給myservice服務的虛擬IP(VIP)。
- 鍵入exit 退出容器返回宿主機
- 檢查myservice的配置驗證VIP的值就是之前ping myservice時候返回的值:10.0.0.2
node1$ docker service inspect myservice
[
{
"ID": "e9xu03wsxhub3bij2tqyjey5t",
"Version": {
"Index": 20
},
"CreatedAt": "2016-11-23T09:28:57.888561605Z",
"UpdatedAt": "2016-11-23T09:28:57.890326642Z",
"Spec": {
"Name": "myservice",
"TaskTemplate": {
"ContainerSpec": {
"Image": "ubuntu",
"Args": [
"sleep",
"infinity"
]
},
<Snip>
"Endpoint": {
"Spec": {
"Mode": "vip"
},
"VirtualIPs": [
{
"NetworkID": "0cihm9yiolp0s9kcczchqorhb",
"Addr": "10.0.0.2/24"
}
<Snip>
在輸出的底部看到列出的服務的VIP,輸出中的VIP爲10.0.0.2, 需要注意的重要一點是,此處列出的VIP與ping myservice命令返回的值匹配。
隨意爲在node2上運行的服務任務(容器)創建一個新的docker exec會話,並執行相同的ping service命令。 將得到同樣VIP的回覆。