docker swarm英文文档学习-8-在集群中部署服务

时间:2024-06-17 21:33:31

Deploy services to a swarm在集群中部署服务

集群服务使用声明式模型,这意味着你需要定义服务的所需状态,并依赖Docker来维护该状态。该状态包括以下信息(但不限于):

应该运行服务容器的镜像名称和标记
有多少容器参与服务
是否有任何端口暴露给集群之外的客户端
当Docker启动时,服务是否应该自动启动
重启服务时发生的特定行为(例如是否使用滚动重启)
服务可以运行的节点的特征(例如资源约束和位置首选项)
有关群模式的概述,请参见 Swarm mode key concepts。有关服务如何工作的概述,请参见How services work

Create a service创建服务

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

$ docker service create nginx

服务被安排在一个可用的节点上。要确认服务已创建并成功启动,请使用docker service ls命令:

$ docker service ls

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

创建的服务并不总是立即运行。如果服务的镜像不可用,如果没有节点满足你为服务配置的需求,或者其他原因,则该服务可能处于pending挂起状态。有关更多信息,请参见 Pending services

要为你的服务提供名称,请使用--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

Create a service using an image on a private registry使用私有注册表上的镜像创建服务

如果你的镜像在需要登录的私有注册中心上可用,请在登录后使用docker service create的--with-registry-auth标志。如果你的镜像存储在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日志将登录令牌从本地客户机传递到部署服务的集群节点。有了这些信息,节点就可以登录到注册中心并拉出镜像。

Update a service更新服务

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

由于Nginx是一个web服务,如果你将端口80发布到集群之外的客户端,那么它的工作效果会更好。你可以在创建服务时使用-p或--publish标志指定这一点。更新现有服务时,标志为--publish-add。还有一个--publish-rm标志,用于删除先前发布的端口。

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

$ docker service update --publish-add  my_web

检查其是否工作,使用:

docker service ls

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

你几乎可以更新关于现有服务的所有配置细节,包括它运行的镜像名称和标记。参见Update a service’s image after creation

Remove a service移除服务

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

$ docker service remove my_web

Service configuration details服务配置细节

下面几节提供关于服务配置的详细信息。本主题并不涵盖每个标志或场景。在几乎所有可以在服务创建时定义配置的实例中,你还可以以类似的方式更新现有服务的配置。

请参阅docker service createdocker service update的命令行引用,或使用--help标志运行这些命令之一。

Configure the runtime environment配置运行环境

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

  • 使用--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

Update the command an existing service runs更新存在的服务运行的命令

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

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

Specify the image version a service should use指定服务应该使用的镜像版本

当你创建一个服务而没有指定要使用的镜像版本的任何细节时,该服务将使用使用latest标记来标记的版本。根据期望的结果,你可以强制服务以几种不同的方式使用镜像的特定版本。
一个镜像版本可以用几种不同的方式表达:
1.如果指定一个标记,则管理器(如果使用content trust,则为Docker客户机)将该标记解析为摘要。当在工作节点上接收到创建容器任务的请求时,工作节点只会看到摘要,而不会看到标记。

注意:

标记即ubuntu:16.04

摘要即对应的sha256:35bc48a1ca97c3971611dc4662d08d131869daa692acb281c7e9e052924e38b1

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

一些标签表示独立的版本,比如ubuntu:16.04。随着时间的推移,这样的标记几乎总是解析为一个稳定的摘要。如果可能的话,建议你使用这种标记。
其他类型的标记,如latest或nightly,可能经常解析为新的摘要,这取决于镜像的作者更新标记的频率。不建议使用频繁更新的标记运行服务,以防止不同的服务复制任务使用不同的镜像版本。

2.如果根本不指定版本,则按照约定将镜像的latest标记解析为摘要。工作人员在创建服务任务时使用此摘要中的镜像。
因此,以下两个命令是等价的:

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

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

3.如果直接指定摘要,则在创建服务任务时总是使用镜像的准确版本。

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

在创建服务时,镜像的标记被解析为服务创建时标记所指向的特定摘要。除非服务被显式更新,否则该服务的工作节点将永远使用该特定摘要。如果你确实使用经常更改的标记(如最新),则此功能尤其重要,因为它确保所有服务任务使用相同版本的镜像。

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

