Docker Swarm部署集群

我会带着你远行 2024-04-17 05:56 206阅读 0赞

一、Swarm简介

Swarm是Docker的一个编排工具,参考官网:https://docs.docker.com/engine/swarm/

Swarm 模式简介

  • 要在Swarm模式下运行docker,需要先安装docker,参考安装教程
  • 当前版本的docker包含了swarm模式,用于管理docker集群。可以使用命令行来创建swarm集群,部署应用,管理swarm的行为。

如果你使用低于1.12.0版本的docker,可以使用独立模式的是swarm,但是建议使用最新版本

特性

  • 与docker集成的集群管理工具
  • 去中心化设计,只使用docker引擎即可创建各类节点
  • 声明式服务模型。可以声明的方式来定义应用。
  • 动态伸缩。管理节点自动调整服务数量。
  • 高可用,对于服务期望状态做到动态调整,swarm的管理节点会持续监控集群状态,集群中有没有达到期望状态的服务,管理节点会自动调度来达到期望状态。
  • 自定义网络。可以为你的服务指定一个网络,容器创建的时候分配一个IP
  • 服务发现。管理节点给集群中每个服务一个特定的DNS名字,并给运行的容器提供负载均衡。
  • 负载均衡。你可以暴露服务端口给外部的负载均衡。内部swarm提供可配置的容器分配到节点的策略。
  • 默认的安全机制。swarm集群中各个节点强制TLS协议验证。连接加密,你可以自定义根证书。

滚动更新。增量跟新,可以自定义更新下个节点的时间间隔,如果有问题,可以会滚到上个版本。

二、安装Swarm

本教程进行如下指导:

  • 在swarm模式下初始化一个基于docker引擎的swarm集群
  • 在swarm集群中添加节点
  • 部署应用服务到swarm集群中
  • 管理swarm集群

本教程使用docker命令行的方式交互

安装

安装环境要求

  • 3台可以网络通信的Linux主机,并且安装了docker
  • 安装1.12.0以上的docker
  • 管理节点的IP地址

  • 主机之间开放端口

准备3台主机

  • 3台主机可以是物理机,虚拟机,云主机,甚至是docker machine创建的主机。并安装docker。三台主机分别是manager1,work1和worker2.

    安装1.12.0以上的docker
  • 参考:在linux上安装docker

  • 管理节点的IP地址
  • 所有swarm集群中的节点都会连接到管理节点的IP地址

    主机间开放端口
  • 以下端口必须是开放的:

    • TCP port 2377为集群管理通信
    • TCP and UDP port 7946 为节点间通信
    • UDP port 4789 为网络间流量
  • 如果你想使用加密网络(—opt encrypted)也需要确保ip protocol 50 (ESP)是可用的

环境说明




























操作系统 主机名 ip地址 docker版本
ubuntu-16.04.4-server-amd64 manager1 192.168.10.104 Docker version 18.09.2
ubuntu-16.04.4-server-amd64 work1 192.168.10.108 Docker version 18.09.2
ubuntu-16.04.4-server-amd64 work2 192.168.10.110 Docker version 18.09.2

创建一个Swarm集群

完成上面的开始过程后,可以开始创建一个swarm集群。确保docker的后台应用已经在主机上运行了。

登陆到manager1上,如果使用docker-machine创建的主机,可以docker-machine ssh manager1

运行以下命令来创建一个新的swarm集群:

  1. docker swarm init --advertise-addr <MANAGER1-IP>

MANAGER1-IP 表示管理节点

本教程中使用如下命令在manager1上创建swarm集群:

  1. root@manager1:~# docker swarm init --advertise-addr 192.168.10.104
  2. Swarm initialized: current node (zmvmswnwv6jcvjt1tmq65zzkg) is now a manager.
  3. To add a worker to this swarm, run the following command:
  4. docker swarm join --token SWMTKN-1-4q7uby9b9vjrjryrvl9r7kgq23hx0y6nwmdt3b9kmxpfcn7vmu-97op3d7nkn8rp31e0boz0308w 192.168.10.104:2377
  5. To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
  • --advertise-addr 选项表示管理节点公布它的IP是多少。其它节点必须能通过这个IP找到管理节点。
  • 命令输出了加入swarm集群的命令。通过—token选项来判断是加入为管理节点还是工作节点
  1. 运行docker info来查看当前swarm集群的状态:

