Docker Swarm Service
Service介绍
要在Docker引擎处于群集模式时部署image,需要创建一个Service(服务)。
创建一个服务时,指定要使用哪个容器镜像,以及要在正在运行的容器中执行哪些命令。还可以为服务定义选项,包括:
- 群集所在的端口使服务在群集外部可用
- 一个覆盖网络,用于服务连接到群中的其他服务
- CPU和内存限制和保留
- 滚动更新策略
- 要在群集中运行的映像副本的数量
Services, tasks, and containers
当部署服务到 swarm,swarm manager接收你对服务期望状态的定义。然后它为服务在 swarm 中的节点调度一个或多个副本任务。这些任务在 swarm 的节点上彼此独立地运行。
例如假设你想负载均衡三个 HTTP 服务器实例。下面的图表展示了三个 HTTP 服务器副本。
三个 HTTP 实例中的每一个是 swarm 中的一个任务。
容器是一个独立的进程。在swarm模式模式中,每个task只调用一个容器。task类似于调度程序放置容器的“插槽”。一旦容器处于活动状态,调度程序就会识别出任务处于运行状态。如果容器未通过健康检查或终止,则任务终止。
Tasks and scheduling
任务是 swarm 内调度的原子单位。当你通过创建或更新服务声明一个期望状态的服务,调度器通过调度任务来实现期望的状态。例如,你指定一个服务始终保持运行三个HTTP 实例。调度器就创建三个任务。每个任务运行一个容器。容器是任务的实例化。如果一个 HTTP 容器之后出现故障停止,此任务被标志为失败,调度器就会创建一个新的任务来生成一个新容器
任务是一个单向机制。它单向地执行一系统状态,assigned,prepared, running 等。如果一个任务失败了,调度器就会删除这个任务和它的容器,然后创建一个新的任务来替换它。
下面的图表显示 swarm 模式是如何接收服务创建请求和调度任务到 worker 节点的。
Replicated and global services
有两种类型的services部署,副本和全局
- Replicated services
你可以指定运行相同任务的数量。例如,你决定部署三个 HTTP 实例的副本,每个提供相同的内容。 - global services
在每个节点上运行一个相同的任务。不需要预先指定任务的数量。每次增加一个节点到 swarm 中,协调器就会创建一个任务,然后调度器把任务分配给新节点。
下图表示用黄色表示拥有三个副本的 Replicated service,用灰色表示了一个global service
task 状态
Docker允许你创建可以启动任务的服务。服务是对所需状态的描述,任务完成这项工作。在集群节点上按以下顺序调度工作:
- 使用docker service create或UCP web UI或CLI创建服务。
- 请求被发送到Docker manager节点。
- Docker manager节点将服务安排在特定节点上运行。
- 每个服务可以启动多个任务。
- 每个任务都有一个生命周期,有像NEW、PENDING和COMPLETE这样的状态。
任务是运行一次直至完成的执行单元。当一个任务停止时,它不会再次执行,但是一个新的任务可能会取而代之。
任务在许多状态中前进,直到它们完成或失败。任务在新状态中初始化。任务通过许多状态向前推进,而它的状态不会后退。例如,任务永远不会从COMPLETE变为RUNNING。
task的生命周期
NEW 任务在初始化状态
PENDING 正在分配任务所用的资源
ASSIGNED Docker分配任务给节点
ACCEPTED 任务被工作节点接受。如果工作节点拒接任务,状态将会转变成REJECTED
PREPARING Docker正在准备任务
STARTING Docker正在开启任务
RUNNING 任务正在执行
COMPLETE 任务结束,不带错误代码
FAILED 任务结束,带着错误代码
SHUTDOWN Docker请求任务关闭
REJECTED 工作节点拒绝任务
ORPHANED 节点宕机时间太长
REMOVE 该任务不是终端,但相关服务已被删除或缩小
查看task状态
运行docker service ps
```script
$ docker service ps webserver
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
owsz0yp6z375 webserver.1 nginx UbuntuVM Running Running 44 seconds ago
j91iahr8s74p \_ webserver.1 nginx UbuntuVM Shutdown Failed 50 seconds ago "No such container: webserver.…"
7dyaszg13mw2 \_ webserver.1 nginx UbuntuVM Shutdown Failed 5 hours ago
```
操作
部署一个Service到swarm
-
执行下面的命令
[root@localhost ~]# docker service create --replicas 1 --name helloworld alpine ping www.baidu.com 7k5nx2b4zj8at0aohqfj6lcqw overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
- docker service create 创建服务
- --name service的名字
- --replicas指定一个service有几个实例运行
-
查看运行的service
[root@localhost ~]# docker service list ID NAME MODE REPLICAS IMAGE PORTS 7k5nx2b4zj8a helloworld replicated 1/1 alpine:latest
查看service的详细信息
```script
[root@localhost ~]# docker service inspect --pretty helloworld (or ServiceID)
ID: 7k5nx2b4zj8at0aohqfj6lcqw
Name: helloworld
Service Mode: Replicated
Replicas: 1
Placement:
UpdateConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Update order: stop-first
RollbackConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Rollback order: stop-first
ContainerSpec:
Image: alpine:latest@sha256:769fddc7cc2f0a1c35abb2f91432e8beecf83916c421420e6a6da9f8975464b6
Args: ping www.baidu.com
Init: false
Resources:
Endpoint Mode: vip
```
-
以json格式返回service的详细信息
[root@localhost ~]# docker service inspect 7k5nx2b4zj8a [ { "ID": "7k5nx2b4zj8at0aohqfj6lcqw", "Version": { "Index": 16 }, "CreatedAt": "2019-06-08T12:21:18.255252358Z", "UpdatedAt": "2019-06-08T12:21:18.255252358Z", "Spec": { "Name": "helloworld", "Labels": {}, "TaskTemplate": { "ContainerSpec": { "Image": "alpine:latest@sha256:769fddc7cc2f0a1c35abb2f91432e8beecf83916c421420e6a6da9f8975464b6", "Args": [ "ping", "www.baidu.com" ], "Init": false, "StopGracePeriod": 10000000000, "DNSConfig": {}, "Isolation": "default" }, "Resources": { "Limits": {}, "Reservations": {} }, "RestartPolicy": { "Condition": "any", "Delay": 5000000000, "MaxAttempts": 0 }, "Placement": { "Platforms": [ { "Architecture": "amd64", "OS": "linux" }, { "OS": "linux" }, { "OS": "linux" }, { "Architecture": "arm64", "OS": "linux" }, { "Architecture": "386", "OS": "linux" }, { "Architecture": "ppc64le", "OS": "linux" }, { "Architecture": "s390x", "OS": "linux" } ] }, "ForceUpdate": 0, "Runtime": "container" }, "Mode": { "Replicated": { "Replicas": 1 } }, "UpdateConfig": { "Parallelism": 1, "FailureAction": "pause", "Monitor": 5000000000, "MaxFailureRatio": 0, "Order": "stop-first" }, "RollbackConfig": { "Parallelism": 1, "FailureAction": "pause", "Monitor": 5000000000, "MaxFailureRatio": 0, "Order": "stop-first" }, "EndpointSpec": { "Mode": "vip" } }, "Endpoint": { "Spec": {} } } ]
-
查看Service在哪些节点运行
[root@localhost ~]# docker service ps helloworld ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS w8gx7yw2j0yu helloworld.1 alpine:latest localhost.localdomain Running Running 12 minutes ago 6ooy7juh1wqi \_ helloworld.1 alpine:latest localhost.localdomain Shutdown Rejected 12 minutes ago "No such image: alpine:latest@…" 34iewe90umel \_ helloworld.1 alpine:latest localhost.localdomain Shutdown Rejected 13 minutes ago "No such image: alpine:latest@…" vyvdbph10jg3 \_ helloworld.1 alpine:latest localhost.localdomain Shutdown Rejected 14 minutes ago "No such image: alpine:latest@…" 1mkb9fdpbnnx \_ helloworld.1 alpine:latest localhost.localdomain Shutdown Rejected 14 minutes ago "No such image: alpine:latest@…" 【注意】由于没有更改主机名,所以在NODE列里无法区分主机,一定要设置合适的主机名,以便于区分。
-
在任务节点上运行docker ps,可以查看关于任务容器的详细信息
[root@localhost harbor]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d7f574d9350b alpine:latest "ping www.baidu.com" 23 minutes ago Up 23 minutes helloworld.1.w8gx7yw2j0yuybx0v1dd165vb
在集群中扩展服务
将service部署到集群中后,可以通过命令行扩展service中的容器数量。在service中运行的容器称为“tasks”(任务)
-
将helloworld service运行的任务扩展为5个
[root@localhost harbor]# docker service scale helloworld=5 helloworld scaled to 5 overall progress: 5 out of 5 tasks 1/5: running [==================================================>] 2/5: running [==================================================>] 3/5: running [==================================================>] 4/5: running [==================================================>] 5/5: running [==================================================>] verify: Service converged [root@localhost harbor]#
-
查看更新后的service 列表
[root@localhost harbor]# docker service ps helloworld ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS w8gx7yw2j0yu helloworld.1 alpine:latest node1 Running Running 34 minutes ago 6ooy7juh1wqi \_ helloworld.1 alpine:latest node1 Shutdown Rejected 34 minutes ago "No such image: alpine:latest@…" 34iewe90umel \_ helloworld.1 alpine:latest node1 Shutdown Rejected 35 minutes ago "No such image: alpine:latest@…" vyvdbph10jg3 \_ helloworld.1 alpine:latest node1 Shutdown Rejected 35 minutes ago "No such image: alpine:latest@…" 1mkb9fdpbnnx \_ helloworld.1 alpine:latest node1 Shutdown Rejected 36 minutes ago "No such image: alpine:latest@…" w44j1ygrmi7s helloworld.2 alpine:latest node2 Running Running 2 minutes ago chfthbqpj178 helloworld.3 alpine:latest node2 Running Running 2 minutes ago v55w9i8xdppb helloworld.4 alpine:latest node1 Running Running 2 minutes ago 3wmd93u5gsjh helloworld.5 alpine:latest node2 Running Running 2 minutes ago
删除Service
```script
[root@localhost harbor]# docker service rm helloworld
helloworld
[root@localhost harbor]# docker service list
ID NAME MODE REPLICAS IMAGE PORTS
[root@localhost harbor]#
```
注意
即使service不在存在,容器也需要几秒钟来清理
Service滚动更新
在上面的步骤中扩展了Service中tasks的数量,下面将部署一个redis 3.0.6,通过滚动更新把redis更新为3.0.7
-
部署一个redis3.0.6集群,并为集群配置10秒的更新延迟
[root@localhost harbor]# docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.6 50gtthzgzwmqjkpubutfsgnu6 overall progress: 3 out of 3 tasks 1/3: running [==================================================>] 2/3: running [==================================================>] 3/3: running [==================================================>] verify: Service converged
2.--update-delay: 更新服务任务(Task)执行间隔 默认情况下,调度程序每次更新一个任务。可以设置--update-parallelism 来调整调度器同时更新任务的最大数量。
默认情况下,当对单个任务的更新结束,调度程序才会对另一个任务进行更新,直到所有的任务都更新为止。如果在更新任务期间失败,调度程序将暂停更新。可以使用--update-failure-action 来控制docker service create or docker service update执行失败后的行为
-
查看redis service的详细信息
[root@localhost harbor]# docker service inspect --pretty redis ID: 50gtthzgzwmqjkpubutfsgnu6 Name: redis Service Mode: Replicated Replicas: 3 Placement: UpdateConfig: Parallelism: 1 Delay: 10s On failure: pause Monitoring Period: 5s Max failure ratio: 0 Update order: stop-first RollbackConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Rollback order: stop-first ContainerSpec: Image: redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842 Init: false Resources: Endpoint Mode: vip
-
现在更新redis容器镜像。swarm manager将根据updateconfig策略对节点应用进行更新
[root@node1 ~]# docker service update --image redis:3.0.7 redis redis overall progress: 3 out of 3 tasks 1/3: running [==================================================>] 2/3: running [==================================================>] 3/3: running [==================================================>] verify: Service converged
滚动更新步骤
- 停止第一个任务(容器)
- 添加更新调度到此任务
- 启动更新后的容器
- 如果任务执行结果为RUNNING, 等待 delay 设置的时间后开始下一个任务
- 如果有任意一个任务失败,停止此次更新
-
查看更新后的信息
[root@node1 ~]# docker service inspect --pretty redis ID: 50gtthzgzwmqjkpubutfsgnu6 Name: redis Service Mode: Replicated Replicas: 3 Placement: UpdateConfig: Parallelism: 1 Delay: 10s On failure: pause Monitoring Period: 5s Max failure ratio: 0 Update order: stop-first RollbackConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Rollback order: stop-first ContainerSpec: Image: redis:3.0.7@sha256:730b765df9fe96af414da64a2b67f3a5f70b8fd13a31e5096fee4807ed802e20 Init: false Resources: Endpoint Mode: vip
如果显示下面的内容,表示由于更新失败而暂停
$ docker service inspect --pretty redis
ID: 0u6a4s31ybk7yw2wyvtikmu50
Name: redis
...snip...
Update status:
State: paused
Started: 11 seconds ago
Message: update paused due to failure or early termination of task 9p7ith557h8ndf0ui9s0q951b
...snip...
重新启动更新
docker service update redis
-
更新后的状态
[root@node1 ~]# docker service ps redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 2au9etgoryzy redis.1 redis:3.0.7 node1 Running Running 23 minutes ago daxio9w01x6f \_ redis.1 redis:3.0.6 node2 Shutdown Shutdown 22 minutes ago t5na1flecwgb redis.2 redis:3.0.7 node1 Running Running 23 minutes ago ny2ia69mibek \_ redis.2 redis:3.0.6 node2 Shutdown Shutdown 22 minutes ago 355xlpbugpt2 redis.3 redis:3.0.7 node1 Running Running 23 minutes ago 305huk42qp07 \_ redis.3 redis:3.0.6 node1 Shutdown Shutdown 8 hours ago [root@node1 ~]#
更新service
当更新service时,Docker将停止其容器并使用新的配置重新启动它们。
Service configuration details
Configure the runtime environment
可以为容器中的运行环境配置以下选项
--env 环境变量
-workdir 容器内的工作目录
--user 用户名或UID
下面的服务将容器环境变量$MYVAR设置为myvaule,从/tmp/目录运行,并作为root用户运行
[root@node1 ~]# docker service create --name helloworld --env MYVAR=myvalue --workdir /tmp --user root alpine ping docker.com
更新现有service运行的命令
要更新现有服务运行的命令,可以使用——args标志
[root@node1 ~]# docker service update --args "ping baidu.com" helloworld
helloworld
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
[root@node1 ~]#
指定service应该使用的image版本
创建一个service而没有指定要使用的image版本时,该service将使用带有最新标记的版本。可以通过几种不同的方式强制服务使用特定版本的映像。
$ docker service create --name="myservice" ubuntu:16.04
控制service的位置
swarm service提供了几种不同的方式来控制service在不同的节点上的规模和位置
- 可以指定服务需要运行特定数量的副本,还是应该在每个工作节点上全局运行。参考 Replicated and global services
- 可以配置service的CPU或内存需求,而service只在能够满足这些需求的节点上运行。
- Placement constraints (位置约束)允许将service配置为仅在具有特定(任意)元数据的节点上运行,如果不存在适当的节点,则会导致部署失败。
- Placement preferences(位置偏好) 允许对每个节点应用具有范围值的任意标签,使用算法将service的task分散到这些节点上。目前唯一支持的算法是spread,它试图将task均匀地放置。例如,如果你每个节点标签与标签架有一个值从1到10,然后指定一个位置偏好的机架,然后service task尽可能均匀地放置在所有节点标签架,在其他位置限制,位置偏好,和其他特定于节点的限制。
与约束不同,位置偏好是最佳选择,如果没有节点能够满足该首选项,service不会部署失败。如果为service指定了一个位置偏好,当swarm manager决定哪些节点应该运行service task时,匹配该位置偏好的节点会优先匹配。
Replicated or global services
群集模式有两种类型的服务:复制服务和全局服务。对于复制的服务,可以指定群集管理器要调度到可用节点上的复制任务的数量。对于全局服务,调度程序在每个可用节点上放置一个任务,以满足服务的位置约束和资源需求。
您可以使用—mode控制服务的类型。默认是复制类型。对于复制的服务,可以指定要使用——replicas启动的复制任务的数量。例如,要启动具有3个复制任务的复制nginx服务:
$ docker service create \
--name my_web \
--replicas 3 \
nginx
要在每个可用节点上启动全局service,请将模式全局传递给docker service create。每当一个新节点可用时,调度程序就在新节点上为全局服务放置一个task。例如,启动一个service,在集群的每个节点上运行alpine:
$ docker service create \
--name myservice \
--mode global \
alpine top
服务约束允许将service部署到满足节点标准的节点上。您可以基于节点属性和元数据或引擎元数据对服务应用约束。有关约束的更多信息,请参阅docker service create CLI reference.
为服务保留内存或cpu
要为服务保留给定数量的内存或cpu数量,请使用--reserve-memory或--reserve-cpu标志。如果没有可用节点能够满足需求(例如,如果您请求4个cpu,而集群中没有节点具有4个cpu),则服务将保持挂起状态,直到有合适的节点可用来运行其任务。
内存不足异常(OOME)
如果服务试图使用超过群集节点可用内存的内存,您可能会遇到内存不足异常(OOME),并且容器(或Docker守护进程)可能被内核OOM杀手杀死。要防止这种情况发生,请确保您的应用程序在内存充足的主机上运行,并了解内存耗尽的风险。
Placement constraints(位置约束)
使用位置约束来控制可以分配给服务的节点。在下面的示例中,service只在标签区域设置为east的节点上运行。如果没有适当标记的节点可用,任务将在Pending中等待,直到它们可用为止。--constraint使用 ==或!=操作符。对于复制的服务,可能所有服务都运行在同一个节点上,或者每个节点只运行一个副本,或者一些节点不运行任何副本。对于全局服务,服务在满足位置约束和资源需求的每个节点上运行。
$ docker service create \
--name my-nginx \
--replicas 5 \
--constraint node.labels.region==east \
nginx
还可以将位置约束、位置偏好和CPU/内存约束一起使用,参考 docker service create CLI reference.
Placement preferences(位置偏好)
由于位置限制限制了服务可以运行的节点,位置首选项尝试以算法的方式将任务放在适当的节点上(目前,仅支持平均分布)。例如,如果为每个节点分配一个机架标签,可以设置一个位置偏好,以便通过值将服务均匀地分布到具有机架标签的节点上。这样,如果您丢失了机架,服务仍然在其他机架上的节点上运行。
位置偏好不是严格执行的。如果没有节点具有在位置偏好中指定的标签,则服务将像未设置首选项一样部署。
对于全局服务,位置偏好将被忽略。
下面的示例设置一个偏好,根据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
缺少或空标签
缺少标签的节点仍然接收任务分配。作为一个组,这些节点接收任务的比例与其他节点相同。在某种意义上,缺少标签与标签上附加空值是一样的。如果服务只在节点上运行,而标签用于spread首选项,则偏好应与约束相结合。
您可以指定多个位置偏好,并按遇到它们的顺序处理它们。下面的示例设置具有多个位置偏好的服务。任务首先分布在各个数据中心上,然后分布在机架上(由各自的标签表示):
$ docker service create \
--replicas 9 \
--name redis_2 \
--placement-pref 'spread=node.labels.datacenter' \
--placement-pref 'spread=node.labels.rack' \
redis:3.0.6
这个图说明了位置偏好是如何工作的
用docker service update更新service时,--placement-pref-add在所有现有的位置偏好之后附加一个新的位置偏好。 --placement-pref-rm删除与参数匹配的位置偏好标签
配置服务的更新
当你创建一个service时,可以指定service滚动更新的方式,
--update-delay 配置更新service task的时间间隔。时间可以用T表示,秒用Ts表示,分钟用Tm表示,小时用Th表示,10m30s表示10分钟30秒
--update-parallelism 调整调度器同时更新任务的最大数量。当对单个任务的更新结束,调度程序才会对另一个任务进行更新,直到所有的任务都更新为止。如果在更新任务期间失败,调度程序将暂停更新。可以使用--update-failure-action 来控制docker service create or docker service update执行失败后的行为
在下面的示例中,调度程序一次最多应用两个副本的更新。当更新后的任务返回运行或失败时,调度程序会等待10秒,然后停止下一个要更新的任务:
$ docker service create \
--replicas 10 \
--name my_web \
--update-delay 10s \
--update-parallelism 2 \
--update-failure-action continue \
alpine
--update-max-failure-ratio 在更新service期间,多少task更新失败后,判定此次更新为失败。比如,--update-max-failure-ratio 0.1 --update-failure-action pause 表示在10%的更新task失败后,更新将暂停。
如果task没有启动,或者在--update-monitor 指定的监视期内停止运行,则认为单个task更新失败。--update-monitor 默认值是30s,这意味着在启动后的前30秒内失败的任务将计入服务更新失败,在此之后的失败将不计算在内。
回滚到服务的前一个版本
如果服务的更新版本没有按预期运行,可以使用 docker service update的--rollback回滚到service的前一个版本。
使用--rollback时可以和--update-delay 0s结合,表示执行回滚时不存在时间间隔
$ docker service update \
--rollback \
--update-delay 0s
my_web
在Docker 17.04或更高版本中,如果服务更新未能部署,可以配置服务自动回滚。
在Docker 17.04或更高版本中,手动回滚是在服务器端而不是客户端处理的.这允许手动启动回滚来遵守新的回滚参数。客户机是版本敏感的,所以它仍然对旧守护进程使用旧方法。(理解不清楚)
更新失败自动回滚
您可以这样配置服务:如果对服务的更新导致重新部署失败,服务可以自动回滚到以前的配置。这有助于保护服务可用性。您可以在服务创建或更新时设置以下一个或多个标志。如果没有设置值,则使用默认值。
参数 | 默认 | 描述 |
---|---|---|
--rollback-delay | 0s | 在回滚一个任务之后,在回滚下一个任务之前需要等待的时间。值0表示在部署第一个回滚任务之后立即回滚第二个任务。 |
--rollback-failure-action | pause | 当任务无法回滚时,[pause]或[continue]回滚其他任务。 |
--rollback-max-failure-ratio | 0 | 在回滚期间容忍的失败率,指定为0到1之间的浮点数。例如,给定5个任务,失败率为0.2可以容忍一个任务无法回滚。值0表示不能容忍任何失败,值1表示可以容忍任意数量的失败。 |
--rollback-monitor | 5s | 每次任务回滚后监视期的持续时间。如果任务在此时间段结束之前停止,则回滚将视为失败。 |
--rollback-parallelism | 1 | 并行回滚的最大任务数。默认情况下,一次回滚一个任务。0将并行回滚所有任务。 |
下面的示例配置一个redis服务,以便在docker服务更新未能部署时自动回滚。两个任务可以并行回滚。在回滚之后,将对任务进行20秒的监视,以确保它们不会退出,并且允许最大故障率为20%。--rollback-delay and --rollback-failure-action使用默认值
$ docker service create --name=my_redis \
--replicas=5 \
--rollback-parallelism=2 \
--rollback-monitor=20s \
--rollback-max-failure-ratio=.2 \
redis:latest
service 访问卷或绑定挂载
为了获得最佳性能和可移植性,应该避免直接将重要数据写入容器的可写层,而是使用数据量或绑定挂载。这一原则也适用于服务。
您可以为swarm中的service创建两种类型的挂载,volume mounts or bind mounts。无论使用哪种类型的挂载,在创建service时使用--mount配置它,或者更新现有的service时使用--mount-add或--mount-rm。如果不指定类型,则默认为数据卷
数据卷
数据卷是独立于容器而存在的存储。swarm service数据卷的生命周期类似于容器下卷的生命周期。卷比task和service声明周期长,因此它们的删除必须单独管理。可以在部署service之前创建卷,或者如果在调度任务时某个特定主机上不存在卷,则根据service上的卷规范自动创建卷。
service使用已有的数据卷--mount
$ docker service create \
--mount src=<VOLUME-NAME>,dst=<CONTAINER-PATH> \
--name myservice \
<IMAGE>
如果将任务调度到特定主机时,不存在具有相同
$ 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 volume。
Bind mounts
Bind mounts是来自调度程序为task部署容器的主机的文件系统路径。Docker将路径挂载到容器中。在swarm初始化task的容器之前,文件系统路径必须存在。
下面的示例显示绑定挂载语法:
- 挂载读写绑定:
$ 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>
重要提示:绑定挂载虽然很有用,但它们也可能导致问题。在大多数情况下,建议您将应用程序架构设计为不需要从主机挂载路径。主要风险包括:
- 如果将主机路径绑定到service的容器中,则该路径必须存在于集群每个节点上。Docker swarm模式调度程序可以在任何满足资源可用性需求并满足您指定的所有约束和位置偏好的机器上调度容器。
- 如果正在运行的服务容器变得不健康或无法访问,Docker swarm模式调度程序可以在任何时候重新调度它们。
主机绑定挂载不可移植。当使用绑定挂载时,不能保证应用程序在开发中以与在生产中相同的方式运行。
Create services using templates
略
参考
https://docs.docker.com/engine/swarm/services/
https://my.oschina.net/u/915811/blog/1593855
https://www.cnblogs.com/wanghui-garcia/p/10240182.html