您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
docker相关--开始使用swarm模式
 
  1879  次浏览      15
 2018-9-3
 
编辑推荐:
本文来自于cnblogs,文章讲述如何在swarm集群上部署一个服务,以及如何检查Swarm集群上的服务等相关知识。

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模式

本教程进行如下指导:

在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)是可用的

创建一个Swarm集群

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

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

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

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

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

james@james-CW65:~ > docker swarm init --advertise-addr 192.168.99.1
Swarm initialized: current node (5n1l6261akogeuxysrgn2ipxz) is now a manager.
To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-2bgkinnbc0rmlj6kpotyrlj0uz51l2ikinttsk960dxro558x4-6zajfnahtv9ye39momddh5kru 192.168.99.1:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

--advertise-addr选项表示管理节点公布它的IP是多少。其它节点必须能通过这个IP找到管理节点。

命令输出了加入swarm集群的命令。通过--token选项来判断是加入为管理节点还是工作节点

运行docker info来查看当前swarm集群的状态:

james@james-CW65:~ > docker info
Containers: 4
Running: 2
Paused: 0
Stopped: 2
Images: 7
Server Version: 17.12.0-ce
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 37
Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: active
NodeID: 5n1l6261akogeuxysrgn2ipxz
Is Manager: true
ClusterID: nhkp9f1l5yq76e0zu0bage2h4
Managers: 1
Nodes: 1
Orchestration:
Task History Retention Limit: 5
Raft:
Snapshot Interval: 10000
Number of Old Snapshots to Retain: 0
Heartbeat Tick: 1
Election Tick: 3
Dispatcher:
Heartbeat Period: 5 seconds
CA Configuration:
Expiry Duration: 3 months
Force Rotate: 0
Autolock Managers: false
Root Rotation In Progress: false
Node Address: 192.168.99.1
Manager Addresses:
192.168.99.1:2377
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 89623f28b87a6004d4b785663257362d1658a729
runc version: b2567b37d7b75eb4cf325b77297b140ea686ce8f
init version: 949e6fa
Security Options:
apparmor
Kernel Version: 3.19.0-32-generic
Operating System: Ubuntu 14.04.3 LTS
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 3.755GiB
Name: james-CW65
ID: EMVF:D3TL:KMEY:2QTR:HESQ:J5ZA:WDYM:GSEV:
INSU:Z4QI:DCIX:LMGK
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false

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

james@james-CW65:~ > docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
n1l6261akogeuxysrgn2ipxz * james-CW65 Ready Active Leader

nodeId旁边的*号表示你当前连接到的节点。

docker引擎的swarm模式自动使用宿主机的主机名作为节点名。

将节点加入到swarm集群中

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

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

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

docker@default:~$ docker swarm join --token SWMTKN-1-2bgkinnbc0rmlj6kpotyrlj0uz51l2ikinttsk960dxro558x4-6zajfnahtv9ye39momd
dh5kru 192.168.99.1:2377
This node joined a swarm as a worker.

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

james@james-CW65:~ > docker swarm join-token worker
To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-2bgkinnbc0rmlj6kpotyrlj0uz51l2ikinttsk960dxro558x4-6zajfnahtv9ye39momddh5kru 192.168.99.1:2377

ssh到worker2

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

Boot2Docker version 17.12.0-ce, build HEAD : 378b049 - Wed Dec 27 23:39:20 UTC 2017
Docker version 17.12.0-ce, build c97c6d6
docker@lab:~$ docker swarm join --token SWMTKN-1-2bgkinnbc0rmlj6kpotyrlj0uz51l2ikinttsk960dxro558x4-6zajfnahtv9ye39momddh5k
ru 192.168.99.1:2377
This node joined a swarm as a worker.

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

james@james-CW65:~ > docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
k89s71elf81vbn7pytwszmgr5 default Ready Active
n1l6261akogeuxysrgn2ipxz * james-CW65 Ready Active Leader
ye5x8hci1chmo8nyjx8y4thhy lab Ready Active

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

在swarm集群上部署一个服务

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

ssh到manager节点

运行如下命令:

james@james-CW65:~ > docker service create --replicas 1 --name helloworld alpine ping docker.com
060zo3u0g3mjdmrilezzbckbe
overall progress: 1 out of 1 tasks
1/1: running [=========================================>]
verify: Service converged

docker service create用来创建服务

