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进行集成。
在使用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) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。
以下展示了集群中管理节点与工作节点的关系。
服务和任务
任务 (Task)是 Swarm 中的最小的调度单位,目前来说就是一个单一的容器。
服务 (Services) 是指一组任务的集合,服务定义了任务的属性。服务有两种模式:
replicated services 按照一定规则在各个工作节点上运行指定个数的任务。
global services 每个工作节点上运行一个任务
两种模式通过 docker service create 的 --mode 参数指定。
来自 Docker 官网的这张图片形象的展示了容器、任务、服务的关系。
整体环境
关于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
以上信息中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
查看某个服务的详情:
[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 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