Docker Swarm初步了解
概括来说,Swarm有两个核心组件。
● 安全集群。
● 编排引擎。
Docker Swarm包含两方面:一个企业级的Docker安全集群,以及一个微服务应用编排引擎。
集群方面,Swarm将一个或多个Docker节点组织起来,使得用户能够以集群方式管理它们。Swarm默认内置有加密的分布式集群存储(encrypted distributed cluster store)、加密网络(Encrypted Network)、公用TLS(Mutual TLS)、安全集群接入令牌Secure Cluster Join Token)以及一套简化数字证书管理的PKI(Public Key Infrastructure)。用户可以自如地添加或删除节点,
编排方面,Swarm提供了一套丰富的API使得部署和管理复杂的微服务应用变得易如反掌。通过将应用定义在声明式配置文件中,就可以使用原生的Docker命令完成部署。此外,甚至还可以执行滚动升级、回滚以及扩缩容操作,同样基于简单的命令即可完成。
Docker Swarm——详解
从以下几个方面展开。
● Swarm的初步介绍。
● 搭建一个安全的Swarm集群。
● 部署Swarm服务。
● 问题定位。
Swarm的初步介绍
从集群角度来说,一个Swarm由一个或多个Docker节点组成。
这些节点可以是物理服务器、虚拟机、树莓派(Raspberry Pi)或云实例。唯一的前提就是要求所有节点通过可靠的网络相连。节点会被配置为管理节点(Manager)或工作节点(Worker)。管理节点负责集群控制面(Control Plane),进行诸如监控集群状态、分发任务至工作节点等操作。工作节点接收来自管理节点的任务并执行。
Swarm的配置和状态信息保存在一套位于所有管理节点上的分布式etcd数据库中。该数据库运行于内存中,并保持数据的最新状态。关于该数据库最棒的是,它几乎不需要任何配置——作为Swarm的一部分被安装,无须管理。
关于集群管理,最大的挑战在于保证其安全性。搭建Swarm集群时将使用TLS,因为它被Swarm集成。Swarm使用TLS进行通信加密、节点认证和角色授权。自动密钥轮换(Automatic Key Rotation)其在后台默默进行
关于应用编排,Swarm中的最小调度单元是服务。
当容器被封装在一个服务中时,我们称之为一个任务或一个副本,服务中增加了诸如扩缩容、滚动升级以及简单回滚等特性。
综上,从概括性的视角来看Swarm
搭建安全Swarm集群
实验环境均在linux操纵系统上操作(对于不同类型Linux操作系统没有太大的区别)
搭建一套安全Swarm集群,其中包含3个管理节点和3个工作节点,节点数也可以自己调整
每个节点都需要安装Docker,并且能够与Swarm的其他节点通信。配置有域名解析就更好了——这样在命令的输出中更容易识别出节点
在网络方面,需要在路由器和防火墙中开放如下端口。
● 2377/tcp:用于客户端与Swarm进行安全通信。
● 7946/tcp与7946/udp:用于控制面gossip分发。
● 4789/udp:用于基于VXLAN的覆盖网络。
如果满足以上前提,就可以着手开始搭建Swarm集群了。搭建Swarm的过程有时也被称为初始化Swarm,大体流程包括初始化第一个管理节点>加入额外的管理节点>加入工作节点>完成。
1.初始化一个全新的Swarm
不包含在任何Swarm中的Docker节点,称为运行于单引擎(Single-Engine)模式。一旦被加入Swarm集群,则切换为Swarm模式
在单引擎模式下的Docker主机上运行docker swarm init会将其切换到Swarm模式,并创建一个新的Swarm,将自身设置为Swarm的第一个管理节点
以下的步骤会将mgr1切换为Swarm模式,并初始化一个新的Swarm。接下来将wrk1、wrk2和wrk3作为工作节点接入——自动将它们切换为Swarm模式。然后将mgr2和mgr3作为额外的管理节点接入,并同样切换为Swarm模式。最终有6个节点切换到Swarm模式,并运行于同一个Swarm中。
(1)登录到mgr1并初始化一个新的Swarm
$ docker swarm init \
-advertise addr 10.0.0.1:2377 \
-listen addr 10.0.0.1:2377
Swarm initialized: current node (d211yz... c79qzkx) is now a manager.
命令分析如下:
● docker swarm init会通知Docker来初始化一个新的Swarm,并将自身设置为第一个管理节点。同时也会使该节点开启Swarm模式。
● --advertise-addr指定其他节点用来连接到当前管理节点的IP和端口。这一属性是可选的,当节点上有多个IP时,可以用于指定使用哪个IP。此外,还可以用于指定一个节点上没有的IP,比如一个负载均衡的IP。
● --listen-addr指定用于承载Swarm流量的IP和端口。其设置通常与–advertise-addr相匹配,但是当节点上有多个IP的时候,可用于指定具体某个IP。并且,如果–advertise-addr设置了一个远程IP地址(如负载均衡的IP地址),该属性也是需要设置的。建议执行命令时总是使用这两个属性来指定具体IP和端口。
Swarm模式下的操作默认运行于2337端口。虽然它是可配置的,但2377/tcp是用于客户端与Swarm进行安全(HTTPS)通信的约定俗成的端口配置。
(2)列出Swarm中的节点。
$ docker node Is
(3)在mgr1上执行docker swarm join-token命令来获取添加新的工作节点和管理节点到Swarm的命令和Token。(token主要是用来添加节点)
请注意,工作节点和管理节点的接入命令中使用的接入Token(SWMTKN…)是不同的。因此,一个节点是作为工作节点还是管理节点接入,完全依赖于使用了哪个Token。接入Token应该被妥善保管,因为这是将一个节点加入Swarm的唯一所需!
(4)登录到wrk1,并使用包含工作节点接入Token的docker swarm join命令将其接入Swarm
就是将上面的token,复制到wrk1的终端中执行即可
–advertise-addr与–listen-addr属性是可选的。在网络配置方面,请尽量明确指定相关参数,方便管理
(5)在wrk2和wrk3上重复上一步骤来将这两个节点作为工作节点加入Swarm。确保使用–advertise-addr与–listen-addr属性来指定各自的IP地址。
(6)登录到mgr2,然后使用含有管理节点接入Token的docker swarm join命令,将该节点作为工作节点接入Swarm。记得在–advertise-addr与–listen-addr属性中指定mgr2的IP地址
(7)在mgr3上重复以上步骤,记得在–advertise-addr与–listen-addr属性中指定mgr3的IP地址。
(8)在任意一个管理节点上执行docker node ls命令来列出Swarm节点。
在这个过程中,每个节点的Docker引擎都被切换到Swarm模式下。并且Swarm已经自动启用了TLS以策安全。
观察MANAGER STATUS一列会发现,3个节点分别显示为“Reachable”或“Leader”。MANAGER STATUS一列无任何显示的节点是工作节点。注意,mgr2的ID列还显示了一个星号(),这个星号会告知用户执行docker node ls命令所在的节点。本例中,命令是在mgr2节点执行的。*
2.Swarm管理器高可用性(HA)
从技术上来说,Swarm实现了一种主从方式的多管理节点的HA。这意味着,即使你可能——并且应该——有多个管理节点,也总是仅有一个节点处于活动状态。通常处于活动状态的管理节点被称为“主节点”(leader),而主节点也是唯一一个会对Swarm发送控制命令的节点。也就是说,只有主节点才会变更配置,或发送任务到工作节点。如果一个备用(非活动)管理节点接收到了Swarm命令,则它会将其转发给主节点。
步骤①指命令从一个远程的Docker客户端发送给一个管理节点;步骤②指非主节点将命令转发给主节点;步骤③指主节点对Swarm执行命令。下图形象的说明了过程
观察上图,管理节点或者是Leader或者是Follower。这是Raft的术语,因为Swarm使用了Raft共识算法(我也不是很懂)的一种具体实现来支持管理节点的HA。关于HA,以下是两条最佳实践原则。
● 部署奇数个管理节点。
● 不要部署太多管理节点(建议3个或5个)。
部署奇数个管理节点有利于减少脑裂(Split-Brain)情况的出现机会
对于所有的共识算法来说,更多的参与节点就意味着需要花费更多的时间来达成共识。
最佳的实践原则是部署3个或5个节点用于HA。7个节点可以工作,但是通常认为3个或5个是更优的选择。当然绝对不要多于7个,因为需要花费更长的时间来达成共识。
下图形象的说明了脑裂问题,多数管理节点的分区继续对集群进行管理
3.内置的Swarm安全机制
Swarm集群内置有繁多的安全机制,并提供了开箱即用的合理的默认配置——如CA设置、接入Token、公用TLS、加密集群存储、加密网络、加密节点ID等。更多细节后面在学习总结
4.锁定Swarm
一个旧的管理节点重新接入Swarm会自动解密并获得Raft数据库中长时间序列的访问权,这会带来安全隐患。进行备份恢复可能会抹掉最新的Swarm配置。
为了规避以上问题,Docker提供了自动锁机制来锁定Swarm,这会强制要求重启的管理节点在提供一个集群解锁码之后才有权从新接入集群
通过在执行docker swarm init命令来创建一个新的Swarm集群时传入–autolock参数可以直接启用锁。然而,前面已经搭建了一个Swarm集群,这时也可以使用docker swarm update命令来启用锁。
$ docker swarm update --autolock=true
命令会输入一个安全解锁码,请确保将解锁码妥善保管在安全的地方!
尝试重启某一个管理节点,会发现管理节点仍然未被允许重新接入集群
执行docker swarm unlock命令来为重启的管理节点解锁Swarm。该命令需要在重启的节点上执行,同时需要提供解锁码。
该节点将被允许重新接入Swarm,并且再次执行docker node ls命令会显示ready和reachable。
Swarm服务
使用docker service create命令创建一个新的服务。
回顾一下命令和输出。使用docker service creale命令告知Docker正在声明一个新服务,并传递–name参数将其命名为web-fe。将每个节点上的8080端口映射到服务副本内部的8080端口。接下来,使用–replicas参数告知Docker应该总是有5个此服务的副本。最后,告知Docker哪个镜像用于副本
1.查看服务
使用docker service ls命令,可以查看Swarm中所有运行中的服务。
执行docker service ps命令可以查看服务副本列表及各副本的状态。
此命令格式为docker service ps 。每一个副本会作为一行输出,其中显示了各副本分别运行在Swarm的哪个节点上,以及期望的状态和实际状态。
关于服务更为详细的信息可以使用docker service inspect命令查看。
如果使用–pretty参数,限制输出中仅包含最感兴趣的内容,并以易于阅读的格式打印出来。不加–pretty的话会给出更加详尽的输出。强烈建议读者能够通读docker inspect命令的输出内容,其中不仅包含大量信息,也是了解底层运行机制的途径。
2.副本服务vs全局服务
服务的默认复制模式(Replication Mode)是副本模式(replicated)。这种模式会部署期望数量的服务副本,并尽可能均匀地将各个副本分布在整个集群中。另一种模式是全局模式(global),在这种模式下,每个节点上仅运行一个副本。可以通过给docker service create命令传递–mode global参数来部署一个全局服务。
3.服务的扩缩容
通过一个简单的docker service scale命令即可对web-fe服务进行扩容。
该命令会将服务副本数由5个增加到10个。后台会将服务的期望状态从5个增加到10个。
运行docker service ls命令来检查操作是否成功。
4.删除服务
如下docker service rm命令可用于删除之前部署的服务。
请谨慎使用docker service rm命令,因为它在删除所有服务副本时并不会进行确认。
5.滚动升级
假设,本次升级任务在将新镜像更新到Swarm中时采用一种阶段性的方式——每次更新两个副本,并且中间间隔20s。那么就可以采用如下的docker service update命令来完成。
故障排除
Swarm服务的日志可以通过执行docker service logs命令来查看,然而并非所有的日志驱动(Logging Driver)都支持该命令。
Docker节点默认的配置是,服务使用json-file日志驱动,其他的驱动还有journald(仅用于运行有systemd的Linux主机)、syslog、splunk和gelf。
json-file和journald是较容易配置的,二者都可用于docker service logs命令。命令格式为docker service logs 。
若使用第三方日志驱动,那么就需要用相应日志平台的原生工具来查看日志。如下是在daemon.json配置文件中定义使用syslog作为日志驱动的示例。
通过在执行docker service create命令时传入–logdriver和–log-opts参数可以强制某服务使用一个不同的日志驱动,这会覆盖daemon.json中的配置。
服务日志能够正常工作的前提是,容器内的应用程序运行于PID为1的进程,并且将日志发送给STDOUT,错误信息发送给STDERR。日志驱动会将这些日志转发到其配置指定的位置。
对于查看日志命令,可以使用–follow进行跟踪、使用–tail显示最近的日志,并使用–details获取额外细节。
Docker Swarm——命令
● docker swarm init命令用户创建一个新的Swarm。执行该命令的节点会成为第一个管理节点,并且会切换到Swarm模式。
● docker swarm join-token命令用于查询加入管理节点和工作节点到现有Swarm时所使用的命令和Token。要获取新增管理节点的命令,请执行docker swarm join-token manager命令;要获取新增工作节点的命令,请执行docker swarm join-token worker命令。
● docker node ls命令用于列出Swarm中的所有节点及相关信息,包括哪些是管理节点、哪个是主管理节点。
● docker service create命令用于创建一个新服务。
● docker service ls命令用于列出Swarm中运行的服务,以及诸如服务状态、服务副本等基本信息
● docker service ps 命令会给出更多关于某个服务副本的信息。
● docker service scale命令用于对服务副本个数进行增减。
● docker service update命令用于对运行中的服务的属性进行变更。
● docker service logs命令用于查看服务的日志。
● docker service rm命令用于从Swarm中删除某服务。该命令会在不做确认的情况下删除服务的所有副本,所以使用时应保持警惕。
小结
Docker Swarm是使Docker规模化的关键方案。Docker Swarm的核心包含一个安全集群组件和一个编排组件。安全集群管理组件是一个企业级的安全套件,提供了丰富的安全机制以及HA特性,这些都是自动配置好的,并且非常易于调整。编排组件允许用户以一种简单的声明式的方式来部署和管理微服务应用。它不仅支持原生的Docker Swarm应用,还支持Kubernetes应用。