管理swarm(13) – 节点介绍

从Docker Engine 1.12版本起开始引进swarm模式来创建一个或多个Docker Engines的集群,称为swarm。一个swarm包含一个或多个节点:运行在Docker Engine1.12或更高版本的swarm模式下的物理的或虚拟的机器。
有两种类型的节点:managers和workers。
虚拟化技术

Manager节点

manager节点处理集群管理任务:

  • 维护集群状态
  • 调度服务
  • 提高swarm模式的HTTP API服务
  • swarm管理器使用Raft来实现维护整个swarm集群一致的内部状态。如果是测试的目的可以只运行一个swarm管理节点。如果单管理器的swarm出问题下线了,服务仍然会运行,不过你需要创建一个新的集群来恢复它。
    要利用swarm模式的容错功能,Docker建议根据你对高可用的要求来创建奇数的管理节点。当你有多个管理节点时,可以不用停机从故障的管理节点中恢复。

  • 三个管理节点的swarm最大允许一个管理节点宕机
  • 五个管理节点的swarm最大允许两个管理节点宕机
  • N个管理节点的swarm最大允许(N-1)/2个管理节点宕机
  • Docker推荐最多创建7个管理节点
  • Worker节点

    Worker节点是Docker Engine的实例,其唯一目的是运行容器。Worker节点不参与Raft分布状态,作调度的决定或提供swam模式的HTTP API服务。
    你可以创建单个管理节点的swarm,不过你不能只有一个Worker节点而没有管理节点。默认情况下,所有的管理节点也是Worker节点。在单管理节点的集群中,你可以运行命令如docker service create,然后调度器会把所有的任务放到本地执行。
    如果你想阻止调度器把任务分配到多个节点的集群的管理节点上,你可以设置管理节点的状态为Drain。调度器就不会继续把任务分发这些节点上执行。

    改变角色

    你可以通过执行docker node promote来把一个worker节点提升为管理节点。例如,你当你的管理节点下线时你可能会想把worker节点提升为管理节点。

    管理swarm(12) – swarm实践 –使用swarm模式的routing mesh路由请求

    Docker Engine的swarm模式使得服务发布端口让服务在swarm外部可用变得容易。所以的节点都参与到routing mesh中,意味着任何的节点(即使该节点没有服务在运行)都可以作为入口,都能路由请求。
    为了能在swarm中使用ingress网络,你需要在节点之间开放如下端口:

  • TCP/UDP端口7946 – 用来发现容器网络
  • UDP端口4789 – 容器ingress网络
  • 当然你也必须在swarm节点之间和做任意外部资源(如外部负载均衡)之间开放published端口。

    发布服务端口

    在创建服务时使用–publish参数来发布一个端口:

    1. $ docker service create
    2.   –name <SERVICE-NAME>
    3.   –publish <PUBLISHED-PORT>:<TARGET-PORT>
    4.   <IMAGE>

    是容器内监听的端口。是对外发布的端口,外部通过此端口能访问到容器内的应用程序。
    例如,以下的命令是发布nginx容器内的80端口到swarm所有节点的8080端口:

    1. $ docker service create
    2.   –name my-web
    3.   –publish 8080:80
    4.   –replicas 2
    5.   nginx

    当你访问任意节点的8080端口,swarm的负载均衡会把你的请求路由到一个任意节点的可用的容器上。routing mesh在swarm节点的所有IP上监听published端口。
    虚拟化技术
    你可以使用以下命令来为已存在的服务发布一个端口:

    1. $ docker service update
    2.   –publish-add <PUBLISHED-PORT>:<TARGET-PORT>
    3.   <SERVICE>

    使用docker service inspect来查看服务的published端口。如:

    1. $ docker service inspect –format="" my-web
    2.  
    3. [{"Protocol":"tcp","TargetPort":80,"PublishedPort":8080}]

    发布一个TCP端口或UDP端口

    默认情况下,以上发布的端口都是TCP端口。你可以指定发布一个UDP端口。当你TCP和UDP两个端口都发布时,Docker 1.12.2及更早版本要求你为TCP端口添加/tcp后缀。

    只发布TCP端口

    下面的两个命令是一样的。

    1. $ docker service create –name dns-cache -p 53:53 dns-cache
    2.  
    3. $ docker service create –name dns-cache -p 53:53/tcp dns-cache

    发布TCP和UDP端口

    1. $ docker service create –name dns-cache -p 53:53/tcp -p 53:53/udp dns-cache

    只发布UDP端口

    1. $ docker service create –name dns-cache -p 53:53/udp dns-cache

    配置一个外部负载均衡

    你可以配置一个外部负载均衡来路由请求到swarm服务。例如,你可以配置HAProxy来路由请求到一个published端口为8080的nginx服务。
    虚拟化技术
    在这个示例中,在负载均衡和所有swarm节点之间需要开放8080端口。
    你可以配置负载均衡负载请求到swarm的任何节点。例如HAProxy的配置文件/etc/haproxy/haproxy.cfg:

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

    当你访问HAProxy负载均衡的80端口时,它会把你的请求转发到swarm节点。然后swarm节点的routing mesh把请求路由到一个可用的服务上。

    管理swarm(11) – swarm实践 –下线节点

    在之前的章节,所以的节点状态都为ACTIVE了。swarm管理器能分配任务到任何ACTIVE的节点,所以目前为止所有的节点都可以接收任务。
    不过有时候如维护期间,你需要设置一个节点为DRAIN状态,也就是下线节点。DRAIN状态的节点不再接受来自swarm管理器发来的新任务。也意味着管理器停止DRAIN状态节点的任务然后再在ACTIVE节点上新起一个副本任务来替代之前的任务。
    1.登录manager1机器。
    2.查看目前所有的节点都为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.如果你没有运行之前滚动更新的步骤,那么先执行如下命令创建redis服务:

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

    4.执行docker service ps redis查看swarm管理器把任务分配到了哪些节点:

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

    在这个示例中,swarm管理器为每个节点分配一个任务。
    5.执行docker node update –availability drain 来下线一个节点:

    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…

    下线的节点显示Drain状态。
    7.执行docker service ps redis来查看swarm管理器是如何重新分配redis任务到其它可用节点的:

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

    swarm管理器停止已下线节点的redis任务并在其它Active节点创建一个新任务来维持设定redis副本数。
    8.执行docker node update –availability active 来上线已下线的节点:

    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状态时
  • 当一个任务在另一个Active节点失败时
  • 管理swarm(10) – swarm实践 – 滚动更新服务

    在上一篇文章中你更新了服务的实例数。在本文中,我们尝试部署一个Redis 3.0.6的容器服务。然后使用滚动更新把它升级到Redis 3.0.7。
    1.登录manger1机器。
    2.部署Redis 3.0.6到swarm和配置swarm为10秒更新延迟:

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

    在服务部署时你配置了滚动更新策略。
    –update-delay参数配置更新服务任务之间的延迟时间或一组任务之间的延迟时间。你可以以秒s,分m,时h单位来配置延迟时间。所以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. Mode:           Replicated
    6.  Replicas:      3
    7. Placement:
    8.  Strategy:      Spread
    9. UpdateConfig:
    10.  Parallelism:   1
    11.  Delay:         10s
    12. ContainerSpec:
    13.  Image:         redis:3.0.6
    14. Resources:

    4.现在开始更新redis容器。swarm管理器根据UpdateConfig策略来对节点应用更新:

    1. $ docker service update –image redis:3.0.7 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. Mode:           Replicated
    6.  Replicas:      3
    7. Placement:
    8.  Strategy:      Spread
    9. UpdateConfig:
    10.  Parallelism:   1
    11.  Delay:         10s
    12. ContainerSpec:
    13.  Image:         redis:3.0.7
    14. Resources:

    如果更新暂时,下面是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:    11 seconds ago
    9.  Message:    update paused due to failure or early termination of task 9p7ith557h8ndf0ui9s0q951b
    10. …snip…

    执行docker service update 命令来重启已暂停的更新,例如:

    1. docker service update redis

    6.执行docker service ps 来查看滚动更新:

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

    在swarm更新完所有的任务前,你会看到有些节点运行着redis:3.0.6,而有些运行redis:3.0.7。

    管理swarm(9) – swarm实践 – 删除服务

    1.登录manager1机器。
    2.执行docker service rm helloworld来删除helloworld服务。

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

    3.执行docker service inspect 命令来验证swarm管理器是否已经把服务删除了。CLI会返回提示服务不存在:

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

    管理swarm(8) – swarm实践 – 调节服务副本数

    本文介绍如何调节服务副本数。
    1.登录manager1机器。
    2.执行如下命令来设置指定服务的副本数:

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

    例如:

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

    3.执行docker service ps 查看更新的任务列表:

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

    你可以看到swarm已经创建了4个新任务来把Alpline Linux实例缩放到5个。这些任务分布到swarm中的三个节点。其中一个运行在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.4.auky6trawmdlcne8ad8phb0f1

    管理swarm(7) – swarm实践 – 查看服务详细信息

    本文介绍如何查看运行在swarm中的服务的详情。
    1.登录manager1机器。
    2.运行docker service inspect –pretty 以便于阅读的格式显示服务的详细信息。
    查看helloworld服务的详细信息:

    1. $ docker service inspect –pretty helloworld
    2.  
    3. ID:     9uk4639qpg7npwf3fn2aasksr
    4. Name:       helloworld
    5. Mode:       REPLICATED
    6.  Replicas:      1
    7. Placement:
    8. UpdateConfig:
    9.  Parallelism:   1
    10. ContainerSpec:
    11.  Image:     alpine
    12.  Args:  ping docker.com

    要以json格式返回服务详细信息的,不带–pretty参数执行相同的命令。

    1. $ docker service inspect helloworld
    2. [
    3. {
    4.     "ID": "9uk4639qpg7npwf3fn2aasksr",
    5.     "Version": {
    6.         "Index": 418
    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": 0
    27.             },
    28.             "Placement": {}
    29.         },
    30.         "Mode": {
    31.             "Replicated": {
    32.                 "Replicas": 1
    33.             }
    34.         },
    35.         "UpdateConfig": {
    36.             "Parallelism": 1
    37.         },
    38.         "EndpointSpec": {
    39.             "Mode": "vip"
    40.         }
    41.     },
    42.     "Endpoint": {
    43.         "Spec": {}
    44.     }
    45. }
    46. ]

    3.执行docker service ps 来查看哪个节点运行这个服务:
    $ docker service ps helloworld

    1. ID                         NAME          SERVICE     IMAGE   LAST STATE         DESIRED STATE  NODE
    2. 8p1vev3fq5zm0mi8g0as41w35  helloworld.1  helloworld  alpine  Running 3 minutes  Running        worker2

    在这个例子中,worker2节点运行着helloworld服务。不过你可能会看到服务运行在管理节点上。默认下,swarm中的管理节点能像worker节点一样执行任务。
    4.在运行这个服务的节点上执行docker ps来查看运行任务的容器。

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

    管理swarm(6) – swarm实践 – 部署服务

    本文尝试在swarm中部署一个服务。
    1.登录到manager1机器。
    2.执行如下命令来部署服务:

    1. $ docker service create –replicas 1 –name helloworld alpine ping docker.com
    2.  
    3. 9uk4639qpg7npwf3fn2aasksr
  • docker service create命令创建服务
  • –name参数设置服务名称
  • –replicas 1指定运行一个实例
  • alpine ping docker.com参数定义alpine容器运行ping docker.com命令的服务
  • 3.执行docker service ls查看运行中的服务列表:

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

    管理swarm(5) – swarm实践 – 添加节点到swarm

    一旦你创建好带一个管理节点的swarm后,你就可以往swarm添加worker节点了。
    1.登录worker1机器。
    2.运行由前文创建swarm输出的把worker节点加入到swarm的命令:

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

    如果你找不到之前添加节点的命令了,可以执行如下命令来查询:

    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-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c
    7.     192.168.99.100:2377

    3.登录worker2机器。
    4.执行与第2步相同的命令把worker2添加到swarm中:

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

    5.登录manage1机器,执行docker node ls命令来查询worker节点:

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

    管理swarm(4) – swarm实践 – 创建一个swarm

    完成上一篇文章的环境准备后,我们准备演示如何创建一个swarm。确保你主机的Docker Engine daemon运行状态。
    1.登录manager1机器
    2.运行如下命令来创建一个新的swarm:

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

    在本实践我们在manager1来创建一个swarm:

    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-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c
    8.     192.168.99.100:2377
    9.  
    10. To add a manager to this swarm, run ‘docker swarm join-token manager’ and follow the instructions.

    –advertise-addr参数配置管理节点发布它的IP地址192.168.99.100。其它的节点必须能通过此IP来连接管理节点。
    上面命令的输出包含了加入新节点到swarm的命令。节点将作为manager或worker加入,具体取决于–token标志的值。
    3.运行docker info来查看目前swarm的状态:

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

    4.执行docker node ls命令来查看节点的相关信息:

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