将服务部署到大量

预计阅读时间:40分钟

Swarm服务使用声明性模型,这意味着您定义了服务的所需状态,并依赖Docker维护该状态。状态包括以下信息,但不限于:

  • 图像名称和服务容器应运行的标签
  • 有多少个容器参与该服务
  • 是否有任何端口暴露给集群外部的客户端
  • Docker启动时服务是否应自动启动
  • 重新启动服务时发生的特定行为(例如是否使用滚动重新启动)
  • 服务可以运行的节点的特征(例如资源约束和放置首选项)

有关群集模式的概述,请参见“群集模式关键概念”。对于服务如何工作的概述,请参阅 如何服务工作

创建服务

要创建没有额外配置的单副本服务,只需提供映像名称。此命令使用随机生成的名称启动Nginx服务,并且没有发布的端口。这是一个幼稚的示例,因为您无法与Nginx服务进行交互。

$ docker service create nginx

该服务是在可用节点上调度的。要确认该服务已创建并成功启动,请使用以下docker service ls命令:

$ docker service ls

ID                  NAME                MODE                REPLICAS            IMAGE                                                                                             PORTS
a3iixnklxuem        quizzical_lamarr    replicated          1/1                 docker.io/library/nginx@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268

创建的服务并非总是立即运行。如果服务的映像不可用,没有节点满足您为该服务配置的要求或其他原因,则该服务可以处于挂起状态。有关更多信息,请参见 待定服务

要为您的服务提供名称,请​​使用--name标志:

$ docker service create --name my_web nginx

与独立容器一样,您可以通过在映像名称之后添加一个命令来指定该服务的容器应运行的命令。本示例启动一个名为服务的服务helloworld,该服务使用alpine图像并运行以下命令ping docker.com

$ docker service create --name helloworld alpine ping docker.com

您还可以指定要使用的服务的图像标签。本示例修改前一个示例以使用alpine:3.6标记:

$ docker service create --name helloworld alpine:3.6 ping docker.com

有关图像标签解析的更多详细信息,请参阅 指定服务应使用的图像版本

群体的gMSA

Swarm现在允许将Docker Config用作gMSA凭据规范-这是Active Directory身份验证的应用程序的要求。这减轻了将凭据规范分发到使用它们的节点的负担。

以下示例假定gMSA及其凭据规范(称为credspec.json)已经存在,并且已为gMSA正确配置了要部署到的节点。

要将Config用作凭据规范,请首先创建包含凭据规范的Docker Config:

docker config create credspec credspec.json

现在,您应该有一个名为credspec的Docker Config,并且可以使用此凭据规范创建服务。为此,请在配置名称中使用--credential-spec标志,如下所示:

docker service create --credential-spec="config://credspec" <your image>

您的服务在启动时将使用gMSA凭据规范,但是与典型的Docker Config(通过传递--config标志使用)不同,凭据规范不会安装到容器中。

使用私有注册表上的映像创建服务

如果您的映像在需要登录的私有注册表上可用,请在登录后使用--with-registry-auth带有的 标志docker service create。如果您的映像存储在registry.example.com私有注册表上,请使用类似以下的命令:

$ docker login registry.example.com

$ docker service  create \
  --with-registry-auth \
  --name my_service \
  registry.example.com/acme/my_image:latest

这将使用加密的WAL日志将登录令牌从本地客户端传递到部署服务的swarm节点。有了这些信息,节点便能够登录到注册表并提取映像。

提供托管服务帐户的凭据规范

在Enterprise Edition 3.0中,通过使用Docker Config功能集中管理和分发组托管服务帐户(gMSA)凭据,提高了安全性。Swarm现在允许将Docker Config用作gMSA凭证规范,这减轻了将凭证规范分发到使用它们的节点的负担。

注意:此选项仅适用于使用Windows容器的服务。

凭据规范文件在运行时应用,从而无需基于主机的凭据规范文件或注册表项-无需将gMSA凭据写入工作节点上的磁盘。您可以在容器启动之前为运行swarm kit worker节点的Docker Engine提供凭据规范。使用基于gMSA的配置部署服务时,凭据规范会直接传递到该服务中容器的运行时。

