Docker Swarm集群管理
文章目录
1. 简介
Swarm是Docker公司推出的用来管理docker集群的平台,几乎全部用GO语言来完成的开发的,代码开源在https://github.com/docker/swarm, 它是将一群Docker宿主机变成一个单一的虚拟主机,Swarm使用标准的Docker API接口作为其前端的访问入口,换言之,各种形式的Docker
Client(compose,docker-py等)均可以直接与Swarm通信,甚至Docker本身都可以很容易的与Swarm集成,这大大方便了用户将原本基于单节点的系统移植到Swarm上,同时Swarm内置了对Docker网络插件的支持,用户也很容易的部署跨主机的容器集群服务。
Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。
从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具,我们就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。
Swarm deamon只是一个调度器(Scheduler)加路由器(router),Swarm自己不运行容器,它只是接受Docker客户端发来的请求,调度适合的节点来运行容器,这就意味着,即使Swarm由于某些原因挂掉了,集群中的节点也会照常运行,放Swarm重新恢复运行之后,他会收集重建集群信息。
2. 架构
docker swarm是docker官方提供的一套容器编排系统,是Docker公司推出的官方容器集群平台。基于 Go语言实现。它的架构如下:
在结构图可以看出 Docker Client使用Swarm对 集群(Cluster)进行调度使用。
Swarm是典型的master-slave结构,通过发现服务来选举manager。manager是中心管理节点,各个node上运行agent接受manager的统一管理,集群会自动通过Raft协议分布式选举出manager节点,无需额外的发现服务支持,避免了单点的瓶颈问题,同时也内置了DNS的负载均衡和对外部负载均衡机制的集成支持
3. Swarm的核心概念
2.1 集群
一个集群由多个 Docker 主机组成,这些Docker主机以集群模式运行,并充当管理者(用于管理 成员资格和委派)和工作人员(运行集群服务)
与独立容器相比,集群服务的主要优势之一是,可以修改服务的配置,包括它所连接的网络和卷, 而无需手动重新启动服务。
独立容器和集群服务之间的主要区别在于,只有集群管理器可以管理集群,而独立容器可以在任何 守护程序上启动。
集群的管理和编排是使用嵌入docker引擎的SwarmKit,可以在docker初始化时启动swarm模式或者加入已存在的swarm
2.2 节点
swarm是一系列节点的集合,而节点可以是一台裸机或者一台虚拟机。一个节点能扮演一个或者两个角色,manager或者worker,一个节点是docker引擎集群的一个实例。您还可以将其视为Docker节点。您可以在单个物理计算机或云服务器上运行一个或多个节点,但生产群集部署通常包括分布在多个物理和云计算机上的Docker节点。要将应用程序部署到swarm,请将服务定义提交给 管理器节点。管理器节点将称为任务的工作单元分派 给工作节点。
- manager节点
Docker Swarm集群需要至少一个manager节点,节点之间使用 进 行协同工作。 通常,第一个启用docker swarm的节点将成为leader,后来加入的都是follower。 当前的leader如果挂掉,剩余的节点将重新选举出一个新的leader。 每一个manager都有一个完 整的当前集群状态的副本,可以保证manager的高可用 - worker节点
worker节点是运行实际应用服务的容器所在的地方。理论上,一个manager节点也能同时成为 worker节点,但在生产环境中,我们不建议这样做。 worker节点之间,通过 control plane 进 行通信,这种通信使用 gossip 协议,并且是异步的
2.3 服务和任务
集群中的stacks, services, tasks的关系,如下图:
-
services(服务)
swarm service是一个抽象的概念,它只是一个对运行在swarm集群上的应用服务,所期望状态的描述。它就像一个描述了下面物品的清单列表一样:- 服务名称
- 使用哪个镜像来创建容器
- 要运行多少个副本
- 服务的容器要连接到哪个网络上
- 应该映射哪些端口
-
task(任务)
在Docker Swarm中,task是一个部署的最小单元,task与容器是一对一的关系 -
stack(栈)
stack是描述一系列相关services的集合。我们通过在一个YAML文件中来定义一个stack -
操作命令:
docker swarm:集群管理,子命令有init, join, leave, update。(docker swarm --help查看帮助)
docker service:服务创建,子命令有create, inspect, update, remove, tasks。(docker service–help查看帮助)
docker node:节点管理,子命令有accept, promote, demote, inspect, update, tasks, ls, rm。(docker node --help查看帮助)
2.4 负载均衡
集群管理器使用入口负载平衡将要从集群外部获取的服务公开给集群。
集群管理器可以自动为服务分配一个已发布端口,也可以为该服务配置一个已发布端口。
可以指定任何未使用的端口。如果未指定端口,则集群管理器会为服务分配 30000-32767 范围内 的端口。
集群模式具有一个内部DNS组件,该组件自动为群集中的每个服务分配一个DNS条目。 集群管理器使用内部负载平衡根据服务的DNS名称在群集内的服务之间分配请求。
4. Swarm的工作模式
4.1 node
4.2 Service
4.3 任务与调度
4.4 服务副本与全局服务
5. Swarm的调度策略
Swarm在调度(scheduler)节点(leader节点)运行容器的时候,会根据指定的策略来计算最适合运行容器的节点,目前支持的策略有:spread, binpack, random.
1)Random
顾名思义,就是随机选择一个Node来运行容器,一般用作调试用,spread和binpack策略会根据各个节点的可用的CPU, RAM以及正在运
行的容器的数量来计算应该运行容器的节点。
2)Spread
在同等条件下,Spread策略会选择运行容器最少的那台节点来运行新的容器,binpack策略会选择运行容器最集中的那台机器来运行新的节点。
使用Spread策略会使得容器会均衡的分布在集群中的各个节点上运行,一旦一个节点挂掉了只会损失少部分的容器。
3)Binpack
Binpack策略最大化的避免容器碎片化,就是说binpack策略尽可能的把还未使用的节点留给需要更大空间的容器运行,尽可能的把容器运行在
一个节点上面。
6. Swarm Cluster模式特性
-
批量创建服务
建立容器之前先创建一个overlay的网络,用来保证在不同主机上的容器网络互通的网络模式 -
强大的集群的容错性
当容器副本中的其中某一个或某几个节点宕机后,cluster会根据自己的服务注册发现机制,以及之前设定的值–replicas n,在集群中剩余的空闲节点上,重新拉起容器副本。整个副本迁移的过程无需人工干预,迁移后原本的集群的load balance依旧好使!不难看出,docker service其实不仅仅是批量启动服务这么简单,而是在集群中定义了一种状态。Cluster会持续检测服务的健康状态并维护集群的高可用性。 -
服务节点的可扩展性
Swarm Cluster不光只是提供了优秀的高可用性,同时也提供了节点弹性扩展或缩减的功能。当容器组想动态扩展时,只需通过scale参数即可复制出新的副本出来。
仔细观察的话,可以发现所有扩展出来的容器副本都run在原先的节点下面,如果有需求想在每台节点上都run一个相同的副本,方法其实很简单,只需要在命令中将"–replicas n"更换成"–mode=global"即可!
-
复制服务(–replicas n)
将一系列复制任务分发至各节点当中,具体取决于您所需要的设置状态,例如“–replicas 3”。 -
全局服务(–mode=global)
适用于集群内全部可用节点上的服务任务,例如“–mode global”。如果大家在 Swarm 集群中设有 7 台 Docker 节点,则全部节点之上都将存在对应容器。
- 调度机制
所谓的调度其主要功能是cluster的server端去选择在哪个服务器节点上创建并启动一个容器实例的动作。它是由一个装箱算法和过滤器组合而成。每次通过过滤器(constraint)启动容器的时候,swarm cluster 都会调用调度机制筛选出匹配约束条件的服务器,并在这上面运行容器。
------------------Swarm cluster的创建过程包含以下三个步骤----------------------
1)发现Docker集群中的各个节点,收集节点状态、角色信息,并监视节点状态的变化
2)初始化内部调度(scheduler)模块
3)创建并启动API监听服务模块
一旦创建好这个cluster,就可以用命令docker service批量对集群内的容器进行操作,非常方便!
在启动容器后,docker 会根据当前每个swarm节点的负载判断,在负载最优的节点运行这个task任务,用"docker service ls" 和"docker service ps + taskID"可以看到任务运行在哪个节点上。容器启动后,有时需要等待一段时间才能完成容器创建。
7. Swarm安装
对于Docker 1.12+版本,Swarm相关命令已经原生嵌入到了Docker Engine中
- 下载镜像
docker pull swarm
- 启动并查看版本
[root@rpp ~]# docker run --rm swarm -v
swarm version 1.2.9 (527a849)
8. Swarm集群搭建
IP:47.94.80.41 担任角色:swarm manager
IP:81.71.31.82 担任角色:swarm node
8.1 创建新集群
[root@rpp ~]# docker swarm init --advertise-addr 47.94.80.41
Swarm initialized: current node (12qrxc743nsmot0to9c30gdom) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-338uighxv8q7j8gyt4quhcoderb267liiate5r4zgihusehx6d-b5daif7ggwtbx4mizn60s5uoo 47.94.80.41:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
[root@rpp ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-338uighxv8q7j8gyt4quhcoderb267liiate5r4zgihusehx6d-61um2v2l3cmsqd2tel6qeswhl 47.94.80.41:2377
[root@rpp ~]#
# 将节点强制驱除集群
docker swarm leave --force
上面命令执行后,该机器自动加入到swarm集群。这个会创建一个集群token,获取全球唯一的 token,作为集群唯一标识。后续将其他节点加入集群都会用到这个token值。
其中,–advertise-addr参数表示其它swarm中的worker节点使用此ip地址与manager联系。命令的输 出包含了其它节点如何加入集群的命令。
docker swarm join-token manager 命令会返回一个加入此集群并且角色为manager的执行命令。
8.2 查看集群状态和节点信息
查看集群状态
[root@rpp ~]# docker info
Client:
Debug Mode: false
Server:
Containers: 2
Running: 0
Paused: 0
Stopped: 2
Images: 4
Server Version: 19.03.13
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: active
NodeID: 12qrxc743nsmot0to9c30gdom
Is Manager: true
ClusterID: y4z9r0j2qjpws7ot7dkzxpyvx
Managers: 1
Nodes: 1
Default Address Pool: 10.0.0.0/8
SubnetSize: 24
Data Path Port: 4789
Orchestration:
Task History Retention Limit: 5
Raft:
Snapshot Interval: 10000
Number of Old Snapshots to Retain: 0
Heartbeat Tick: 1
Election Tick: 10
Dispatcher:
Heartbeat Period: 5 seconds
CA Configuration:
Expiry Duration: 3 months
Force Rotate: 0
Autolock Managers: false
Root Rotation In Progress: false
Node Address: 47.94.80.41
Manager Addresses:
47.94.80.41:2377
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 8fba4e9a7d01810a393d5d25a3621dc101981175
runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd
init version: fec3683
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-957.21.3.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 3.518GiB
Name: rpp
ID: X3TD:OYHI:XAXO:NS45:GOWN:XQ3T:B7I2:4OTR:6FJX:43RB:272K:TC67
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://registry.docker-cn.com/
Live Restore Enabled: false
查看节点信息
[root@rpp ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
12qrxc743nsmot0to9c30gdom * rpp Ready Active Leader 19.03.13
8.3 添加工作节点到集群
创建了一个集群与管理器节点,就可以添加工作节点。
在工作节点81.71.31.82上安装docker和docker swarm
[root@VM-0-14-centos ~]# docker swarm join --token SWMTKN-1-338uighxv8q7j8gyt4quhcoderb267liiate5r4zgihusehx6d-b5daif7ggwtbx4mizn60s5uoo 47.94.80.41:2377
This node joined a swarm as a worker.
# 将节点强制驱除集群
docker swarm leave --force
如果忘记了token的值,在管理节点47.94.80.41上执行如下命令
#在管理者节点上写
[root@rpp ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-338uighxv8q7j8gyt4quhcoderb267liiate5r4zgihusehx6d-61um2v2l3cmsqd2tel6qeswhl 47.94.80.41:2377
[root@rpp ~]# docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-338uighxv8q7j8gyt4quhcoderb267liiate5r4zgihusehx6d-b5daif7ggwtbx4mizn60s5uoo 47.94.80.41:2377
在管理节点上再次查看节点信息,可以看到集群中有两个节点
[root@rpp ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
iwaoag19d91jmq3tdn5yjp36h VM-0-14-centos Ready Active 19.03.13
12qrxc743nsmot0to9c30gdom * rpp Ready Active Leader 19.03.13
8.4 更改节点的availablity状态
swarm集群中node的availability状态可以为 active或者drain,其中:
active状态下,node可以接受来自manager节点的任务分派;
drain状态下,node节点会结束task,且不再接受来自manager节点的任务分派(也就是下线节点)
# 将VM-0-14-centos节点下线。如果要删除节点,命令是"docker node rm --force VM-0-14-centos"
[root@rpp ~]# docker node update --availability drain VM-0-14-centos
VM-0-14-centos
[root@rpp ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
iwaoag19d91jmq3tdn5yjp36h VM-0-14-centos Ready Drain 19.03.13
12qrxc743nsmot0to9c30gdom * rpp Ready Active Leader 19.03.13
如上,当VM-0-14-centos的状态改为drain后,那么该节点就不会接受task任务分发,就算之前已经接受的任务也会转移到别的节点上。
再次修改为active状态(及将下线的节点再次上线)
[root@rpp ~]# docker node update --availability active VM-0-14-centos
VM-0-14-centos
[root@rpp ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
iwaoag19d91jmq3tdn5yjp36h VM-0-14-centos Ready Active 19.03.13
12qrxc743nsmot0to9c30gdom * rpp Ready Active Leader 19.03.13
8.5 发布服务到集群
- 部署服务
[root@rpp ~]# docker service create -p 80:80 --replicas 2 --name nginx1 nginx
tp23jh5n17n3ia0ayvdw5mabh
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service converged
-p :端口映射 --replicas:运行实例个数 --name:服务名 nginx : 镜像
- 使用 docker service ls 查看正在运行服务的列表
[root@rpp ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
tp23jh5n17n3 nginx1 replicated 2/2 nginx:latest *:80->80/tcp
- 详细查询Swarm中服务的信息
-pretty 使命令输出格式化为可读的格式,不加 --pretty 可以输出更详细的信息:
[root@rpp ~]# docker service inspect --pretty nginx1
ID: tp23jh5n17n3ia0ayvdw5mabh
Name: nginx1
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: nginx:latest@sha256:6b1daa9462046581ac15be20277a7c75476283f969cb3a61c8725ec38d3b01c3
Init: false
Resources:
Endpoint Mode: vip
Ports:
PublishedPort = 80
Protocol = tcp
TargetPort = 80
PublishMode = ingress
- 查看哪些节点正在运行服务
[root@rpp ~]# docker service ps nginx1
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
uoqitrznmx21 nginx1.1 nginx:latest rpp Running Running 4 minutes ago
zcj5f53j3vel nginx1.2 nginx:latest VM-0-14-centos Running Running 5 minutes ago
由上面命令可知,该服务在两个节点上运行。登陆节点,可以查看到nginx容器在运行中
[root@rpp ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
27aa9f567b0c nginx:latest "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 80/tcp nginx1.1.uoqitrznmx21df630ca32172m
[root@VM-0-14-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec6f01d2f32c nginx:latest "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 80/tcp nginx1.2.zcj5f53j3vel1xmq7aceouqh1
3e71906885bb nginx "/docker-entrypoint.…" 46 hours ago Up 46 hours 80/tcp, 0.0.0.0:8080->8080/tcp webserver
注意:以上命令均在管理节点上运行
- 停止并删除发布的服务
[root@rpp ~]# docker service rm nginx1
nginx1
8.6 在Swarm中动态扩展服务(scale)
当然,如果只是通过service启动容器,swarm也算不上什么新鲜东西了。Service还提供了复制(类似kubernetes里的副本)功能。可以通过 docker service scale 命令来设置服务中容器的副本数
比如将上面的nginx1容器动态扩展到3个
[root@rpp ~]# docker service scale nginx1=3
nginx1 scaled to 3
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
和创建服务一样,增加scale数之后,将会创建新的容器,这些新启动的容器也会经历从准备到运行的过程,过一分钟左右,服务应该就会启动完成,这时候可以再来看一下 nginx 服务中的容器
[root@rpp ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
rb95k2qvxe79 nginx1 replicated 3/3 nginx:latest *:80->80/tcp
[root@rpp ~]# docker service ps nginx1
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
i6qemrp16cbv nginx1.1 nginx:latest VM-0-14-centos Running Running 2 minutes ago
gq5eg4yosvqw nginx1.2 nginx:latest rpp Running Running 2 minutes ago
nidrmp0c1dez nginx1.3 nginx:latest rpp Running Running 34 seconds ago
8.7 更新服务
除了上面使用scale进行容器的扩容或缩容之外,还可以使用docker service update 命令。 可对 服务的启动 参数 进行 更新/修改。
[root@rpp ~]# docker service update --publish-rm 80:80 --publish-add 88:80 nginx1
nginx1
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
```bash
[root@rpp ~]# docker service update --replicas 2 nginx1
nginx1
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service converged
docker service update 命令,也可用于直接 升级 镜像等
docker service update --image nginx:new nginx1
8.8 节点管理
命令名称 | 说明 |
---|---|
docker node demote | 从群集(swarm)管理器中降级一个或多个节点 |
docker node inspect | 显示一个或多个节点的详细信息 |
docker node ls | 列出群集(swarm)中的节点 |
docker node promote | 从群集(swarm)管理器中升级一个或多个节点 |
docker node ps | 列出在一个或多个节点上运行的任务,默认为当前节点 |
docker node rm | 从群集(swarm)删除一个或多个节点 |
docker node update | 更新一个节点 |