一、什么是Docker Swarm

Swarm是Docker公司推出的用来管理docker集群的平台,几乎全部用GO语言来完成的开发的,代码开源在https://github.com/docker/swarm, 它是将一群Docker宿主机变成一个单一的虚拟主机,Swarm使用标准的Docker API接口作为其前端的访问入口,换言之,各种形式的Docker
Client(compose,docker-py等)均可以直接与Swarm通信,甚至Docker本身都可以很容易的与Swarm集成,这大大方便了用户将原本基于单节点的系统移植到Swarm上,同时Swarm内置了对Docker网络插件的支持,用户也很容易的部署跨主机的容器集群服务。
Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。
从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具,我们就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。
Swarm deamon只是一个调度器(Scheduler)加路由器(router),Swarm自己不运行容器,它只是接受Docker客户端发来的请求,调度适合的节点来运行容器,这就意味着,即使Swarm由于某些原因挂掉了,集群中的节点也会照常运行,放Swarm重新恢复运行之后,他会收集重建集群信息。
二、Docker Swarm 基本结构图

在结构图可以看出 Docker Client使用Swarm对 集群(Cluster)进行调度使用。
上图可以看出,Swarm是典型的master-slave结构,通过发现服务来选举manager。manager是中心管理节点,各个node上运行agent接受manager的统一管理,集群会自动通过Raft协议分布式选举出manager节点,无需额外的发现服务支持,避免了单点的瓶颈问题,同时也内置了DNS的负载均衡和对外部负载均衡机制的集成支持
三.Swarm的几个关键概念
11.Swarm 2集群的管理和编排是使用嵌入docker引擎的SwarmKit,可以在docker初始化时启动swarm模式或者加入已存在的swarm 3 42.Node 5一个节点是docker引擎集群的一个实例。您还可以将其视为Docker节点。您可以在单个物理计算机或云服务器上运行一个或多个节点,但生产群集部署通常包括分布在多个物理和云计算机上的Docker节点。 6要将应用程序部署到swarm,请将服务定义提交给 管理器节点。管理器节点将称为任务的工作单元分派 给工作节点。 7Manager节点还执行维护所需群集状态所需的编排和集群管理功能。Manager节点选择单个领导者来执行编排任务。 8工作节点接收并执行从管理器节点分派的任务。默认情况下,管理器节点还将服务作为工作节点运行,但您可以将它们配置为仅运行管理器任务并且是仅管理器节点。代理程序在每个工作程序节点上运行,并报告分配给它的任务。工作节点向管理器节点通知其分配的任务的当前状态,以便管理器可以维持每个工作者的期望状态。 9 103.Service 11一个服务是任务的定义,管理机或工作节点上执行。它是群体系统的中心结构,是用户与群体交互的主要根源。创建服务时,你需要指定要使用的容器镜像。 12 134.Task 14任务是在docekr容器中执行的命令,Manager节点根据指定数量的任务副本分配任务给worker节点 15 16------------------------------------------使用方法------------------------------------- 17docker swarm:集群管理,子命令有init, join, leave, update。(docker swarm --help查看帮助) 18docker service:服务创建,子命令有create, inspect, update, remove, tasks。(docker service--help查看帮助) 19docker node:节点管理,子命令有accept, promote, demote, inspect, update, tasks, ls, rm。(docker node --help查看帮助) 20 21node是加入到swarm集群中的一个docker引擎实体,可以在一台物理机上运行多个node,node分为: 22manager nodes,也就是管理节点 23worker nodes,也就是工作节点 24 251)manager node管理节点:执行集群的管理功能,维护集群的状态,选举一个leader节点去执行调度任务。 262)worker node工作节点:接收和执行任务。参与容器集群负载调度,仅用于承载task。 273)service服务:一个服务是工作节点上执行任务的定义。创建一个服务,指定了容器所使用的镜像和容器运行的命令。 28 service是运行在worker nodes上的task的描述,service的描述包括使用哪个docker 镜像,以及在使用该镜像的容器中执行什么命令。 294)task任务:一个任务包含了一个容器及其运行的命令。task是service的执行实体,task启动docker容器并在容器中执行任务。
四、Swarm的工作模式
1. Node

2. Service

3. 任务与调度

4. 服务副本与全局服务

