Docker Swarm 入門

Swarm 在 Docker 1.12 版本之前屬於一個獨立的項目,在 Docker 1.12 版本發佈之後,該項目合併到了 Docker 中,成爲 Docker 的一個子命令。目前,Swarm 是 Docker 社區提供的唯一一個原生支持 Docker 集羣管理的工具。它可以把多個 Docker 主機組成的系統轉換爲單一的虛擬 Docker 主機,使得容器可以組成跨主機的子網網絡。

Swarm 認識

Swarm 是目前 Docker 官方唯一指定(綁定)的集羣管理工具。Docker 1.12 內嵌了 swarm mode 集羣管理模式。
爲了方便演示跨主機網絡,我們需要用到一個工具——Docker Machine,這個工具與 Docker Compose、Docker Swarm 並稱 Docker 三劍客,下面我們來看看如何安裝 Docker Machine:
$ curl -L https://github.com/docker/machine/releases/download/v0.9.0-rc2/docker-machine-uname -s-uname -m >/tmp/docker-machine &&
chmod +x /tmp/docker-machine &&
sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
安裝過程和 Docker Compose 非常類似。現在 Docker 三劍客已經全部到齊了。
在開始之前,我們需要了解一些基本概念,有關集羣的 Docker 命令如下:
● docker swarm:集羣管理,子命令有 init, join,join-token, leave, update
● docker node:節點管理,子命令有 demote, inspect,ls, promote, rm, ps, update
● docker service:服務管理,子命令有 create, inspect, ps, ls ,rm , scale, update
● docker stack/deploy:試驗特性,用於多應用部署,等正式版加進來再說。

創建集羣

首先使用 Docker Machine 創建一個虛擬機作爲 manger 節點。
$ docker-machine create –driver virtualbox manager1
Running pre-create checks…
(manager1) Unable to get the latest Boot2Docker ISO release version: Get https://api.github.com/repos/boot2docker/boot2docker/releases/latest: dial tcp: lookup api.github.com on [::1]:53: server misbehaving
Creating machine…
(manager1) Unable to get the latest Boot2Docker ISO release version: Get https://api.github.com/repos/boot2docker/boot2docker/releases/latest: dial tcp: lookup api.github.com on [::1]:53: server misbehaving
(manager1) Copying /home/zuolan/.docker/machine/cache/boot2docker.iso to /home/zuolan/.docker/machine/machines/manager1/boot2docker.iso…
(manager1) Creating VirtualBox VM…
(manager1) Creating SSH key…
(manager1) Starting the VM…
(manager1) Check network to re-create if needed…
(manager1) Found a new host-only adapter: “vboxnet0”
(manager1) Waiting for an IP…
Waiting for machine to be running, this may take a few minutes…
Detecting operating system of created instance…
Waiting for SSH to be available…
Detecting the provisioner…
Provisioning with boot2docker…
Copying certs to the local machine directory…
Copying certs to the remote machine…
Setting Docker configuration on the remote daemon…
Checking connection to Docker…
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env manager1
查看虛擬機的環境變量等信息,包括虛擬機的 IP 地址:
dockermachineenvmanager1exportDOCKERTLSVERIFY=1exportDOCKERHOST=tcp://192.168.99.100:2376exportDOCKERCERTPATH=/home/zuolan/.docker/machine/machines/manager1exportDOCKERMACHINENAME=manager1Runthiscommandtoconfigureyourshell:eval (docker-machine env manager1)
然後再創建一個節點作爲 work 節點。
dockermachinecreatedrivervirtualboxworker1使Machine docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
manager1 - virtualbox Running tcp://192.168.99.100:2376 v1.12.3
worker1 - virtualbox Running tcp://192.168.99.101:2376 v1.12.3
但是目前這兩臺虛擬主機並沒有什麼聯繫,爲了把它們聯繫起來,我們需要 Swarm 登場了。
因爲我們使用的是 Docker Machine 創建的虛擬機,因此可以使用 docker-machine ssh 命令來操作虛擬機,在實際生產環境中,並不需要像下面那樣操作,只需要執行 docker swarm 即可。
把 manager1 加入集羣:
$ docker-machine ssh manager1 docker swarm init –listen-addr 192.168.99.100:2377 –advertise-addr 192.168.99.100
Swarm initialized: current node (23lkbq7uovqsg550qfzup59t6) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join \
--token SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
192.168.99.100:2377

