服务工作原理
要在Docker Engine处于Swarm模式时部署应用程序镜像,您需要创建一个服务。服务通常是在某个更大应用程序的上下文中,某个微服务的镜像。服务的示例可能包括HTTP服务器、数据库或您希望在分布式环境中运行的任何其他类型的可执行程序。
创建服务时,您需要指定要使用的容器镜像以及在运行的容器内执行哪些命令。您还需要为服务定义选项,包括:
- Swarm使服务在Swarm外部可用的端口
- 用于连接Swarm中其他服务的覆盖网络
- CPU和内存限制和预留
- 滚动更新策略
- 要在Swarm中运行的镜像副本数量
服务、任务和容器
将服务部署到Swarm时,Swarm管理器会接受您的服务定义作为服务的期望状态。然后,它会在Swarm中的节点上将服务调度为一个或多个副本任务。这些任务在Swarm中的节点上彼此独立运行。
例如,假设您希望在HTTP侦听器的三个实例之间进行负载均衡。下图显示了一个具有三个副本的HTTP侦听器服务。侦听器的三个实例中的每一个都是Swarm中的一个任务。


容器是一个隔离的进程。在Swarm模式模型中,每个任务只调用一个容器。任务类似于调度程序放置容器的“槽”。容器启动后,调度程序会识别任务处于运行状态。如果容器失败健康检查或终止,则任务终止。
任务和调度
任务是Swarm内调度的原子单元。创建或更新服务时,您定义了期望的服务状态,协调器通过调度任务来实现期望状态。例如,您定义了一个服务,该服务指示协调器始终保持HTTP侦听器的三个实例运行。协调器会通过创建三个任务来响应。每个任务都是一个槽,调度程序通过生成容器来填充它。容器是任务的实例化。如果HTTP侦听器任务随后未能通过其健康检查或崩溃,则协调器会创建一个新的副本任务,该任务会生成一个新的容器。
任务是一种单向机制。它单调地经过一系列状态:已分配、已准备、运行等。如果任务失败,协调器会删除任务及其容器,然后根据服务指定的期望状态创建一个新任务来替换它。
Docker Swarm模式的底层逻辑是一个通用的调度程序和协调器。服务和任务抽象本身不知道它们实现的容器。假设您可以实现其他类型的任务,例如虚拟机任务或非容器化进程任务。调度程序和协调器对任务的类型是不可知的。但是,当前版本的Docker只支持容器任务。
下图显示了Swarm模式如何接受服务创建请求并将任务调度到工作节点。


待处理服务
可以对服务进行配置,以便Swarm中当前没有任何节点可以运行其任务。在这种情况下,服务将保持pending
状态。以下是一些服务可能保持pending
状态的示例。
提示
如果您的唯一目的是阻止部署服务,请将服务扩展到0,而不是尝试以使其保持
pending
状态的方式进行配置。
如果所有节点都被暂停或移除,并且您创建了一个服务,则该服务将保持挂起状态,直到有节点可用。实际上,第一个可用的节点将获得所有任务,因此这在生产环境中不是一个好主意。
您可以为服务预留特定数量的内存。如果Swarm中的任何节点都没有所需的内存量,则服务将保持挂起状态,直到有可运行其任务的节点可用。如果您指定一个非常大的值,例如500 GB,则任务将永远保持挂起状态,除非您真的有一个可以满足它的节点。
您可以对服务施加位置约束,并且在给定时间可能无法满足这些约束。
此行为说明了您的任务的需求和配置与Swarm的当前状态没有紧密联系。作为Swarm的管理员,您声明Swarm的期望状态,管理器会与Swarm中的节点协同工作以创建该状态。您不需要微观管理Swarm上的任务。
复制服务和全局服务
有两种类型的服务部署:复制和全局。
对于复制服务,您需要指定要运行的相同任务的数量。例如,您决定部署一个具有三个副本的HTTP服务,每个副本都提供相同的内容。
全局服务是在每个节点上运行一项任务的服务。任务数量没有预先设定。每次向集群添加节点时,编排器都会创建一个任务,调度器会将该任务分配给新节点。全局服务的理想选择包括监控代理、反病毒扫描程序或您希望在集群中每个节点上运行的其他类型的容器。
下图以灰色显示一个三副本服务,以黑色显示一个全局服务。