如果管理器不能将标记解析为摘要,则每个工作节点负责将标记解析为摘要,不同的节点可能使用不同版本的镜像。如果发生这种情况,将记录如下所示的警告,用占位符替换实际信息。

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

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

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

创建服务之后,除非你使用--image标记显式地运行docker service update,否则它的镜像永远不会更新,如下所述。其他更新操作(如扩展服务、添加或删除网络或卷、重命名服务或任何其他类型的更新操作)不更新服务的镜像。

Update a service’s image after creation创建后更新服务的镜像

每个标记表示一个摘要,类似于Git散列。有些标记(如latest)经常更新以指向新的摘要。其他的,比如ubuntu:16.04,代表了一个已经发布的软件版本,不需要经常更新以指向一个新的摘要。在Docker 1.13及更高版本中,当你创建服务时,它被限制为使用镜像的特定摘要来创建任务,直到你使用--image标志的service update来更新服务为止。如果使用旧版本的Docker引擎,则必须删除并重新创建服务以更新其镜像。

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

注意:如果使用内容可信content trust,Docker客户机解析镜像,swarm manager接收镜像和摘要,而不是标记。
通常,管理器可以将标记解析为新的摘要和服务更新,重新部署每个任务以使用新镜像。如果管理器无法解决标记或出现其他问题,则接下来的两个部分将概述将会发生的情况。

IF THE MANAGER RESOLVES THE TAG如果管理器解析标记

如果集群管理器可以将镜像标记解析为摘要,它将指示工作节点重新部署任务并在摘要中使用镜像。

  • 如果工作人员在该摘要中缓存了镜像,则使用它。
  • 如果不是,则尝试从Docker Hub或私有注册中心提取镜像:
  1. 如果成功,则使用新镜像部署任务。
  2. 如果worker无法拉出镜像,则服务无法在该worker节点上部署。Docker再次尝试部署任务,可能是在不同的工作节点上。

IF THE MANAGER CANNOT RESOLVE THE TAG如果管理器不能解析标记

如果集群管理器不能将镜像解析为摘要,那么一切都不会丢失:

  • 管理器指示工作节点使用标记处的镜像重新部署任务。
  • 如果worker有一个本地缓存的镜像,该镜像将解析到该标记,那么它将使用该镜像。
  • 如果worker没有解析到标记的本地缓存镜像,则该worker将尝试连接到Docker Hub或私有注册中心以从该标记提取镜像。
  1. 如果成功,工作人员将使用该镜像。
  2. 如果失败,任务将无法部署,管理员将再次尝试部署任务,可能是在不同的工作节点上。

Publish ports发布端口

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

  • 你可以依赖路由网格。当你发布一个服务端口时,集群使服务在每个节点上的目标端口都可以访问,而不管在该节点上运行的服务是否有任务。这并不复杂,而且对于许多类型的服务来说都是正确的选择。
  • 你可以将服务任务的端口直接发布到运行该服务的集群节点上。该特性在Docker 1.13及更高版本中可用。这绕过了路由网格,并提供了最大的灵活性,包括开发自己的路由框架的能力。但是,你负责跟踪每个任务的运行位置,并将请求路由到任务,以及跨节点的负载平衡。

1.PUBLISH A SERVICE’S PORTS USING THE ROUTING MESH使用路由网格发布服务端口

要向集群外部发布服务的端口,使用--publish <PUBLISHED-PORT>:<SERVICE-PORT>。集群使得服务可以在每个集群节点上的已发布端口*问。如果外部主机连接到任何集群节点上的该端口,则路由网格将其路由到一个任务。外部主机不需要知道与服务交互的服务任务的IP地址或内部使用的端口。当用户或流程连接到服务时,运行服务任务的任何工作节点都可能响应。有关集群服务网络的详细信息,请参见Manage swarm service networks

Example: Run a three-task Nginx service on 10-node swarm 例子:在10个节点集群中运行三个任务的Ngnix服务

想象你有10个节点的集群,然后你部署了一个Ngnix服务在10个节点上运行三个任务:

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

