https://docs.docker.com/engine/swarm/swarm-tutorial/

1)Getting started with swarm mode

本教程向你介绍Docker Engine Swarm模式的特性。在开始之前,你可能想先熟悉一下关键概念。
本教程通过以下活动指导你:

  • 在集群swarm模式下初始化Docker引擎集群
  • 向集群swarm中添加节点nodes
  • 将应用程序服务services部署到集群swarm中
  • 一旦所有东西都在运行,就开始管理集群

Set up设置

要运行本教程,你需要以下内容:

  • 安装了Docker后,可以通过网络进行通信的三个Linux主机
  • 安装Docker引擎1.12或更高版本
  • 管理机器的IP地址
  • 在主机之间打开端口

Three networked host machines三台联网主机

本教程需要安装了Docker并可以通过网络进行通信的三个Linux主机。它们可以是物理机器、虚拟机、Amazon EC2实例,或者以其他方式托管。你甚至可以在Linux、Mac或Windows主机上使用Docker机器。检查开始-群集为主机的一个可能的设置。

我使用的是virtualBox安装的三台Linux主机,如下图所示:


其中一台机器是manager(称为manager1),其中两台是worker (worker1和worker2)。

注意:你也可以按照教程中的许多步骤来测试单节点群,在这种情况下,你只需要一台主机。多节点命令不起作用,但是你可以初始化集群、创建服务并扩展它们。

这里只是文档,如果想要看在机器上的实现过程,可见本博客的docker swarm 实例

Docker Engine 1.12 or newer

本教程要求在每台主机上安装Docker Engine 1.12或更新的引擎。安装Docker引擎并验证Docker引擎守护进程是否在每台机器上运行。

The IP address of the manager machine 管理主机的IP地址

IP地址必须分配给主机操作系统可用的网络接口。集群中的所有节点都需要在IP地址上连接到管理器。
因为其他节点在其IP地址上与manager节点联系,所以应该使用固定的IP地址。
你可以在Linux或macOS上运行ifconfig来查看可用网络接口的列表。
如果你正在使用Docker Machine,你可以使用docker-machine ls或docker-machine ip <MACHINE-NAME>来得到管理器IP地址,例如:

  1. docker-machine ip manager1

本教程使用manager1: 192.168.99.100。

Open protocols and ports between the hosts在主机之间打开协议和端口

以下端口必须可用。在某些系统上,这些端口默认情况下是打开的。

  • 用于集群管理通信的TCP端口2377
  • 用于节点间通信的TCP和UDP端口7946
  • 用于覆盖网络流量的UDP端口4789

如果你计划使用加密(--opt encryption)创建覆盖网络,还需要确保允许ip protocol 50 (ESP)流量。

2)Create a swarm创建集群

完成教程设置步骤后,就可以创建集群了。确保Docker引擎守护进程在主机上启动。
1.打开终端并ssh到要运行管理器节点的机器中。本教程使用名为manager1的机器。如果你使用Docker Machine,你可以使用以下命令通过SSH连接到它:

  1. $ docker-machine ssh manager1

2.运行下面的命令去创建一个新集群

  1. $ docker swarm init --advertise-addr <MANAGER-IP>

注意:如果你在Mac上使用Docker或者Windows上使用Docker来测试单节点集群,只需运行Docker swarm init,不带参数。在本例中没有必要指定--advertising -addr。要了解更多信息,请参见Use Docker for Mac or Docker for Windows主题。

在该教程中,下面的命令在manager1机器上创建了一个集群:

  1. $ docker swarm init --advertise-addr 192.168.99.100
  2. Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager.
  3.  
  4. To add a worker to this swarm, run the following command:
  5.  
  6. docker swarm join \
  7. --token SWMTKN--49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
  8. 192.168.99.100:
  9.  
  10. To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

--advertise-addr标志将manager节点配置为将其地址发布为192.168.99.100。集群中的其他节点必须能够访问IP地址上的管理器。
输出包括将新节点加入集群的命令。根据--token标志的值,节点将作为管理器或工作者连接。

3.运行docker info查看集群的当前状态:

  1. $ docker info
  2.  
  3. Containers:
  4. Running:
  5. Paused:
  6. Stopped:
  7. ...snip...
  8. Swarm: active
  9. NodeID: dxn1zf6l61qsb1josjja83ngz
  10. Is Manager: true
  11. Managers:
  12. Nodes:
  13. ...snip...