To add a manager to this swarm, run ‘docker swarm join-token manager’ and follow the instructions.
用 –listen-addr 指定監聽的 ip 與端口,實際的 Swarm 命令格式如下,本例使用 Docker Machine 來連接虛擬機而已:
dockerswarminitlistenaddr:work1 docker-machine ssh worker1 docker swarm join –token \
SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
192.168.99.100:2377
This node joined a swarm as a worker.
上面 join 命令中可以添加 –listen-addr WORKER1IP:2377workmanger使IP docker-machine ssh manager1 docker swarm init --listen-addr MANAGER1IP:2377Errorresponsefromdaemon:couldnotchooseanIPaddresstoadvertisesincethissystemhasmultipleaddressesondifferentinterfaces(10.0.2.15oneth0and192.168.99.100oneth1)specifyonewithadvertiseaddrexitstatus1IPSwarm使IP docker-machine ssh manager1 docker swarm init –advertise-addr 192.168.99.100 –listen-addr 192.168.99.100:2377
Swarm initialized: current node (ahvwxicunjd0z8g0eeosjztjx) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join \
--token SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
192.168.99.100:2377

To add a manager to this swarm, run ‘docker swarm join-token manager’ and follow the instructions.
集羣初始化成功。

現在我們新建了一個有兩個節點的“集羣”,現在進入其中一個管理節點使用 docker node 命令來查看節點信息:
$ docker-machine ssh manager1 docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
23lkbq7uovqsg550qfzup59t6 * manager1 Ready Active Leader
dqb3fim8zvcob8sycri3hy98a worker1 Ready Active

現在每個節點都歸屬於 Swarm,並都處在了待機狀態。Manager1 是領導者,work1 是工人。
現在,我們繼續新建虛擬機 manger2、worker2、worker3,現在已經有五個虛擬機了,使用 docker-machine ls 來查看虛擬機:
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
manager1 - virtualbox Running tcp://192.168.99.100:2376 v1.12.3
manager2 - virtualbox Running tcp://192.168.99.105:2376 v1.12.3
worker1 - virtualbox Running tcp://192.168.99.102:2376 v1.12.3
worker2 - virtualbox Running tcp://192.168.99.103:2376 v1.12.3
worker3 - virtualbox Running tcp://192.168.99.104:2376 v1.12.3
然後我們把剩餘的虛擬機也加到集羣中。
● 添加 worker2 到集羣中:
dockermachinesshworker2dockerswarmjoin tokenSWMTKN13z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvjc036gwrakjejql06klrfc585r 192.168.99.100:2377Thisnodejoinedaswarmasaworker.worker3 docker-machine ssh worker3 docker swarm join \
–token SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
192.168.99.100:2377
This node joined a swarm as a worker.
● 添加 manager2 到集羣中:
先從 manager1 中獲取 manager 的 token:
$ docker-machine ssh manager1 docker swarm join-token manager
To add a manager to this swarm, run the following command:

  docker swarm join \
  --token SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-8tn855hkjdb6usrblo9iu700o \
192.168.99.100:2377

然後添加 manager2 到集羣中:

$ docker-machine ssh manager2 docker swarm join \
  --token SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-8tn855hkjdb6usrblo9iu700o \
  192.168.99.100:2377

This node joined a swarm as a manager.
現在再來查看集羣信息:
$ docker-machine ssh manager2 docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
16w80jnqy2k30yez4wbbaz1l8 worker1 Ready Active
2gkwhzakejj72n5xoxruet71z worker2 Ready Active
35kutfyn1ratch55fn7j3fs4x worker3 Ready Active
a9r21g5iq1u6h31myprfwl8ln * manager2 Ready Active Reachable
dpo7snxbz2a0dxvx6mf19p35z manager1 Ready Active Leader

建立跨主機網絡

爲了演示更清晰,下面我們把宿主機也加入到集羣之中,這樣我們使用 Docker 命令操作會清晰很多。
直接在本地執行加入集羣命令:
dockerswarmjoin tokenSWMTKN13z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj8tn855hkjdb6usrblo9iu700o 192.168.99.100:2377Thisnodejoinedaswarmasamanager.managerworker宿 docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
6z2rpk1t4xucffzlr2rpqb8u3 worker3 Ready Active
7qbr0xd747qena4awx8bx101s * user-pc Ready Active Reachable
9v93sav79jqrg0c7051rcxxev manager2 Ready Active Reachable
a1ner3zxj3ubsiw4l3p28wrkj worker1 Ready Active
a5w7h8j83i11qqi4vlu948mad worker2 Ready Active
d4h7vuekklpd6189fcudpfy18 manager1 Ready Active Leader
查看網絡狀態:
dockernetworklsNETWORKIDNAMEDRIVERSCOPE764ff31881e5bridgebridgelocalfbd9a977aa03hosthostlocal6p6xlousvsy2ingressoverlayswarme81af24d643dnonenulllocalswarmingressoverlay,swarm使overlay docker network create –driver overlay swarm_test
4dm8cy9y5delvs5vd0ghdd89s
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
764ff31881e5 bridge bridge local
fbd9a977aa03 host host local
6p6xlousvsy2 ingress overlay swarm
e81af24d643d none null local
4dm8cy9y5del swarm_test overlay swarm
這樣一個跨主機網絡就搭建好了,但是現在這個網絡只是處於待機狀態,下一小節我們會在這個網絡上部署應用。

