docker swarm
docker swarm 介绍
Swarm是Docker公司推出的用来管理docker集群的平台,几乎全部用GO语言来完成的开发的,代码开源在https://github.com/docker/swarm, 它是将一群Docker宿主机变成一个单一的虚拟主机,Swarm使用标准的Docker API接口作为其前端的访问入口,换言之,各种形式的DockerClient (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重新恢复运行之后,他会收集重建集群信息。 swarm集群特色 docker引擎综合了集群管理功能: 默认自带集群服务的管理工具,不需要额外的工具。 分布式的设计思路: 部署docker时不区分节点角色,当启动时根据不同角色使用不同参数。docker引擎分为管理器和工作程序 ,这就意味着你可以使用一个磁盘构建一个完整集群。 服务声明模式 docker引擎可以让你在海量应用服务里面,给服务定义你想要状态。例如:你可以描述一个程序服务集群包括消息队列服务,数据库后端,web前端组成。 服务的弹性可伸缩 对于你想要运行的每个服务你可以声明想要运行的任务数。当你批量启动和停止服务时,swarm集群管理器自动适应添加和移除任务来达到你想要维护的服务状态 服务状态自愈 swarm管理器通过不断的监控集群状态,让集群从现实状态不断接近你期望的状态。例如:你现在需要运行10个容器副本,并且其中两个容器副本worker机器崩溃了, 这个swarm manager将创建两个容器副本来替换崩溃的这两个副本。 多主机网络 你可以创建容器指定一个覆盖型网络。swarm 管理器初始化或更新应用程序时,会自动为覆盖网络上的容器分配地址。 服务发现机制 swarm管理器节点会分配给每个服务唯一dns容器名并负载均各个容器。您可以通过嵌入在swarm中的DNS服务器查询在群中运行的每个容器。 负载均衡 你可以使用容器暴露的端口使用外部应用进行负载均衡,在内部你可以使用swarm指定如何在节点之间分发服务容器,默认service分发到后端容器的算法是“顺序轮询”。 默认安全网络 每个swarm的节点里强制使用TLS双向认证和加密传输,以保证本机和其它节点间通讯安全。这里你可以使用自签名的证书或者自定义CA的证书。 滚动更新 在升级时你可以渐进的升级(滚动升级),swarm管理器可以控制多同节点间的调度部署升级的延时,一旦出现问题你可以回退到之前版本。
Swarm的几个关键概念
1.Swarm 集群的管理和编排是使用嵌入docker引擎的SwarmKit,可以在docker初始化时启动swarm模式或者加入已存在的swarm,node是加入到swarm集群中的一个docker引擎实体,可以在一台物理机上运行多个node 2.Node 一个节点是docker引擎集群的一个实例。您还可以将其视为Docker节点。您可以在单个物理计算机或云服务器上运行一个或多个节点,但生产群集部署通常包括分布在多个物理和云计算机上的Docker节点。 要将应用程序部署到swarm,请将服务定义提交给管理器节点。管理器节点将称为任务的工作单元分派给工作节点。 Manager节点还执行维护所需群集状态所需的编排和集群管理功能。Manager节点选择单个领导者来执行编排任务。 工作节点接收并执行从管理器节点分派的任务。默认情况下,管理器节点还将服务作为工作节点运行,但您可以将它们配置为仅运行管理器任务并且是仅管理器节点。代理程序在每个工作程序节点上运行,并报告分配给它的任务。工作节点向管理器节点通知其分配的任务的当前状态,以便管理器可以维持每个工作者的期望状态。 manager模式:也就是管理节点,任务的分派,执行编排,集群管理(集群状态,任务数维持,选举一个leader节点去执行调度任务。) Worker模式: 也就是工作节点,接受并执行manager节点分派任务.默认情况下,manager节点还将服务作为Worker节点运行,当你把它配置为manager-only的时候就可以为独占管理器了。 agent在每个worker 节点上运行,并报告分配给它的任务。Worker节点向manager节点通知其分配的任务的当前状态,使得manager可以维持每个Worker的期望状态。 3.Service 一个服务是任务的定义,管理机或工作节点上执行。它是群体系统的中心结构,是用户与群体交互的主要根源。创建一个服务,指定了容器所使用的镜像和容器运行的命令。 service是运行在worker nodes上的task的描述,service的描述包括使用哪个docker 镜像,以及在使用该镜像的容器中执行什么命令。 4.Task 任务是在docekr容器中执行的命令,task是service的执行实体,task启动docker容器并在容器中执行任务,Manager节点根据指定数量的任务副本分配任务给worker节点 swarm有三个角色,分别是管理者(manager)、工作者(worker)和被选举者(Reachable), 管理者管理工作者。一般管理者节点也是一个工作者。被选举者是当管理者宕机后可被选举为管理者的节点。 Swarm的调度策略 Swarm在调度(scheduler)节点(leader节点)运行容器的时候,会根据指定的策略来计算最适合运行容器的节点,目前支持的策略有:spread, binpack, random. 1)Random 顾名思义,就是随机选择一个Node来运行容器,一般用作调试用,spread和binpack策略会根据各个节点的可用的CPU, RAM以及正在运行的容器的数量来计算应该运行容器的节点。 2)Spread 在同等条件下,Spread策略会选择运行容器最少的那台节点来运行新的容器,binpack策略会选择运行容器最集中的那台机器来运行新的节点。 使用Spread策略会使得容器会均衡的分布在集群中的各个节点上运行,一旦一个节点挂掉了只会损失少部分的容器。 3)Binpack Binpack策略最大化的避免容器碎片化,就是说binpack策略尽可能的把还未使用的节点留给需要更大空间的容器运行,尽可能的把容器运行在一个节点上面。 Swarm Cluster模式特性 1)批量创建服务 建立容器之前先创建一个overlay的网络,用来保证在不同主机上的容器网络互通的网络模式 2)强大的集群的容错性 当容器副本中的其中某一个或某几个节点宕机后,cluster会根据自己的服务注册发现机制,以及之前设定的值--replicas n,在集群中剩余的空闲节点上, 重新拉起容器副本。整个副本迁移的过程无需人工干预,迁移后原本的集群的load balance依旧好使!不难看出,docker service其实不仅仅是批量启动服务这么简单, 而是在集群中定义了一种状态。Cluster会持续检测服务的健康状态并维护集群的高可用性。 3)服务节点的可扩展性 Swarm Cluster不光只是提供了优秀的高可用性,同时也提供了节点弹性扩展或缩减的功能。当容器组想动态扩展时,只需通过scale参数即可复制出新的副本出来。 仔细观察的话,可以发现所有扩展出来的容器副本都run在原先的节点下面,如果有需求想在每台节点上都run一个相同的副本,方法其实很简单, 只需要在命令中将"--replicas n"更换成"--mode=global"即可! 复制服务(--replicas n) 将一系列复制任务分发至各节点当中,具体取决于您所需要的设置状态,例如“--replicas 3”。 全局服务(--mode=global) 适用于集群内全部可用节点上的服务任务,例如“--mode global”。如果大家在 Swarm 集群中设有 7 台 Docker 节点,则全部节点之上都将存在对应容器。 4. 调度机制 所谓的调度其主要功能是cluster的server端去选择在哪个服务器节点上创建并启动一个容器实例的动作。它是由一个装箱算法和过滤器组合而成。每次通过过滤器(constraint)启动容器的时候, swarm cluster 都会调用调度机制筛选出匹配约束条件的服务器,并在这上面运行容器。 Swarm cluster的创建过程包含以下三个步骤 1)发现Docker集群中的各个节点,收集节点状态、角色信息,并监视节点状态的变化 2)初始化内部调度(scheduler)模块 3)创建并启动API监听服务模块 Swarm 创建服务时,可以为服务定义以下信息: 服务名称; 使用哪个镜像来创建容器; 要运行多少个副本; 服务的容器要连接到哪个网络上; 要映射哪些端口。 防火墙开放端口 2377/tcp,7949/udp,4789/udp firewall-cmd --zone=public --add-port=2377/tcp --permanentfirewall-cmd --zone=public --add-port=2376/tcp --permanentfirewall-cmd --zone=public --add-port=7949/udp --permanentfirewall-cmd --zone=public --add-port=4789/udp --permanentsystemctl restart firewalld
命令说明:
docker swarm ca 显示根CA init 初始化群集,布对外服务地址 join 作为节点和/或管理者加入群 join-token 管理加入群集令牌 leave 离开群,当前节点离开群集。 unlock 解锁群 unlock-key 管理解锁钥匙 update 更新群 docker swarm update --autolock 更改管理器自动锁定设置(true|false) --cert-expiry duration 节点证书的有效期(ns|us|ms|s|m|h)(默认为2160h0m0s) --dispatcher-heartbeat duration 调度器心跳周期(ns|us|ms|s|m|h)(默认5s) --external-ca external-ca 一个或多个证书签名终结点的规范 --max-snapshots uint 要保留的其他Raft快照数 --snapshot-interval uint Raft快照之间的日志条目数(默认值为10000) --task-history-limit int 任务历史记录保留限制(默认值5) docker service create 创建新服务 inspect 显示一个或多个服务的详细信息 logs 获取服务或任务的日志 ls 列出服务 ps 列出一个或多个服务的任务 rm 删除一个或多个服务 rollback 还原对服务配置的更改 scale 扩展一个或多个复制服务 update 更新服务(docker service create的所有参数都能更新。如 网络 DNS CPU) docker service create 常用参数(类似docker run) --constraint 放置约束 --container-label 容器标签 --dns 设置自定义 DNS 服务器 --dns-option 设置 DNS 选 --dns-search 设置自定义 DNS 搜索域 --endpoint-mode 端点模式(vip 或 dnsrr) --env,-e 设置环境变量 --env-file 读入环境变量文件 --group 为容器设置一个或多个补充用户组 --health-cmd 运行以检查运行状况的命令 --health-interval 运行检查之间的时间 (ns/us/ms/s/m/h) --health-retries 需要报告不健康的连续失败 --health-timeout 允许运行一项检查的最长时间 (ns/us/ms/s/m/h) --host 设置一个或多个自定义主机到 IP 映射 (host:ip) --hostname 容器主机名 --label,-l 服务标签 --limit-cpu 限制 CPU --limit-memory 限制内存 --log-driver 服务的日志记录驱动程序 --log-opt 记录驱动程序选项 --mode 服务模式(复制或全局) --mount 将文件系统挂载附加到服务 --name 服务名称 --network 网络组 --no-healthcheck 禁用任何容器指定的 HEALTHCHECK --publish,-p 将端口发布为节点端口 --replicas 副本数 --reserve-cpu 预留 CPU --reserve-memory 预留内存 --restart-condition 满足条件时重新启动(无、失败或任何) --restart-delay 重新启动尝试之间的延迟 (ns/us/ms/s/m/h) --restart-max-attempts 放弃前的最大重启次数 --restart-window 用于评估重启策略的窗口 (ns/us/ms/s/m/h) --secret 指定要公开给服务的秘密 --stop-grace-period 强制杀死容器前的等待时间 (ns/us/ms/s/m/h) --tty,-t 分配一个伪 TTY --update-delay 更新之间的延迟(ns/us/ms/s/m/h)(默认 0s) --update-failure-action 更新失败的操作(暂停/继续) --update-max-failure-ratio 更新期间容忍的失败率 --update-monitor 每次任务更新后监控失败的持续时间(ns/us/ms/s/m/h)(默认 0s) --update-parallelism 同时更新的最大任务数(0 表示一次全部更新) --user,-u 用户名或 UID(格式:[:]) --with-registry-authswarm 代理发送注册表身份验证详细信息 --workdir,-w 容器内的工作目录 docker nodes demote 从群中的管理器降级一个或多个节点 inspect 显示一个或多个节点的详细信息 ls 列出群中的节点 promote 将群中的一个或多个节点提升为管理员(先成为(Reachable选举者)) ps 列出在一个或多个节点上运行的任务,默认为当前节点 rm 从群中删除一个或多个节点 update 更新节点 docker config create 从文件或STDIN创建配置 inspect 显示一个或多个配置的详细信息 ls 列出配置 rm 删除一个或多个配置 例子: vi default.conf [root@swarm-master test]# cat default.conf server { listen 88; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } } # docker config ls ID NAME CREATED UPDATED je21ykql9tzebr0j2v7ep0kat conf 5 minutes ago 5 minutes ago 在conf配置中,将nginx的监听端口改成了88,替换掉nginx中的默认80端口的配置文件,创建service时,将容器内部端口88端口映射成主机上90端口 # docker service create --name nginx-01 --config source=conf,target=/etc/nginx/conf.d/default.conf -p 90:88 nginx:latest ----------------------------------------------------------------------------------------------- 实例说明: localhost7B 192.168.80.110 manager localhost7C 192.168.80.120 manager localhost7D 192.168.80.130 work localhost7E 192.168.80.140 work docker swarm 命令使用 #初始化群集,布对外服务地址 [root@localhost7C ~]# docker swarm init --advertise-addr 192.168.80.120 查看加入群集的token和加入群集的命令 [root@localhost7C ~]# docker swarm join-token manager To add a manager to this swarm, run the following command: #加入manager节点 docker swarm join --token SWMTKN-1-2fdks2vymuoiaolu2q2k4gkilghelc3k8znlntp1wz2pmnc3mp-7m9zzrlehvs2rv7v792pxhq3s 192.168.80.120:2377 [root@localhost7C ~]# docker swarm join-token worker To add a worker to this swarm, run the following command: #加入worker节点 docker swarm join --token SWMTKN-1-2fdks2vymuoiaolu2q2k4gkilghelc3k8znlntp1wz2pmnc3mp-bvgtlh57ll088ntmzizjjwkdz 192.168.80.120:2377 查看当前集群节点 [root@localhost7C ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION j88sjwbrevwqm03iiz7wvei49 * localhost7B.localdomain Ready Active Reachable 19.03.15 mx601h0ggyv4flpj2v71198i2 * localhost7C.localdomain Ready Active Leader 19.03.15 5vn8djdfgumhmh8nec7r0cn8m localhost7D.localdomain Ready Active 19.03.15 hloa0qv21rklk81md0zkmswa3 localhost7e.localdomain Ready Active 19.03.15 当前节点操作离开群 [root@localhost7B ~]# docker swarm leave --force [root@localhost7e ~]# docker swarm leave [root@localhost7C ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION j88sjwbrevwqm03iiz7wvei49 localhost7B.localdomain Down Active Unreachable 19.03.15 mx601h0ggyv4flpj2v71198i2 * localhost7C.localdomain Ready Active Leader 19.03.15 5vn8djdfgumhmh8nec7r0cn8m localhost7D.localdomain Ready Active 19.03.15 z9q0w30ysc7u254tjjoet970c localhost7e.localdomain Down Active 19.03.15 集群管理者,移除前必须将其降级为工人 [root@localhost7D ~]# docker node demote localhost7B.localdomain Manager localhost7B.localdomain demoted in the swarm. 删除节点 [root@localhost7D ~]# docker node rm localhost7B.localdomain [root@localhost7C ~]# docker node rm localhost7c.localdomain [root@localhost7D ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION mx601h0ggyv4flpj2v71198i2 * localhost7C.localdomain Ready Active Leader 19.03.15 5vn8djdfgumhmh8nec7r0cn8m localhost7D.localdomain Ready Active 19.03.15 worker节点删除的步骤 1.在“要删除的节点”先使用leave ,再manager节点上使用 rm. manager节点删除的步骤1.移除前必须demote降级为工人,2.在“要删除的节点”先使用leave ,再manager节点上使用 rm. ------------------------------------------------------------- 查看当前集群节点 [root@localhost7C ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION j88sjwbrevwqm03iiz7wvei49 localhost7B.localdomain Ready Active Reachable 19.03.15 mx601h0ggyv4flpj2v71198i2 * localhost7C.localdomain Ready Active Leader 19.03.15 5vn8djdfgumhmh8nec7r0cn8m localhost7D.localdomain Ready Active 19.03.15 hloa0qv21rklk81md0zkmswa3 localhost7e.localdomain Ready Active 19.03.15 “*”代表你连接的节点 Active 表示调度程序可以将任务分配给节点。 Pause 表示调度程序不会将新任务分配给节点,但现有任务仍在运行。 Drain 表示调度程序不会将新任务分配给节点。调度程序关闭所有现有任务并在可用节点上。 Leader 领导(管理者) Reachable 选举者(管理者) Unreachable 不可用或已离开群集 查看节点信息状态 [root@localhost7C ~]# docker node inspect localhost7D.localdomain --pretty ID: 5vn8djdfgumhmh8nec7r0cn8m Hostname: localhost7D.localdomain Joined at: 2022-11-24 02:46:52.778902358 +0000 utc Status: State: Ready Availability: Active Address: 192.168.80.130 Platform: Operating System: linux Architecture: x86_64 Resources: CPUs: 1 Memory: 972.4MiB Plugins: Log: awslogs, fluentd, gcplogs, gelf, journald, json-file, local, logentries, splunk, syslog Network: bridge, host, ipvlan, macvlan, null, overlay Volume: local Engine Version: 19.03.15 TLS Info: TrustRoot: -----BEGIN CERTIFICATE----- MIIBaTCCARCgAwIBAgIUUWSgPsVEjC8fCoCFQ6ZCJ7VUm6AwCgYIKoZIzj0EAwIw EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMjIxMTI0MDI0MTAwWhcNNDIxMTE5MDI0 MTAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH A0IABGmzf5UlhvstnD6pVmodTKLfrwJaNKy5GgD34V4o/2ctDedkE5AUDUDQmQKe H8F+bNPhbwtQjs/2TLaCE8HWPFujQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB Af8EBTADAQH/MB0GA1UdDgQWBBSU40mixDn+k7kzQWECCUtEGfOc+zAKBggqhkjO PQQDAgNHADBEAiBlDMZsHx/t+B3Kd6BdIMxcpt6GtmxO9ykw925zds4qcgIgdes7 xHYDny5Zj/jKNsA9/7ic4LRgi6/OOvh2M5hExNk= -----END CERTIFICATE----- Issuer Subject: MBMxETAPBgNVBAMTCHN3YXJtLWNh Issuer Public Key: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEabN/lSWG+y2cPqlWah1Mot+vAlo0rLkaAPfhXij/Zy0N52QTkBQNQNCZAp4fwX5s0+FvC1COz/ZMtoITwdY8Ww== 先成为(Reachable选举者提升为管理员 [root@localhost7C ~]# docker node promote localhost7D.localdomain Node localhost7D.localdomain promoted to a manager in the swarm. [root@localhost7C ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION im8lli71rtdxn4npik8zjra8u localhost7B.localdomain Ready Active Reachable 19.03.15 mx601h0ggyv4flpj2v71198i2 * localhost7C.localdomain Ready Active Leader 19.03.15 5vn8djdfgumhmh8nec7r0cn8m localhost7D.localdomain Ready Active Reachable 19.03.15 i58spxe0mkai4g9et7snjum6t localhost7e.localdomain Ready Active 19.03.15 列出在一个或多个节点上运行的任务 [root@localhost7C ~]# docker service create --replicas 4 -p 80:80 --name nginx-test harbor1.abc.com/web/nginx:v1 [root@localhost7C ~]# docker node ps localhost7D.localdomain ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS ta8jd47vf9z0 nginx-test.2 harbor1.abc.com/web/nginx:v1 localhost7D.localdomain Running Running 37 seconds ago 3trkp4oz4v2m nginx-test.4 harbor1.abc.com/web/nginx:v1 localhost7D.localdomain Running Running 12 seconds ago [root@localhost7C ~]# --------------------------------------------------------- 部署服务到集群 [root@localhost7C ~]#docker service create --replicas 4 -p 80:80 --name nginx-zzhz harbor1.abc.com/web/nginx:v1 列出服务 [root@localhost7C ~]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS ysyvgenklo0v nginx-test replicated 4/4 harbor1.abc.com/web/nginx:v1 *:80->80/tcp 服务的详细信息 [root@localhost7C ~]# docker service inspect nginx-test --pretty ID: ysyvgenklo0vp2klh8qwt0ngr Name: nginx-test Service Mode: Replicated Replicas: 4 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: harbor1.abc.com/web/nginx:v1@sha256:b39f7d7a09cdcaefbb63811503fcb6b2b2a1035029b44d1b262c26c06ca4d6f3 Init: false Resources: Endpoint Mode: vip Ports: PublishedPort = 80 Protocol = tcp TargetPort = 80 PublishMode = ingress 列出一个或多个服务的任务,其中一个副本没有创建成功。 [root@localhost7C ~]# docker service ps nginx-test ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS j2dbxxcau86x nginx-test.1 harbor1.abc.com/web/nginx:v1 localhost7e.localdomain Running Running 6 minutes ago ta8jd47vf9z0 nginx-test.2 harbor1.abc.com/web/nginx:v1 localhost7D.localdomain Running Running 6 minutes ago qitnjw6nl3ez nginx-test.3 harbor1.abc.com/web/nginx:v1 localhost7C.localdomain Running Running 6 minutes ago 3trkp4oz4v2m nginx-test.4 harbor1.abc.com/web/nginx:v1 localhost7D.localdomain Running Running 6 minutes ago i3jvdr2rxu47 \_ nginx-test.4 harbor1.abc.com/web/nginx:v1 localhost7B.localdomain Shutdown Rejected 6 minutes ago "No such image: harbor1.abc.co…" [root@localhost7C ~]#docker service create --replicas 4 -p 80:80 --name nginx-zzhz harbor1.abc.com/web/nginx:v1 [root@localhost7C ~]# docker service ps nginx-zzhz ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 07my91de575h nginx-zzhz.1 harbor1.abc.com/web/nginx:v1 localhost7e.localdomain Running Running 12 seconds ago [root@localhost7C ~]# docker service scale nginx-zzhz=2 [root@localhost7C ~]# docker service ps nginx-zzhz ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 07my91de575h nginx-zzhz.1 harbor1.abc.com/web/nginx:v1 localhost7e.localdomain Running Running 33 seconds ago uol3ipvxmfim nginx-zzhz.2 harbor1.abc.com/web/nginx:v1 localhost7D.localdomain Running Running 8 seconds ago 更新服务的replicas [root@localhost7C ~]#docker service update nginx-zzhz --replicas 3