4.运行docker node ls命令查看节点消息:

  1. $ docker node ls
  2.  
  3. ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
  4. dxn1zf6l61qsb1josjja83ngz * manager1 Ready Active Leader

节点ID旁边的*表示你当前正在此节点上连接。
Docker引擎集群模式自动为机器主机名命名节点。本教程将在后面的步骤中介绍其他列。

3)Add nodes to the swarm添加节点到集群中

一旦你已经创建了具有管理节点的集群之后,就可以添加工作节点了。
1.打开终端并ssh到要运行工作节点的机器中。本教程使用名称worker1。
2.运行从Create a swarm教程步骤中生成的docker swarm init输出命令,创建一个连接到现有swarm的工作节点:

  1. $ docker swarm join \
  2. --token SWMTKN--49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
  3. 192.168.99.100:
  4.  
  5. This node joined a swarm as a worker.

如果没有可用的命令,可以在manager节点上运行以下命令来检索worker的join命令:

  1. $ docker swarm join-token worker
  2.  
  3. To add a worker to this swarm, run the following command:
  4.  
  5. docker swarm join \
  6. --token SWMTKN--49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
  7. 192.168.99.100:

3.打开终端并ssh到要运行第二个工作节点的机器中。本教程使用名称worker2。
4.运行从Create a swarm教程步骤中生成的docker swarm init输出命令,创建连接到现有swarm的第二个工作节点:

  1. $ docker swarm join \
  2. --token SWMTKN--49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
  3. 192.168.99.100:
  4.  
  5. This node joined a swarm as a worker.

5.打开终端ssh进入管理节点运行的机器,运行docker node ls命令查看工作节点:

  1. ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
  2. 03g1y59jwfg7cf99w4lt0f662 worker2 Ready Active
  3. 9j68exjopxe7wfl6yuxml7a7j worker1 Ready Active
  4. dxn1zf6l61qsb1josjja83ngz * manager1 Ready Active Leader

MANAGER列标识群中的MANAGER节点。worker1和worker2的MANAGER列中的空状态表示将它们标识为工作节点。
像docker node ls这样的集群管理命令只在管理器节点上工作。

4)Deploy a service to the swarm在集群中部署服务

在创建集群之后,可以将服务部署到集群中。在本教程中,你还添加了工作节点,但这不是部署服务的必要条件。
1.打开终端并ssh到运行管理器节点的机器中。例如,本教程使用名为manager1的机器。
2.运行以下命令:

  1. $ docker service create --replicas --name helloworld alpine ping docker.com
  2.  
  3. 9uk4639qpg7npwf3fn2aasksr
  • docker service create命令创建服务。
  • --name标志将服务命名为helloworld。
  • --replicas标志指定1个正在运行的实例的所需状态。
  • alpine ping docker.com参数将服务定义为一个alpine Linux容器,它执行ping docker.com命令。

3.运行docker service ls,查看正在运行的服务列表:

  1. $ docker service ls
  2.  
  3. ID NAME SCALE IMAGE COMMAND
  4. 9uk4639qpg7n helloworld / alpine ping docker.com

5)Inspect a service on the swarm检查集群中的服务

在集群中部署服务后,可以使用Docker CLI查看集群中运行的服务的详细信息。
1.如果还没有,那么打开终端并ssh到运行manager节点的机器中。例如,本教程使用名为manager1的机器。
2.运行docker service inspect --pretty <SERVICE-ID>,以一种易于阅读的格式显示关于服务的详细信息。
为了查看helloworld服务的详情:

  1. [manager1]$ docker service inspect --pretty helloworld
  2.  
  3. ID: 9uk4639qpg7npwf3fn2aasksr
  4. Name: helloworld
  5. Service Mode: REPLICATED
  6. Replicas:
  7. Placement:
  8. UpdateConfig:
  9. Parallelism:
  10. ContainerSpec:
  11. Image: alpine
  12. Args: ping docker.com
  13. Resources:
  14. Endpoint Mode: vip