在跨主機網絡上部署應用

首先我們上面創建的節點都是沒有鏡像的,因此我們要逐一 pull 鏡像到節點中,這裏我們使用前面搭建的私有倉庫。
dockermachinesshmanager1dockerpullreg.example.com/library/nginx:alpinealpine:Pullingfromlibrary/nginxe110a4a17941:Pullingfslayer7648f5d87006:PullcompleteDigest:sha256:65063cb82bf508fd5a731318e795b2abbfb0c22222f02ff5c6b30df7f23292feStatus:Downloadednewerimageforreg.example.com/library/nginx:alpine docker-machine ssh manager2 docker pull reg.example.com/library/nginx:alpine
alpine: Pulling from library/nginx
e110a4a17941: Pulling fs layer
… …
7648f5d87006: Pull complete
Digest: sha256:65063cb82bf508fd5a731318e795b2abbfb0c22222f02ff5c6b30df7f23292fe
Status: Downloaded newer image for reg.example.com/library/nginx:alpine
dockermachinesshworker1dockerpullreg.example.com/library/nginx:alpinealpine:Pullingfromlibrary/nginxe110a4a17941:Pullingfslayer7648f5d87006:PullcompleteDigest:sha256:65063cb82bf508fd5a731318e795b2abbfb0c22222f02ff5c6b30df7f23292feStatus:Downloadednewerimageforreg.example.com/library/nginx:alpine docker-machine ssh worker2 docker pull reg.example.com/library/nginx:alpine
alpine: Pulling from library/nginx
e110a4a17941: Pulling fs layer
… …
7648f5d87006: Pull complete
Digest: sha256:65063cb82bf508fd5a731318e795b2abbfb0c22222f02ff5c6b30df7f23292fe
Status: Downloaded newer image for reg.example.com/library/nginx:alpine
dockermachinesshworker3dockerpullreg.example.com/library/nginx:alpinealpine:Pullingfromlibrary/nginxe110a4a17941:Pullingfslayer7648f5d87006:PullcompleteDigest:sha256:65063cb82bf508fd5a731318e795b2abbfb0c22222f02ff5c6b30df7f23292feStatus:Downloadednewerimageforreg.example.com/library/nginx:alpine使dockerpullnginx:alpineNginx使swarmtest docker service create –replicas 2 –name helloworld –network=swarm_test nginx:alpine
5gz0h2s5agh2d2libvzq6bhgs
查看服務狀態:
dockerservicelsIDNAMEREPLICASIMAGECOMMAND5gz0h2s5agh2helloworld0/2nginx:alpinehelloworld便調 docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
ay081uome3 helloworld.1 nginx:alpine manager1 Running Preparing 2 seconds ago
16cvore0c96 helloworld.2 nginx:alpine worker2 Running Preparing 2 seconds ago
可以看到兩個實例分別運行在兩個節點上。
進入兩個節點,查看服務狀態(爲了方便閱讀,已調整輸出內容):
dockermachinesshmanager1dockerpsaCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES119f787622c2nginx:alpinenginxg4minutesagoUp4minutes80/tcp,443/tcphello docker-machine ssh worker2 docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5db707401a06 nginx:alpine “nginx -g …” 4 minutes ago Up 4 minutes 80/tcp, 443/tcp hello …
上面輸出做了調整,實際的 NAMES 值爲:
helloworld.1.ay081uome3eejeg4mspa8pdlx
helloworld.2.16cvore0c96rby1vp0sny3mvt
記住上面這兩個實例的名稱。現在我們來看這兩個跨主機的容器是否能互通:
首先使用 Machine 進入 manager1 節點,然後使用 docker exec -i 命令進入 helloworld.1 容器中 ping 運行在 worker2 節點的 helloworld.2 容器。
dockermachinesshmanager1dockerexecihelloworld.1.ay081uome3eejeg4mspa8pdlx pinghelloworld.2.16cvore0c96rby1vp0sny3mvtPINGhelloworld.2.16cvore0c96rby1vp0sny3mvt(10.0.0.4):56databytes64bytesfrom10.0.0.4:seq=0ttl=64time=0.591ms64bytesfrom10.0.0.4:seq=1ttl=64time=0.594ms64bytesfrom10.0.0.4:seq=2ttl=64time=0.624ms64bytesfrom10.0.0.4:seq=3ttl=64time=0.612msC使Machineworker2使dockerexecihelloworld.2pingmanager1helloworld.1 docker-machine ssh worker2 docker exec -i helloworld.2.16cvore0c96rby1vp0sny3mvt \
ping helloworld.1.ay081uome3eejeg4mspa8pdlx
PING helloworld.1.ay081uome3eejeg4mspa8pdlx (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=0.466 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=0.465 ms
64 bytes from 10.0.0.3: seq=2 ttl=64 time=0.548 ms
64 bytes from 10.0.0.3: seq=3 ttl=64 time=0.689 ms
^C
可以看到這兩個跨主機的服務集羣裏面各個容器是可以互相連接的。
爲了體現 Swarm 集羣的優勢,我們可以使用虛擬機的 ping 命令來測試對方虛擬機內的容器。
dockermachinesshworker2pinghelloworld.1.ay081uome3eejeg4mspa8pdlxPINGhelloworld.1.ay081uome3eejeg4mspa8pdlx(221.179.46.190):56databytes64bytesfrom221.179.46.190:seq=0ttl=63time=48.651ms64bytesfrom221.179.46.190:seq=1ttl=63time=63.239ms64bytesfrom221.179.46.190:seq=2ttl=63time=47.686ms64bytesfrom221.179.46.190:seq=3ttl=63time=61.232msC docker-machine ssh manager1 ping helloworld.2.16cvore0c96rby1vp0sny3mvt
PING helloworld.2.16cvore0c96rby1vp0sny3mvt (221.179.46.194): 56 data bytes
64 bytes from 221.179.46.194: seq=0 ttl=63 time=30.150 ms
64 bytes from 221.179.46.194: seq=1 ttl=63 time=54.455 ms
64 bytes from 221.179.46.194: seq=2 ttl=63 time=73.862 ms
64 bytes from 221.179.46.194: seq=3 ttl=63 time=53.171 ms
^C
上面我們使用了虛擬機內部的 ping 去測試容器的延遲,可以看到延遲明顯比集羣內部的 ping 值要高。

Swarm 集羣負載

現在我們已經學會了 Swarm 集羣的部署方法,現在來搭建一個可訪問的 Nginx 集羣吧。體驗最新版的 Swarm 所提供的自動服務發現與集羣負載功能。
首先刪掉上一節我們啓動的 helloworld 服務:
$ docker service rm helloworld
helloworld
然後在新建一個服務,提供端口映射參數,使得外界可以訪問這些 Nginx 服務:

$ docker service create --replicas 2 --name helloworld -p 7080:80 --network=swarm_test nginx:alpine
9gfziifbii7a6zdqt56kocyun

查看服務運行狀態:
dockerservicelsIDNAMEREPLICASIMAGECOMMAND9gfziifbii7ahelloworld2/2nginx:alpine使replicasREPLICAS0/2REPLICAS2/2使dockerserviceps調CURRENTSTATERunningCURRENTSTATEPreparing docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
9ikr3agyi… helloworld.1 nginx:alpine user-pc Running Running 13 seconds ago
7acmhj0u… helloworld.2 nginx:alpine worker2 Running Running 6 seconds ago
這就涉及到 Swarm 內置的發現機制了,目前 Docker 1.12 中 Swarm 已經內置了服務發現工具,我們不再需要像以前使用 Etcd 或者 Consul 這些工具來配置服務發現。對於一個容器來說如果沒有外部通信但又是運行中的狀態會被服務發現工具認爲是 Preparing 狀態,本小節例子中因爲映射了端口,因此有了 Running 狀態。
現在我們來看 Swarm 另一個有趣的功能,當我們殺死其中一個節點時,會發生什麼。
首先 kill 掉 worker2 的實例:
dockermachinesshworker2dockerkillhelloworld.2.7acmhj0udzusv1d7lu2tbuhu4helloworld.2.7acmhj0udzusv1d7lu2tbuhu4 docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
9ikr3agyi… helloworld.1 nginx:alpine zuolan-pc Running Running 19 minutes ago
8f866igpl… helloworld.2 nginx:alpine manager1 Running Running 4 seconds ago
7acmhj0u… _ helloworld.2 nginx:alpine worker2 Shutdown Failed 11 seconds ago …exit…
dockerservicelsIDNAMEREPLICASIMAGECOMMAND9gfziifbii7ahelloworld2/2nginx:alpine使killSwarm使scale docker service scale helloworld=3
helloworld scaled to 3
查看服務詳情,可以看到有三個實例啓動了:
dockerservicepshelloworldIDNAMEIMAGENODEDESIREDSTATECURRENTSTATEERROR9ikr3agyihelloworld.1nginx:alpineuserpcRunningRunning30minutesago8f866igplhelloworld.2nginx:alpinemanager1RunningRunning11minutesago7acmhj0uhelloworld.2nginx:alpineworker2ShutdownFailed11minutesagoexit1371vexr1jmhelloworld.3nginx:alpineworker2RunningRunning4secondsago使scale docker service scale helloworld=2
helloworld scaled to 2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章