五、Swarm的调度策略
1Swarm在调度(scheduler)节点(leader节点)运行容器的时候,会根据指定的策略来计算最适合运行容器的节点,目前支持的策略有:spread, binpack, random. 21)Random 3顾名思义,就是随机选择一个Node来运行容器,一般用作调试用,spread和binpack策略会根据各个节点的可用的CPU, RAM以及正在运 4行的容器的数量来计算应该运行容器的节点。 5 62)Spread 7在同等条件下,Spread策略会选择运行容器最少的那台节点来运行新的容器,binpack策略会选择运行容器最集中的那台机器来运行新的节点。 8使用Spread策略会使得容器会均衡的分布在集群中的各个节点上运行,一旦一个节点挂掉了只会损失少部分的容器。 9 103)Binpack 11Binpack策略最大化的避免容器碎片化,就是说binpack策略尽可能的把还未使用的节点留给需要更大空间的容器运行,尽可能的把容器运行在 12一个节点上面。
六、Swarm Cluster模式特性
11)批量创建服务 2建立容器之前先创建一个overlay的网络,用来保证在不同主机上的容器网络互通的网络模式 3 42)强大的集群的容错性 5当容器副本中的其中某一个或某几个节点宕机后,cluster会根据自己的服务注册发现机制,以及之前设定的值--replicas n, 6在集群中剩余的空闲节点上,重新拉起容器副本。整个副本迁移的过程无需人工干预,迁移后原本的集群的load balance依旧好使! 7不难看出,docker service其实不仅仅是批量启动服务这么简单,而是在集群中定义了一种状态。Cluster会持续检测服务的健康状态 8并维护集群的高可用性。 9 103)服务节点的可扩展性 11Swarm Cluster不光只是提供了优秀的高可用性,同时也提供了节点弹性扩展或缩减的功能。当容器组想动态扩展时,只需通过scale 12参数即可复制出新的副本出来。 13 14仔细观察的话,可以发现所有扩展出来的容器副本都run在原先的节点下面,如果有需求想在每台节点上都run一个相同的副本,方法 15其实很简单,只需要在命令中将"--replicas n"更换成"--mode=global"即可! 16 17复制服务(--replicas n) 18将一系列复制任务分发至各节点当中,具体取决于您所需要的设置状态,例如“--replicas 3”。 19 20全局服务(--mode=global) 21适用于集群内全部可用节点上的服务任务,例如“--mode global”。如果大家在 Swarm 集群中设有 7 台 Docker 节点,则全部节点之上都将存在对应容器。 22 234. 调度机制 24所谓的调度其主要功能是cluster的server端去选择在哪个服务器节点上创建并启动一个容器实例的动作。它是由一个装箱算法和过滤器 25组合而成。每次通过过滤器(constraint)启动容器的时候,swarm cluster 都会调用调度机制筛选出匹配约束条件的服务器,并在这上面运行容器。 26 27------------------Swarm cluster的创建过程包含以下三个步骤---------------------- 281)发现Docker集群中的各个节点,收集节点状态、角色信息,并监视节点状态的变化 292)初始化内部调度(scheduler)模块 303)创建并启动API监听服务模块 31 32一旦创建好这个cluster,就可以用命令docker service批量对集群内的容器进行操作,非常方便! 33 34在启动容器后,docker 会根据当前每个swarm节点的负载判断,在负载最优的节点运行这个task任务,用"docker service ls" 和"docker service ps + taskID" 35可以看到任务运行在哪个节点上。容器启动后,有时需要等待一段时间才能完成容器创建。
七、Dcoker Swarm 集群部署
温馨提示:
机器环境(三台机器,centos系统)
IP:192.168.31.43 主机名:manager43 担任角色:swarm manager
IP:192.168.31.188 主机名:node188 担任角色:swarm node
IP:192.168.31.139 主机名:node139 担任角色:swarm node
1、准备工作
11) 修改主机名 2# 192.168.31.43 主机上执行 3[root@manager43 ~]# hostnamectl set-hostname manager43 4 5# 192.168.31.188 主机上执行 6[root@node188 ~]# hostnamectl set-hostname node188 7 8# 192.168.31.139 主机上执行 9[root@node139 ~]# hostnamectl set-hostname node139 10 112)配置hosts文件(可配置可不配置) 12[root@manager43 ~]# cat /etc/hosts 13127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 14::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 15 16192.168.31.43 manager43 17192.168.31.188 node188 18192.168.31.139 node139 19 20# 使用scp复制到node主机 21[root@manager43 ~]# scp /etc/hosts root@192.168.31.188:/etc/hosts 22[root@manager43 ~]# scp /etc/hosts root@192.168.31.139:/etc/hosts 23 243) 设置防火墙 25关闭三台机器上的防火墙。如果开启防火墙,则需要在所有节点的防火墙上依次放行2377/tcp(管理端口)、7946/udp(节点间通信端口)、4789/udp(overlay 网络端口)端口。 26[root@manager43 ~]# systemctl disable firewalld.service 27[root@manager43 ~]# systemctl stop firewalld.service 28 294) 安装docker并配置加速器(在三台主机都要安装哟...) 30[root@manager43 ~]# yum -y install docker 31[root@node188 ~]# yum -y install docker 32[root@node139 ~]# yum -y install docker
也可以安装最新版docker,可查考:docker安装教程
加速器配置,可查考:docker加速器配置教程
2、创建Swarm并添加节点
11) 创建Swarm集群 2[root@manager43 ~]# docker swarm init --advertise-addr 192.168.31.43 3Swarm initialized: current node (z2n633mty5py7u9wyl423qnq0) is now a manager. 4 5To add a worker to this swarm, run the following command: 6 7 # 这就是添加节点的方式(要保存初始化后token,因为在节点加入时要使用token作为通讯的密钥) 8 docker swarm join --token SWMTKN-1-2lefzq18zohy9yr1vskutf1sfb2a590xz9d0mjj2m15zu9eprw-2938j5f50t35ycut0vbj2sx0s 192.168.31.43:2377 9 10To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. 11 12上面命令执行后,该机器自动加入到swarm集群。这个会创建一个集群token,获取全球唯一的 token,作为集群唯一标识。后续将其他节点加入集群都会用到这个token值。 13其中,--advertise-addr参数表示其它swarm中的worker节点使用此ip地址与manager联系。命令的输出包含了其它节点如何加入集群的命令。 14 15这里无意中遇到了一个小小的问题: 16# 在次执行上面的命令,回报下面的错误 17[root@manager43 ~]# docker swarm init --advertise-addr 192.168.31.43 18Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one. 19# 解决方法 20[root@manager43 ~]# docker swarm leave -f 21这里的leave就是在集群中删除节点,-f参数强制删除,执行完在重新执行OK 22 232) 查看集群的相关信息 24[root@manager43 ~]# docker info 25上面的命令执行后 找到Swarm的关键字,就可以看到相关信息了 26 27[root@manager43 ~]# docker node ls 28ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION 293jcmnzjh0e99ipgshk1ykuovd * manager43 Ready Active Leader 18.06.0-ce 30上面的命令是查看集群中的机器(注意上面node ID旁边那个*号表示现在连接到这个节点上) 31 323) 添加节点主机到Swarm集群 33上面我们在创建Swarm集群的时候就已经给出了添加节点的方法 34 35# 192.168.31.188 主机上执行 36[root@node188 ~]# docker swarm join --token SWMTKN-1-2lefzq18zohy9yr1vskutf1sfb2a590xz9d0mjj2m15zu9eprw-2938j5f50t35ycut0vbj2sx0s 192.168.31.43:2377 37This node joined a swarm as a worker. 38 39# 192.168.31.139 主机上执行 40[root@node139 ~]# docker swarm join --token SWMTKN-1-2lefzq18zohy9yr1vskutf1sfb2a590xz9d0mjj2m15zu9eprw-2938j5f50t35ycut0vbj2sx0s 192.168.31.43:2377 41This node joined a swarm as a worker. 42 43如果想要将其他更多的节点添加到这个swarm集群中,添加方法如上一致 44 45在manager43主机上我们可以看一下集群中的机器及状态 46[root@manager43 ~]# docker node ls 47ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION 483jcmnzjh0e99ipgshk1ykuovd * manager43 Ready Active Leader 18.06.0-ce 49vww7ue2xprzg46bjx7afo4h04 node139 Ready Active 18.06.1-ce 50c5klw5ns4adcvumzgiv66xpyj node188 Ready Active 18.06.1-ce 51 52-------------------------------------------------------------------------------------------------------------------- 53温馨提示:更改节点的availablity状态 54swarm集群中node的availability状态可以为 active或者drain,其中: 55active状态下,node可以接受来自manager节点的任务分派; 56drain状态下,node节点会结束task,且不再接受来自manager节点的任务分派(也就是下线节点) 57[root@manager43 ~]# docker node update --availability drain node139 # 将node139节点下线。如果要删除node139节点,命令是"docker node rm --force node139" 58node139 59[root@manager43 ~]# docker node ls 60ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION 613jcmnzjh0e99ipgshk1ykuovd * manager43 Ready Active Leader 18.06.0-ce 62vww7ue2xprzg46bjx7afo4h04 node139 Ready Drain 18.06.1-ce 63c5klw5ns4adcvumzgiv66xpyj node188 Ready Active 18.06.1-ce 64 65如上,当node1的状态改为drain后,那么该节点就不会接受task任务分发,就算之前已经接受的任务也会转移到别的节点上。 66再次修改为active状态(及将下线的节点再次上线) 67[root@manager43 ~]# docker node update --availability active node139 68node139 69[root@manager43 ~]# docker node ls 70ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION 713jcmnzjh0e99ipgshk1ykuovd * manager43 Ready Active Leader 18.06.0-ce 72vww7ue2xprzg46bjx7afo4h04 node139 Ready Active 18.06.1-ce 73c5klw5ns4adcvumzgiv66xpyj node188 Ready Active 18.06.1-ce
3、在Swarm中部署服务(nginx为例)
1Docker 1.12版本提供服务的Scaling、health check、滚动升级等功能,并提供了内置的dns、vip机制,实现service的服务发现和负载均衡能力 21) 创建网络在部署服务 3# 创建网络 4[root@manager43 ~]# docker network create -d overlay nginx_net 5a52jy33asc5o0ts0rq823bf0m 6[root@manager43 ~]# docker network ls | grep nginx_net 7a52jy33asc5o nginx_net overlay swarm 8 9# 部署服务 10[root@manager43 ~]# docker service create --replicas 1 --network nginx_net --name my_nginx -p 80:80 nginx # 就创建了一个具有一个副本(--replicas 1 )的nginx服务,使用镜像nginx 11olexfmtdf94sxyeetkchwhehg 12overall progress: 1 out of 1 tasks 131/1: running [==================================================>] 14verify: Service converged 15在manager-node节点上使用上面这个覆盖网络创建nginx服务: 16其中,--replicas 参数指定服务由几个实例组成。 17注意:不需要提前在节点上下载nginx镜像,这个命令执行后会自动下载这个容器镜像(比如此处创建tomcat容器,就将下面命令中的镜像改为tomcat镜像)。 18 19# 使用 docker service ls 查看正在运行服务的列表 20[root@manager43 ~]# docker service ls 21ID NAME MODE REPLICAS IMAGE PORTS 22olexfmtdf94s my_nginx replicated 1/1 nginx:latest *:80->80/tcp 23 242) 查询Swarm中服务的信息 25-pretty 使命令输出格式化为可读的格式,不加 --pretty 可以输出更详细的信息: 26[root@manager43 ~]# docker service inspect --pretty my_nginx 27ID: zs7fw4ereo5w7ohd4n9ii06nt 28Name: my_nginx 29Service Mode: Replicated 30 Replicas: 1 31Placement: 32UpdateConfig: 33 Parallelism: 1 34 On failure: pause 35 Monitoring Period: 5s 36 Max failure ratio: 0 37 Update order: stop-first 38RollbackConfig: 39 Parallelism: 1 40 On failure: pause 41 Monitoring Period: 5s 42 Max failure ratio: 0 43 Rollback order: stop-first 44ContainerSpec: 45 Image: nginx:latest@sha256:b73f527d86e3461fd652f62cf47e7b375196063bbbd503e853af5be16597cb2e 46 Init: false 47Resources: 48Networks: nginx_net 49Endpoint Mode: vip 50Ports: 51 PublishedPort = 80 52 Protocol = tcp 53 TargetPort = 80 54 PublishMode = ingress 55 56# 查询到哪个节点正在运行该服务。如下该容器被调度到manager-node节点上启动了,然后访问http://192.168.31.43即可访问这个容器应用(如果调度到其他节点,访问也是如此) 57[root@manager43 ~]# docker service ps my_nginx 58ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 59yzonph0zu7km my_nginx.1 nginx:latest manager43 Running Running about an hour ago 60温馨提示:如果上面命令执行后,上面的 STATE 字段中刚开始的服务状态为 Preparing,需要等一会才能变为 Running 状态,其中最费时间的应该是下载镜像的过程 61 62有上面命令可知,该服务在manager-node节点上运行。登陆该节点,可以查看到nginx容器在运行中 63[root@manager43 ~]# docker ps 64CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 650dc7103f8030 nginx:latest "nginx -g 'daemon of…" About an hour ago Up About an hour 80/tcp my_nginx.1.yzonph0zu7km0211uj0ro5brj 66 673) 在Swarm中动态扩展服务(scale) 68当然,如果只是通过service启动容器,swarm也算不上什么新鲜东西了。Service还提供了复制(类似kubernetes里的副本)功能。可以通过 docker service scale 命令来设置服务中容器的副本数 69比如将上面的my_nginx容器动态扩展到4个 70[root@manager43 ~]# docker service scale my_nginx=4 71my_nginx scaled to 4 72overall progress: 4 out of 4 tasks 731/4: running [==================================================>] 742/4: running [==================================================>] 753/4: running [==================================================>] 764/4: running [==================================================>] 77verify: Service converged 78 79和创建服务一样,增加scale数之后,将会创建新的容器,这些新启动的容器也会经历从准备到运行的过程,过一分钟左右,服务应该就会启动完成,这时候可以再来看一下 nginx 服务中的容器 80[root@manager43 ~]# docker service ps my_nginx 81ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 82yzonph0zu7km my_nginx.1 nginx:latest manager43 Running Running about an hour ago 83mlprstt9ds5x my_nginx.2 nginx:latest node139 Running Running 52 seconds ago 84y09lk90tdzdp my_nginx.3 nginx:latest node139 Running Running 52 seconds ago 85clolfl3zlvj0 my_nginx.4 nginx:latest node188 Running Running 2 minutes ago 86 87可以看到,之前my_nginx容器只在manager-node节点上有一个实例,而现在又增加了3个实例。 88这4个副本的my_nginx容器分别运行在这三个节点上,登陆这三个节点,就会发现已经存在运行着的my_nginx容器 89 90 914) 模拟宕机node节点 92特别需要清楚的一点: 93如果一个节点宕机了(即该节点就会从swarm集群中被踢出),则Docker应该会将在该节点运行的容器,调度到其他节点,以满足指定数量的副本保持运行状态。 94 95比如: 96将node139宕机后或将node139的docker服务关闭,那么它上面的task实例就会转移到别的节点上。当node139节点恢复后,它转移出去的task实例不会主动转移回来, 97只能等别的节点出现故障后转移task实例到它的上面。使用命令"docker node ls",发现node139节点已不在swarm集群中了(状态为:Down)。 98[root@node139 ~]# systemctl stop docker 99[root@manager43 ~]# docker node ls 100ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION 101ppk7q0bjond8a58xja7in1qid * manager43 Ready Active Leader 18.06.0-ce 102mums8azgbrffnecp3q8fz70pl node139 Down Active 18.06.1-ce 103z3n36maf03yjg7odghikuv574 node188 Ready Active 18.06.1-ce 104 105然后过一会查询服务的状态列表 106[root@manager43 ~]# docker service ps my_nginx 107ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 108yzonph0zu7km my_nginx.1 nginx:latest manager43 Running Running about an hour ago 109wb1cpk9k22rl my_nginx.2 nginx:latest node188 Running Running about a minute ago 110mlprstt9ds5x \_ my_nginx.2 nginx:latest node139 Shutdown Running 4 minutes ago 111rhbj4bcr4t2c my_nginx.3 nginx:latest manager43 Running Running about a minute ago 112y09lk90tdzdp \_ my_nginx.3 nginx:latest node139 Shutdown Running 4 minutes ago 113clolfl3zlvj0 my_nginx.4 nginx:latest node188 Running Running 6 minutes ago 114 115上面我们可以发现node139故障后,它上面之前的两个task任务已经转移到node188和manager43节点上了 116 117登陆到node188和manager43节点上,可以看到这两个运行的task任务。当访问192.168.31.188和192.168.31.43节点的80端口,swarm的负载均衡会把请求路由到一个任意节点的可用的容器上 118[root@manager43 ~]# docker ps -a 119CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 120ae4c5c2e6f3f nginx:latest "nginx -g 'daemon of…" 4 minutes ago Up 4 minutes 80/tcp my_nginx.3.rhbj4bcr4t2c3y2f8vyfmbi21 1210dc7103f8030 nginx:latest "nginx -g 'daemon of…" About an hour ago Up About an hour 80/tcp my_nginx.1.yzonph0zu7km0211uj0ro5brj 122 123[root@node188 ~]# docker ps -a 124CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 125a63ef253f7dd nginx:latest "nginx -g 'daemon of…" 3 minutes ago Up 3 minutes 80/tcp my_nginx.2.wb1cpk9k22rl1ydab7aozl2b5 12674a1a1db81d4 nginx:latest "nginx -g 'daemon of…" 8 minutes ago Up 8 minutes 80/tcp my_nginx.4.clolfl3zlvj0ewmh85c2ljnza 127 128再次在node188和manager43节点上将从node139上转移过来的两个task关闭 129[root@manager43 ~]# docker stop my_nginx.3.rhbj4bcr4t2c3y2f8vyfmbi21 130my_nginx.3.rhbj4bcr4t2c3y2f8vyfmbi21 131 132[root@node188 ~]# docker stop my_nginx.2.wb1cpk9k22rl1ydab7aozl2b5 133my_nginx.2.wb1cpk9k22rl1ydab7aozl2b5 134 135再次查询服务的状态列表,发现这两个task又转移到node139上了 136[root@manager43 ~]# docker service ps my_nginx 137ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 138yzonph0zu7km my_nginx.1 nginx:latest manager43 Running Running 2 hours ago 139j2q61f8jtzba my_nginx.2 nginx:latest node188 Running Running 24 seconds ago 140wb1cpk9k22rl \_ my_nginx.2 nginx:latest node188 Shutdown Complete 29 seconds ago 141mlprstt9ds5x \_ my_nginx.2 nginx:latest node139 Shutdown Running 11 minutes ago 142oz9wyjuldw1t my_nginx.3 nginx:latest manager43 Running Running 40 seconds ago 143rhbj4bcr4t2c \_ my_nginx.3 nginx:latest manager43 Shutdown Complete 45 seconds ago 144y09lk90tdzdp \_ my_nginx.3 nginx:latest node139 Shutdown Running 11 minutes ago 145clolfl3zlvj0 my_nginx.4 nginx:latest node188 Running Running 12 minutes ago 146结论:即在swarm cluster集群中启动的容器,在worker node节点上删除或停用后,该容器会自动转移到其他的worker node节点上 147 148 1495) Swarm 动态缩容服务(scale) 150同理,swarm还可以缩容,同样是使用scale命令 151如下,将my_nginx容器变为1个 152[root@manager43 ~]# docker service scale my_nginx=1 153my_nginx scaled to 1 154overall progress: 1 out of 1 tasks 1551/1: 156verify: Service converged 157 158[root@manager43 ~]# docker service ls 159ID NAME MODE REPLICAS IMAGE PORTS 160zs7fw4ereo5w my_nginx replicated 1/1 nginx:latest *:80->80/tcp 161 162[root@manager43 ~]# docker service ps my_nginx 163ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 164yzonph0zu7km my_nginx.1 nginx:latest manager43 Running Running 11 hours ago 165wb1cpk9k22rl my_nginx.2 nginx:latest node188 Shutdown Complete 9 hours ago 166mlprstt9ds5x \_ my_nginx.2 nginx:latest node139 Shutdown Shutdown 29 seconds ago 167rhbj4bcr4t2c my_nginx.3 nginx:latest manager43 Shutdown Complete 9 hours ago 168y09lk90tdzdp \_ my_nginx.3 nginx:latest node139 Shutdown Shutdown 29 seconds ago 169 170通过docker service ps my_nginx 可以看到node节点上已经为Shutdown状态了 171 172在登录到node节点主机上查看 173[root@node188 ~]# docker ps -a 174CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 175f93c0a27374a nginx:latest "nginx -g 'daemon of…" 9 hours ago Exited (0) 44 seconds ago my_nginx.2.j2q61f8jtzba9kb3unupkhl25 176a63ef253f7dd nginx:latest "nginx -g 'daemon of…" 9 hours ago Exited (0) 9 hours ago my_nginx.2.wb1cpk9k22rl1ydab7aozl2b5 177[root@node139 ~]# docker ps -a 178CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 179e8ac2e44f5c4 nginx:latest "nginx -g 'daemon of…" 9 hours ago Exited (0) 9 hours ago my_nginx.2.mlprstt9ds5xi48u1rzscgfdk 1805b031aa5a2cc nginx:latest "nginx -g 'daemon of…" 9 hours ago Exited (0) 9 hours ago my_nginx.3.y09lk90tdzdp8cwj6mm5oyr3f 181登录node节点,使用docker ps -a 查看,会发现容器被stop而非rm 182 1836) 除了上面使用scale进行容器的扩容或缩容之外,还可以使用docker service update 命令。 可对 服务的启动 参数 进行 更新/修改。 184[root@manager43 ~]# docker service update --replicas 3 my_nginx 185my_nginx 186overall progress: 3 out of 3 tasks 1871/3: running [==================================================>] 1882/3: running [==================================================>] 1893/3: running [==================================================>] 190verify: Service converged 191 192[root@manager43 ~]# docker service ls 193ID NAME MODE REPLICAS IMAGE PORTS 194zs7fw4ereo5w my_nginx replicated 3/3 nginx:latest *:80->80/tcp 195 196[root@manager43 ~]# docker service ps my_nginx 197ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 198yzonph0zu7km my_nginx.1 nginx:latest manager43 Running Running 11 hours ago 199j3hduzd9pret my_nginx.2 nginx:latest node188 Running Running 18 seconds ago 200wb1cpk9k22rl \_ my_nginx.2 nginx:latest node188 Shutdown Complete 9 hours ago 201mlprstt9ds5x \_ my_nginx.2 nginx:latest node139 Shutdown Shutdown 4 minutes ago 202gng96vc5vqpv my_nginx.3 nginx:latest node139 Running Running 18 seconds ago 203rhbj4bcr4t2c \_ my_nginx.3 nginx:latest manager43 Shutdown Complete 9 hours ago 204y09lk90tdzdp \_ my_nginx.3 nginx:latest node139 Shutdown Shutdown 4 minutes ago 205 206docker service update 命令,也可用于直接 升级 镜像等 207[root@manager43 ~]# docker service update --image nginx:new my_nginx 208 209[root@manager43 ~]# docker service ls 210ID NAME MODE REPLICAS IMAGE PORTS 211zs7fw4ereo5w my_nginx replicated 3/3 nginx:new *:80->80/tcp 212注意IMAGE列 变成了nginx:new 213 214 2157) 为了下面的直观显示,我这里把my_nginx服务直接删除了 216[root@manager43 ~]# docker service rm my_nginx 217 218这样就会把所有节点上的所有容器(task任务实例)全部删除了
4、Swarm中使用Volume(挂在目录,mount命令)
11) 查看volume的帮助信息 2[root@manager43 ~]# docker volume --help 3 4Usage: docker volume COMMAND 5 6Manage volumes 7 8Commands: 9 create Create a volume 10 inspect Display detailed information on one or more volumes 11 ls List volumes 12 prune Remove all unused local volumes 13 rm Remove one or more volumes 14 15Run 'docker volume COMMAND --help' for more information on a command. 16 172) 创建一个volume 18[root@manager43 ~]# docker volume create --name testvolume 19testvolume 20 21# 查看创建的volume 22[root@manager43 ~]# docker volume ls 23DRIVER VOLUME NAME 24local testvolume 25 26# 查看volume详情 27[root@manager43 ~]# docker volume inspect testvolume 28[ 29 { 30 "CreatedAt": "2018-10-21T10:50:02+08:00", 31 "Driver": "local", 32 "Labels": {}, 33 "Mountpoint": "/var/lib/docker/volumes/testvolume/_data", 34 "Name": "testvolume", 35 "Options": {}, 36 "Scope": "local" 37 } 38] 39 40 413) 创建新的服务并挂载testvolume(nginx为例) 42[root@manager43 ~]# docker service create --replicas 3 --mount type=volume,src=testvolume,dst=/zjz --name test_nginx nginx 43sh7wc8yzcvr0xaedo4tnraj7l 44overall progress: 3 out of 3 tasks 451/3: running [==================================================>] 462/3: running [==================================================>] 473/3: running [==================================================>] 48verify: Service converged 49 50温馨提示: 51参数src写成source也可以;dst表示容器内的路径,也可以写成target 52 53# 查看创建服务 54[root@manager43 ~]# docker service ls 55ID NAME MODE REPLICAS IMAGE PORTS 56sh7wc8yzcvr0 test_nginx replicated 3/3 nginx:latest 57[root@manager43 ~]# docker service ps test_nginx 58ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 59m7m41kwt4q6w test_nginx.1 nginx:latest node188 Running Running 56 seconds ago 60kayh81q1o1kx test_nginx.2 nginx:latest node139 Running Running 56 seconds ago 61eq11v0rcwy38 test_nginx.3 nginx:latest manager43 Running Running 56 seconds ago 62 63# 查看有没有挂载成功(登录各个节点的容器看看有没有指定的目录并创建文件测试) 64# 容器中操作 65[root@manager43 ~]# docker exec -it 63451219cb4e /bin/bash 66root@63451219cb4e:/# cd /zjz/ 67root@63451219cb4e:/zjz# ls 68root@63451219cb4e:/zjz# echo "gen wo xue docker" > docker.txt 69root@63451219cb4e:/zjz# ls 70docker.txt 71 72执行docker volume inspect testvolume 可以看到本地的路径(上面已经执行过了) 73本地路径:/var/lib/docker/volumes/testvolume/_data 74[root@manager43 ~]# cd /var/lib/docker/volumes/testvolume/_data 75[root@manager43 _data]# ls 76docker.txt 77[root@manager43 _data]# cat docker.txt 78gen wo xue docker 79 80还可以将node节点机上的volume数据目录做成软链接 81[root@manager43 _data]# ln -s /var/lib/docker/volumes/testvolume/_data /zjz 82[root@manager43 _data]# cd /zjz/ 83[root@manager43 zjz]# ls 84docker.txt 85[root@manager43 zjz]# echo "123" > 1.txt 86[root@manager43 zjz]# ll 87总用量 8 88-rw-r--r-- 1 root root 4 10月 21 11:04 1.txt 89-rw-r--r-- 1 root root 18 10月 21 11:00 docker.txt 90 91# 容器中查看 92[root@manager43 zjz]# docker exec -it 63451219cb4e /bin/bash 93root@63451219cb4e:/# cd /zjz/ 94root@63451219cb4e:/zjz# ls 951.txt docker.txt 96root@63451219cb4e:/zjz# cat 1.txt 97123 98root@63451219cb4e:/zjz# cat docker.txt 99gen wo xue docker 100 101# 还有一种挂载方式简单说一下吧,上面的会了下面的肯定简单 102命令格式: 103docker service create --mount type=bind,target=/container_data/,source=/host_data/ 104其中,参数target表示容器里面的路径,source表示本地硬盘路径 105 106# 示例创建并挂载并使用网络 107[root@manager43 ~]# docker service create --replicas 1 --mount type=bind,target=/usr/share/nginx/html/,source=/opt/web/ --network nginx_net --name zjz_nginx -p 8880:80 nginx
5、多服务Swarm集群部署
问:上面我们只是对单独的一个nginx服务进行的集群部署,那如果要统一编排多个服务呢?
答:docker 三剑客中有个compose 这个就是对单机进行统一编排的,它的实现是通过docker-compose.yml的文件,这里我们就可以结合compose和swarm进行多服务的编排(docker compose教程)
1温馨提示: 2我们这里要部署的服务有三个(nginx服务,visualizer服务,portainer服务) 都是集群 GUI 管理服务 3docker service部署的是单个服务,我们可以使用docker stack进行多服务编排部署 4 51) 编写docker-compose.yml文件 6[root@manager43 ~]# mkdir testswarm 7[root@manager43 ~]# cd testswarm/ 8[root@manager43 testswarm]# cat docker-compose.yml 9version: "3" 10services: 11 nginx: 12 image: nginx 13 ports: 14 - 8888:80 15 deploy: 16 mode: replicated 17 replocas: 3 18 19 visualizer: 20 image: dockersamples/visualizer 21 ports: 22 - "8080:8080" 23 volumes: 24 - "/var/run/docker.sock:/var/run/docker.sock" 25 deploy: 26 replicas: 1 27 placement: 28 constraints: [node.role == manager] 29 30 portainer: 31 image: portainer/portainer 32 ports: 33 - "9000:9000" 34 volumes: 35 - "/var/run/docker.sock:/var/run/docker.sock" 36 deploy: 37 replicas: 1 38 placement: 39 constraints: [node.role == manager] 40 412) 通过这个yml文件部署服务 42[root@manager43 testswarm]# docker stack deploy -c docker-compose.yml deploy_deamon 43Creating network deploy_deamon_default 44Creating service deploy_deamon_portainer 45Creating service deploy_deamon_nginx 46Creating service deploy_deamon_visualizer 47 48通过上面的执行过程可以看出这样创建会默认创建一个网络并使用它,名字都是我们给的名字的前缀加上服务名 49 50# 查看创建服务 51[root@manager43 testswarm]# docker service ls 52ID NAME MODE REPLICAS IMAGE PORTS 53xj2f1t5ax3nm deploy_deamon_nginx replicated 3/3 nginx:latest *:8888->80/tcp 54ky9qpldr5abb deploy_deamon_portainer replicated 1/1 portainer/portainer:latest *:9000->9000/tcp 55r47ff177x1ir deploy_deamon_visualizer replicated 1/1 dockersamples/visualizer:latest *:8080->8080/tcp 56 57[root@manager43 testswarm]# docker service ps deploy_deamon_nginx 58ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 59z3v4uc1ujsnq deploy_deamon_nginx.1 nginx:latest node139 Running Running about a minute ago 60jhg3ups0cko5 deploy_deamon_nginx.2 nginx:latest manager43 Running Running about a minute ago 613e6guv791x21 deploy_deamon_nginx.3 nginx:latest node188 Running Running about a minute ago 62 63[root@manager43 testswarm]# docker service ps deploy_deamon_portainer 64ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 65whyuvy82cvvw deploy_deamon_portainer.1 portainer/portainer:latest manager43 Running Running about a minute ago 66 67[root@manager43 testswarm]# docker service ps deploy_deamon_visualizer 68ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 69wge5w1eqykg3 deploy_deamon_visualizer.1 dockersamples/visualizer:latest manager43 Running Starting 7 seconds ago
测试