提示:要以json格式返回服务细节,请运行相同的命令,但不要使--pretty标志。

  1. [manager1]$ docker service inspect helloworld
  2. [
  3. {
  4. "ID": "9uk4639qpg7npwf3fn2aasksr",
  5. "Version": {
  6. "Index":
  7. },
  8. "CreatedAt": "2016-06-16T21:57:11.622222327Z",
  9. "UpdatedAt": "2016-06-16T21:57:11.622222327Z",
  10. "Spec": {
  11. "Name": "helloworld",
  12. "TaskTemplate": {
  13. "ContainerSpec": {
  14. "Image": "alpine",
  15. "Args": [
  16. "ping",
  17. "docker.com"
  18. ]
  19. },
  20. "Resources": {
  21. "Limits": {},
  22. "Reservations": {}
  23. },
  24. "RestartPolicy": {
  25. "Condition": "any",
  26. "MaxAttempts":
  27. },
  28. "Placement": {}
  29. },
  30. "Mode": {
  31. "Replicated": {
  32. "Replicas":
  33. }
  34. },
  35. "UpdateConfig": {
  36. "Parallelism":
  37. },
  38. "EndpointSpec": {
  39. "Mode": "vip"
  40. }
  41. },
  42. "Endpoint": {
  43. "Spec": {}
  44. }
  45. }
  46. ]

3.运行docker service ps <SERVICE-ID>去查看是那个节点正在运行服务:

  1. [manager1]$ docker service ps helloworld
  2.  
  3. NAME IMAGE NODE DESIRED STATE LAST STATE
  4. helloworld..8p1vev3fq5zm0mi8g0as41w35 alpine worker2 Running Running minutes

在这种情况下,helloworld服务的一个实例在worker2节点上运行。你可能会看到服务在manager节点上运行。默认情况下,集群中的管理节点可以像工作节点一样执行任务。
Swarm还向你显示服务任务的DESIRED STATE和LAST STATE,这样你就可以看到任务是否根据服务定义运行。
4.在任务运行的节点上运行docker ps,以查看关于任务容器的详细信息。

提示:如果helloworld运行在管理器节点以外的节点上,则必须ssh到该节点。

  1. [worker2]$docker ps
  2.  
  3. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  4. e609dde94e47 alpine:latest "ping docker.com" minutes ago Up minutes helloworld..8p1vev3fq5zm0mi8g0as41w35

6)Scale the service in the swarm在集群中扩展服务

一旦将服务部署到集群中,就可以使用Docker CLI来扩展服务中的容器数量。在服务中运行的容器称为“任务tasks”。
1如果还没有,那么打开终端并ssh到运行manager节点的机器中。例如,本教程使用名为manager1的机器。
2.运行以下命令来更改群集中运行的服务的期望状态:

  1. $ docker service scale <SERVICE-ID>=<NUMBER-OF-TASKS>

例如:

  1. $ docker service scale helloworld=
  2.  
  3. helloworld scaled to

3.运行命令去查看更新的任务列表:

  1. $ docker service ps helloworld
  2.  
  3. NAME IMAGE NODE DESIRED STATE CURRENT STATE
  4. helloworld..8p1vev3fq5zm0mi8g0as41w35 alpine worker2 Running Running minutes
  5. helloworld..c7a7tcdq5s0uk3qr88mf8xco6 alpine worker1 Running Running seconds
  6. helloworld..6crl09vdcalvtfehfh69ogfb1 alpine worker1 Running Running seconds
  7. helloworld..auky6trawmdlcne8ad8phb0f1 alpine manager1 Running Running seconds
  8. helloworld..ba19kca06l18zujfwxyc5lkyn alpine worker2 Running Running seconds

你可以看到swarm创建了4个新任务,以扩展到总共5个Alpine Linux运行实例。这些任务分布在群体的三个节点之间。一个在manager1上运行。
4.运行docker ps查看连接节点上运行的容器。下面的例子展示了在manager1上运行的任务:

  1. $ docker ps
  2.  
  3. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  4. 528d68040f95 alpine:latest "ping docker.com" About a minute ago Up About a minute helloworld..auky6trawmdlcne8ad8phb0f1

如果希望看到容器在其他节点上运行的信息,请将ssh导入这些节点并运行docker ps命令。

7)Delete the service running on the swarm 删除运行在集群中的服务

本教程的其余步骤不使用helloworld服务,因此现在可以从集群中删除该服务。
1.如果还没有,那么打开终端并ssh到运行manager节点的机器中。例如,本教程使用名为manager1的机器。
2.运行docker service rm helloworld来删除helloworld服务。

  1. $ docker service rm helloworld
  2.  
  3. helloworld

3.运行docker service inspect <SERVICE-ID>去检查移除了服务的管理机。CLI返回服务找不到的信息:

  1. $ docker service inspect helloworld
  2. []
  3. Error: no such service: helloworld