--credential-spec必须是下列格式之一:

  • file://<filename>:引用的文件必须存在于CredentialSpecsdocker数据目录的子目录中,该目录C:\ProgramData\Docker\在Windows上默认为。例如,指定file://spec.jsonloads C:\ProgramData\Docker\CredentialSpecs\spec.json
  • registry://<value-name>:凭据规范是从守护程序主机上的Windows注册表中读取的。
  • config://<config-name>:配置名称会在CLI中自动转换为配置ID。config使用指定中包含的凭证规范。

以下简单示例从您的Active Directory(AD)实例中检索gMSA名称和JSON内容:

name="mygmsa"
contents="{...}"
echo $contents > contents.json

确保已为gMSA正确配置了要部署到的节点。

要将Config用作凭据规范,请在名为的凭据规范文件中创建Docker Config credpspec.json。您可以为的名称指定任何名称config

docker config create --label com.docker.gmsa.name=mygmsa credspec credspec.json

现在,您可以使用此凭据规范创建服务。--credential-spec使用配置名称指定标志:

docker service create --credential-spec="config://credspec" <your image>

您的服务在启动时会使用gMSA凭据规范,但与典型的Docker Config(通过传递--config标志使用)不同,凭据规范未安装到容器中。

更新服务

您可以使用以下docker service update命令更改有关现有服务的几乎所有内容 。当您更新服务时,Docker会停止其容器并使用新配置重新启动它们。

由于Nginx是一项Web服务,因此如果将端口80发布到集群外部的客户端,它将更好地工作。您可以在创建服务时使用-p--publish标志进行指定。更新现有服务时,标记为--publish-add。还有一个--publish-rm标记用于删除以前发布的端口。

假设上my_web一节中的服务仍然存在,请使用以下命令对其进行更新以发布端口80。

$ docker service update --publish-add 80 my_web

要验证其是否有效,请使用docker service ls

$ docker service ls

ID                  NAME                MODE                REPLICAS            IMAGE                                                                                             PORTS
4nhxl7oxw5vz        my_web              replicated          1/1                 docker.io/library/nginx@sha256:41ad9967ea448d7c2b203c699b429abe1ed5af331cd92533900c6d77490e0268   *:0->80/tcp

有关发布端口如何工作的更多信息,请参见 发布端口

您可以更新有关现有服务的几乎所有配置详细信息,包括映像名称和运行的标记。请参阅 创建后更新服务的映像

删除服务

要删除服务,请使用docker service remove命令。您可以通过服务的ID或名称删除服务,如docker service ls 命令的输出所示。以下命令删除该my_web服务。

$ docker service remove my_web

服务配置详细信息

以下各节提供有关服务配置的详细信息。本主题并不涵盖所有标志或方案。在几乎每个可以在创建服务时定义配置的情况下,都可以以类似的方式更新现有服务的配置。

看命令行的引用为 docker service createdocker service update,或运行与所述那些命令中的一个--help标志。

配置运行时环境

您可以在容器中为运行时环境配置以下选项:

  • 使用--env标志的环境变量
  • 使用--workdir标志在容器内的工作目录
  • 使用--user标志的用户名或UID

以下服务的容器的环境变量$MYVAR 设置为myvalue,从/tmp/目录运行,并以my_user用户身份运行 。

$ docker service create --name helloworld \
  --env MYVAR=myvalue \
  --workdir /tmp \
  --user my_user \
  alpine ping docker.com

更新现有服务运行的命令

要更新现有服务运行的命令,可以使用该--args标志。以下示例更新了一个名为的现有服务helloworld,以使其运行命令ping docker.com而不是之前运行的命令:

$ docker service update --args "ping docker.com" helloworld

指定服务应使用的映像版本

当您创建服务时未指定要使用的图像版本的任何详细信息时,该服务将使用带有latest标签标记的版本。您可以根据期望的结果,以几种不同的方式强制服务使用图像的特定版本。