ContractedBlock.gif ExpandedBlockStart.gif

  1. root@manager1:~# docker -v
  2. Docker version 18.09.2, build 6247962
  3. root@manager1:~# docker info
  4. Containers: 0
  5. Running: 0
  6. Paused: 0
  7. Stopped: 0
  8. Images: 0
  9. Server Version: 18.09.2
  10. Storage Driver: overlay2
  11. Backing Filesystem: extfs
  12. Supports d_type: true
  13. Native Overlay Diff: true
  14. Logging Driver: json-file
  15. Cgroup Driver: cgroupfs
  16. Plugins:
  17. Volume: local
  18. Network: bridge host macvlan null overlay
  19. Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
  20. Swarm: active
  21. NodeID: zmvmswnwv6jcvjt1tmq65zzkg
  22. Is Manager: true
  23. ClusterID: 04doas9mydex8aq4vadh0b0go
  24. Managers: 1
  25. Nodes: 1
  26. Default Address Pool: 10.0.0.0/8
  27. SubnetSize: 24
  28. Orchestration:
  29. Task History Retention Limit: 5
  30. Raft:
  31. Snapshot Interval: 10000
  32. Number of Old Snapshots to Retain: 0
  33. Heartbeat Tick: 1
  34. Election Tick: 10
  35. Dispatcher:
  36. Heartbeat Period: 5 seconds
  37. CA Configuration:
  38. Expiry Duration: 3 months
  39. Force Rotate: 0
  40. Autolock Managers: false
  41. Root Rotation In Progress: false
  42. Node Address: 192.168.10.104
  43. Manager Addresses:
  44. 192.168.10.104:2377
  45. Runtimes: runc
  46. Default Runtime: runc
  47. Init Binary: docker-init
  48. containerd version: 9754871865f7fe2f4e74d43e2fc7ccd237edcbce
  49. runc version: 09c8266bf2fcf9519a651b04ae54c967b9ab86ec
  50. init version: v0.18.0 (expected: fec3683b971d9c3ef73f284f176672c44b448662)
  51. Security Options:
  52. apparmor
  53. seccomp
  54. Profile: default
  55. Kernel Version: 4.4.0-116-generic
  56. Operating System: Ubuntu 16.04.4 LTS
  57. OSType: linux
  58. Architecture: x86_64
  59. CPUs: 1
  60. Total Memory: 3.859GiB
  61. Name: manager1
  62. ID: 7N32:4Z4C:V5JN:L4I4:PR3K:KRN7:RR6M:MYR6:TBYG:EB5C:MDTA:CRTY
  63. Docker Root Dir: /var/lib/docker
  64. Debug Mode (client): false
  65. Debug Mode (server): false
  66. Registry: https://index.docker.io/v1/
  67. Labels:
  68. Experimental: false
  69. Insecure Registries:
  70. 127.0.0.0/8
  71. Live Restore Enabled: false
  72. WARNING: No swap limit support

运行docker node ls来查看节点信息

  1. root@manager1:~# docker node ls
  2. ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
  3. zmvmswnwv6jcvjt1tmq65zzkg * manager1 Ready Active Leader 18.09.2
  • nodeId 旁边的*号表示你当前连接到的节点。
  • docker引擎的swarm模式自动使用宿主机的主机名作为节点名。

将节点加入到swarm集群中

一旦前面的创建swarm集群完成,你就可以加入工作节点了。

ssh到要加入集群的节点上,我们要加入worker1.

运行创建swarm集群时候产生的命令来将woker1加入到集群中:

  1. root@work1:~# docker swarm join --token SWMTKN-1-4q7uby9b9vjrjryrvl9r7kgq23hx0y6nwmdt3b9kmxpfcn7vmu-97op3d7nkn8rp31e0boz0308w 192.168.10.104:2377
  2. This node joined a swarm as a worker.

如果你找不到加入命令了,可以在管理节点运行下列命令找回加入命令:

  1. root@manager1:~# docker swarm join-token worker
  2. To add a worker to this swarm, run the following command:
  3. docker swarm join --token SWMTKN-1-4q7uby9b9vjrjryrvl9r7kgq23hx0y6nwmdt3b9kmxpfcn7vmu-97op3d7nkn8rp31e0boz0308w 192.168.10.104:2377

ssh到worker2
运行加入集群的命令来将worker2加入到集群:

  1. root@worker2:~# docker swarm join --token SWMTKN-1-4q7uby9b9vjrjryrvl9r7kgq23hx0y6nwmdt3b9kmxpfcn7vmu-97op3d7nkn8rp31e0boz0308w 192.168.10.104:2377
  2. This node joined a swarm as a worker.

ssh到manager1节点运行docker node ls命令来查看集群节点情况:

  1. root@manager1:~# docker node ls
  2. ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
  3. zmvmswnwv6jcvjt1tmq65zzkg * manager1 Ready Active Leader 18.09.2
  4. pi6ori8t1tuestb3hzhnn265v work1 Ready Active 18.09.2
  5. ohivom1sdi1vz1oaer1b9wpl0 work2 Ready Active 18.09.2

MANAGER列表明了集群中的管理节点。worker节点的空意味着它们是工作节点