4.即使服务不再存在,任务task容器还需要一点时间去清除。你可以在节点中使用docker ps去核查什么时候任务被移除:

  1. $ docker ps
  2.  
  3. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  4. db1651f50347 alpine:latest "ping docker.com" minutes ago Up seconds helloworld..9lkmos2beppihw95vdwxy1j3w
  5. 43bf6e532a92 alpine:latest "ping docker.com" minutes ago Up seconds helloworld..a71i8rp6fua79ad43ycocl4t2
  6. 5a0fb65d8fa7 alpine:latest "ping docker.com" minutes ago Up seconds helloworld..2jpgensh7d935qdc857pxulfr
  7. afb0ba67076f alpine:latest "ping docker.com" minutes ago Up seconds helloworld..1c47o7tluz7drve4vkm2m5olx
  8. 688172d3bfaa alpine:latest "ping docker.com" minutes ago Up About a minute helloworld..74nbhb3fhud8jfrhigd7s29we
  9.  
  10. $ docker ps
  11. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS

8)Apply rolling updates to a service对服务应用滚动更新

在本教程的前一步中,你扩展了服务实例的数量。在本教程的这一部分中,你将部署一个基于Redis 3.0.6容器镜像的服务。然后使用滚动更新将服务升级为使用Redis 3.0.7容器镜像。
1.如果还没有,那么打开终端并ssh到运行manager节点的机器中。例如,本教程使用名为manager1的机器。
2.将Redis 3.0.6部署到集群中,并将集群配置为10秒更新延迟:

  1. $ docker service create \
  2. --replicas \
  3. --name redis \
  4. --update-delay 10s \
  5. redis:3.0.
  6.  
  7. 0u6a4s31ybk7yw2wyvtikmu50

在服务部署时配置滚动更新策略。
 --update-delay标志配置服务任务或任务集更新之间的时间延迟。你可以将时间T描述为Ts秒数、Tm分钟数或Th小时数的组合。所以10m30s表示10分30秒的延迟。
默认情况下,调度程序每次更新一个任务。你可以传--update-parallelism标志来配置调度程序同时更新的服务任务的最大数量。
默认情况下,当对单个任务的更新返回一个 RUNNING的状态时,调度器将调度另一个任务进行更新,直到所有任务都被更新。如果在更新期间某个任务返回 FAILED,调度程序将暂停更新。你可以使用docker service create或docker service update的--update-failure-action标志来控制该行为。

3.查看redis服务:

  1. $ docker service inspect --pretty redis
  2.  
  3. ID: 0u6a4s31ybk7yw2wyvtikmu50
  4. Name: redis
  5. Service Mode: Replicated
  6. Replicas:
  7. Placement:
  8. Strategy: Spread
  9. UpdateConfig:
  10. Parallelism:
  11. Delay: 10s
  12. ContainerSpec:
  13. Image: redis:3.0.
  14. Resources:
  15. Endpoint Mode: vip

4.现在可以为redis更新容器镜像。集群管理器根据UpdateConfig策略对节点进行更新:

  1. $ docker service update --image redis:3.0. redis
  2. redis

调度程序在默认情况下应用滚动更新如下:

  • 停止第一个任务。
  • 为已停止的任务安排更新。
  • 启动更新任务的容器。
  • 如果某个任务的更新返回RUNNING,则等待指定的延迟期,然后启动下一个任务。
  • 如果更新期间某个任务返回FAILED,则暂停更新。

5.运行docker service inspect --pretty redis看到的新镜像在所需的状态的信息:

  1. $ docker service inspect --pretty redis
  2.  
  3. ID: 0u6a4s31ybk7yw2wyvtikmu50
  4. Name: redis
  5. Service Mode: Replicated
  6. Replicas:
  7. Placement:
  8. Strategy: Spread
  9. UpdateConfig:
  10. Parallelism:
  11. Delay: 10s
  12. ContainerSpec:
  13. Image: redis:3.0.
  14. Resources:
  15. Endpoint Mode: vip

service inspect的输出显示你的更新暂停是否是因为失败:

  1. $ docker service inspect --pretty redis
  2.  
  3. ID: 0u6a4s31ybk7yw2wyvtikmu50
  4. Name: redis
  5. ...snip...
  6. Update status:
  7. State: paused
  8. Started: seconds ago
  9. Message: update paused due to failure or early termination of task 9p7ith557h8ndf0ui9s0q951b
  10. ...snip...

运行docker service update <SERVICE-ID>命令去重启一个暂停的更新。比如:

  1. docker service update redis