--name表明服务名字是helloworld

--replicas 表示期望1个服务实例

alpine ping docker.com 表示运行镜像是alpine,命令是ping

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

james@james-CW65:~ > docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
060zo3u0g3mj helloworld replicated 1/1 alpine:latest

检查Swarm集群上的服务

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

ssh到管理节点

运行命令docker service inspect --pretty 来查看优化显示的服务详情

james@james-CW65:~ > docker service inspect --pretty 060zo3u0g3mj

ID: 060zo3u0g3mjdmrilezzbckbe
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:7b848083f93822dd21b0a2f14a1
10bd99f6efb4b838d499df6d04a49d0debf8b
Args: ping docker.com
Resources:
Endpoint Mode: vip

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

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

james@james-CW65:~ > docker service ps 060zo3u0g3mj
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
cbiq1ne3ij9a helloworld.1 alpine:latest james-CW65 Running Running 9 minutes ago

服务可能运行在管理或工作节点上,默认的管理节点可以像工作节点一样运行任务。

该命令也显示服务期望的状态DESIRED STATE ,和实际的状态CURRENT STATE。

在运行任务的节点上运行docker ps也能看到这个任务运行的容器

james@james-CW65:~ > docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cad59e7398de alpine:latest "ping docker.com" 2 minutes ago Up 2 minutes helloworld.1.ngbknb89dzyxdas81emw0jz63

在swarm集群中动态伸缩服务实例数

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

ssh到manager节点

运行以下命令来改变服务的期望实例数:

james@james-CW65:~ > docker service scale 60zo3u0g3mj=3
60zo3u0g3mj scaled to 3
overall progress: 3 out of 3 tasks
1/3: running [=============================================>]
2/3: running [=============================================>]
3/3: running [=============================================>]
verify: Waiting 1 seconds to verify that tasks are stable...
verify: Service converged

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

james@james-CW65:~ > docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
060zo3u0g3mj helloworld replicated 3/3 alpine:latest
james@james-CW65:~ > docker service ps 060zo3u0g3mj
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ngbknb89dzyx helloworld.1 alpine:latest james-CW65 Running Running 9 minutes ago
cbiq1ne3ij9a \_ helloworld.1 alpine:latest james-CW65 Shutdown Failed 9 minutes ago "task: non-zero exit (1)"
3fl3mfrvubu1 helloworld.2 alpine:latest default Running Running about a minute ago
hy5pqcmqfw67 helloworld.3 alpine:latest lab Running Running about a minute ago

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

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

docker@default:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cad897086027 alpine:latest "ping docker.com" 4 minutes ago Up 4 minutes helloworld.2.3fl3mfrvubu1hf16argabe5qt

从swarm集群上删除应用

接下来删除应用

ssh到管理节点

运行docker service rm helloworld来删除服务:

james@james-CW65:~ > docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
060zo3u0g3mj helloworld replicated 3/3 alpine:latest
james@james-CW65:~ > docker service rm 060zo3u0g3mj
060zo3u0g3mj
james@james-CW65:~ > docker service ls
ID NAME MODE REPLICAS IMAGE PORTS

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

james@james-CW65:~ > docker service inspect 060zo3u0g3mj
[]
Status: Error: no such service: 060zo3u0g3mj, Code: 1

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

滚动更新

在前面的章节中,修改了实例数。本节使用Ghost0.11.12 镜像来部署服务,然后滚动升级到Ghost1.21.3

ssh到管理节点

部署Ghost0.11.12 服务,配置10s的更新间隔:

james@james-CW65:~ > docker service create --replicas 2 --name ghost --update-delay 10s ghost:0.11.12
tynb9d9pu0nqm7f1vmmffy9j0
overall progress: 2 out of 2 tasks
1/2: running [==========================================>]
2/2: running [==========================================>]
verify: Service converged

注意:教程使用的是redis镜像,我使用的是Ghost博客镜像,拉

在服务部署阶段就指定滚动升级策略

--update-delay配置了更新服务的时间间隔,你可以指定时间T为秒是Ts,分是Tm,或时是Th,所以10m30s就是10分30秒的延迟

默认的调度器scheduler一次更新一个任务.你可以传入参数--update-parallelism来配置调度器同时更新的最大任务数量

