Docker的集群实战之Swarm模式

小熊 Docker评论2,908字数 4662阅读15分32秒阅读模式

Docker的集群实战之Swarm模式

随着业务规模的扩大,一台机器的Docker已经无法满足我们的要求,为了保证性能和高可用,Docker提供了一种叫Swarm的解决方案。
他可以跨多个Docker主机来部署容器,具有完备的安全机制、内置负载均衡器;支持扩缩容、升级和回滚。
这次让我们用Swarm来部署一个2节点集群,并使用其负载均衡特性部署一个2副本Web应用。

何谓Swarm ?

一个Swarm集群由一个或多个Docker节点组成。这些节点可以是物理机、虚拟机等。只要保证节点之间的网络通畅即可。Docker Swarm的结构如下:

Docker的集群实战之Swarm模式

上图是六个节点的集群,我们来引入三个概念:
节点:分为管理节点(Manager)或工作节点(Worker)两种类型,Manager负责监控集群状态、分发任务到Worker等操作;Woker负责接收Manager发来的任务并执行,每个节点就是一台Docker主机,Manager同时也是Worker节点,因为老板某种程序上来说也是员工,只不过老板是在为自己打工。
服务:服务是Worker节点执行任务相关的概念,把每个在Swarm上跑的应用都是以服务的方式运行。
副本:每个服务为了达到高可用,会复制部署多个,部署了三个我们就称这个服务部署了三个副本。
负载均衡: Swarm自带负载均衡器,用来处理的请求。
值得一提的是Swarm的配置和状态信息保存在位于所有Manager上的分布式etcd数据库中;同时在集群内部,有一个安全系统,用于节点间通信加密、认证和授权等操作,这整个过程都是自动的,和etcd一样不需要任何配置,几乎察觉不到他们的存在。

  • Docker Swarm自docker 1.12版本以后已经和Docker直接集成在一起了,一条命令就可以启用。

第0步 - 准备

Docker的集群实战之Swarm模式

我们要搭建一个两节点集群,整个集群只有一个服务,两个副本,每个副本就是一个容器,均匀分布在每个节点上。
准备:

  1. 两个互通的Docker主机 主机名为host01 host02
  2. 一个能获取到主机名的html网站镜像

第1步 - 初始化Swarm模式(创建第一个manager)

Docker的集群实战之Swarm模式

使用以下命令把docker转成Swarm模式。

$ docker swarm init

执行完这条命令,当前节点就成为了Manager节点,并打出一个token,以后在拓展的时候就要用的到token验证了。

# host01执行
$ docker swarm init
Swarm initialized: current node (hzdjc2iv3m7onlz54k8hkhfpe) is now a manager.
To add a worker to this swarm, run the following command:
    docker swarm join --token SWMTKN-1-1hkuj0ya0ppj2qbmnq3tiqtyfbudo3wp6xcfmy446tadde1gpl-2ldsknja98b6s94k4pc3huno4 172.17.0.15:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

172.17.0.15是host01的ip,2377是Swarm默认的集群管理端口,加入集群就是向此端口通信。这个端口要控制好访问权限来防止不信任的用户或者节点访问到。

第2步 - 加入集群

集群的好处就是崩溃一个节点的时候,节点上运行的容器就会自动迁移到其他正常节点上。
Docker的集群实战之Swarm模式
要向集群加入新的节点,首先要做的就是获得token

#输出添加worker所需要的token
docker swarm join-token -q worker 
#输出添加manager所需要的token docker swarm join-token -q manager

我们现在host01已经创建为manager节点了,现在把host02节点以worker的身份加入集群。
在host02上执行以下命令(命令较长,\>代表换行)

$ token=$(ssh -o StrictHostKeyChecking=no 172.17.0.15 \
> "docker swarm join-token -q worker") && echo $token
Warning: Permanently added '172.17.0.15' (ECDSA) to the list of known hosts.
SWMTKN-1-1hkuj0ya0ppj2qbmnq3tiqtyfbudo3wp6xcfmy446tadde1gpl-2ldsknja98b6s94k4pc3huno4

在host02上执行以下命令,可以远程登陆host01并把worker所需的token赋值到token变量中(172.17.0.15是host01的ip)

$ docker swarm join 172.17.0.15:2377 --token $token
This node joined a swarm as a worker.