为了避免重复某些更新失误,你可能需要通过传递标志到docker service update去重新配置服务

6.运行docker service ps <SERVICE-ID>命令去查看回滚更新:

  1. $ docker service ps redis
  2.  
  3. NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
  4. redis..dos1zffgeofhagnve8w864fco redis:3.0. worker1 Running Running seconds
  5. \_ redis..88rdo6pa52ki8oqx6dogf04fh redis:3.0. worker2 Shutdown Shutdown seconds ago
  6. redis..9l3i4j85517skba5o7tn5m8g0 redis:3.0. worker2 Running Running About a minute
  7. \_ redis..66k185wilg8ele7ntu8f6nj6i redis:3.0. worker1 Shutdown Shutdown minutes ago
  8. redis..egiuiqpzrdbxks3wxgn8qib1g redis:3.0. worker1 Running Running seconds
  9. \_ redis..ctzktfddb2tepkr45qcmqln04 redis:3.0. mmanager1 Shutdown Shutdown minutes ago

在Swarm更新所有的任务之前,你可以看到一些在运行redis:3.0.6,而另一些在运行redis:3.0.7。上面的输出显示了滚动更新完成后的状态。

9)Drain a node on the swarm

在本教程的前面步骤中,所有节点都以ACTIVE可用性运行。集群管理器可以将任务分配给任何ACTIVE节点,因此到目前为止,所有节点都可以接收任务。
有时,例如计划的维护时间,你需要设置一个节点来DRAIN(耗尽)可用性。DRAIN可用性阻止节点从集群管理器接收新任务。它还意味着管理器停止节点上运行的任务,并在具有ACTIVE可用性的节点上启动副本任务。

重要提示:将节点设置为DRAIN并不会从该节点删除独立容器,例如使用docker run、docker- composition或docker Engine API创建的容器。节点的状态(包括DRAIN)只影响节点调度集群服务工作负载的能力。

1.如果还没有,那么打开终端并ssh到运行manager节点的机器中。例如,本教程使用名为manager1的机器。
2.验证所有节点的AVAILABILITY都是Active:

  1. $ docker node ls
  2.  
  3. ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
  4. 1bcef6utixb0l0ca7gxuivsj0 worker2 Ready Active
  5. 38ciaotwjuritcdtn9npbnkuz worker1 Ready Active
  6. e216jshn25ckzbvmwlnh5jr3g * manager1 Ready Active Leader

3.如果你还没有在rolling update教程中运行redis,那就现在开始:

  1. $ docker service create --replicas --name redis --update-delay 10s redis:3.0.
  2.  
  3. c5uo6kdmzpon37mgj9mwglcfw

4.运行docker service ps redis去查看swarm管理器如何分配任务给不同的节点:

  1. $ docker service ps redis
  2.  
  3. NAME IMAGE NODE DESIRED STATE CURRENT STATE
  4. redis..7q92v0nr1hcgts2amcjyqg3pq redis:3.0. manager1 Running Running seconds
  5. redis..7h2l8h3q3wqy5f66hlv9ddmi6 redis:3.0. worker1 Running Running seconds
  6. redis..9bg7cezvedmkgg6c8yzvbhwsd redis:3.0. worker2 Running Running seconds

在这种情况下,集群管理器将一个任务分配给每个节点。你可能会看到任务在你的环境中的节点之间以不同的方式分布。

5.运行docker node update --availability drain <NODE-ID>命令去耗尽一个有任务分配的节点:

  1. docker node update --availability drain worker1
  2.  
  3. worker1

6.查看节点去检查它的可用性:

  1. $ docker node inspect --pretty worker1
  2.  
  3. ID: 38ciaotwjuritcdtn9npbnkuz
  4. Hostname: worker1
  5. Status:
  6. State: Ready
  7. Availability: Drain
  8. ...snip...

耗尽的节点显示其AVAILABILITY属性为Drain

7.运行docker service ps redis命令去看swarm管理器是如何为redis服务更新任务分配的:

  1. $ docker service ps redis
  2.  
  3. NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR
  4. redis..7q92v0nr1hcgts2amcjyqg3pq redis:3.0. manager1 Running Running minutes
  5. redis..b4hovzed7id8irg1to42egue8 redis:3.0. worker2 Running Running About a minute
  6. \_ redis..7h2l8h3q3wqy5f66hlv9ddmi6 redis:3.0. worker1 Shutdown Shutdown minutes ago
  7. redis..9bg7cezvedmkgg6c8yzvbhwsd redis:3.0. worker2 Running Running minutes