默认的当一个更新任务返回RUNNING状态后,调度器才调度另一个更新任务,直到所有任务都更新了。如果更新过程中任何任务返回了FAILED,调度器就会停止更新。你可以给命令docker service create or docker service update配置配置--update-failure-action,来配置这个行为。

查看redis服务:

james@james-CW65:~ > docker service inspect --pretty ghost

ID: tynb9d9pu0nqm7f1vmmffy9j0
Name: ghost
Service Mode: Replicated
Replicas: 2
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: ghost:0.11.12@sha256:45811b5a50254bdf0a05d68
3ddf1dd9eb1be98640305fb82317bcaa35a00c20e
Resources:
Endpoint Mode: vip

现在可以更新redis的容器镜像了。运行以下命令,swarm的管理节点将会根据更新策略UpdateConfig来更新各个节点:

james@james-CW65:~ > docker service update --image ghost:1.21.3 ghost
ghost
overall progress: 2 out of 2 tasks
1/2: running [===========================================>]
2/2: running [===========================================>]
verify: Service converged

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

停止第一个任务

对停止的任务进行更新

对更新的任务进行启动

如果更新的任务返回RUNNING,等待特定间隔后启动下一个任务

如果在任何更新的时间,任务返回了FAILED,则停止更新。

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

james@james-CW65:~ > docker service inspect --pretty ghost

ID: tynb9d9pu0nqm7f1vmmffy9j0
Name: ghost
Service Mode: Replicated
Replicas: 2
UpdateStatus:
State: completed
Started: 2 minutes ago
Completed: 2 minutes ago
Message: update completed
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: ghost:1.21.3@sha256:4c8868f41180589583e6eb20
8a8529ca8dad3d18bddf56834740b715f3e6b691
Resources:
Endpoint Mode: vip
james@james-CW65:~ >

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

$ 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

为了避免重复失败升级,要重新配置服务服务,添加适当的参数在运行docker service update

运行docker service ps 来查看本次滚动更新的过程:

james@james-CW65:~ > docker service ps ghost
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
5ae8hwemegrg ghost.1 ghost:1.21.3 james-CW65 Running Running 54 seconds ago
akwqfsarjvy1 \_ ghost.1 ghost:0.11.12 james-CW65 Shutdown Shutdown 54 seconds ago
hzzq00ckovdg ghost.2 ghost:1.21.3 default Running Running 41 seconds ago
ivtd60xuggk0 \_ ghost.2 ghost:0.11.12 default Shutdown Shutdown 42 seconds ago
james@james-CW65:~ >

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

docker@default:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f855c00da7b7 ghost:1.21.3 "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 2368/tcp ghost.2.hzzq00ckovdgb48373lwn8xp6
c151f3535a3b ghost:0.11.12 "docker-entrypoint.s…" 32 minutes ago Exited (0) 6 minutes ago ghost.2.ivtd60xuggk0y56oguehtirni

从集群中下线一个节点

前面的教程中管理节点会把任务分配给ACTIVE的节点,所有ACTIVE的节点都能接到任务

有时候,例如特定的维护时间,我们就需要从集群中下线一个节点。下线节点使节点不会接受新任务,管理节点会停止该节点上的任务,分配到别的ACTIVE的节点上。

注意:下线一个节点不移除节点中的独立容器,如docker run,docker-compose up或docker API启动的容器都不会删除。节点的状态仅影响集群服务的负载是否分到该节点。

ssh到manageer1

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

james@james-CW65:~ > docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
k89s71elf81vbn7pytwszmgr5 default Ready Active
n1l6261akogeuxysrgn2ipxz * james-CW65 Ready Active Leader

如果弄的redis服务还没有从滚动更新中起来,需要启动起来:

运行docker service ps redis查看管理节点如何分配任务到不同节点:

james@james-CW65:~ > docker service ps ghost
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
5ae8hwemegrg ghost.1 ghost:1.21.3 james-CW65 Running Running 19 minutes ago
akwqfsarjvy1 \_ ghost.1 ghost:0.11.12 james-CW65 Shutdown Shutdown 19 minutes ago
hzzq00ckovdg ghost.2 ghost:1.21.3 default Running Running 19 minutes ago
ivtd60xuggk0 \_ ghost.2 ghost:0.11.12 default Shutdown Shutdown 19 minutes ago

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

james@james-CW65:~ > docker node update --availability drain default
default

运行以下来检查节点的可用性:

可以看到该节点的可用性是Drain