三、部署服务

在创建一个swarm集群后,就可以部署服务了。本教程中你也可以加入工作节点,但是不是必须的。

ssh到manager1节点
运行如下命令:

  1. root@manager1:~# docker service create --replicas 1 --name helloworld alpine ping docker.com
  2. qf8qydwuah1ym9xj5yxrxvhak
  3. overall progress: 1 out of 1 tasks
  4. 1/1: running
  5. verify: Service converged
  • docker service create用来创建服务
  • --name表明服务名字是helloworld
  • --replicas 表示期望1个服务实例
  • alpine ping docker.com 表示运行镜像是alpine,命令是ping

运行docker service ls来查看运行的服务:

  1. root@manager1:~# docker service ls
  2. ID NAME MODE REPLICAS IMAGE PORTS
  3. qf8qydwuah1y helloworld replicated 1/1 alpine:latest

四、检查服务

在你部署服务到Swarm集群上后,可以使用命令行来检查运行的服务

ssh到管理节点
运行命令docker service inspect —pretty 来查看优化显示的服务详情

ContractedBlock.gif ExpandedBlockStart.gif

  1. root@manager1:~# docker service inspect --pretty qf8qydwuah1y
  2. ID: qf8qydwuah1ym9xj5yxrxvhak
  3. Name: helloworld
  4. Service Mode: Replicated
  5. Replicas: 1
  6. Placement:
  7. UpdateConfig:
  8. Parallelism: 1
  9. On failure: pause
  10. Monitoring Period: 5s
  11. Max failure ratio: 0
  12. Update order: stop-first
  13. RollbackConfig:
  14. Parallelism: 1
  15. On failure: pause
  16. Monitoring Period: 5s
  17. Max failure ratio: 0
  18. Rollback order: stop-first
  19. ContainerSpec:
  20. Image: alpine:latest@sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb
  21. Args: ping docker.com
  22. Init: false
  23. Resources:
  24. Endpoint Mode: vip

去掉—pretty选项将以json格式输出

运行docker service ps 将查看到哪些节点在运行该服务实例:

  1. root@manager1:~# docker service ps qf8qydwuah1y
  2. ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
  3. 6u05btfqzo6j helloworld.1 alpine:latest manager1 Running Running 5 minutes ago
  • 服务可能运行在管理或工作节点上,默认的管理节点可以像工作节点一样运行任务。
  • 该命令也显示服务期望的状态DESIRED STATE ,和实际的状态CURRENT STATE。

在运行任务的节点上运行docker ps也能看到这个任务运行的容器。备注:目前运行在manager1上面

  1. root@manager1:~# docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 236ed4a13f7a alpine:latest "ping docker.com" 6 minutes ago Up 6 minutes helloworld.1.6u05btfqzo6j4mo4uxm5543mi

五、动态伸缩服务实例数

一旦你在swarm集群中部署一个服务后,你就可以使用命令行来改变服务的实例个数。在服务中运行的容器称为“任务”

语法:

  1. docker service scale <ID>=数量

ssh到manager1节点
运行以下命令来改变服务的期望实例数:

  1. root@manager1:~# docker service scale qf8qydwuah1y=3
  2. qf8qydwuah1y scaled to 3
  3. overall progress: 3 out of 3 tasks
  4. 1/3: running
  5. 2/3: running
  6. 3/3: running
  7. verify: Service converged

运行以下命令来查看更新的任务列表:

  1. root@manager1:~# docker service ls
  2. ID NAME MODE REPLICAS IMAGE PORTS
  3. qf8qydwuah1y helloworld replicated 3/3 alpine:latest
  4. root@manager1:~# docker service ps qf8qydwuah1y
  5. ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
  6. 6u05btfqzo6j helloworld.1 alpine:latest manager1 Running Running 10 minutes ago
  7. m96ohuz60dw4 helloworld.2 alpine:latest work1 Running Running about a minute ago
  8. 9dldkulmsvwj helloworld.3 alpine:latest work2 Running Running about a minute ago

可以看到这3个任务被分布到了集群中的不同节点

ssh到运行服务的主机work1上运行docker ps查看运行的容器:

  1. root@work1:~# docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. fafaa17a2c6a alpine:latest "ping docker.com" 2 minutes ago Up 2 minutes helloworld.2.m96ohuz60dw4twr9np4kd8hz3

六、删除应用

接下来删除应用

ssh到管理节点
运行docker service rm 来删除服务:

  1. root@manager1:~# docker service ls
  2. ID NAME MODE REPLICAS IMAGE PORTS
  3. qf8qydwuah1y helloworld replicated 3/3 alpine:latest
  4. root@manager1:~# docker service rm qf8qydwuah1y
  5. qf8qydwuah1y
  6. root@manager1:~# docker service ls
  7. ID NAME MODE REPLICAS IMAGE PORTS

