What is Docker Swarm?

    Docker Swarm是一套管理docker集群的工具。它将一群docker宿主机转变为单个的虚拟主机。由于Swarm提供标准的API接口,因此,任何能够和docker守护进程通信的工具,都可以利用swarm去扩展多个主机,支持的docker工具如,Dokku、Docker compose、Docker machine、jenkis、docker-py、Krane、Deis等等。Docker本身都可以很容易与Swarm进行集成。    

Docker三剑客之Swarm_swarm

在使用Swarm管理docker集群时,会有一个swarm manager以及若干的swarm node,swarm manager上运行swarm daemon,用户只需要跟swarm manager通信,然后swarm manager再根据discovery service的信息选择一个swarm node来运行container。

值得注意的是 swarm daemon 只是一个任务调度器(scheduler)和路由器(router),它本身不运行容器,它只接受Docker client发送过来的请求,调度合适的swarm node来运行container。这意味着,即使 swarm daemon 由于某些原因挂掉了,已经运行起来的容器也不会有任何影响。

有以下两点需要注意:

  • 集群中的每台节点上面的Docker的版本都不能小于1.4

  • 为了让swarm manager能够跟每台swarm node进行通信,集群中的每台节点的 Docker daemon都必须监听同一个网络接口。

基本概念

节点

运行 Docker 的主机可以主动初始化一个 Swarm 集群或者加入一个已存在的 Swarm 集群,这样这个运行 Docker 的主机就成为一个 Swarm 集群的节点 (node) 。

节点分为管理 (manager) 节点和工作 (worker) 节点。

管理节点用于 Swarm 集群的管理,docker swarm 命令基本只能在管理节点执行(节点退出集群命令 docker swarm leave 可以在工作节点执行)。一个 Swarm 集群可以有多个管理节点,但只有一个管理节点可以成为 leader,leader 通过 raft 协议实现。

工作节点是任务执行节点,管理节点将服务 (service) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。

以下展示了集群中管理节点与工作节点的关系。

Docker三剑客之Swarm_swarm_02

服务和任务

任务 (Task)是 Swarm 中的最小的调度单位,目前来说就是一个单一的容器。

服务 (Services) 是指一组任务的集合,服务定义了任务的属性。服务有两种模式:

  • replicated services 按照一定规则在各个工作节点上运行指定个数的任务。

  • global services 每个工作节点上运行一个任务

两种模式通过 docker service create 的 --mode 参数指定。

来自 Docker 官网的这张图片形象的展示了容器、任务、服务的关系。

Docker三剑客之Swarm_docker_03

整体环境

Docker三剑客之Swarm_docker_04

关于Swarm集群构建

    在构建Docker swarm集群时,可以通过docker自带的Swarm mode进行构建。Swarm mode是Docker Engine内置支持的一种默认实现模式,很容易使用,并且不需要安装任何额外的软件。Docker 1.12或者更高的版本中,都默认支持Swarm mode。通过Swarm mode构建Docker集群的方式很简单,基本包括:初始化一个Swarm集群、将node节点加入到集群中、将应用服务部署到Swarm集群中。这样一个Swarm集群及应用部署就构建好了。

Swarm集群基本特性:

  • 集群管理模式集成于Docker Engine

  • 灵活添加集群Manager节点或node节点

  • 服务的发现、滚动更新和扩容及缩容

  • 指定node节点分发服务容器,实现负载均衡

设置Swarm集群

初始化集群

[root@centos7 ~]# docker swarm init --advertise-addr 192.168.39.185
Swarm initialized: current node (cu0e19sasn77t44wbjnsjtn8s) is now a manager.
To add a worker to this swarm, run the following command:
    docker swarm join --token SWMTKN-1-503tbj031pm5udwskezixpeu666bce2valkvt9wq0uco1af2os-4a1z8tbjhf3diyxo7kghf26v4 192.168.39.185:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

多个网卡需要--advertise-addr参数指定相应网卡,其中node个节点都是通过此参数指定的网卡与Manager节点建立的通信。此时通过netstat命令可以查看到端口2377监听集群节点请求。