james@james-CW65:~ > docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
k89s71elf81vbn7pytwszmgr5 default Ready Drain
5n1l6261akogeuxysrgn2ipxz * james-CW65 Ready Active Leader
james@james-CW65:~ > docker node inspect --pretty default
ID: k89s71elf81vbn7pytwszmgr5
Hostname: default
Joined at: 2018-02-28 06:25:23.718220559 +0000 utc
Status:
State: Ready
Availability: Drain
Address: 192.168.99.100
Platform:
Operating System: linux
Architecture: x86_64
Resources:
CPUs: 1
Memory: 995.9MiB
Plugins:
Log: awslogs, fluentd, gcplogs, gelf, journald, json-file, logentries, splunk, syslog
Network: bridge, host, macvlan, null, overlay
Volume: local
Engine Version: 17.12.0-ce
Engine Labels:
- provider=virtualbox
TLS Info:
TrustRoot:
-----BEGIN CERTIFICATE-----
MIIBajCCARCgAwIBAgIUJdysIbjEKr/Xr+SvWKd8S0Upgqcw
CgYIKoZIzj0EAwIw EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNM
TgwMjI4MDYwNDAwWhcNMzgwMjIzMDYw NDAwWjATMREwDw
YDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH A0IABFgzZnc/77Zo87KKNrJK83z6ASk1YNHwXYWQvfny
f5aqhLUuOOdGXMgvEj5s GHGkNitCK2y11XQdSzsRQE5
JsGKjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB Af8EBTADAQH/MB0GA1UdDgQWBBSaliomGnuL2p+
xndnzrIfncS9TezAKBggqhkjO PQQDAgNIADBFAiA8c
7Qn3OA62I4APdAqzwK8z4rNgJug7Nheuo7pOOBybgIhAM5W t2NvL1EBMjCQZGRk45W/X0C2UN2NQ+cA7
CVBHh7I -----END CERTIFICATE-----

Issuer Subject: MBMxETAPBgNVBAMTCHN3YXJtLWNh
Issuer Public Key: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWDNm
dz/vtmjzsoo2skrzfPoBKTVg0fBdhZC9+fJ/lqqEtS4450Zc
yC8SPmwYcaQ2K0IrbLXVdB1LOxFATkmwYg==

运行docker service ps redis来查看管理节点是如何重新分配任务的:

可以看到管理节点将下线节点的任务停止了,为了保障副本数量,重新在active的节点上调度了任务。

james@james-CW65:~ > docker service ps ghost
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
5ae8hwemegrg ghost.1 ghost:1.21.3 james-CW65 Running Running 21 minutes ago
akwqfsarjvy1 \_ ghost.1 ghost:0.11.12 james-CW65 Shutdown Shutdown 21 minutes ago
lefwcfo1s44k ghost.2 ghost:1.21.3 james-CW65 Running Running 22 seconds ago
hzzq00ckovdg \_ ghost.2 ghost:1.21.3 default Shutdown Shutdown 22 seconds ago
ivtd60xuggk0 \_ ghost.2 ghost:0.11.12 default Shutdown Shutdown 21 minutes ago

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

james@james-CW65:~ > docker node update --availability active default
default
james@james-CW65:~ > docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
k89s71elf81vbn7pytwszmgr5 default Ready Active
5n1l6261akogeuxysrgn2ipxz * james-CW65 Ready Active Leader

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

james@james-CW65:~ > docker node inspect --pretty default
ID: k89s71elf81vbn7pytwszmgr5
Hostname: default
Joined at: 2018-02-28 06:25:23.718220559 +0000 utc
Status:
State: Ready
Availability: Active
Address: 192.168.99.100
Platform:
Operating System: linux
Architecture: x86_64
Resources:
CPUs: 1
Memory: 995.9MiB
Plugins:
Log: awslogs, fluentd, gcplogs, gelf, journald, json-file, logentries, splunk, syslog
Network: bridge, host, macvlan, null, overlay
Volume: local
Engine Version: 17.12.0-ce
Engine Labels:
- provider=virtualbox
TLS Info:
TrustRoot:

当节点重新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,就会为每个服务绑定一个随机的高数字端口。你需要检查任务才能确定端口