运行docker service inspect 会发现服务不存在了

  1. root@manager1:~# docker service inspect qf8qydwuah1y
  2. []
  3. Status: Error: no such service: qf8qydwuah1y, Code: 1

尽管服务不存在了,任务容器还需要几秒钟来清理,你可以在节点上docker ps查看任务什么时候被移除。

七、滚动更新

在前面的章节中,修改了实例数。本节使用etcd:2.0.5 镜像来部署服务,然后滚动升级到etcd:2.0.10

ssh到管理节点
部署etcd:2.0.5 服务,配置10s的更新间隔:

  1. root@manager1:~# docker service create --replicas 2 --name etcd --update-delay 10s elcolio/etcd:2.0.5
  2. vh7w3mq5q0vc634w8x6m8r3m6
  3. overall progress: 2 out of 2 tasks
  4. 1/2: running
  5. 2/2: running
  6. verify: Service converged
  • 注意:教程使用的是redis镜像,我使用的是etcd镜像拉
  • 在服务部署阶段就指定滚动升级策略
  • --update-delay配置了更新服务的时间间隔,你可以指定时间T为秒是Ts,分是Tm,或时是Th,所以10m30s就是10分30秒的延迟
  • 默认的调度器scheduler一次更新一个任务.你可以传入参数—update-parallelism来配置调度器同时更新的最大任务数量
  • 默认的当一个更新任务返回RUNNING状态后,调度器才调度另一个更新任务,直到所有任务都更新了。如果更新过程中任何任务返回了FAILED,调度器就会停止更新。你可以给命令docker service create or docker service update配置配置—update-failure-action,来配置这个行为。

查看etcd服务

ContractedBlock.gif ExpandedBlockStart.gif

  1. root@manager1:~# docker service inspect --pretty etcd
  2. ID: vh7w3mq5q0vc634w8x6m8r3m6
  3. Name: etcd
  4. Service Mode: Replicated
  5. Replicas: 2
  6. Placement:
  7. UpdateConfig:
  8. Parallelism: 1
  9. Delay: 10s
  10. On failure: pause
  11. Monitoring Period: 5s
  12. Max failure ratio: 0
  13. Update order: stop-first
  14. RollbackConfig:
  15. Parallelism: 1
  16. On failure: pause
  17. Monitoring Period: 5s
  18. Max failure ratio: 0
  19. Rollback order: stop-first
  20. ContainerSpec:
  21. Image: elcolio/etcd:2.0.5@sha256:fa9c5bdfd7164b75d944da3693d891e1fd18c7c757bbb5c00caa99aef312a428
  22. Init: false
  23. Resources:
  24. Endpoint Mode: vip

现在可以更新etcd的容器镜像了,语法:

  1. docker service update --image <镜像名> <服务名>

运行以下命令,swarm的管理节点将会根据更新策略UpdateConfig来更新各个节点:

  1. root@manager1:~# docker service update --image elcolio/etcd:2.0.10 etcd
  2. etcd
  3. overall progress: 2 out of 2 tasks
  4. 1/2: running
  5. 2/2: running
  6. verify: Service converged

调度器依照以下步骤来滚动更新:

  • 停止第一个任务
  • 对停止的任务进行更新
  • 对更新的任务进行启动
  • 如果更新的任务返回RUNNING,等待特定间隔后启动下一个任务
  • 如果在任何更新的时间,任务返回了FAILED,则停止更新。

运行命令docker service inspect —pretty etcd来查看新镜像的期望状态,可以看到显示了UpdateStatus完成。

ContractedBlock.gif ExpandedBlockStart.gif

  1. root@manager1:~# docker service inspect --pretty etcd
  2. ID: vh7w3mq5q0vc634w8x6m8r3m6
  3. Name: etcd
  4. Service Mode: Replicated
  5. Replicas: 2
  6. UpdateStatus:
  7. State: completed
  8. Started: 2 minutes ago
  9. Completed: About a minute ago
  10. Message: update completed
  11. Placement:
  12. UpdateConfig:
  13. Parallelism: 1
  14. Delay: 10s
  15. On failure: pause
  16. Monitoring Period: 5s
  17. Max failure ratio: 0
  18. Update order: stop-first
  19. RollbackConfig:
  20. Parallelism: 1
  21. On failure: pause
  22. Monitoring Period: 5s
  23. Max failure ratio: 0
  24. Rollback order: stop-first
  25. ContainerSpec:
  26. Image: elcolio/etcd:2.0.10@sha256:9a2e9a6ad26ddd87204b248c38d18b397881fc16283e4ac4ed5bfbf2ce03fa4c
  27. Init: false
  28. Resources:
  29. Endpoint Mode: vip