向manager节点发加入集群的请求,token为附带参数(根据token来判断新加入的节点角色)
默认情况下,manager将自动接受添加到集群的新节点。
可以使用docker node ls来查看节点状态

$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
hzdjc2iv3m7onlz54k8hkhfpe * host01 Ready Active Leader 18.09.5
c5fsn2z7p1tw5iqwa2d54698m host02 Ready Active 18.09.5

第3步 - 创建覆盖网络(overlay网络)

Docker的集群实战之Swarm模式
在创建服务之前,需要创建一个覆盖网络,它是一个二层网络(没有汇聚层)。
以下命令将创建一个名为skynet的新overlay网络。注册到此网络的所有容器都可以互相通信,不管部署在哪个节点上。
第一台

$ docker network create -d overlay skynet
8t0ntbrcbo

第4步 - 部署服务

默认情况下,Docker会均匀的把副本部署在集群中,如果删掉一个节点,上面所有的服务都会重新分配在其他机器上。
Docker的集群实战之Swarm模式
现在就要把我们准备好的镜像拿出来了,一个名为hostname-web:v1的镜像,他部署在哪台机器上就到获取到哪个主机的hostname,设置到容器内部的index.html里。
manager执行

docker service create --name http --network skynet --replicas 2 -p 80:80 hostname-web:v1

--name     服务名
--network 指定网络
--replicas  副本数
-p 映射端口
上面的命令创建了一个名为http的服务,指定的网络为上一步创建的skynet覆盖网络,2个副本,映射80到容器中的80端口,使用hostname-web:v1镜像。
请求80端口就是在访问服务,swarm会在所有副本之间进行负载均衡,
可以在manager上运行docker service ls查看状态

$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
tvidvge94pzt http replicated 2/2 hostname-web:v1

可以使用docker ps分别在两个主机上查看创建的镜像,这里我们就不废话了。
在host01上请求,查看结果

$ curl host01
<h1>host01</h1>
$ curl host01
<h1>host02</h1>

第5步 - 检查状态

查看服务下所有的容器列表详细信息,包括容器跑在哪台机器上,用的什么镜像,跑了多长时间等。

$ docker service ps http
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
zydwyr2tpzd4 http.1 hostname-web:v1 host02 Running Running 3 minutes ago
38ih400au70t http.2 hostname-web:v1 host01 Running Running 3 minutes ago

查看服务的详细信息和配置

$ docker service inspect --pretty http

可以使用docker node ls来查看节点状态

$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
hzdjc2iv3m7onlz54k8hkhfpe * host01 Ready Active Leader 18.09.5
c5fsn2z7p1tw5iqwa2d54698m host02 Ready Active 18.09.5

可以把上面输出结果的第一列ID当做docker node ps 的参数,查询此节点上的服务列表,如果用self参数则代表本机。

扩容与缩容自动均衡

我们可以在服务运行的时候,修改副本数量实现自动扩容
执行以下命令把http服务扩容成五个副本运行。

$ docker service scale 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

在host01上查看扩容结果,可以看到有两个容器,另一台机器上有三个容器。Swarm会尽量保证各个副本均匀的分布在每个节点上(就算负载大的机器还是会被均匀分配,有兴趣可以研究真正的负载均衡方案,也欢迎在留言器和我交流)

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fe374853b402  hostname-web:v1 "/app" 48 seconds ago Up 47seconds 80/tcp http.3.8xx1eo4qop3ctefim9k685xz7
01241f07c109  hostname-web:v1 "/app" 7 minutes ago Up 7 minutes 80/tcp http.2.38ih400au70tvbs76xa10xmpa

小结

docker swarm init初始化新的Swarm,并把当前节点设置为第一个Manager。
docker swarm join-token --tags <token>节点加入集群
docker swarm join-token -q manager|worker打印加入集群时节点对应角色所需要的token
docker node ls列出所有节点信息
docker node ps <id>查看某个节点下的所有服务
docker service create创建服务
docker service inspect <service>服务详细信息
docker service ps <service>服务的副本(容器)信息
docker service scale <service>=<number>扩缩容
docker service update更新服务属性
docker service logs查看服务日志
docker service rm删除服务(在不做确认的情况下删掉服务的所有副本)
Docker 还有滚动升级、自动锁机制等优秀的特性,感兴趣可以一起学习一下!

weinxin
公众号
扫码订阅最新深度技术文,回复【资源】获取技术大礼包
Docker最后更新:2020-8-31
小熊