图像版本可以用几种不同的方式表示:

  • 如果指定标签,则管理器(或Docker客户端,如果您使用 content trust)将标签解析为摘要。当在工作节点上收到创建容器任务的请求时,工作节点仅看到摘要,而不看到标签。

    $ docker service create --name="myservice" ubuntu:16.04
    

    一些标签代表离散发行,例如ubuntu:16.04。像这样的标签几乎总是随着时间的流逝而稳定地分解。建议您尽可能使用这种标签。

    其他类型的标签(例如latestnightly)可能经常解析为新摘要,具体取决于图像作者更新标签的频率。不建议使用经常更新的标记来运行服务,以防止不同的服务副本任务使用不同的映像版本。

  • 如果您根本不指定版本,则按照惯例,图像的latest标签将解析为摘要。在创建服务任务时,工作人员会在此摘要中使用映像。

    因此,以下两个命令是等效的:

    $ docker service create --name="myservice" ubuntu
    
    $ docker service create --name="myservice" ubuntu:latest
    
  • 如果直接指定摘要,则在创建服务任务时将始终使用该映像的确切版本。

    $ docker service create \
        --name="myservice" \
        ubuntu:16.04@sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1
    

创建服务时,图像的标签将解析为服务创建时标签指向的特定摘要。除非显式更新了该服务,否则该服务的工作节点将永远使用该特定摘要。如果您确实使用经常更改的标记(例如)latest,则此功能特别重要,因为它可确保所有服务任务使用相同版本的映像。

注意:如果启用了内容信任,则客户端实际上会在联系群管理器之前将图像的标签解析为摘要,以验证图像是否已签名。因此,如果您使用内容信任,则群管理器将接收到预先解决的请求。在这种情况下,如果客户端无法将映像解析为摘要,则请求将失败。

如果管理器无法将标签解析为摘要,则每个工作节点都负责将标签解析为摘要,并且不同的节点可能会使用不同版本的映像。如果发生这种情况,则会记录如下警告,用占位符代替真实信息。

unable to pin image <IMAGE-NAME> to digest: <REASON>

要查看图像的当前摘要,请发出命令 docker inspect <IMAGE>:<TAG>并查找RepoDigests行。以下是ubuntu:latest编写此内容时的当前摘要。为了清楚起见,输出将被截断。

$ docker inspect ubuntu:latest
"RepoDigests": [
    "ubuntu@sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1"
],

创建服务后,除非您docker service update使用--image如下所述的标志明确运行,否则它的映像永远不会更新 。其他更新操作(例如缩放服务,添加或删除网络或卷,重命名服务或任何其他类型的更新操作)不会更新服务的映像。

创建后更新服务的映像

每个标签代表一个摘要,类似于Git哈希。某些标记(例如) latest经常会更新以指向新的摘要。其他(如 ubuntu:16.04)表示已发布的软件版本,并且根本不会经常更新以指向新的摘要。创建服务时,必须限制使用映像的特定摘要创建任务,直到您使用service update带有--image标志的服务来更新为止。

service update使用该--image标志运行时,群集管理器会查询Docker Hub或您的私有Docker注册表以获取标记当前指向的摘要,并更新服务任务以使用该摘要。

注意:如果您使用内容信任,则Docker客户端将解析图像,并且swarm管理器将接收图像和摘要,而不是标签。

通常,管理者可以将标签解析为新的摘要,然后更新服务,重新部署每个任务以使用新的映像。如果管理员无法解决代码或发生其他问题,接下来的两节将概述预期的情况。

如果经理解决了标签

如果群管理器可以将映像标签解析为摘要,则指示工作节点重新部署任务并在该摘要处使用映像。

  • 如果工作人员已在该摘要处缓存了图像,则它将使用它。

  • 如果不是,它将尝试从Docker Hub或私有注册表中拉取映像。

    • 如果成功,则使用新映像部署任务。

    • 如果工作服务器无法拉出映像,则该服务将无法在该工作服务器节点上部署。Docker再次尝试将任务部署在其他工作节点上。

