文章目录
- 什么是Docker Swarm
- 关键概念
- 1. 初始化Docker Swarm
- 2. 加入Docker Swarm
- 3. 创建`overlay`网络
- 4. 创建`service`服务
- 5. 查看状态
- 6. 扩展服务
在这篇文章中,大家将会了解如何初始化一个Docker Swarm集群,并利用Docker本身的编排技术来部署容器。我们用2个Docker主机作为整个系列的环境。
什么是Docker Swarm
在1.12版本中,Docker引入了Swarm,用于实现跨多台主机部署容器,并利用overlay
网络作为服务发现、利用内置负载均衡扩展服务。Docker Swarm作为Docker CLI的一部分,可以无缝体验Docker的整个生态。
关键概念
Docker Swarm引入三个新概念,我们将在文章中探讨。
- 节点:节点是Swarm集群中的一个主机,它充当
manager
或worker
角色中的一种。manager
用于安排任务(容器应该在哪里运行),而worker
用于执行任务。manager
默认也是worker
。 - 服务:服务是
worker
用于执行的一系列任务的集合,分副本、全局两种。 - 负载均衡:Docker包含一个负载均衡器,用于分发集群中的请求。
1. 初始化Docker Swarm
host | hostname | role |
172.17.0.15 | host01 | manager |
172.17.0.16 | host02 | worker |
默认情况下,Docker独立运行,所有容器都部署在自身节点。Swarm模式把几个独立节点转变成具有多节点的一个集群。Docker Swarm初始化的第一个节点是集群的manager
,新加入的节点可以是manager
或worker
角色中的一种。为了保证集群高可用,Docker官方建议,生产环境应该运行3、5最多7个manager
节点,但不是越多越好。
运行docker swarm --help
查看命令帮助:
Usage: docker swarm COMMAND
Manage Swarm
Commands:
ca Display and rotate the root CA
init Initialize a swarm
join Join a swarm as a node and/or manager
join-token Manage join tokens
leave Leave the swarm
unlock Unlock swarm
unlock-key Manage the unlock key
update Update the swarm
Run 'docker swarm COMMAND --help' for more information on a command.
我们发现,通过运行docker swarm init
可以初始化集群:
Swarm initialized: current node (x534ed58ftf7v54epuus5jlnq) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-1yjkoa4ctd5xs0gl583j55a39xbdynk273ofc6f232b0te8o7s-08sqsgdzk268ll826azeaw0vk 172.17.0.15:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
运行docker node ls
查看集群节点:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
x534ed58ftf7v54epuus5jlnq * host01 Ready Active Leader 18.03.1-ce
此时,该Docker节点已经从一个独立节点转变为集群中的一部分,且是manager
角色。
2. 加入Docker Swarm
启用Swarm模式后,就可以向集群中添加节点。如果节点发生故障,在该节点上运行的所有容器都会自动转移到其它可用的节点。这种集群自动重新安排的方式可以确保服务的副本数不会减少,依旧提供高可用。Docker Swarm通过token令牌的方式来加入集群并区分manager
或worker
角色。
在初始化节点上运行docker swarm join-token manager
,从而以manager
的身份加入集群(实际没添加新的manager
):
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-1yjkoa4ctd5xs0gl583j55a39xbdynk273ofc6f232b0te8o7s-en7o42aj3aaaqt2m1qf4o70cb 172.17.0.15:2377
在初始化节点上运行docker swarm join-token worker
,从而以worker
的身份加入集群:
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-1yjkoa4ctd5xs0gl583j55a39xbdynk273ofc6f232b0te8o7s-08sqsgdzk268ll826azeaw0vk 172.17.0.15:2377
此时运行docker node ls
查看集群节点:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
x534ed58ftf7v54epuus5jlnq * host01 Ready Active Leader 18.03.1-ce
81cf1ft35sc0vc3ndv91j3k0q host02 Ready Active 18.03.1-ce
3. 创建overlay
网络
在1.12版本之前,Docker需要利用外部的K-V存储,例如Consul
,来确保跨网络的一致性。在1.12版本之后,Swarm模式引入了一种改进的网络模型,将K-V存储
和一致性
集成在Docker内部,从而不再需要外部的网络服务,它就是overlay
网络模型。
改进的网络机制遵循之前的语法,它允许不同节点之间的容器进行通信,是一个虚拟可扩展网络(Virtual Extensible LAN),专为大规模云部署而设计。
通过docker network create -d overlay --attachable httpnet
命令,我们将创建一个名为httpnet
的overlay网络。使用--attachable
标志,如果其它的服务或容器在创建时指定network=httpnet
,相当于注册到此网络中(位于一个子网),这样,此网络中得所有得容器都可以相互通信,无论它们部署在哪个节点。
4. 创建service
服务
默认情况下,Docker使用扩展复制模型来确定哪些容器应该在哪些节点上运行,它可确保容器被均匀地部署在集群中。service
这个新概念用于在集群中运行容器,它是一个比容器更高级的概念。服务允许定义部署多少个容器来运行应用程序,并通过更新服务来调整数量。
在本次演示中,我们部署nandy/show-host-info:v1
镜像,同时给服务起名为http
,并将它关联到刚才创建的httpnet
网络。为了确保副本和可用,我们在集群中运行2个副本实例。注意,对于集群的操作都是在manager
上运行。
最后,我们在端口80
上将这两个容器进行负载平衡。向集群中的任何节点发送HTTP请求将由集群中的一个容器处理。接受请求的节点可能不是容器响应的节点。相反,Docker会在所有可用容器之间对请求进行负载平衡。
docker service create --name http --network httpnet --replicas 2 -p 80:80 nandy/show-host-info:v1
通过docker service ls
查看集群中运行的服务:
ID NAME MODE REPLICAS IMAGE PORTS
m9mcg7vzmdmc http replicated 2/2 nandy/show-host-info:v1 *:80->80/tcp
并通过docker ps
看到每个节点上容器的一个实例/副本:
# host01
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
195f225a8e47 nandy/show-host-info:v1 "python run.py" 18 seconds ago Up 17 seconds 80/tcp http.1.mzzus1shvqg3crxct6qt40avz
# host02
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6bf3107d0fcc nandy/show-host-info:v1 "python run.py" 25 seconds ago Up 23 seconds 80/tcp http.2.z3nszwhlxtfc0qkgv1bijyflc
这个时候,我们通过访问curl 172.17.0.15
或者curl 172.17.0.16
,可以看到:
$ curl 172.17.0.15
{"version":"v1","hostname":"6bf3107d0fcc","address":"10.0.0.6"}
$ curl 172.17.0.15
{"version":"v1","hostname":"195f225a8e47","address":"10.0.0.5"}
$ curl 172.17.0.15
{"version":"v1","hostname":"6bf3107d0fcc","address":"10.0.0.6"}
$ curl 172.17.0.16
{"version":"v1","hostname":"195f225a8e47","address":"10.0.0.5"}
$ curl 172.17.0.16
{"version":"v1","hostname":"6bf3107d0fcc","address":"10.0.0.6"}
$ curl 172.17.0.16
{"version":"v1","hostname":"195f225a8e47","address":"10.0.0.5"}
注意,如果通过浏览器访问,因为浏览器会默认添加Connection: keep-alive
,可能导致返回值不变。
5. 查看状态
通过docker service ps http
查看服务http
在集群中的运行状态:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
i89a438hvli6 http.1 nandy/show-host-info:v1 host02 Running Running 41 seconds ago
07gk3btmvc8l http.2 nandy/show-host-info:v1 host01 Running Running 41 seconds ago
通过docker service inspect --pretty http
查看http
服务的配置详情:
ID: n80r4huoggjfjoxbwos1q9hjq
Name: http
Service Mode: Replicated
Replicas: 2
Placement:
UpdateConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Update order: stop-first
RollbackConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Rollback order: stop-first
ContainerSpec:
Image: nandy/show-host-info:v1@sha256:8e90fa508565421478212a6e29aed68dd53cd4cc4a0e8e71415a70ce8cb1a01d
Resources:
Networks: httpnet
Endpoint Mode: vip
Ports:
PublishedPort = 80
Protocol = tcp
TargetPort = 80
PublishMode = ingress
通过docker node ps <hostname>
查看每个节点的运行状态:
$ docker node ps host01
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
07gk3btmvc8l http.2 nandy/show-host-info:v1 host01 Running Running 7 minutes ago
$ docker node ps host02
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
i89a438hvli6 http.1 nandy/show-host-info:v1 host02 Running Running 7 minutes ago
6. 扩展服务
服务允许我们扩展在群集中运行的任务的实例数,它了解如何启动容器以及运行哪些容器,因此可以根据需要轻松启动或移除容器。
目前,我们有两个负载均衡的容器在运行并处理请求,通过docker service scale http=5
,我们可以把http
服务扩展到5个容器[副本/实例]:
http scaled to 5
overall progress: 5 out of 5 tasks
1/5: running [==================================================>]
2/5: running [==================================================>]
3/5: running [==================================================>]
4/5: running [==================================================>]
5/5: running [==================================================>]
verify: Service converged
负载均衡会被自动更新,现在请求可以被5个实例间轮流响应。docker service ps http
再次查看:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
i89a438hvli6 http.1 nandy/show-host-info:v1 host02 Running Running 20 minutes ago
07gk3btmvc8l http.2 nandy/show-host-info:v1 host01 Running Running 20 minutes ago
rjcw3ltpvpy9 http.3 nandy/show-host-info:v1 host02 Running Running 5 minutes ago
weo19cib7eqi http.4 nandy/show-host-info:v1 host01 Running Running 5 minutes ago
eagf0afmg5p4 http.5 nandy/show-host-info:v1 host02 Running Running 5 minutes ago
试着通过docker service scale http=3
缩减服务的实例,看看会发生什么。