james@james-CW65:~ > docker service create --name ghostBlog --publish published=80,target=2368 --replicas 1 ghost:1.21.3
xpnc3ga8yvh71zx5dvq94fbsn
overall progress: 1 out of 1 tasks
1/1: running [============================================>]
verify: Service converged
james@james-CW65:~ > docker service ps ghostBlog
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE
ERROR PORTS
5a0tepfqasqu ghostBlog.1 ghost:1.21.3 default
Running Running 18 seconds ago

注意旧版的语法是冒号分开的published:target,例如 -p 8080:80。新语法更易读且灵活。

当你在任何节点访问8080端口时,路由网络将把请求分发到一个active的容器中。在各个节点,8080端口可能并没有绑定,但是路由网络知道如何路由流量,并防止任何端口冲突。

路由网络监听各个节点的IP上的 published port 。从外面看,这些端口是各个节点暴露的。对于别的IP地址,只在该主机内可以访问。

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

james@james-CW65:~ > docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
tynb9d9pu0nq ghost replicated 2/2 ghost:1.21.3
xpnc3ga8yvh7 ghostBlog replicated 1/1 ghost:1.21.3 *:80->2368/tcp
james@james-CW65:~ > docker service update
--publish-add published=8080,target=2368 ghost
ghost
overall progress: 2 out of 2 tasks
1/2: running [============================================>]
2/2: running [============================================>]
verify: Service converged

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

james@james-CW65:~ > docker service inspect --format="{{json
.Endpoint.Spec.Ports}}" ghost
[{"Protocol":"tcp","TargetPort":2368,"PublishedPort":
8080,"PublishMode":"ingress"}]
james@james-CW65:~ > docker service inspect --format="{{json .Endpoint.Spec.Ports}}" ghostBlog
[{"Protocol":"tcp","TargetPort":2368,"PublishedPort"
:80,"PublishMode":"ingress"}]

仅暴露一个TCP或UDP端口

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

仅TCP

长语法
$ docker service create --name dns-cache \
--publish published=53,target=53 \
dns-cache
短语法
$ docker service create --name dns-cache \
-p 53:53 \
dns-cache

TCP和UDP

长语法
$ docker service create --name dns-cache \
--publish published=53,target=53 \
--publish published=53,target=53,protocol=udp \
dns-cache
短语法
$ docker service create --name dns-cache \
-p 53:53 \
-p 53:53/udp \
dns-cache

只暴露UDP

长语法
$ docker service create --name dns-cache \
--publish published=53,target=53,protocol=udp \
dns-cache
短语法
$ docker service create --name dns-cache \
-p 53:53/udp \
dns-cache

绕过路由网络

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

如果该节点上没有服务运行,服务也没有监听端口,则可能无法通信。

你不能在一个节点上运行多个服务实例他们绑定同一个静态target端口。或者你让docker分配随机高数字端口(通过空配置target),或者确保该节点上只运行一个服务实例(通过配置全局服务global service 而不是副本服务,或者使用配置限制)。

为了绕过路由网络,必须使用长格式--publish,设置模式mode为host模式。如果你忽略了mode设置或者设置为内网ingress,则路由网络将启动。下面的命令创建了全局应用使用host模式绕过路由网络:

$ docker service create --name dns-cache \
--publish published=53,target=53,protocol=udp,mode=host \
--mode global \
dns-cache

配置外部的负载均衡

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

使用路由网络

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

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

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

global
log /dev/log local0
log /dev/log local1 notice
...snip...

# Configure HAProxy to listen on port 80
frontend http_front
bind *:80
stats uri /haproxy?stats
default_backend http_back

# Configure HAProxy to route requests to swarm nodes on port 8080
backend http_back
balance roundrobin
server node1 192.168.99.100:8080 check
server node2 192.168.99.101:8080 check
server node3 192.168.99.102:8080 check

当你请求HAProxy的80端口的时候,它会转发请求到后端节点。swarm的路由网络会路由到相应的服务节点。这样无论任何原因swarm的调度器调度服务到不同节点,都不需要重新配置负载均衡。

你可以配置任何类型的负载均衡来分流请求。关于HAProxy参考 HAProxy documentation

不使用路由网络

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

 

   
1879 次浏览       15
相关文章

云计算的架构
对云计算服务模型
云计算核心技术剖析
了解云计算的漏洞
相关文档

云计算简介
云计算简介与云安全
下一代网络计算--云计算
软浅析云计算
相关课程

云计算原理与应用
云计算应用与开发
CMMI体系与实践
基于CMMI标准的软件质量保证