三个任务最多在三个节点上运行。你不需要知道哪些节点正在运行任务;在这10个节点中,连接到端口8080可以将你连接到三个nginx任务之一。你可以用curl来测试。下面的示例假设localhost是集群节点之一。如果不是这种情况,或者本地主机没有解析到你的主机上的IP地址,则替换主机的IP地址或可解析的主机名。

HTML输出被截断:

$ curl localhost:

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

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

PUBLISH A SERVICE’S PORTS DIRECTLY ON THE SWARM NODE直接在集群节点中发布服务端口

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

注意:如果你使用mode=host在swarm节点上直接发布一个服务的端口,并且还设置published=<PORT>,这就造成了一个隐含的限制,即你只能在给定的swarm节点上为该服务运行一个任务。你可以通过在没有端口定义的情况下指定published来解决这个问题,这会导致Docker为每个任务分配一个随机端口。

此外,如果你使用mode=host而不使用docker service create上的--mode=global标志,那么很难知道哪些节点正在运行服务来将工作路由到它们。

Example: Run an nginx web server service on every swarm node 例子:在每个集群节点上运行nginx web服务器服务

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

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

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

你可以在每个集群节点的端口8080*问nginx服务器。如果向集群中添加一个节点,就会启动nginx任务。你不能在任何绑定到端口8080的集群节点上启动另一个服务或容器。

注意:这是一个简单的例子。为多层服务创建应用层路由框架非常复杂,超出了本主题的范围。

Connect the service to an overlay network连接服务到覆盖网络

你可以使用覆盖网络来连接群中的一个或多个服务。
首先,使用docker network create命令和--driver overlay标记在管理器节点上创建覆盖网络。

$ docker network create --driver overlay my-network

在集群模式下创建覆盖网络之后,所有管理器节点都可以访问该网络。
你可以创建一个新的服务,并传递--network标志,将服务附加到覆盖网络:

$ docker service create \
--replicas \
--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

Grant a service access to secrets授予服务对机密的访问权

要创建对docker管理的机密内容有访问权限的服务,请使用--secret标志。有关更多信息,请参见Manage sensitive strings (secrets) for Docker services

Customize a service’s isolation mode自定义服务的隔离模式

Docker 17.12 CE及更高版本允许你指定集群服务的隔离模式。此设置仅适用于Windows主机,对于Linux主机则忽略此设置。隔离模式可以是以下模式之一:

  • default:使用为Docker主机配置的默认隔离模式,如daemon.json中的-exec-opt标志或exec-opts数组所配置的那样。如果守护进程没有指定隔离技术,则process是Windows服务器的默认设置,而hyperv是Windows 10的默认(且唯一)选择。
  • process:将服务任务作为独立的进程在主机上运行。

    注意:process隔离模式仅在Windows服务器上受支持。Windows 10只支持hyperv隔离模式。

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

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

Control service placement控制服务位置

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

  • 你可以指定服务需要运行特定数量的副本,还是应该在每个工作节点上全局运行。参见Replicated or global services
  • 你可以配置服务的CPU或内存需求,并且服务只在满足这些需求的节点上运行。
  • 位置约束允许你将服务配置为仅在具有特定(任意)元数据集的节点上运行,如果不存在适当的节点,则会导致部署失败。例如,你可以指定你的服务只能在任意标签pci_compatible设置为true的节点上运行。
  • 位置首选项让你可以对每个节点应用具有一系列值的任意标签,并使用算法将服务的任务分散到这些节点上。目前,唯一受支持的算法是spread,它试图将它们平均放置。例如,如果你标记每个节点带着一个值从1到10的标签rack,然后指定一个位置首选项值标签rack,然后在其他位置限制,位置偏好,和其他特定于节点的限制后,服务任务将尽可能均匀地放置在所有带着标签rack的节点,。

与约束不同,位置首选项是最有效的,如果没有节点能够满足首选项,服务不会失败部署。如果你指定了服务的位置首选项,那么当集群管理器决定哪些节点应该运行服务任务时,与该首选项匹配的节点的排名会更高。其他因素,如服务的高可用性,也会影响到计划在其中运行服务任务的节点。举个例子,如果你有N个节点带着标签(还有一些其他人),和你的服务配置是要运行N + 1副本,首先将会降N个任务放置到带有rack标签的节点上,然后+ 1将调度到一个并没有服务在上面的节点,如果这个节点存在,无论该节点带有rack标签或不带有。