如果中间有升级失败的,则会显示如下信息:

  1. $ docker service inspect --pretty etcd
  2. ID: 0u6a4s31ybk7yw2wyvtikmu50
  3. Name: redis
  4. ...snip...
  5. Update status:
  6. State: paused
  7. Started: 11 seconds ago
  8. Message: update paused due to failure or early termination of task 9p7ith557h8ndf0ui9s0q951b
  9. ...snip...
  • 重新开始一个升级过程:docker service update
  • 为了避免重复失败升级,要重新配置服务服务,添加适当的参数在运行docker service update

运行docker service ps <服务名>来查看本次滚动更新的过程:

  1. root@manager1:~# docker service ps etcd
  2. ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
  3. nzwtsi4p8stw etcd.1 elcolio/etcd:2.0.10 work1 Running Running 3 minutes ago
  4. lom9z7y8rlps \_ etcd.1 elcolio/etcd:2.0.5 work1 Shutdown Shutdown 3 minutes ago
  5. 8h8xjzyhlq1a etcd.2 elcolio/etcd:2.0.10 manager1 Running Running 3 minutes ago
  6. 6hpxbv34jnfz \_ etcd.2 elcolio/etcd:2.0.5 manager1 Shutdown Shutdown 3 minutes ago

注意升级后老的容器只是停止了,并没有删除

  1. root@manager1:~# docker ps -a
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. e905f60e2ec3 elcolio/etcd:2.0.10 "/bin/run.sh" 4 minutes ago Up 4 minutes 2379-2380/tcp, 4001/tcp, 7001/tcp etcd.2.8h8xjzyhlq1a7o5wu5tfqq17z
  4. 13886eb8ea94 elcolio/etcd:2.0.5 "/bin/run.sh" 7 minutes ago Exited (137) 4 minutes ago etcd.2.6hpxbv34jnfz0bjl1yx4xnwdd
  5. b0963cce9bf3 elcolio/etcd:2.0.5 "/bin/run.sh /bin/ba…" 12 minutes ago Exited (130) 11 minutes ago hopeful_feistel

八、从集群中下线一个节点

  • 前面的教程中管理节点会把任务分配给ACTIVE的节点,所有ACTIVE的节点都能接到任务
  • 有时候,例如特定的维护时间,我们就需要从集群中下线一个节点。下线节点使节点不会接受新任务,管理节点会停止该节点上的任务,分配到别的ACTIVE的节点上。
  • 注意:下线一个节点不移除节点中的独立容器,如docker run,docker-compose up或docker API启动的容器都不会删除。节点的状态仅影响集群服务的负载是否分到该节点。

ssh到manageer1
运行docker node ls,验证所有节点都是ACTIVE的:

  1. root@manager1:~# docker node ls
  2. ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
  3. zmvmswnwv6jcvjt1tmq65zzkg * manager1 Ready Active Leader 18.09.2
  4. pi6ori8t1tuestb3hzhnn265v work1 Ready Active 18.09.2
  5. ohivom1sdi1vz1oaer1b9wpl0 work2 Ready Active 18.09.2

如果弄的etcd服务还没有从滚动更新中起来,需要启动起来:
运行docker service ps etcd查看管理节点如何分配任务到不同节点:

  1. root@manager1:~# docker service ps etcd
  2. ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
  3. nzwtsi4p8stw etcd.1 elcolio/etcd:2.0.10 work1 Running Running 6 minutes ago
  4. lom9z7y8rlps \_ etcd.1 elcolio/etcd:2.0.5 work1 Shutdown Shutdown 6 minutes ago
  5. 8h8xjzyhlq1a etcd.2 elcolio/etcd:2.0.10 manager1 Running Running 6 minutes ago
  6. 6hpxbv34jnfz \_ etcd.2 elcolio/etcd:2.0.5 manager1 Shutdown Shutdown 6 minutes ago

运行docker node update —availability drain 来下线一个节点:

  1. root@manager1:~# docker node update --availability drain manager1
  2. manager1

运行以下来检查节点的可用性:
可以看到该节点的可用性是Drain

  1. root@manager1:~# docker node ls
  2. ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
  3. zmvmswnwv6jcvjt1tmq65zzkg * manager1 Ready Drain Leader 18.09.2
  4. pi6ori8t1tuestb3hzhnn265v work1 Ready Active 18.09.2
  5. ohivom1sdi1vz1oaer1b9wpl0 work2 Ready Active 18.09.2

docker node inspect —pretty manager1