八、Docker Swarm 容器网络
1在Docker版本1.12之后swarm模式原生支持覆盖网络(overlay networks),可以先创建一个覆盖网络,然后启动容器的时候启用这个覆盖网络, 2这样只要是这个覆盖网络内的容器,不管在不在同一个宿主机上都能相互通信,即跨主机通信!不同覆盖网络内的容器组之间是相互隔离的(相互ping不通)。 3 4swarm模式的覆盖网络包括以下功能: 51)可以附加多个服务到同一个网络。 62)默认情况下,service discovery为每个swarm服务分配一个虚拟IP地址(vip)和DNS名称,使得在同一个网络中容器之间可以使用服务名称为互相连接。 73)可以配置使用DNS轮循而不使用VIP 84)为了可以使用swarm的覆盖网络,在启用swarm模式之间你需要在swarm节点之间开放以下端口: 95)TCP/UDP端口7946 – 用于容器网络发现 106)UDP端口4789 – 用于容器覆盖网络 11 12实例如下: 13-----------在Swarm集群中创建overlay网络------------ 14[root@manager-node ~]# docker network create --driver overlay --opt encrypted --subnet 10.10.19.0/24 ngx_net 15 16参数解释: 17–opt encrypted 默认情况下swarm中的节点通信是加密的。在不同节点的容器之间,可选的–opt encrypted参数能在它们的vxlan流量启用附加的加密层。 18--subnet 命令行参数指定overlay网络使用的子网网段。当不指定一个子网时,swarm管理器自动选择一个子网并分配给网络。 19 20[root@manager-node ~]# docker network ls 21NETWORK ID NAME DRIVER SCOPE 22d7aa48d3e485 bridge bridge local 239e637a97a3b9 docker_gwbridge bridge local 24b5a41c8c71e7 host host local 257f4fx3jf4dbr ingress overlay swarm 263x2wgugr6zmn ngx_net overlay swarm 270808a5c72a0a none null local 28 29由上可知,Swarm当中拥有2套覆盖网络。其中"ngx_net"网络正是我们在部署容器时所创建的成果。而"ingress"覆盖网络则为默认提供。 30Swarm 管理节点会利用 ingress 负载均衡以将服务公布至集群之外。 31在将服务连接到这个创建的网络之前,网络覆盖到manager节点。上面输出的SCOPE为 swarm 表示将服务部署到Swarm时可以使用此网络。 32在将服务连接到这个网络后,Swarm只将该网络扩展到特定的worker节点,这个worker节点被swarm调度器分配了运行服务的任务。 33在那些没有运行该服务任务的worker节点上,网络并不扩展到该节点。 34 35------------------将服务连接到overlay网络------------------- 36[root@manager-node ~]# docker service create --replicas 5 --network ngx_net --name my-test -p 80:80 nginx 37 38上面名为"my-test"的服务启动了3个task,用于运行每个任务的容器都可以彼此通过overlay网络进行通信。Swarm集群将网络扩展到所有任务处于Running状态的节点上。 39[root@manager-node ~]# docker service ls 40ID NAME REPLICAS IMAGE COMMAND 41dsaxs6v463g9 my-test 5/5 nginx 42 43在manager-node节点上,通过下面的命令查看哪些节点有处于running状态的任务: 44[root@manager-node ~]# docker service ps my-test 45ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 468433fuiy7vpu0p80arl7vggfe my-test.1 nginx node2 Running Running 2 minutes ago 47f1h7a0vtojv18zrsiw8j0rzaw my-test.2 nginx node1 Running Running 2 minutes ago 48ex73ifk3jvzw8ukurl8yu7fyq my-test.3 nginx node1 Running Running 2 minutes ago 49cyu73jd8psupfhken23vvmpud my-test.4 nginx manager-node Running Running 2 minutes ago 50btorxekfix4hcqh4v83dr0tzw my-test.5 nginx manager-node Running Running 2 minutes ago 51 52可见三个节点都有处于running状态的任务,所以my-network网络扩展到三个节点上。 53 54可以查询某个节点上关于my-network的详细信息: 55[root@manager-node ~]# docker network inspect ngx_net 56[ 57 { 58 "Name": "ngx_net", 59 "Id": "3x2wgugr6zmn1mcyf9k1du27p", 60 "Scope": "swarm", 61 "Driver": "overlay", 62 "EnableIPv6": false, 63 "IPAM": { 64 "Driver": "default", 65 "Options": null, 66 "Config": [ 67 { 68 "Subnet": "10.10.19.0/24", 69 "Gateway": "10.10.19.1" 70 } 71 ] 72 }, 73 "Internal": false, 74 "Containers": { 75 "00f47e38deea76269eb03ba13695ec0b0c740601c85019546d6a9a17fd434663": { 76 "Name": "my-test.5.btorxekfix4hcqh4v83dr0tzw", 77 "EndpointID": "ea962d07eee150b263ae631b8a7f8c1950337c11ef2c3d488a7c3717defd8601", 78 "MacAddress": "02:42:0a:0a:13:03", 79 "IPv4Address": "10.10.19.3/24", 80 "IPv6Address": "" 81 }, 82 "957620c6f7abb44ad8dd2d842d333f5e5c1655034dc43e49abbbd680de3a5341": { 83 "Name": "my-test.4.cyu73jd8psupfhken23vvmpud", 84 "EndpointID": "f33a6e9ddf1dd01bcfc43ffefd19e19514658f001cdf9b2fbe23bc3fdf56a42a", 85 "MacAddress": "02:42:0a:0a:13:07", 86 "IPv4Address": "10.10.19.7/24", 87 "IPv6Address": "" 88 } 89 }, 90 "Options": { 91 "com.docker.network.driver.overlay.vxlanid_list": "257" 92 }, 93 "Labels": {} 94 } 95] 96 97从上面的信息可以看出在manager-node节点上,名为my-test的服务有一个名为my-test.5.btorxekfix4hcqh4v83dr0tzw和 98my-test.4.cyu73jd8psupfhken23vvmpud的task连接到名为ngx_net的网络上(另外两个节点node1和node2同样可以用上面命令查看) 99[root@node1 ~]# docker network inspect ngx_net 100....... 101 "Containers": { 102 "7d9986fad5a7d834676ba76ae75aff2258f840953f1dc633c3ef3c0efd2b2501": { 103 "Name": "my-test.3.ex73ifk3jvzw8ukurl8yu7fyq", 104 "EndpointID": "957ca19f3d5480762dbd14fd9a6a1cd01a8deac3e8e35b23d1350f480a7b2f37", 105 "MacAddress": "02:42:0a:0a:13:06", 106 "IPv4Address": "10.10.19.6/24", 107 "IPv6Address": "" 108 }, 109 "9e50fceada1d7c653a886ca29d2bf2606debafe8c8a97f2d79104faf3ecf8a46": { 110 "Name": "my-test.2.f1h7a0vtojv18zrsiw8j0rzaw", 111 "EndpointID": "b1c209c7b68634e88e0bf5e100fe03435b3096054da6555c61e6c207ac651ac2", 112 "MacAddress": "02:42:0a:0a:13:05", 113 "IPv4Address": "10.10.19.5/24", 114 "IPv6Address": "" 115 } 116 }, 117......... 118 119[root@node2 web]# docker network inspect ngx_net 120........ 121 "Containers": { 122 "4bdcce0ee63edc08d943cf4a049eac027719ff2dc14b7c3aa85fdddc5d1da968": { 123 "Name": "my-test.1.8433fuiy7vpu0p80arl7vggfe", 124 "EndpointID": "df58de85b0a0e4d128bf332fc783f6528d1f179b0f9f3b7aa70ebc832640d3bc", 125 "MacAddress": "02:42:0a:0a:13:04", 126 "IPv4Address": "10.10.19.4/24", 127 "IPv6Address": "" 128 } 129 }, 130 131可以通过查询服务来获得服务的虚拟IP地址,如下: 132[root@manager-node ~]# docker service inspect --format='{{json .Endpoint.VirtualIPs}}' my-test 133[{"NetworkID":"7f4fx3jf4dbrp97aioc05pul4","Addr":"10.255.0.6/16"},{"NetworkID":"3x2wgugr6zmn1mcyf9k1du27p","Addr":"10.10.19.2/24"}] 134 135由上结果可知,10.10.19.2其实就是swarm集群内部的vip,整个网络结构如下图所示:

加入ngx_net网络的容器彼此之间可以通过IP地址通信,也可以通过名称通信。
1[root@node2 ~]# docker ps 2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 34bdcce0ee63e nginx:latest "nginx -g 'daemon off" 22 minutes ago Up 22 minutes 80/tcp my-test.1.8433fuiy7vpu0p80arl7vggfe 4 5[root@node2 ~]# docker exec -ti 4bdcce0ee63e /bin/bash 6root@4bdcce0ee63e:/# ip addr 71: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 8 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 9 inet 127.0.0.1/8 scope host lo 10 valid_lft forever preferred_lft forever 11 inet6 ::1/128 scope host 12 valid_lft forever preferred_lft forever 131786: eth0@if1787: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default 14 link/ether 02:42:0a:ff:00:08 brd ff:ff:ff:ff:ff:ff link-netnsid 0 15 inet 10.255.0.8/16 scope global eth0 16 valid_lft forever preferred_lft forever 17 inet 10.255.0.6/32 scope global eth0 18 valid_lft forever preferred_lft forever 19 inet6 fe80::42:aff:feff:8/64 scope link 20 valid_lft forever preferred_lft forever 211788: eth1@if1789: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 22 link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 1 23 inet 172.18.0.3/16 scope global eth1 24 valid_lft forever preferred_lft forever 25 inet6 fe80::42:acff:fe12:3/64 scope link 26 valid_lft forever preferred_lft forever 271791: eth2@if1792: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default 28 link/ether 02:42:0a:0a:13:04 brd ff:ff:ff:ff:ff:ff link-netnsid 2 29 inet 10.10.19.4/24 scope global eth2 30 valid_lft forever preferred_lft forever 31 inet 10.10.19.2/32 scope global eth2 32 valid_lft forever preferred_lft forever 33 inet6 fe80::42:aff:fe0a:1304/64 scope link 34 valid_lft forever preferred_lft forever 35 36root@4bdcce0ee63e:/# ping 10.10.19.3 37PING 10.10.19.3 (10.10.19.3): 56 data bytes 3864 bytes from 10.10.19.3: icmp_seq=0 ttl=64 time=0.890 ms 3964 bytes from 10.10.19.3: icmp_seq=1 ttl=64 time=0.622 ms 40.....- 412 packets transmitted, 2 packets received, 0% packet loss 42round-trip min/avg/max/stddev = 0.622/0.756/0.890/0.134 ms 43 44root@4bdcce0ee63e:/# ping 10.10.19.6 45PING 10.10.19.6 (10.10.19.6): 56 data bytes 4664 bytes from 10.10.19.6: icmp_seq=0 ttl=64 time=0.939 ms 4764 bytes from 10.10.19.6: icmp_seq=1 ttl=64 time=0.590 ms 48 49----------------------------使用swarm模式的服务发现-------------------------- 50默认情况下,当创建了一个服务并连接到某个网络后,swarm会为该服务分配一个VIP。此VIP根据服务名映射到DNS。在网络上的容器共享该服务的DNS映射, 51所以网络上的任意容器可以通过服务名访问服务。 52 53在同一overlay网络中,不用通过端口映射来使某个服务可以被其它服务访问。Swarm内部的负载均衡器自动将请求发送到服务的VIP上,然后分发到所有的 54active的task上。 55 56如下示例: 57在同一个网络中添加了一个centos服务,此服务可以通过名称my-test访问前面创建的nginx服务: 58[root@manager-node ~]# docker service create --name my-centos --network ngx_net centos 59 60查询centos运行在哪个节点上(上面创建命令执行后,需要一段时间才能完成这个centos服务的创建) 61[root@manager-node ~]# docker service ps my-centos 62ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 63e03pqgkjs3l1qizc6v4aqaune my-centos.1 centos node2 Running Preparing 4 seconds ago 64 65登录centos运行的节点(由上可知是node2节点),打开centos的交互shell: 66[root@node2 ~]# docker ps 67CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES 68e4554490d891 centos:latest "/bin/bash" About an hour ago Up About an hour my-centos.1.9yk5ie28gwk9mw1h1jovb68ki 69 70[root@node2 ~]# docker exec -ti my-centos.1.9yk5ie28gwk9mw1h1jovb68ki /bin/bash 71root@4bdcce0ee63e:/# nslookup my-test 72Server: 127.0.0.11 73Address 1: 127.0.0.11 74 75Name: my-test 76Address 1: 10.10.19.2 10.10.19.2 77 78 79从centos容器内部,使用特殊查询 查询DNS,来找到my-test服务的所有容器的IP地址: 80root@4bdcce0ee63e:/# nslookup tasks.my-test 81Server: 127.0.0.11 82Address 1: 127.0.0.11 83 84Name: tasks.my-test 85Address 1: 10.10.19.4 my-test.1.8433fuiy7vpu0p80arl7vggfe 86Address 2: 10.10.19.5 my-test.2.f1h7a0vtojv18zrsiw8j0rzaw 87Address 3: 10.10.19.6 my-test.3.ex73ifk3jvzw8ukurl8yu7fyq 88Address 2: 10.10.19.7 my-test.4.cyu73jd8psupfhken23vvmpud 89Address 3: 10.10.19.3 my-test.5.btorxekfix4hcqh4v83dr0tzw 90 91从centos容器内部,通过wget来访问my-test服务中运行的nginx网页服务器 92root@4bdcce0ee63e:/# wget -O- my-test 93Connecting to my-test (10.10.19.2:80) 94<!DOCTYPE html> 95<html> 96<head> 97<title>Welcome to nginx!</title> 98... 99 100Swarm的负载均衡器自动将HTTP请求路由到VIP上,然后到一个active的task容器上。它根据round-robin选择算法将后续的请求分发到另一个active的task上。 101 102-----------------------------------为服务使用DNS round-robin----------------------------- 103在创建服务时,可以配置服务直接使用DNS round-robin而无需使用VIP。这是通过在创建服务时指定 --endpoint-mode dnsrr 命令行参数实现的。 104当你想要使用自己的负载均衡器时可以使用这种方式。 105 106如下示例(注意:使用DNS round-robin方式创建服务,不能直接在命令里使用-p指定端口) 107[root@manager-node ~]# docker service create --replicas 3 --name my-dnsrr-nginx --network ngx_net --endpoint-mode dnsrr nginx 108 109[root@manager-node ~]# docker service ps my-dnsrr-nginx 110ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR 11165li2zbhxvvoaesndmwjokouj my-dnsrr-nginx.1 nginx node1 Running Running 2 minutes ago 1125hjw7wm4xr877879m0ewjciuj my-dnsrr-nginx.2 nginx manager-node Running Running 2 minutes ago 113afo7acduge2qfy60e87liz557 my-dnsrr-nginx.3 nginx manager-node Running Running 2 minutes ago 114 115 116当通过服务名称查询DNS时,DNS服务返回所有任务容器的IP地址: 117root@4bdcce0ee63e:/# nslookup my-dnsrr-nginx 118Server: 127.0.0.11 119Address 1: 127.0.0.11 120 121Name: my-dnsrr-nginx 122Address 1: 10.10.19.10 my-dnsrr-nginx.3.0sm1n9o8hygzarv5t5eq46okn.my-network 123Address 2: 10.10.19.9 my-dnsrr-nginx.2.b3o1uoa8m003b2kk0ytl9lawh.my-network 124Address 3: 10.10.19.8 my-dnsrr-nginx.1.55za4c83jq9846rle6eigiq15.my-network 125 126需要注意的是:一定要确认VIP的连通性 127通常Docker官方推荐使用dig,nslookup或其它DNS查询工具来查询通过DNS对服务名的访问。因为VIP是逻辑IP,ping并不是确认VIP连通性的正确的工具。