Docker Swarm 集群

Swarm 在 Docker 1.12 版本之前属于一个独立的项目,在 Docker 1.12 版本发布之后,该项目合并到了 Docker 中,成为 Docker 的一个子命令。目前,Swarm 是 Docker 社区提供的唯一一个原生支持 Docker 集群管理的工具。它可以把多个 Docker 主机组成的系统转换为单一的虚拟 Docker 主机,使得容器可以组成跨主机的子网网络。

了解 Swarm 集群

群集是一组运行 Docker 的计算机组成,其中部分机器是集群管理机(Swarm Manager) ,其他的是工作机(Worker)。在集群中,在 Manager 机器上使用 Docker 命令,会在群集上执行。群集中的机器可以是物理机或虚拟机。加入群集后,它们被统称节点(Node)。

Swarm 管理机可以使用几种策略来运行容器,例如“最空闲节点”- 容器会填充最少使用的机器。或“全局策略”,它确保每个机器能只能获得指定容器的一个实例。您可以将这些策略写在 docker-compose.yml 这样的服务组合定义文件中,Swarm管理机会按策略部署。

Swarm Manager 是群集中唯一可以执行 docker 命令的机器,或授权其他机器作为工人机(worker)加入群集。worker 只是提供能力,没有权力指挥其他机器工作。

如果您已经熟悉单主机中使用 Docker。现在,可切换到 Docker 集群模式。启用群组模式(swarm mode)使当前的机器成为群组管理机。这时,这台 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:用于多应用部署

Swarm 集群工作原理

一个 docker swarm 集群的组成结构,如图:

它分为两类节点,manager 和 worker。

manager 节点处理集群管理任务:

维护集群状态(配置)
调度服务
提供集群模式 HTTP API 端点服务

管理节点共同维护一个强一致状态数据(你可以认为每个管理节点拥有一个同步的集群状态/配置数据库),任何一个经理退出都不会导致集群失效。

高可靠模式 是指容器集群拥有 3 个以上 manager。一个 manager 是基数(如 3、5、7),一半以下 manager 失效都不会导致集群状态失效。Docker为群组建议最多七个管理器节点。

多个 7 个 manager 不会提高可靠性,反而会提高开销

强一致状态数据库常见实现包括: etcd 、consul 、zookeeper 等等。

worker 节点的唯一目的就是运行容器(服务)。默认情况下,manager 同时承担 worker 的职能,所以一个 manager 可以单节点运行,所有容器运行在一个节点中。

对于大型的容器集群,需要设置管理器节点的可用性设置为 Drain 以阻止服务的任务运行。

docker node update 是一个很有用的命令,可以改变节点的 role,label 等

配置 Swarm 集群

准备3个虚拟机,分别是 manager,worker1和worker2,如果还没有配置的同学可以查看前两篇《Docker 集群网络规划与 VM 网络配置》进行配置。

清理 manager 虚拟机

清理所有的容器 docker rm -f $(docker ps -q)
退出可能的集群状态 docker swarm leave –force

在 manager 上启动 docker swarm mode:

1
docker swarm init --advertise-addr 192.168.56.100

这时,manager 将在端口 192.168.56.100:2377 侦听集群节点请求。

加入集群的指令:

worker: docker swarm join-token worker
manager: docker swarm join-token manager

获取 worker1 和 worker2 加入的指令:

1
docker swarm join-token worker

将 worker1 和 worker2 加入集群

分别用 ssh 连接两个 worker,输入刚刚在 manager 获取到的指令:

1
2
3
docker swarm join \
--token <token> \
<ip>:<port>

这时,我们的第一个集群就建完了。 如果因为防火墙,无法加入集群,要先关闭防火墙。

manager 上检查结果

1
docker node ls

portainer 上检查结果

在 manager 上启动 Portainer ,打开浏览器

在集群中部署服务和使用服务

1、部署服务,在 manager 虚拟机中,cd 到 service_test目录,再输入:

1
docker stack deploy -c docker-compose.yml myservice

成功将服务(容器)平均分配到三台机器上了。

访问集群

使用集群中任意一台机器的 IP, 我们都能看到循环访问不同容器服务的结果,体现了负载均衡。

每个IP地址都工作的原因是群集中的节点参与入口路由网格(route mesh)。这样可以确保在群集中某个端口部署的服务始终将该端口保留给其自身,无论实际运行的是哪个节点。以下是在三节点群集my-web端口8080上发布的服务的路由网格的示例:

结束服务:

1
docker stack rm myservice

部署一个简单应用

1、新建一个 compose 文件

1
2
3
cd && mkdir myapp && cd myapp
cp ../service_test/docker-compose.yml docker-compose.yml
mkdir data

注: data 目录用来存放 redis 的数据

2、修改服务栈配置

1
sudo vim docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
# image: registry.cn-shenzhen.aliyuncs.com/aidansu/hello-python:1.0
image: <username/repository:tag>
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- webnet
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
- webnet
redis:
image: redis
ports:
- "6379:6379"
volumes:
- ./data:/data
deploy:
placement:
constraints: [node.role == manager]
networks:
- webnet
networks:
webnet:

上述配置中,添加了 visualizer 集群容器可视化工具和 redis 这个服务,visualizer 和 redis 服务被指定到 [node.role == manager] 机器,因为它与这台机器要共享数据卷 ./data 映射到容器 /data 数据卷

3、启动这个栈:

1
docker stack deploy -c docker-compose.yml myservice

网站会计数了,它们共享一个 Redis 数据服务。

visualizer 集群容器可视化工具的工作原理同 Portainer 相同, docker 的示例源代码 docker-swarm-visualizer

想了解更多关于 Docker 信息的可以查看最新的官方文档:https://docs.docker.com/

完!

坚持原创技术分享,您的支持将鼓励我继续创作!