ContractedBlock.gif ExpandedBlockStart.gif

  1. root@manager1:~# docker node inspect --pretty manager1
  2. ID: zmvmswnwv6jcvjt1tmq65zzkg
  3. Hostname: manager1
  4. Joined at: 2019-08-24 12:11:37.150001136 +0000 utc
  5. Status:
  6. State: Ready
  7. Availability: Drain
  8. Address: 192.168.10.104
  9. Manager Status:
  10. Address: 192.168.10.104:2377
  11. Raft Status: Reachable
  12. Leader: Yes
  13. Platform:
  14. Operating System: linux
  15. Architecture: x86_64
  16. Resources:
  17. CPUs: 1
  18. Memory: 3.859GiB
  19. Plugins:
  20. Log: awslogs, fluentd, gcplogs, gelf, journald, json-file, local, logentries, splunk, syslog
  21. Network: bridge, host, macvlan, null, overlay
  22. Volume: local
  23. Engine Version: 18.09.2
  24. TLS Info:
  25. TrustRoot:
  26. -----BEGIN CERTIFICATE-----
  27. MIIBajCCARCgAwIBAgIUHwOd2JFLTCBePSGfOYdPvomygdEwCgYIKoZIzj0EAwIw
  28. EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTkwODI0MTIwNzAwWhcNMzkwODE5MTIw
  29. NzAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH
  30. A0IABDQ1v1QxJoRfkoo6hWcKkYD6ixGtd/YCnTVuqOcpyh97dQ3qVPUIEJoafORt
  31. 5yQCu8mLOCH1mWrXjA2yVo/Z6DqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
  32. Af8EBTADAQH/MB0GA1UdDgQWBBT3zbMseoYHkZ60+VhVDGn1qdv4njAKBggqhkjO
  33. PQQDAgNIADBFAiA/nXEN/f6wpUtOWwUBDNAXlKmhp7j+MjfD84+ksu+JEgIhAL6O
  34. ZYp25KHMOGQaVWDPJZIzObWofJvxFwE4hHRkbCaH
  35. -----END CERTIFICATE-----
  36. Issuer Subject: MBMxETAPBgNVBAMTCHN3YXJtLWNh
  37. Issuer Public Key: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENDW/VDEmhF+SijqFZwqRgPqLEa139gKdNW6o5ynKH3t1DepU9QgQmhp85G3nJAK7yYs4IfWZateMDbJWj9noOg==

运行docker service ps etcd来查看管理节点是如何重新分配任务的:
可以看到管理节点将下线节点的任务停止了,为了保障副本数量,重新在active的节点上调度了任务。

  1. root@manager1:~# docker service ps etcd
  2. ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
  3. nzwtsi4p8stw etcd.1 elcolio/etcd:2.0.10 work1 Running Running 9 minutes ago
  4. lom9z7y8rlps \_ etcd.1 elcolio/etcd:2.0.5 work1 Shutdown Shutdown 9 minutes ago
  5. 31x8luhz56zn etcd.2 elcolio/etcd:2.0.10 work2 Running Running about a minute ago
  6. 8h8xjzyhlq1a \_ etcd.2 elcolio/etcd:2.0.10 manager1 Shutdown Shutdown about a minute ago
  7. 6hpxbv34jnfz \_ etcd.2 elcolio/etcd:2.0.5 manager1 Shutdown Shutdown 9 minutes ago

运行docker node update —availability active 来重新active该节点:

  1. root@manager1:~# docker node update --availability active manager1
  2. manager1

查看节点状态,可以看到节点状态重新为Active

ContractedBlock.gif ExpandedBlockStart.gif

  1. root@manager1:~# docker node inspect --pretty manager1
  2. ID: zmvmswnwv6jcvjt1tmq65zzkg
  3. Hostname: manager1
  4. Joined at: 2019-08-24 12:11:37.150001136 +0000 utc
  5. Status:
  6. State: Ready
  7. Availability: Active
  8. Address: 192.168.10.104
  9. Manager Status:
  10. Address: 192.168.10.104:2377
  11. Raft Status: Reachable
  12. Leader: Yes
  13. Platform:
  14. Operating System: linux
  15. Architecture: x86_64
  16. Resources:
  17. CPUs: 1
  18. Memory: 3.859GiB
  19. Plugins:
  20. Log: awslogs, fluentd, gcplogs, gelf, journald, json-file, local, logentries, splunk, syslog
  21. Network: bridge, host, macvlan, null, overlay
  22. Volume: local
  23. Engine Version: 18.09.2
  24. TLS Info:
  25. TrustRoot:
  26. -----BEGIN CERTIFICATE-----
  27. MIIBajCCARCgAwIBAgIUHwOd2JFLTCBePSGfOYdPvomygdEwCgYIKoZIzj0EAwIw
  28. EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTkwODI0MTIwNzAwWhcNMzkwODE5MTIw
  29. NzAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH
  30. A0IABDQ1v1QxJoRfkoo6hWcKkYD6ixGtd/YCnTVuqOcpyh97dQ3qVPUIEJoafORt
  31. 5yQCu8mLOCH1mWrXjA2yVo/Z6DqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
  32. Af8EBTADAQH/MB0GA1UdDgQWBBT3zbMseoYHkZ60+VhVDGn1qdv4njAKBggqhkjO
  33. PQQDAgNIADBFAiA/nXEN/f6wpUtOWwUBDNAXlKmhp7j+MjfD84+ksu+JEgIhAL6O
  34. ZYp25KHMOGQaVWDPJZIzObWofJvxFwE4hHRkbCaH
  35. -----END CERTIFICATE-----
  36. Issuer Subject: MBMxETAPBgNVBAMTCHN3YXJtLWNh
  37. Issuer Public Key: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENDW/VDEmhF+SijqFZwqRgPqLEa139gKdNW6o5ynKH3t1DepU9QgQmhp85G3nJAK7yYs4IfWZateMDbJWj9noOg==