输出包括以下命令:

docker swarm join --token SWMTKN-1-503tbj031pm5udwskezixpeu666bce2valkvt9wq0uco1af2os-4a1z8tbjhf3diyxo7kghf26v4 192.168.39.185:2377

在node节点上执行此条命令即可将node节点加入到集群中。

通过docker info命令查询状态信息:

[root@centos7 ~]# docker info
Containers: 7
 Running: 5
 Paused: 0
 Stopped: 2
Images: 3
Server Version: 18.06.0-ce
Storage Driver: devicemapper
 Pool Name: docker-8:2-107044267-pool
 Pool Blocksize: 65.54kB
 Base Device Size: 10.74GB
 Backing Filesystem: xfs
 Udev Sync Supported: true
 Data file: /dev/loop0
 Metadata file: /dev/loop1
 Data loop file: /var/lib/docker/devicemapper/devicemapper/data
 Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata
 Data Space Used: 488.7MB
 Data Space Total: 107.4GB
 Data Space Available: 8.372GB
 Metadata Space Used: 1.176MB
 Metadata Space Total: 2.147GB
 Metadata Space Available: 2.146GB
 Thin Pool Minimum Free Space: 10.74GB
 Deferred Removal Enabled: true
 Deferred Deletion Enabled: true
 Deferred Deleted Device Count: 0
 Library Version: 1.02.140-RHEL7 (2017-05-03)
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: active
 NodeID: mhfkjl27xt3d459ioz23ve2om
 Is Manager: true
 ClusterID: cnrh9656rqjmd0bvpyhz0zhlu
 Managers: 1
 Nodes: 5
 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: 192.168.39.185
 Manager Addresses:
  192.168.39.185:2377
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: d64c661f1d51c48782c9cec8fda7604785f93587
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:
 seccomp
  Profile: default
Kernel Version: 3.10.0-693.17.1.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 975.3MiB
Name: centos7
ID: CYJZ:PO67:6LBM:BCPB:DZLG:J4ZS:TKYS:UTD7:7P5Y:6MI2:SM5U:RSFD
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false
WARNING: devicemapper: usage of loopback devices is strongly discouraged for production use.
         Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.

加入Swarm集群

在所有要加入集群的节点上面执行 docker swarm join命令,表示要把这台机器加入这 个集群当中。通过Salt命令将4个Slave节点加入集群中:

[root@centos7 ~]# salt "*" cmd.run "docker swarm join --token SWMTKN-1-503tbj031pm5udwskezixpeu666bce2valkvt9wq0uco1af2os-4a1z8tbjhf3diyxo7kghf26v4 192.168.39.185:2377"

执行结果返回“This node joined a swarm as a worker.”,说明已经将Slave节点加入集群当中。

注意:如果不能正常加入集群,请检查防火墙。

查看集群

通过docker node命令,在master端可以查看当前集群状态:

[root@centos7 ~]# docker node ls

Docker三剑客之Swarm_swarm_05

以上信息中AVAILABILITY表示Swarm Scheduler是否可以向集群中的某个node指派Task,对应的有三种状态:

  • Active:集群中该Node可以被指派Task

  • Pause:集群中该Node不可以被指派新的Task,但是其他已经存在的Task保持运行

  • Drain:集群中该Node不可以被指派新的Task,Swarm scheduler停掉已经存在的Task,并将它们调度到可用的Node上

查看某个Node状态详细信息:

docker node inspect [NodeID]

管理Swarm node状态

Node的AVAILABILITY有三种状态,因此,可以将AVAILABILITY值通过docker node update修改不同的状态,下面常见的变更操作有:

  • 设置Manager node只具备管理功能

  • 对服务进行停止维护,可以修改AVAILABILITY值为Drain状态

  • 暂停一个Node,然后该node不再接收新的Task

  • 恢复一个不可用或者暂停的Node

例如:

1)将Manager Node的AVAILABILITY值修改为Drain状态,使其只具备管理功能,执行如下:

[root@centos7 ~]# docker node update  --availability drain centos7