如果经理无法解析标签

如果群集管理器无法将映像解析为摘要,则不会丢失所有内容:

  • 管理器指示工作节点使用该标签上的图像重新部署任务。

  • 如果工作程序具有解析为该标签的本地缓存图像,则它将使用该图像。

  • 如果工作进程没有解析为该标签的本地缓存映像,则该工作进程会尝试连接到Docker Hub或私有注册表以将该映像拉到该标签处。

    • 如果成功,则工作人员将使用该图像。

    • 如果失败,则任务将无法部署,并且管理器可能会在其他工作节点上再次尝试部署任务。

发布端口

创建群集服务时,可以通过两种方式将该服务的端口发布到群集外部的主机:

  • 您可以依靠路由网格。发布服务端口时,无论是否在该节点上运行该服务的任务,群集都可在每个节点上的目标端口上访问该服务。这不太复杂,并且是许多类型服务的正确选择。

  • 您可以直接在 运行该服务的swarm节点上发布服务任务的端口。这绕过了路由网格,并提供了最大的灵活性,包括您开发自己的路由框架的能力。但是,您负责跟踪每个任务的运行位置,并将请求路由到这些任务,并负责跨节点进行负载平衡。

请继续阅读以获取更多信息以及每种方法的用例。

使用路由网格发布服务的端口

要将服务的端口从外部发布到群集,请使用该 --publish <PUBLISHED-PORT>:<SERVICE-PORT>标志。群使服务可以在每个群节点上的已发布端口访问。如果外部主机连接到任何群集节点上的该端口,则路由网格会将其路由到任务。外部主机不需要知道服务任务的IP地址或内部使用的端口即可与服务进行交互。当用户或进程连接到服务时,任何运行服务任务的工作程序节点都可以响应。有关群集服务网络的更多详细信息,请参阅 管理群集服务网络

示例:在10节点群上运行三任务Nginx服务

想象一下,您有一个10节点的集群,并且部署了一个在10节点的集群上运行三个任务的Nginx服务:

$ docker service create --name my_web \
                        --replicas 3 \
                        --publish published=8080,target=80 \
                        nginx

三个任务最多可在三个节点上运行。您无需知道哪些节点正在运行任务;您无需知道哪个节点正在运行任务。连接到10个节点中的任何一个上的端口8080,就可以将您连接到三个nginx任务之一。您可以使用进行测试curl。以下示例假定它localhost是群集节点之一。如果不是这种情况,或者localhost无法解析为主机上的IP地址,请替换主机的IP地址或可解析的主机名。

HTML输出被截断:

$ curl localhost:8080

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...truncated...
</html>

随后的连接可以路由到相同的群集节点或不同的群集节点。

直接在swarm节点上发布服务的端口

如果您需要根据应用程序状态做出路由决策,或者需要完全控制将请求路由到服务任务的过程,则使用路由网格对于您的应用程序可能不是正确的选择。要将服务的端口直接发布在运行它的节点上,请使用mode=host--publish标志的选项。

注意:如果使用mode=host并在群集节点上直接发布服务的端口 ,并且进行了设置,published=<PORT>则会创建一个隐式限制,即您只能在给定群集节点上为该服务运行一项任务。您可以通过published不指定端口定义来解决此问题,这会导致Docker为每个任务分配一个随机端口。

另外,如果使用mode=host且不使用--mode=globalon上的 标志docker service create,则很难知道哪些节点正在运行服务以将工作路由到它们。

示例:nginx在每个群集节点上运行Web服务器服务

nginx是一个开源反向代理,负载平衡器,HTTP缓存和Web服务器。如果使用路由网格将nginx作为服务运行,则连接到任何群集节点上的nginx端口都会显示(有效地)运行该服务的随机群集节点的网页。

以下示例在群集中的每个节点上将nginx作为服务运行,并在每个群集节点上本地公开nginx端口。