REPLICATED OR GLOBAL SERVICES复制或全局服务

集群模式有两种服务类型:复制replicated服务和全局global服务。对于复制的服务,你可以为swarm manager指定要调度到可用节点上的复制任务的数量。对于全局服务,调度器在满足服务的位置约束和资源需求的每个可用节点上放置一个任务。
使用--mode标志控制服务的类型。如果不指定模式,则服务默认为复制。对于复制的服务,指定要开始使用--replicas标志的复制任务的数量。例如,使用3个复制任务启动一个复制的nginx服务:

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

要在每个可用节点上启动全局服务,请将--mode global传递给docker service create。每当新节点可用时,调度器将全局服务的任务放置在新节点上。例如,启动一个在群中的每个节点上运行alpine的服务:

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

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

RESERVE MEMORY OR CPUS FOR A SERVICE为服务保留内存或cpu

若要为服务保留给定的内存或cpu数量,请使--reserve-memory或--reserve-cpu标志。如果没有可用的节点可以满足需求(例如,如果你请求4个cpu,而集群中没有节点有4个cpu),则服务将保持挂起状态,直到有合适的节点可以运行其任务为止。

Out Of Memory Exceptions (OOME)

如果你的服务试图使用比群集节点可用的内存更多的内存,那么你可能会遇到内存不足异常(OOME),内核OOM杀手可能会杀死容器或Docker守护进程。要防止这种情况发生,请确保你的应用程序在具有足够内存的主机上运行,查看 Understand the risks of running out of memory.。
Swarm服务允许你使用资源约束、位置首选项和标签来确保你的服务被部署到适当的Swarm节点。

PLACEMENT CONSTRAINTS位置约束

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

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

你还可以在docker-compose.yml文件中使用constraint服务级别键。
如果指定多个放置约束,则服务只部署到所有节点都满足的节点上。下面的示例将服务限制为在所有节点上运行,其中region设置为east, type设置为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 reference

PLACEMENT PREFERENCES位置首选项

虽然位置约束限制了服务可以在其上运行的节点,但是位置首选项尝试以算法的方式将服务放置在适当的节点上(目前,仅平均分布)。例如,如果你为每个节点分配一个rack标签,那么你可以设置一个位置首选项,通过值将服务均匀地分布到带有rack标签的节点上。这样,如果你丢失了一个rack,服务仍然在其他rack上的节点上运行。
位置首选项不严格执行。如果没有节点具有你在首选项中指定的标签,则会像未设置首选项一样部署服务。
全局服务忽略位置首选项。
下面的示例设置了一个首选项,根据datacenter标签的值将部署分散到节点上。如果某些节点具有datacenter=us-east,而其他节点具有datacenter=us-west,则服务在这两组节点之间尽可能均匀地部署。

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

⚠️Missing or null labels

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

你可以指定多个位置首选项,并按照遇到的顺序处理它们。下面的示例设置具有多个位置首选项的服务。任务首先分布在各个datacenters,然后分布在rack上(如各自的标签所示):

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

还可以将位置首选项与位置约束或CPU/内存约束结合使用。注意不要使用不可能完成的设置。
这个图表说明了如何放置首选项工作:

docker swarm英文文档学习-8-在集群中部署服务

当使用docker service update更新服务时,--placater -pref-add在所有现有的放置首选项之后追加一个新的放置首选项。--placater-pref-rm删除与参数匹配的现有位置首选项。

Configure a service’s update behavior配置服务的更新行为

在创建服务时,可以指定一个滚动更新行为,说明在运行docker service update时集群应该如何将更改应用于服务。你还可以将这些标志指定为更新的一部分,作为docker service update的参数。
--update-delay标志配置服务任务或任务集更新之间的时间延迟。你可以将时间T描述为Ts秒数、Tm分钟数或Th小时数的组合。所以10m30s表示10分30秒的延迟。
默认情况下,调度程序每次更新一个任务。你可以传递--update-parallelism标志来配置调度程序同时更新的服务任务的最大数量。

当对单个任务的更新返回RUNNING的状态时,调度器将继续更新,方法是继续到另一个任务,直到所有任务都被更新。如果在更新期间某个任务返回FAILED,调度程序将暂停更新。你可以使用docker service create或docker service update的--update-failure-action标志来控制行为。

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

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

