服务的工作原理
当 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 服务,每个副本都提供相同的内容。
全局服务是在每个节点上运行一个任务的服务。没有预先指定的任务数量。每次向 Swarm 添加一个节点时,编排器都会创建一个任务,调度器会将该任务分配给新节点。全局服务的理想选择是监控代理、防病毒扫描程序或您希望在 Swarm 的每个节点上运行的其他类型的容器。
下图显示了一个灰色的三服务副本和一个黑色的全局服务。