$ docker service create \
  --mode global \
  --publish mode=host,target=80,published=8080 \
  --name=nginx \
  nginx:latest

您可以在每个群集节点的端口8080上访问Nginx服务器。如果将节点添加到群集,则会在该群集上启动nginx任务。您无法在绑定到端口8080的任何swarm节点上启动其他服务或容器。

注意:这是一个幼稚的示例。为多层服务创建应用程序层路由框架很复杂,并且超出了本主题的范围。

将服务连接到覆盖网络

您可以使用覆盖网络来连接群集中的一项或多项服务。

首先,使用docker network create 带有--driver overlay标志的命令在管理器节点上创建覆盖网络。

$ docker network create --driver overlay my-network

在以群集模式创建覆盖网络之后,所有管理器节点都可以访问该网络。

您可以创建一个新服务并传递该--network标志以将该服务附加到覆盖网络:

$ docker service create \
  --replicas 3 \
  --network my-network \
  --name my-web \
  nginx

群扩展my-network到运行该服务的每个节点。

您还可以使用该--network-add标志将现有服务连接到覆盖网络 。

$ docker service update --network-add my-network my-web

要断开正在运行的服务与网络的连接,请使用该--network-rm标志。

$ docker service update --network-rm my-network my-web

有关覆盖网络和服务发现的更多信息,请参阅 将服务附加到覆盖网络Docker群集模式覆盖网络安全模型

授予服务访问机密的权限

要创建可访问Docker管理的机密的服务,请使用该--secret 标志。有关更多信息,请参阅 管理Docker服务的敏感字符串(秘密)。

自定义服务的隔离模式

Docker允许您指定群集服务的隔离模式。该设置仅适用于Windows主机,而对于Linux主机则被忽略。隔离模式可以是下列其中一种:

  • default:使用为Docker主机配置的默认隔离模式,由中的-exec-opt标志或exec-opts数组配置daemon.json。如果守护程序未指定隔离技术,process则该守护程序是Windows Serverhyperv的默认选项,也是Windows 10的默认(唯一)选项。

  • process:在主机上将服务任务作为单独的进程运行。

    注意process隔离模式仅在Windows Server上受支持。Windows 10仅支持hyperv隔离模式。

  • hyperv:将服务任务作为独立hyperv任务运行。这增加了开销,但提供了更多的隔离。

您可以在使用--isolation标志创建或更新新服务时指定隔离模式。

控制服务放置

群服务为您提供了几种不同的方法来控制服务在不同节点上的规模和位置。

  • 您可以指定服务是需要运行特定数量的副本还是应该在每个工作节点上全局运行。请参阅 复制服务或全局服务

  • 您可以配置服务的 CPU或内存要求,并且该服务仅在可以满足这些要求的节点上运行。

  • 放置约束使您可以将服务配置为仅在具有特定(任意)元数据集的节点上运行,并且如果不存在适当的节点,则会导致部署失败。例如,您可以指定服务应仅在将任意标签pci_compliant设置为的节点上运行 true

  • 放置首选项使您可以将具有一定范围值的任意标签应用于每个节点,并使用算法在这些节点上分布服务任务。当前,唯一受支持的算法是spread,它尝试将它们均匀放置。例如,如果您rack使用值介于1到10之间的标签来标记每个节点,然后指定键为的放置首选项rack,则rack在采取其他放置约束后,服务任务将在所有节点上尽可能均匀地放置到带有该标签的节点上,展示位置首选项以及其他特定于节点的限制。

    与约束不同,放置首选项是尽力而为的,如果没有节点可以满足该需求,则服务不会部署失败。如果您为服务指定放置首选项,则在集群管理器决定哪些节点应运行服务任务时,与该首选项匹配的节点排名更高。其他因素(例如服务的高可用性)也决定了将节点安排在其中运行服务任务的因素。例如,如果您有N个带有机架标签的节点(然后是其他一些),并且您的服务配置为运行N + 1个副本,则在没有该服务的节点上安排+1,如果不管该节点是否带有rack标签,都只有一个。

