Docker的集群实战之Swarm模式
随着业务规模的扩大,一台机器的Docker已经无法满足我们的要求,为了保证性能和高可用,Docker提供了一种叫Swarm的解决方案。
他可以跨多个Docker主机来部署容器,具有完备的安全机制、内置负载均衡器;支持扩缩容、升级和回滚。
这次让我们用Swarm来部署一个2节点集群,并使用其负载均衡特性部署一个2副本Web应用。
何谓Swarm ?
一个Swarm集群由一个或多个Docker节点组成。这些节点可以是物理机、虚拟机等。只要保证节点之间的网络通畅即可。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主机 主机名为host01 host02
- 一个能获取到主机名的html网站镜像
第1步 - 初始化Swarm模式(创建第一个manager)
使用以下命令把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步 - 加入集群
集群的好处就是崩溃一个节点的时候,节点上运行的容器就会自动迁移到其他正常节点上。
要向集群加入新的节点,首先要做的就是获得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网络)
在创建服务之前,需要创建一个覆盖网络,它是一个二层网络(没有汇聚层)。
以下命令将创建一个名为skynet的新overlay网络。注册到此网络的所有容器都可以互相通信,不管部署在哪个节点上。
第一台
$ docker network create -d overlay skynet
8t0ntbrcbo
第4步 - 部署服务
默认情况下,Docker会均匀的把副本部署在集群中,如果删掉一个节点,上面所有的服务都会重新分配在其他机器上。
现在就要把我们准备好的镜像拿出来了,一个名为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 还有滚动升级、自动锁机制等优秀的特性,感兴趣可以一起学习一下!
评论