群管理器通过在节点上以Drain可用性结束任务并在具有Active可用性的节点上创建新任务来维护所需的状态。

8.运行docker node update --availability active <NODE-ID>去将耗尽节点返回活跃状态:

  1. $ docker node update --availability active worker1
  2.  
  3. worker1

9.查看节点去看更新状态:

  1. $ docker node inspect --pretty worker1
  2.  
  3. ID: 38ciaotwjuritcdtn9npbnkuz
  4. Hostname: worker1
  5. Status:
  6. State: Ready
  7. Availability: Active
  8. ...snip...

当你将节点设置回Active可用性时,当下面的状况发生时,它就可以接收新任务了:

  • 在服务更新期间进行扩展
  • 在滚动更新期间
  • 当你设置另一个节点以Drain可用性时
  • 当另一个活动节点上的任务失败时

10)Use swarm mode routing mesh使用集群模式路由网格

Docker Engine swarm模式使发布服务端口变得很容易,从而使服务端口对集群之外的资源可用。所有节点都参与一个ingress路由网格。路由网格允许集群中的每个节点接受集群中运行的任何服务的已发布端口上的连接,即使节点上没有运行任务。路由网格将所有传入的请求路由到可用节点上的已发布端口到活跃容器。
要在集群中使用入口网络,在启用群模式之前,需要在群节点之间打开以下端口:

  • 用于容器网络发现的端口7946 TCP/UDP。
  • 用于容器入口网络的端口4789 UDP。

你还必须在集群节点和任何外部资源(如外部负载平衡器)之间打开已发布的端口,这些外部资源需要访问该端口。
你还可以绕过给定服务的路由网格。

Publish a port for a service为服务发布端口

创建服务时,使用--publish标志发布端口。target用于指定容器内的端口,published用于指定要在路由网格上绑定的端口。如果不使用已发布的端口,则为每个服务任务绑定一个随机的高编号端口。你需要检查任务以确定端口。

  1. $ docker service create \
  2. --name <SERVICE-NAME> \
  3. --publish published=<PUBLISHED-PORT>,target=<CONTAINER-PORT> \
  4. <IMAGE>

注意:这种语法的旧形式是冒号分隔的字符串,其中发布的端口是第一个,目标端口是第二个,例如-p 8080:80。新的语法是首选的,因为它更容易阅读,并允许更多的灵活性。

<PUBLISHED-PORT>是集群提供服务的端口。如果省略它,则会绑定一个随机的高编号端口。<CONTAINER-PORT>是容器监听的端口。此参数是必需的。
例如,下面的命令将nginx容器中的端口80发布到集群中任意节点的端口8080:

  1. $ docker service create \
  2. --name my-web \
  3. --publish published=,target= \
  4. --replicas \
  5. nginx

当你访问任何节点上的端口8080时,Docker将你的请求路由到活跃容器。在集群节点本身上,端口8080实际上可能没有被绑定,但是路由网格知道如何路由流量并防止任何端口冲突的发生。
路由网格监听发布端口上分配给节点的任何IP地址。对于外部可路由的IP地址,端口可以从主机外部获得。对于所有其他IP地址,只能从主机内部访问。

从上面的图可以看出来,当从外部访问192.168.99.100:8080、192.168.99.101:8080或192.168.99.101:8080其中之一的服务时,其实会通过swarm的负载均衡去调用对应的10.0.0.1:80或10.0.0.2:80之一的容器

你可以使用下面的命令去为存在的服务发布节点:

  1. $ docker service update \
  2. --publish-add published=<PUBLISHED-PORT>,target=<CONTAINER-PORT> \
  3. <SERVICE>

你可以使用docker service inspect命令去查看服务的发布端口。比如:

  1. $ docker service inspect --format="{{json .Endpoint.Spec.Ports}}" my-web
  2.  
  3. [{"Protocol":"tcp","TargetPort":,"PublishedPort":}]

输出显示来自容器的<CONTAINER-PORT>(标记为TargetPort)和节点侦听服务请求的<PUBLISHED-PORT>(标记为PublishedPort)。

Publish a port for TCP only or UDP only 仅发布TCP端口或UDP端口

默认情况下,当你发布端口时,它是TCP端口。你可以专门发布UDP端口,而不是TCP端口,或者在TCP端口之外发布。当你同时发布TCP和UDP端口时,如果你省略了protocol说明符,则该端口将作为TCP端口发布。如果使用较长的语法(建议使用Docker 1.13或更高版本),则将protocol密钥设置为tcp或udp。