复制或全局服务

群集模式具有两种服务类型:复制服务和全局服务。对于复制的服务,您可以为群集管理器指定计划在可用节点上的复制任务数。对于全局服务,调度程序在满足服务的放置限制资源要求的每个可用节点上放置一个任务 。

您可以使用该--mode标志控制服务的类型。如果您未指定模式,则该服务默认为replicated。对于复制的服务,您可以使用该--replicas标志指定要开始的复制任务的数量。例如,要使用3个副本任务启动复制的nginx服务:

$ docker service create \
  --name my_web \
  --replicas 3 \
  nginx

要在每个可用节点上启动全局服务,请传递--mode globaldocker service create。每当新节点可用时,调度程序都会在新节点上放置全局服务的任务。例如,要启动在集群中每个节点上高山运行的服务:

$ docker service create \
  --name myservice \
  --mode global \
  alpine top

通过服务约束,您可以在调度程序将服务部署到节点之前为节点设置要满足的条件。您可以基于节点属性和元数据或引擎元数据将约束应用于服务。有关约束的更多信息,请参考docker service create CLI参考

保留服务的内存或CPU

要为服务保留给定的内存量或CPU数量,请使用 --reserve-memory--reserve-cpu标志。如果没有可用的节点可以满足要求(例如,如果您请求4个CPU,并且群集中的节点没有4个CPU),则该服务将保持待处理状态,直到有适当的节点可用于运行其任务为止。

内存不足异常(OOME)

如果您的服务尝试使用的内存超过了swarm节点可用的内存,那么您可能会遇到内存不足异常(OOME),并且内核OOM杀手可能会杀死容器或Docker守护程序。为防止这种情况的发生,请确保您的应用程序在具有足够内存的主机上运行,​​请参阅了解内存不足 的风险

群集服务允许您使用资源约束,放置首选项和标签来确保将服务部署到适当的群集节点。

放置约束

使用放置约束来控制可以将服务分配给的节点。在以下示例中,该服务仅在标签 region设置为的节点上运行 east。如果没有适当标记的节点可用,则任务将等待 Pending直到它们变为可用。该--constraint标志使用相等运算符(==!=)。对于复制的服务,可能所有服务都在同一节点上运行,或者每个节点仅运行一个副本,或者某些节点不运行任何副本。对于全局服务,该服务在满足放置限制和任何资源要求的每个节点上运行。

$ docker service create \
  --name my-nginx \
  --replicas 5 \
  --constraint node.labels.region==east \
  nginx

您还可以constraintdocker-compose.yml 文件中使用服务级别密钥。

如果指定多个放置约束,则该服务仅部署到所有它们都满足的节点上。下面的例子限制到所有节点上运行的服务region被设置为easttype没有设置为devel

$ docker service create \
  --name my-nginx \
  --mode global \
  --constraint node.labels.region==east \
  --constraint node.labels.type!=devel \
  nginx

您还可以将放置约束与放置首选项和CPU /内存约束结合使用。注意不要使用无法实现的设置。

有关约束的更多信息,请参考docker service create CLI参考

展示位置偏好设置

尽管放置约束限制了服务可以在其上运行的节点,但是放置首选项会尝试以算法方式将任务放置在适当的节点上(当前,仅均匀分布)。例如,如果为每个节点分配rack标签,则可以设置放置首选项rack,以按值在带有标签的节点之间平均分布服务。这样,如果丢失了机架,该服务仍将在其他机架上的节点上运行。

展示位置偏好设置没有严格执行。如果没有节点具有您在首选项中指定的标签,则将部署服务,就像未设置首选项一样。

全局服务会忽略展示位置偏好设置。

下面的示例设置一个首选项,以根据datacenter标签的值在节点之间分布部署。如果某些节点具有datacenter=us-east,其他节点具有 datacenter=us-west,则将服务尽可能均匀地部署在两组节点之间。

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  redis:3.0.6

标签缺失或为空