当节点重新active的时候,在以下情况下它会重新接受任务:

  • 当一个服务缩容扩容时
  • 在滚动更新的时候
  • 当另一个节点Drain下线的时候
  • 当一个任务在另一个active节点上运行失败的时候

九、使用swarm模式的路由网络

  • docker的swarm模式使服务暴露给外部端口更加方便。所有的节点都在一个路由网络里。这个路由网络使得集群内的所有节点都能在开放的端口上接受请求。即使节点上没有任务运行,这个服务的端口也暴露的。路由网络路由所有的请求到暴露端口的节点上。
  • 前提是需要暴露以下端口来使节点间能通信

    • Port 7946 TCP/UDP for container network discovery.用于容器间网络发现
    • Port 4789 UDP for the container ingress network.用于容器进入网络
  • 你也必须开放节点之间的公开端口,和任何外部资源端口,例如一个外部的负载均衡。
  • 你也可以使特定服务绕过路由网络

为一个服务暴露端口

使用--publish来在创建一个服务的时候暴露端口。target指明容器内暴露的端口。published指明绑定到路由网络上的端口。如果不写published,就会为每个服务绑定一个随机的高数字端口。你需要检查任务才能确定端口

先删除etcd,再重新部署etcd,指定映射端口,查看进程

  1. root@manager1:~# docker service rm etcd
  2. etcd
  3. root@manager1:~# docker service create --name etcd --publish published=2379,target=2379 --replicas 1 elcolio/etcd:2.0.10
  4. 0xej3ym93411svulph7f5l0m0
  5. overall progress: 1 out of 1 tasks
  6. 1/1: running
  7. verify: Service converged
  8. root@manager1:~# docker service ps etcd
  9. ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
  10. tqmgklo7fbmb etcd.1 elcolio/etcd:2.0.10 manager1 Running Running 14 seconds ago
  • 注意旧版的语法是冒号分开的published:target,例如 -p 8080:80。新语法更易读且灵活。
  • 当你在任何节点访问8080端口时,路由网络将把请求分发到一个active的容器中。在各个节点,8080端口可能并没有绑定,但是路由网络知道如何路由流量,并防止任何端口冲突。
  • 路由网络监听各个节点的IP上的 published port 。从外面看,这些端口是各个节点暴露的。对于别的IP地址,只在该主机内可以访问。

1341090-20190824212634597-1925343216.png

https://docs.docker.com/engine/swarm/images/ingress-routing-mesh.png

你可以用以下命令给一个已经存在的服务暴露端口

  1. root@manager1:~# docker service ls
  2. ID NAME MODE REPLICAS IMAGE PORTS
  3. 0xej3ym93411 etcd replicated 1/1 elcolio/etcd:2.0.10 *:2379->2379/tcp
  4. root@manager1:~#
  5. root@manager1:~# docker service update --publish-add published=20379,target=2379 etcd
  6. etcd
  7. overall progress: 1 out of 1 tasks
  8. 1/1: running
  9. verify: Service converged

你可以使用docker service inspect来查看服务暴露的端口:

  1. root@manager1:~# docker service inspect --format="{
  2. {json .Endpoint.Spec.Ports}}" etcd
  3. [{
  4. "Protocol":"tcp","TargetPort":2379,"PublishedPort":20379,"PublishMode":"ingress"},{
  5. "Protocol":"tcp","TargetPort":2379,"PublishedPort":2379,"PublishMode":"ingress"}]
  • The output shows the (labeled TargetPort) from the containers and the (labeled PublishedPort) where nodes listen for requests for the service.

访问etcd api,查看版本

使用命令:docker service ps etcd 得知etcd运行在manager1,因此访问地址为:

  1. root@manager1:~# curl http://192.168.10.104:20379/version
  2. etcd 2.0.10

仅暴露一个TCP或UDP端口

注意:这部分内容出现的命令,不需要执行