TCP ONLY

长语法:

  1. $ docker service create --name dns-cache \
  2. --publish published=,target= \
  3. dns-cache

短语法:

  1. $ docker service create --name dns-cache \
  2. -p : \
  3. dns-cache

TCP AND UDP

长语法:

  1. $ docker service create --name dns-cache \
  2. --publish published=,target= \
  3. --publish published=,target=,protocol=udp \
  4. dns-cache

短语法:

  1. $ docker service create --name dns-cache \
  2. -p : \
  3. -p :/udp \
  4. dns-cache

UDP ONLY

长语法:

  1. $ docker service create --name dns-cache \
  2. --publish published=,target=,protocol=udp \
  3. dns-cache

短语法:

  1. $ docker service create --name dns-cache \
  2. -p :/udp \
  3. dns-cache

Bypass the routing mesh绕过路由网格

你可以绕过路由网格,以便在访问给定节点上的绑定端口时,你总是在访问该节点上运行的服务的实例。这称为host模式。有几件事要记住。
如果你访问的节点不运行服务任务,则该服务不会监听该端口。可能没有什么在监听,或者是一个完全不同的应用程序在监听。
如果希望在每个节点上运行多个服务任务(例如有5个节点但运行10个副本),则无法指定静态目标端口。要么允许Docker分配一个随机的高编号端口(通过删除已发布的端口),要么通过使用全局服务而不是副本服务,或者通过使用位置约束,确保在给定的节点上只运行一个服务实例。
要绕过路由网格,必须使用长 --publish服务并将mode设置为host。如果省略mode键或将其设置为ingress,则使用路由网格。下面的命令使用host主机模式并绕过路由网格创建全局服务。

  1. $ docker service create --name dns-cache \
  2. --publish published=,target=,protocol=udp,mode=host \
  3. --mode global \
  4. dns-cache

总结:使用路由网络就是不管你的节点上是否运行了某个任务,是否监听着端口80,你这个节点都会去接受集群中发布的连接;而绕过路由网络就是如果你的节点上没有运行某个任务,那么你就不会去接受集群中发布的连接,只有有这个任务的节点才接受

Configure an external load balancer配置一个外部负载均衡

你可以为集群服务配置外部负载平衡器,可以与路由网格结合使用,也可以完全不使用路由网格。

Using the routing mesh使用路由网格

你可以配置外部负载均衡器来将请求路由到集群服务。例如,你可以配置HAProxy来平衡对发布到端口8080的nginx服务的请求。

在这种情况下,负载均衡器和集群中的节点之间的端口8080必须打开。集群节点可以驻留在代理服务器可以访问的私有网络上,但不能公开访问。
你可以配置负载均衡器来平衡集群中每个节点之间的请求,即使节点上没有调度任务。例如,你可以在/etc/haproxy/haproxy.cfg中配置以下HAProxy:

  1. global
  2. log /dev/log local0
  3. log /dev/log local1 notice
  4. ...snip...
  5.  
  6. # Configure HAProxy to listen on port
  7. frontend http_front
  8. bind *:
  9. stats uri /haproxy?stats
  10. default_backend http_back
  11.  
  12. # Configure HAProxy to route requests to swarm nodes on port
  13. backend http_back
  14. balance roundrobin
  15. server node1 192.168.99.100: check
  16. server node2 192.168.99.101: check
  17. server node3 192.168.99.102: check

当你访问端口80上的HAProxy负载均衡器时,它将请求转发给集群中的节点。集群路由网格将请求路由到一个活动任务。如果由于任何原因,集群调度器将任务分派到不同的节点,则不需要重新配置负载均衡器。
你可以配置任何类型的负载均衡器来将请求路由到集群节点。要了解更多关于HAProxy的信息,请参阅HAProxy文档HAProxy documentation

Without the routing mesh

若要在没有路由网格的情况下使用外部负载均衡器,请将--endpoint-mode设置为dnsrr,而不是vip的默认值。在这种情况下,没有一个虚拟IP。相反,Docker为服务设置DNS条目,以便服务名称的DNS查询返回一个IP地址列表,客户端直接连接到其中之一。你负责向负载均衡器提供IP地址和端口的列表。更多信息参见配置服务发现 Configure service discovery