这样,ManagerNode不能被指派Task,也就是不能部署实际的Docker容器来运行服务,而只作为管理Node角色。

2)Node提权/降权

Worker node可以变为Manager Node,执行如下:

[root@centos7 ~]# docker  node demote centos7-1

3) 退出Swarm集群

如果node想要退出Swarm,可以在node节点上执行如下:

# docker swarm node leave

问题:

有时候在执行Swarm集群相关命令时候,会出现以下报错信息,如:

[root@centos7 ~]# docker node ls
Error response from daemon: rpc error: code = 2 desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.

出现这个问题的主要原因是因为集群节点中manager节点出现异常导致,可以强制初始化集群解决此问题:

docker swarm init --force-new-cluster

部署服务

我们部署服务可以通过docker service 命令去部署和管理Swarm集群中的服务,或者可以通过图形化工具Portainer快速部署swarm集群下服务。通过Swarm可以实现服务运行、服务扩容缩容、删除服务、滚动升级等功能。

新建服务

新建服务过程主要包括,Manager节点执行docker service create命令,node节点从仓库下载相应镜像,并且创建相应容器。

在Swarm集群中创建一个名为redis的服务,其nginx版本选定1.10.3:

[root@centos7 ~]# docker service create --replicas 4 -p 80:80 --name nginx nginx:1.10.3 
njq0hw2ksap3mz2s4qg3bpoks
overall progress: 4 out of 4 tasks 
1/4: running   [==================================================>] 
2/4: running   [==================================================>] 
3/4: running   [==================================================>] 
4/4: running   [==================================================>] 
verify: Service converged
  • docker service create:创建服务

  • --replicas 4:指定服务副本数为4

  • --name:指定服务名称为nginx

查看当前swarm集群中运行的服务:Docker三剑客之Swarm_swarm_06

查看某个服务的详情:

[root@centos7 ~]# docker service ps nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
keto9vpc1bgi        nginx.1             nginx:1.10.3        centos7             Running             Running 8 minutes ago                       
314oeshow4la        nginx.2             nginx:1.10.3        centos7-4           Running             Running 8 minutes ago                       
rchz606fd5wx        nginx.3             nginx:1.10.3        centos7-3           Running             Running 8 minutes ago                       
pzeyazxk3p6a        nginx.4             nginx:1.10.3        centos7-1           Running             Running 8 minutes ago

查看服务相关日志:

[root@centos7 ~]# docker service logs nginx
nginx.4.pzeyazxk3p6a@centos7-1    | 10.255.0.6 - - [14/Sep/2018:06:39:48 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

扩容服务及缩容服务

Docker Swarm支持服务的扩容和缩容,Swarm通过--mode选项设置服务类型,提供两种模式:一种是replicated,可以指定服务的Task的个数(需要创建几个冗余副本),这是Swarm默认使用的服务类型;另一个是golbal,这样会在Swarm集群中的每个Node上创建一个服务。

例如,刚才创建服务时指定了4个副本nginx服务,可以扩容到5个副本,如下:

[root@centos7 ~]# docker service scale nginx=5
nginx 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

通过docker service ps查看扩容后的状态:Docker三剑客之Swarm_docker_07

服务缩容只需要将副本数小于当前副本数即可,大雨指定缩容副本会被删除。如下:

# docker service scale nginx=3

删除服务

删除服务,只需要在Manager节点上执行如下即可:

[root@centos7 ~]# docker service rm nginx

滚动升级

参考官网对redis服务升级示例:

docker service create \
 --replicas 3 \
 --name redis \
 --update-delay 10s \
 redis:3.0.6

上面通过指定--update-delay标志配置服务任务或任务集更新之间的时间延迟。 需要进行更新的服务,每次成功部署一个,延迟10分钟,然后更新下一个服务。如果某个服务更新失败,则swarm的调度器就会暂停本次服务的部署更新。

详细升级方法可以参考官方示例:https://docs.docker.com/engine/swarm/swarm-tutorial/rolling-update/


参考资料:

https://docs.docker.com/swarm/overview/

https://www.kancloud.cn/docker_practice/docker_practice