缺少用于传播的标签的节点仍会接收任务分配。这些节点作为一个组以与由特定标签值标识的任何其他组相等的比例接收任务。从某种意义上说,缺少标签与为其附加了空值的标签是相同的。如果服务应在标签用于扩展首选项的节点上运行,则应将首选项与约束组合。

您可以指定多个放置首选项,并按照遇到的顺序对其进行处理。以下示例设置具有多个展示位置首选项的服务。任务首先分布在各个数据中心,然后分布在机架上(如各个标签所示):

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  --placement-pref 'spread=node.labels.rack' \
  redis:3.0.6

您还可以结合使用放置首选项和放置约束或CPU /内存约束。注意不要使用无法实现的设置。

此图说明了放置首选项的工作方式:

展示位置偏好设置示例

当使用来更新服务时docker service update,会--placement-pref-add 在所有现有的展示位置首选项之后附加一个新的展示位置首选项。 --placement-pref-rm删除与参数匹配的现有展示位置偏好设置。

配置服务的更新行为

创建服务时,可以指定滚动更新行为,以说明运行时群集应如何将更改应用于服务docker service update。您还可以将这些标志指定为更新的一部分,作为的参数 docker service update

--update-delay标志配置在更新一个服务任务或一组任务之间的时间延迟。您可以将时间描述T为秒Ts,分钟Tm或小时数的组合Th。因此10m30s表示10分钟30秒延迟。

默认情况下,调度程序一次更新1个任务。您可以传递该 --update-parallelism标志来配置调度程序同时更新的最大服务任务数。

当对单个任务的更新返回状态为时RUNNING,调度程序将继续执行另一个任务,直到所有任务都被更新为止,从而继续进行更新。如果在更新过程中的任何时间返回任务FAILED,则调度程序将暂停更新。您可以使用或的--update-failure-action 标志来控制行为。docker service createdocker service update

在下面的示例服务中,调度程序一次将更新应用于最多2个副本。当更新的任务返回RUNNING或时FAILED,调度程序将等待10秒,然后再停止下一个要更新的任务:

$ docker service create \
  --replicas 10 \
  --name my_web \
  --update-delay 10s \
  --update-parallelism 2 \
  --update-failure-action continue \
  alpine

--update-max-failure-ratio标志控制在更新过程中哪些部分任务可能失败,然后才将整个更新视为失败。例如,使用--update-max-failure-ratio 0.1 --update-failure-action pause,在10%的更新任务失败后,更新被暂停。

如果单个任务更新没有启动,或者在--update-monitor标记指定的监视期内停止运行,则认为单个任务更新失败。默认值为--update-monitor30秒,这意味着在任务启动后的前30秒内失败的任务计入服务更新失败阈值,此后的失败不计入。

回滚到服务的先前版本

如果服务的更新版本无法按预期运行,则可以使用docker service update--rollback标志将其手动回滚到服务的先前版本 。这会将服务还原为最新docker service update命令之前的配置 。

其他选项可以与--rollback; 例如, --update-delay 0s要执行回滚而没有任务之间的延迟:

$ docker service update \
  --rollback \
  --update-delay 0s
  my_web

您可以将服务配置为在部署服务更新失败时自动回滚。如果更新失败,请参阅自动回滚

手动回滚是在服务器端处理的,它允许手动启动的回滚遵守新的回滚参数。请注意,--rollback不能与的其他标志一起使用docker service update

如果更新失败,将自动回滚

您可以通过以下方式配置服务:如果对服务的更新导致重新部署失败,则该服务可以自动回滚到以前的配置。这有助于保护服务可用性。您可以在创建或更新服务时设置以下一个或多个标志。如果未设置值,则使用默认值。