--update-max-failure-ratio标志控制在整个更新被认为失败之前的更新过程中有多少任务会失败。例如,使用--update-max-failure-ratio 0.1 --update-failure-action pause,在更新的任务中有10%失败后,更新将暂停。

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

Roll back to the previous version of a service回滚到服务的上一个版本

如果服务的更新版本没有如预期那样发挥作用,可以使用docker service update的--rollback标志手动回滚到服务的前一个版本。这将服务恢复到docker service update命令之前的配置。

其他选项可以与--rollback结合使用;例如--update-delay 0s执行回滚,任务之间不存在延迟:

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

在Docker 17.04及更高版本中,可以配置服务,以便在服务更新部署失败时自动回滚。参见Automatically roll back if an update fails
与新的自动回滚特性相关的是,在Docker 17.04及更高版本中,如果守护进程运行Docker 17.04或更高版本,则手动回滚将在服务器端处理,而不是在客户端处理。这允许手动启动的回滚尊重新的回滚参数。客户机是版本敏感的,因此它仍然对较旧的守护进程使用旧方法。
最后,在Docker 17.04及更高版本中,--rollback不能与Docker服务更新的其他标志一起使用。

Automatically roll back if an update fails如果更新失败则自动回滚

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

Flag Default Description
--rollback-delay 0s 指定在回滚一个任务之后等待的时间,然后再回滚下一个任务。值0表示在第一个回滚任务部署之后立即回滚第二个任务。
--rollback-failure-action pause 当一个任务无法回滚时,是暂停还是继续尝试回滚其他任务。
--rollback-max-failure-ratio 0 回滚期间容忍的失败率,指定为0到1之间的浮点数。例如,给定5个任务,.2的失败率将允许一个任务(0.2*5=1)不能回滚。值为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= \
--rollback-parallelism= \
--rollback-monitor=20s \
--rollback-max-failure-ratio=. \
redis:latest

Give a service access to volumes or bind mounts授予服务访问卷或绑定挂载的权限

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

你可以为群集中的服务创建两种类型的挂载,volume挂载或bind挂载。无论使用哪种类型的挂载,在创建服务时使用--mount标志配置它,在更新现有服务时使用--mount-add或--mount-rm标志配置它。如果不指定类型,默认值是一个数据卷。

DATA VOLUMES数据卷

数据卷是独立于容器存在的存储。集群服务下的数据量的生命周期类似于容器下的生命周期。卷的寿命比任务和服务长,因此它们的删除必须单独管理。可以在部署服务之前创建卷,或者在部署任务时,如果在特定主机上不存在卷,则根据服务上的卷规范自动创建卷。
要将现有数据卷与服务一起使用,请使用--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>

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

BIND MOUNTS绑定挂载

绑定挂载是来自调度程序为任务部署容器的主机的文件系统路径。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群模式调度程序可能会在任何时候重新调度它们。
  • 主机绑定安装是不可移植的。在使用绑定挂载时,不能保证应用程序在开发中以与在生产中相同的方式运行。

Create services using templates使用模版创建服务

你可以使用Go的文本/模板包提供的语法,为service create的一些标志使用模板。
支持以下标志:

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

Go模板的有效占位符如下:

Placeholder Description
.Service.ID Service ID
.Service.Name Service name
.Service.Labels Service labels
.Node.ID Node ID
.Node.Hostname Node hostname
.Task.Name Task name
.Task.Slot Task slot

TEMPLATE EXAMPLE模版例子

这个示例根据服务的名称和运行容器的节点的ID设置创建的容器的模板:

$ docker service create --name hosttempl \
--hostname="{{.Node.ID}}-{{.Service.Name}}"\
busybox top

要查看使用模板的结果,请使用docker service ps和docker inspect命令。

$ docker service ps va8ew30grofhjoychbr6iot8c

ID            NAME         IMAGE                                                                                   NODE          DESIRED STATE  CURRENT STATE               ERROR  PORTS
wo41w8hg8qan hosttempl. busybox:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912 2e7a8a9c4da2 Running Running about a minute ago
$ docker inspect --format="{{.Config.Hostname}}" hosttempl..wo41w8hg8qanxwjwsg4kxpprj