docker swarm英文文档学习-3-开始的更多相关文章

  1. docker swarm英文文档学习-11-上锁你的集群来保护你的加密密钥

    Lock your swarm to protect its encryption key上锁你的集群来保护你的加密密钥 在Docker 1.13及更高版本中,默认情况下,群管理器使用的Raft日志在 ...

  2. docker swarm英文文档学习-12-在集群模式中的Raft共识

    Raft consensus in swarm mode 在集群模式中的Raft共识 当Docker引擎在集群模式下运行时,manager节点实现Raft 共识算法来管理全局集群状态.Docker s ...

  3. docker swarm英文文档学习-10-使用Docker密钥管理敏感数据

    Manage sensitive data with Docker secrets使用Docker secrets管理敏感数据 About secrets 对于Docker Swarm服务来说,sec ...

  4. docker swarm英文文档学习-6-添加节点到集群

    Join nodes to a swarm添加节点到集群 当你第一次创建集群时,你将单个Docker引擎置于集群模式中.为了充分利用群体模式,可以在集群中添加节点: 添加工作节点可以增加容量.当你将服 ...

  5. docker swarm英文文档学习-7-在集群中管理节点

    Manage nodes in a swarm在集群中管理节点 List nodes列举节点 为了查看集群中的节点列表,可以在管理节点中运行docker node ls: $ docker node ...

  6. docker swarm英文文档学习-4-swarm模式如何运行

    1)How nodes work Docker引擎1.12引入了集群模式,使你能够创建一个由一个或多个Docker引擎组成的集群,称为集群.集群由一个或多个节点组成:在群模式下运行Docker引擎1. ...

  7. docker swarm英文文档学习-5-在swarm模式中运行Docker引擎

    Run Docker Engine in swarm mode在swarm模式中运行Docker引擎 当你第一次安装并开始使用Docker引擎时,默认情况下禁用swarm模式.在启用集群模式时,需要处 ...

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

    Deploy services to a swarm在集群中部署服务 集群服务使用声明式模型,这意味着你需要定义服务的所需状态,并依赖Docker来维护该状态.该状态包括以下信息(但不限于): 应该运 ...

  9. docker swarm英文文档学习-9-使用Docker Configs存储配置数据

    Store configuration data using Docker Configs 使用Docker Configs存储配置数据 Docker 17.06引入了集群服务配置,允许你在服务镜像或 ...

随机推荐

  1. Ubuntu安装完成后设置root密码

    安装完ubuntu后没有默认的root密码,如果要设置root密码需要进行如下步骤: 1 sudo passwd 2 连续输入两次新密码

  2. 我是菜鸟,我怕谁(hdu2520)

    我是菜鸟,我怕谁 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  3. openstack-on-centos7之各组件服务

    认证服务keystone(安装和配置) 在配置 OpenStack 身份认证服务前,必须创建一个数据库和管理员令牌 [用数据库连接客户端以root用户连接到数据库服务] # mysql -u root ...

  4. SD从零开始59-61,跨公司的库存转移,Interface 修改,可用性检查和需求传递

    [原创]SD从零开始59 跨公司的库存转移处理流程 库存转移流程Stock Transfer Procedure 2个工厂间的库存转移能够使用不同的流程来执行: 只执行一个库存转移记账的流程使用MM库 ...

  5. Android--播放Gif的取巧办法

    由于做的项目,要有个动画的等待效果,第一时间想到的就是Gif(懒,省事),但是试了好多据说能播放Gif的控件,也写过,但是放到魅族手机上就是不能播放,所有就想了个招,既然Gif能在浏览器上播放,那an ...

  6. Expo大作战(十六)--expo结合firebase 一个nosql数据库(本章令我惊讶但又失望!)

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  7. eclipse中如何使用struts2

    简介 这篇文章主要讲如何在eclipse中使用struts2,文章使用的struts2的版本是2.5.2,会与其他的版本有一小点的差别,文章里已经说明.例子的完整源码在文末,亲测没有任何错误. str ...

  8. C# 获得目录下所有文件或指定文件类型文件(包含所有子文件夹)

    public partial class FileGet { /// <summary> /// 私有变量 /// </summary> private static List ...

  9. 【转】C++11的enum class & enum struct和enum

    转自:https://blog.csdn.net/sanoseiichirou/article/details/50180533 C++标准文档——n2347(学习笔记) 链接:http://www. ...

  10. 【Python】定时调度

    from datetime import datetime from apscheduler.schedulers.blocking import BlockingScheduler def tick ...