旗帜 默认 描述
--rollback-delay 0s 回滚任务后回滚下一个任务要等待的时间。的值0的装置,以所述第一回滚任务展开时后,立即回滚所述第二任务。
--rollback-failure-action pause 当某个任务无法回滚时,是回滚pause还是continue尝试回滚其他任务。
--rollback-max-failure-ratio 0 回滚期间可容忍的失败率,指定为0到1之间的浮点数。例如,给定5个任务,失败率.2会容忍一个任务无法回滚。0表示没有故障的平均值意味着可以容忍1任何数量的故障。
--rollback-monitor 5s 每个任务回滚后监视失败的持续时间。如果任务在此时间段之前停止,则回滚被视为失败。
--rollback-parallelism 1 并行回滚的最大任务数。默认情况下,一次回滚一个任务。值0导致所有任务并行回滚。

以下示例将redis服务配置为docker service update在部署失败时自动回滚。可以并行回滚两个任务。回滚后会监视任务20秒钟,以确保它们不会退出,并且允许的最大故障率是20%。--rollback-delay和和使用默认值--rollback-failure-action

$ docker service create --name=my_redis \
                        --replicas=5 \
                        --rollback-parallelism=2 \
                        --rollback-monitor=20s \
                        --rollback-max-failure-ratio=.2 \
                        redis:latest

授予服务访问卷或绑定装载的权限

为了获得最佳性能和可移植性,应避免将重要数据直接写入容器的可写层,而不要使用数据卷或绑定挂载。该原则也适用于服务。

您可以为群集中的服务创建两种类型的安装:volume安装或 bind安装。无论使用哪种类型的挂载,--mount在创建服务时都使用标志进行配置 ,或者 在更新现有服务时使用--mount-add--mount-rm标志进行配置。如果未指定类型,则默认为数据量。

数据量

数据卷是独立于容器而存在的存储。群服务下的数据量生命周期与容器下的生命周期相似。卷使任务和服务失效,因此必须分别管理它们的删除。卷可以在部署服务之前创建,或者如果在计划某个任务的特定主机上不存在这些卷,则会根据服务上的卷规范自动创建它们。

要将现有数据卷与服务一起使用,请使用--mount标志:

$ docker service create \
  --mount src=<VOLUME-NAME>,dst=<CONTAINER-PATH> \
  --name myservice \
  <IMAGE>

如果<VOLUME-NAME>在将任务调度到特定主机时不存在具有相同卷的卷,则会创建一个卷。默认的音量驱动程序是local。要将其他卷驱动程序与按需创建模式一起使用,请通过以下--mount标志指定驱动程序及其选项:

$ docker service create \
  --mount type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=<DRIVER>,volume-opt=<KEY0>=<VALUE0>,volume-opt=<KEY1>=<VALUE1>
  --name myservice \
  <IMAGE>

有关如何创建数据卷和使用卷驱动程序的更多信息,请参见使用卷

绑定坐骑

绑定安装是调度程序为任务部署容器的主机的文件系统路径。Docker将路径安装到容器中。在群集初始化任务容器之前,文件系统路径必须存在。

以下示例显示了绑定安装语法:

  • 要安装读写绑定:

    $ docker service create \
      --mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH> \
      --name myservice \
      <IMAGE>
    
  • 要安装只读绑定:

    $ docker service create \
      --mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH>,readonly \
      --name myservice \
      <IMAGE>
    

重要说明:绑定安装很有用,但也会引起问题。在大多数情况下,建议您对应用程序进行架构设计,以免从主机挂载路径。主要风险包括:

  • 如果将主机路径绑定安装到服务的容器中,则该路径必须存在于每个群集节点上。Docker群模式调度程序可以在满足资源可用性要求并满足您指定的所有约束和放置首选项的任何机器上调度容器。

  • 如果Docker群集模式调度程序变得不健康或无法访问,它们可能会在任何时候重新调度您正在运行的服务容器。

  • 主机绑定安装是不可移植的。当您使用绑定安装时,不能保证您的应用程序在开发中的运行方式与在生产中的运行方式相同。

使用模板创建服务

您可以使用service createGo的text / template 包提供的语法将模板用于的某些标志。

支持以下标志:

  • --hostname
  • --mount
  • --env

Go模板的有效占位符为:

占位符 描述
.Service.ID 服务编号
.Service.Name 服务名称
.Service.Labels 服务