1)How nodes work
Docker引擎1.12引入了集群模式,使你能够创建一个由一个或多个Docker引擎组成的集群,称为集群。集群由一个或多个节点组成:在群模式下运行Docker引擎1.12或更高版本的物理或虚拟机。
有两种类型的节点:管理人员managers和工作人员workers。
Manager nodes
Manager节点处理集群管理任务:
- 维护集群状态
- 调度服务
- 服务集群模式的HTTP API端点
通过使用Raft实现,管理人员维护整个群及其上运行的所有服务的一致内部状态。出于测试目的,使用单个管理器运行群是可以的。如果单管理器集群中的管理器失败,你的服务将继续运行,但是你需要创建一个新的集群来恢复。
为了利用集群模式的容错特性,Docker建议根据组织的高可用性需求实现奇数个节点。当你有多个管理器时,你可以从管理器节点的故障中恢复,而不会停机。
- 一个三个管理员的集群可以承受一个管理员的最大损失。
- 一个五个管理器的集群可以同时承受两个管理器节点的最大损失。
- 一个N个管理器的集群最多可以容忍(N-1)/2个管理器的丢失。
- Docker为集群推荐最多7个管理器节点。
重要提示:添加更多的管理器并不意味着增加可扩展性或更高的性能。一般来说,事实正好相反。
Worker nodes
工作节点也是Docker引擎的实例,Docker引擎的唯一目的是执行容器。工作节点不参与Raft分布式状态,不做调度决策,也不服务于集群模式HTTP API。
你可以创建一个由一个管理器节点组成的集群,但是如果没有至少一个管理器节点,就不能有一个工作节点。默认情况下,所有经理都是工人。在单个管理器节点集群中,可以运行docker service create等命令,调度程序将所有任务放在本地引擎上。
为了防止调度器将任务放在多节点集群中的管理器节点上,请设置管理器节点的可用性为Drain。调度程序以Drain模式优雅地停止节点上的任务,并在Active节点上调度任务。调度程序不会将新任务分配给具有Drain可用性的节点。
参考docker node update
命令行来查看如何更改节点可用性。
Change roles 改变角色
你可以通过运行docker node promote将工作节点提升为管理器。例如,你可能希望在脱机管理器节点进行维护时提升工作节点。详情查看 node promote。
还可以将管理器节点降级为工作节点。详情查看node demote。
2)How services work
要在Docker引擎处于集群模式时部署应用程序镜像,需要创建一个服务service。服务通常是某个较大应用程序上下文中微服务的镜像。服务的示例可能包括HTTP服务器、数据库或希望在分布式环境中运行的任何其他类型的可执行程序。
在创建服务时,要指定要使用哪个容器镜像,以及在运行的容器中执行哪些命令。你还可以为服务定义选项,包括:
- 群集使服务在集群外部可用的端口
- 一个覆盖网络,用于服务连接到集群中的其他服务
- CPU和内存限制和保留
- 滚动更新策略
- 在集群中运行的镜像副本的数量
Services, tasks, and containers
当你将服务部署到swarm时,swarm manager接受你的服务定义作为服务的期望状态。然后,它将集群中的节点上的服务作为一个或多个副本任务进行调度。这些任务在集群中的节点上独立运行。
例如,假设你希望在HTTP侦听器的三个实例之间实现负载平衡。下图显示了一个带有三个副本的HTTP侦听器服务。侦听器的三个实例中的每个实例都是集群中的一个任务。
容器是一个独立的进程。在集群模式模型中,每个任务只调用一个容器。任务类似于调度程序放置容器的“槽”。一旦容器处于活跃状态,调度程序就会识别任务处于运行状态。如果容器的健康检查失败或终止,则任务终止。
Tasks and scheduling 任务和协调器
任务task是集群中调度的原子单位。通过创建或更新服务来声明所需的服务状态时,协调器通过调度任务来实现所需的状态。例如,你定义了一个服务,该服务指示编排器始终保持HTTP侦听器的三个实例运行。协调器通过创建三个任务进行响应。每个任务都是调度程序通过生成容器填充的槽。容器是任务的实例化。如果HTTP侦听器任务的健康检查随后失败或崩溃,协调器将创建一个新的副本任务,该副本任务生成一个新的容器。
任务是单向机制。它单调地通过一系列状态:分配、准备、运行等。如果任务失败,协调器将删除任务及其容器,然后根据服务指定的所需状态创建一个新任务来替换它。
Docker集群模式的底层逻辑是一个通用调度器和编排器。服务和任务抽象本身并不知道它们实现的容器。假设,你可以实现其他类型的任务,例如虚拟机任务或非容器化的流程任务。调度程序和编排器不知道任务的类型。然而,Docker的当前版本只支持容器任务。
下图显示了集群模式如何接受服务创建请求并将任务调度到工作节点。
当Docker engine运行了docker service create命令后,swarm manager接受该命令并创建service对象;然后使用编排器协调为service对象创建任务的循环;接着是分配器为任务分配IP地址;再来就是调度程序dispatcher将为节点分配任务;最后就是协调器为运行任务构建worker。
在worker节点中的反应是worker为分配的任务连接调度程序去查看详细信息;然后是执行器执行分配给worker节点的任务
Pending services
服务的配置的方式可能是当前集群中的任何节点都无法运行其任务。在这种情况下,服务仍然处于pending挂起状态。下面是一些服务可能处于pending挂起状态的例子。
注意:如果你的唯一意图是阻止服务被部署,那么将服务扩展到0,而不是尝试以它仍然处于pending挂起状态的方式配置它。
- 如果所有节点都暂停或耗尽,并且你创建了一个服务,那么它将一直挂起,直到某个节点可用为止。实际上,第一个可用的节点将获得所有任务,因此在生产环境中这不是一件好事。
- 你可以为服务保留特定数量的内存。如果集群中没有节点具有所需的内存量,那么服务将一直处于挂起状态,直到有一个节点可以运行其任务为止。如果你指定一个非常大的值,例如500gb,任务将永远挂起,除非你确实有一个节点可以满足它。
- 你可以对服务施加位置约束,而这些约束可能无法在给定的时间得到满足。
这种行为说明你的任务的需求和配置并不与集群的当前状态紧密相关。作为集群的管理员,你可以声明集群所需的状态,管理器与集群中的节点一起创建该状态。你不需要对集群上的任务进行微管理。
Replicated and global services
有两种类型的服务部署,复制的和全局的。
对于复制的服务,指定要运行的相同任务的数量。例如,你决定部署具有三个副本的HTTP服务,每个副本提供相同的内容。
全局服务是在每个节点上运行一个任务的服务。没有预先指定的任务数量。每次向集群中添加节点时,编配器都会创建一个任务,调度程序将该任务分配给新节点。全局服务的最佳候选者是监视代理、防病毒扫描器或其他类型的容器,你希望在集群中的每个节点上运行这些容器。
下图显示了一个黄色的三服务副本和一个灰色的全局服务。
3)Manage swarm security with public key infrastructure (PKI)使用公钥基础设施管理集群安全
Docker中内置的群模式公钥基础设施(PKI)系统使安全部署容器编配系统变得简单。集群中的节点使用相互传输层安全性(TLS)对集群中其他节点的通信进行身份验证、授权和加密。
当你通过运行docker swarm init来创建一个swarm时,docker将自己指定为一个manager节点。默认情况下,管理器节点生成一个新的根证书颁发机构(CA)和一个密钥对,用于保护与集群中其他节点的通信。如果愿意,可以使用docker swarm init命令的--external-ca标志指定自己的外部生成的根CA。
管理器节点还生成两个令牌tokens,以便在将其他节点加入集群时使用:一个工作令牌和一个管理器令牌。每个令牌包括根CA证书的摘要和随机生成的密钥。当节点加入集群时,加入节点使用摘要验证来自远程管理器的根CA证书。远程管理器使用密匙来确保连接节点是已批准的节点。
每当一个新节点加入集群,管理器就向该节点发出一个证书。证书包含随机生成的节点ID,用于标识证书公共名称(CN)下的节点和组织单元(OU)下的角色。节点ID在当前集群中节点的生命周期中充当加密的安全节点标识。
下图演示了管理节点和工作节点如何使用最少的TLS 1.2加密通信。
下面的例子展示了一个来自工作节点的证书信息:
Certificate:
Data:
Version: (0x2)
Serial Number:
3b:1c::::fb::ff::c3:f7:a2:fe::c1::e2:::3b
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN=swarm-ca
Validity
Not Before: Aug :: GMT
Not After : Nov :: GMT
Subject: O=ec2adilxf4ngv7ev8fwsi61i7, OU=swarm-worker, CN=dw02poa4vqvzxi5c10gm4pq2g
...snip...
默认情况下,集群中的每个节点每三个月更新一次证书。你可以通过运行docker swarm update --cert-expiry <TIME PERIOD>命令来配置这个时间间隔。最小旋转时间为1小时。有关详细信息,请参阅 docker swarm update参考资料。
Rotating the CA certificate 轮换CA证书
在集群CA密钥或管理器节点受到损害的情况下,你可以轮换群根CA,以便不再有由旧根CA签名的节点信任证书。
运行docker swarm ca --rotate生成一个新的ca证书和密钥。如果愿意,可以传递--ca-cert和--external-ca标志来指定根证书,并使用集群外部的根CA。另外,你还可以传递--ca-cert--ca-key标志,以指定集群希望使用的确切证书和密钥。
当你发出docker swarm ca --rotate命令时,会依次发生以下事情:
1.Docker生成一个交叉签名的证书。这意味着新根CA证书的一个版本与旧根CA证书签署。此交叉签名证书用作所有新节点证书的中间证书。这确保仍然信任旧根CA的节点仍然可以验证由新CA签名的证书。
2.在Docker 17.06及更高版本中,Docker还告诉所有节点立即更新它们的TLS证书。根据集群中节点的数量,这个过程可能需要几分钟。
注意:如果你的集群有不同Docker版本的节点,以下两点是正确的:
- 只有以leader身份运行并运行Docker 17.06或更高版本的管理器才会告诉节点更新它们的TLS证书。
- 只有运行Docker 17.06或更高版本的节点才遵守此指令。
对于最可预测的行为,确保所有集群节点都运行Docker 17.06或更高版本。
3.当集群中的每个节点都有一个由新的CA签名的新的TLS证书后,Docker就会忘记旧的CA证书和密钥材料,并告诉所有节点只信任新的CA证书。
这也会导致群的连接令牌发生变化。以前的连接令牌不再有效。
从现在开始,发出的所有新节点证书都使用新的根CA进行签名,不包含任何中间体。
4)Swarm task states集群任务状态
Docker允许你创建可以启动任务的服务。服务是对所需状态的描述,任务完成这项工作。在集群节点上按以下顺序调度工作:
- 使用docker service create或UCP web UI或CLI创建服务。
- 请求被发送到Docker manager节点。
- Docker manager节点将服务安排在特定节点上运行。
- 每个服务可以启动多个任务。
- 每个任务都有一个生命周期,有像NEW、PENDING和COMPLETE这样的状态。
任务是运行一次直到完成的执行单元。当一个任务停止时,它不会再次执行,但是一个新任务可能会代替它。
任务通过许多状态前进,直到完成或失败。任务在NEW状态下初始化。任务通过许多状态向前推进,其状态不会向后。例如,任务从不从COMPLETE到RUNNING。
任务按照以下顺序通过状态:
NEW 任务在初始化状态
PENDING 正在分配任务所用的资源
ASSIGNED Docker assigned the task to nodes. Docker分配任务给节点
ACCEPTED 任务被工作节点接受。如果工作节点拒接任务,状态将会转变成REJECTED
PREPARING Docker正在准备任务
STARTING Docker正在开启任务
RUNNING 任务正在执行
COMPLETE 任务结束,不带错误代码
FAILED 任务结束,带着错误代码
SHUTDOWN Docker请求任务关闭
REJECTED 工作节点拒绝任务
ORPHANED 节点宕机时间太长
REMOVE 该任务不是终端,但相关服务已被删除或缩小
View task state查看工作状态
运行docker service ps <service-name>去得到任务状态。CURRENT STATE字段显示了任务状态以及该任务存在时间
$ docker service ps webserver
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
owsz0yp6z375 webserver. nginx UbuntuVM Running Running seconds ago
j91iahr8s74p \_ webserver. nginx UbuntuVM Shutdown Failed seconds ago "No such container: webserver.…"
7dyaszg13mw2 \_ webserver. nginx UbuntuVM Shutdown Failed hours ago "No such container: webserver.…"