默认你暴露的端口都是TCP的。如果你使用长语法(Docker 1.13 and higher),设置protocol为tcp或udp即可暴露相应端口

仅TCP

  1. 长语法
  2. $ docker service create --name dns-cache \
  3. --publish published=53,target=53 \
  4. dns-cache
  5. 短语法
  6. $ docker service create --name dns-cache \
  7. -p 53:53 \
  8. dns-cache

TCP和UDP

  1. 长语法
  2. $ docker service create --name dns-cache \
  3. --publish published=53,target=53 \
  4. --publish published=53,target=53,protocol=udp \
  5. dns-cache
  6. 短语法
  7. $ docker service create --name dns-cache \
  8. -p 53:53 \
  9. -p 53:53/udp \
  10. dns-cache
只暴露UDP
  1. 长语法
  2. $ docker service create --name dns-cache \
  3. --publish published=53,target=53,protocol=udp \
  4. dns-cache
  5. 短语法
  6. $ docker service create --name dns-cache \
  7. -p 53:53/udp \
  8. dns-cache

绕过路由网络

  • 你可以绕过路由网络,直接和一个节点上的端口通信,来访问服务。这叫做Host模式:

    • 如果该节点上没有服务运行,服务也没有监听端口,则可能无法通信。
    • 你不能在一个节点上运行多个服务实例他们绑定同一个静态target端口。或者你让docker分配随机高数字端口(通过空配置target),或者确保该节点上只运行一个服务实例(通过配置全局服务global service 而不是副本服务,或者使用配置限制)。
  • 为了绕过路由网络,必须使用长格式—publish,设置模式mode为host模式。如果你忽略了mode设置或者设置为内网ingress,则路由网络将启动。下面的命令创建了全局应用使用host模式绕过路由网络:
  1. $ docker service create --name dns-cache \
  2. --publish published=53,target=53,protocol=udp,mode=host \
  3. --mode global \
  4. dns-cache

十、配置外部的负载均衡

  • 你可以为swarm集群配置外部的负载均衡,或者结合路由网络使用或者完全不使用:

    使用路由网络

  • 你可以使用一个外部的HAProxy来负载均衡,服务是8080端口上的nginx服务:

    1341090-20190824215112893-1889457249.png

  • 在这个例子中负载均衡器和集群节点之间的8080端口必须是开放的。swarm集群节点在一个外部不可访问的内网中,节点可以与HAProxy通信。

  • 你可以配置负载均衡器分流请求到不同的集群节点,即使节点上没有服务运行。例如你可以如下配置HAProxy:/etc/haproxy/haproxy.cfg:

安装haproxy

由于机器资源不够,这里在manager1节点,安装haproxy

  1. apt-get install -y haproxy

配置haproxy

  1. vim /etc/haproxy/haproxy.cfg

最后一行添加

  1. # Configure HAProxy to listen on port 80
  2. frontend http_front
  3. bind *:80
  4. stats uri /haproxy?stats
  5. default_backend http_back
  6. # Configure HAProxy to route requests to swarm nodes on port 8080
  7. backend http_back
  8. balance roundrobin
  9. server node1 192.168.10.104:2379 check
  10. server node2 192.168.10.108:2379 check
  11. server node3 192.168.10.110:2379 check
  • 当你请求HAProxy的80端口的时候,它会转发请求到后端节点。swarm的路由网络会路由到相应的服务节点。这样无论任何原因swarm的调度器调度服务到不同节点,都不需要重新配置负载均衡。
  • 你可以配置任何类型的负载均衡来分流请求。关于HAProxy参考 HAProxy documentation

  • 不使用路由网络

  • 如果不使用路由网络,配置—endpoint-mode的值为dnsrr,而不是vip。在本例子中没有一个固定的虚拟IP。Docker为服务做了DNS注册,这样一个服务的DNS查询会返回一系列IP地址。客户端就可以直接连接其中一个节点。你负责提供这一系列的IP地址,开放端口给你的负载均衡器。参考Configure service discovery.

重新加载配置

  1. service haproxy reload

访问haproxy

  1. http://192.168.10.104/haproxy?stats

效果如下:

1341090-20190824215541689-1992022188.png

可以发现3台node的Act状态为Y,表示活跃。

访问etcd api的版本

  1. http://192.168.10.104/version

效果如下:

1341090-20190824215706223-426675443.png

本文参考链接:

https://www.cnblogs.com/drawnkid/p/8487337.html

发表评论

表情:
评论列表 (有 0 条评论,206人围观)

还没有评论,来说两句吧...

相关阅读

    相关 docker-swarm

    一、Swarm Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各

    相关 Docker Swarm

    Docker Swarm集群的搭建 Docker Swarm是一个用于创建和管理Docker集群的工具。它具有以下的特点: 方便集群的管理 可扩展 可