Docker Swarm 集群环境搭建及弹性服务部署

Network
• 阅读 229

  上一篇文章《Docker Swarm 集群管理利器核心概念扫盲》中我们把 Swarm 重要的概念性知识给大家讲解了一波,理论完事就该实战了,这篇文章带大家从零开始,搭建 Docker Swarm 集群环境,并通过 Swarm 实现服务的弹性部署,滚动更新服务及回滚服务等功能。

  

集群搭建

  

环境准备

  

Docker Swarm 集群环境搭建及弹性服务部署

  • 五台安装了 Docker 的 CentOS 机器,版本为:CentOS 7.8.2003
  • Docker Engine 1.12+(最低要求 1.12,本文使用 19.03.12)
  • 防火墙开启以下端口或者关闭防火墙:

    • TCP 端口 2377,用于集群管理通信;
    • TCP 和 UDP 端口 7946,用于节点之间通信;
    • UDP 端口 4789,用于覆盖网络。

  

机器分布

  

角色IPHOSTNAMEDocker 版本
Manager192.168.10.101manager119.03.12
Manager192.168.10.102manager219.03.12
Manager192.168.10.103manager319.03.12
Worker192.168.10.10worker119.03.12
Worker192.168.10.11worker219.03.12
  • 可以通过 hostname 主机名 修改机器的主机名(立即生效,重启后失效);
  • 或者 hostnamectl set-hostname 主机名 修改机器的主机名(立即生效,重启也生效);
  • 或者 vi /etc/hosts 编辑 hosts 文件,如下所示, 给 127.0.0.1 添加主机名(重启生效)。
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 manager1
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

  

创建集群

  

  在任意节点下通过 docker swarm init 命令创建一个新的 Swarm 集群并加入,且该节点会默认成为 Manager 节点。根据我们预先定义的角色,在 101 ~ 103 的任意一台机器上运行该命令即可。

  通常,第一个加入集群的管理节点将成为 Leader,后来加入的管理节点都是 Reachable。当前的 Leader 如果挂掉,所有的 Reachable 将重新选举一个新的 Leader。

[root@localhost ~]# docker swarm init --advertise-addr 192.168.10.101
Swarm initialized: current node (clumstpieg0qzzxt1caeazg8g) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-5ob7jlej85qsygxubqypjuftiwruvew8e2cr4u3iuo4thxyrhg-3hbf2u3i1iagurdprl3n3yra1 192.168.10.101:2377

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

Docker Swarm 集群环境搭建及弹性服务部署

  

加入集群

  

  Docker 中内置的集群模式自带了公钥基础设施(PKI)系统,使得安全部署容器变得简单。集群中的节点使用传输层安全协议(TLS)对集群中其他节点的通信进行身份验证、授权和加密。

  默认情况下,通过 docker swarm init 命令创建一个新的 Swarm 集群时,Manager 节点会生成新的根证书颁发机构(CA)和密钥对,用于保护与加入群集的其他节点之间的通信安全。

  Manager 节点会生成两个令牌,供其他节点加入集群时使用:一个 Worker 令牌,一个 Manager 令牌。每个令牌都包括根 CA 证书的摘要和随机生成的密钥。当节点加入群集时,加入的节点使用摘要来验证来自远程管理节点的根 CA 证书。远程管理节点使用密钥来确保加入的节点是批准的节点。

  

Docker Swarm 集群环境搭建及弹性服务部署

  

Manager

  

  若要向该集群添加 Manager 节点,管理节点先运行 docker swarm join-token manager 命令查看管理节点的令牌信息。

docker swarm join-token manager

Docker Swarm 集群环境搭建及弹性服务部署

Docker Swarm 集群环境搭建及弹性服务部署

  

  然后在其他节点上运行 docker swarm join 并携带令牌参数加入 Swarm 集群,该节点角色为 Manager。

Docker Swarm 集群环境搭建及弹性服务部署

Docker Swarm 集群环境搭建及弹性服务部署

  

Worker

  

  通过创建集群时返回的结果可以得知,要向这个集群添加一个 Worker 节点,运行下图中的命令即可。或者管理节点先运行 docker swarm join-token worker 命令查看工作节点的令牌信息。

Docker Swarm 集群环境搭建及弹性服务部署

  

  然后在其他节点上运行 docker swarm join 并携带令牌参数加入 Swarm 集群,该节点角色为 Worker。

Docker Swarm 集群环境搭建及弹性服务部署

Docker Swarm 集群环境搭建及弹性服务部署

  

查看集群信息

  

  在任意 Manager 节点中运行 docker info 可以查看当前集群的信息。

Docker Swarm 集群环境搭建及弹性服务部署

  

查看集群节点

  

  在任意 Manager 节点中运行 docker node ls 可以查看当前集群节点信息。

docker node ls

Docker Swarm 集群环境搭建及弹性服务部署

* 代表当前节点,现在的环境为 3 个管理节点构成 1 主 2 从,以及 2 个工作节点。

  

  节点 MANAGER STATUS 说明:表示节点是属于 Manager 还是 Worker,没有值则属于 Worker 节点。

  • Leader:该节点是管理节点中的主节点,负责该集群的集群管理和编排决策;
  • Reachable:该节点是管理节点中的从节点,如果 Leader 节点不可用,该节点有资格被选为新的 Leader;
  • Unavailable:该管理节点已不能与其他管理节点通信。如果管理节点不可用,应该将新的管理节点加入群集,或者将工作节点升级为管理节点。

  

  节点 AVAILABILITY 说明:表示调度程序是否可以将任务分配给该节点。

  • Active:调度程序可以将任务分配给该节点;
  • Pause:调度程序不会将新任务分配给该节点,但现有任务仍可以运行;
  • Drain:调度程序不会将新任务分配给该节点,并且会关闭该节点所有现有任务,并将它们调度在可用的节点上。

  

删除节点

  

Manager

  

  删除节点之前需要先将该节点的 AVAILABILITY 改为 Drain。其目的是为了将该节点的服务迁移到其他可用节点上,确保服务正常。最好检查一下容器迁移情况,确保这一步已经处理完成再继续往下。

docker node update --availability drain 节点名称|节点ID

  

  然后,将该 Manager 节点进行降级处理,降级为 Worker 节点。

docker node demote 节点名称|节点ID

  

  然后,在已经降级为 Worker 的节点中运行以下命令,离开集群。

docker swarm leave

  

  最后,在管理节点中对刚才离开的节点进行删除。

docker node rm 节点名称|节点ID

  

Worker

  

  删除节点之前需要先将该节点的 AVAILABILITY 改为 Drain。其目的是为了将该节点的服务迁移到其他可用节点上,确保服务正常。最好检查一下容器迁移情况,确保这一步已经处理完成再继续往下。

docker node update --availability drain 节点名称|节点ID

  

  然后,在准备删除的 Worker 节点中运行以下命令,离开集群。

docker swarm leave

  

  最后,在管理节点中对刚才离开的节点进行删除。

docker node rm 节点名称|节点ID

  

服务部署

  

注意:跟集群管理有关的任何操作,都是在 Manager 节点上操作的。

  

创建服务

  

  下面这个案例,使用 nginx 镜像创建了一个名为 mynginx 的服务,该服务会被随机指派给一个工作节点运行。

docker service create --replicas 1 --name mynginx -p 80:80 nginx

Docker Swarm 集群环境搭建及弹性服务部署

  • docker service create:创建服务;
  • --replicas:指定一个服务有几个实例运行;
  • --name:服务名称。

  

查看服务

  

  可以通过 docker service ls 查看运行的服务。

[root@manager1 ~]# docker service ls
ID                NAME           MODE              REPLICAS        IMAGE              PORTS
hepx06k5ik5n      mynginx        replicated        1/1             nginx:latest       *:80->80/tcp

  

  可以通过 docker service inspect 服务名称|服务ID 查看服务的详细信息。

[root@manager1 ~]# docker service inspect mynginx
[
    {
        "ID": "k0dbjg1zzy3l3g71kdwa56ect",
        "Version": {
            "Index": 127
        },
        "CreatedAt": "2020-09-16T10:05:55.627974095Z",
        "UpdatedAt": "2020-09-16T10:05:55.629507771Z",
        "Spec": {
            "Name": "mynginx",
            "Labels": {},
            "TaskTemplate": {
                "ContainerSpec": {
                    "Image": "nginx:latest@sha256:c628b67d21744fce822d22fdcc0389f6bd763daac23a6b77147d0712ea7102d0",
                    "Init": false,
                    "StopGracePeriod": 10000000000,
                    "DNSConfig": {},
                    "Isolation": "default"
                },
                "Resources": {
                    "Limits": {},
                    "Reservations": {}
                },
                "RestartPolicy": {
                    "Condition": "any",
                    "Delay": 5000000000,
                    "MaxAttempts": 0
                },
                "Placement": {
                    "Platforms": [
                        {
                            "Architecture": "amd64",
                            "OS": "linux"
                        },
                        {
                            "OS": "linux"
                        },
                        {
                            "OS": "linux"
                        },
                        {
                            "Architecture": "arm64",
                            "OS": "linux"
                        },
                        {
                            "Architecture": "386",
                            "OS": "linux"
                        },
                        {
                            "Architecture": "mips64le",
                            "OS": "linux"
                        },
                        {
                            "Architecture": "ppc64le",
                            "OS": "linux"
                        },
                        {
                            "Architecture": "s390x",
                            "OS": "linux"
                        }
                    ]
                },
                "ForceUpdate": 0,
                "Runtime": "container"
            },
            "Mode": {
                "Replicated": {
                    "Replicas": 1
                }
            },
            "UpdateConfig": {
                "Parallelism": 1,
                "FailureAction": "pause",
                "Monitor": 5000000000,
                "MaxFailureRatio": 0,
                "Order": "stop-first"
            },
            "RollbackConfig": {
                "Parallelism": 1,
                "FailureAction": "pause",
                "Monitor": 5000000000,
                "MaxFailureRatio": 0,
                "Order": "stop-first"
            },
            "EndpointSpec": {
                "Mode": "vip",
                "Ports": [
                    {
                        "Protocol": "tcp",
                        "TargetPort": 80,
                        "PublishedPort": 80,
                        "PublishMode": "ingress"
                    }
                ]
            }
        },
        "Endpoint": {
            "Spec": {
                "Mode": "vip",
                "Ports": [
                    {
                        "Protocol": "tcp",
                        "TargetPort": 80,
                        "PublishedPort": 80,
                        "PublishMode": "ingress"
                    }
                ]
            },
            "Ports": [
                {
                    "Protocol": "tcp",
                    "TargetPort": 80,
                    "PublishedPort": 80,
                    "PublishMode": "ingress"
                }
            ],
            "VirtualIPs": [
                {
                    "NetworkID": "st2xiy7pjzap093wz4w4u6nbs",
                    "Addr": "10.0.0.15/24"
                }
            ]
        }
    }
]

  

  可以通过 docker service ps 服务名称|服务ID 查看服务运行在哪些节点上。

Docker Swarm 集群环境搭建及弹性服务部署

  在对应的任务节点上运行 docker ps 可以查看该服务对应容器的相关信息。

Docker Swarm 集群环境搭建及弹性服务部署

  

调用服务

  

  接下来我们测试一下服务是否能被正常访问,并且该集群下任意节点的 IP 地址都要能访问到该服务才行。

  测试结果:5 台机器均可正常访问到该服务。

Docker Swarm 集群环境搭建及弹性服务部署

  

弹性服务

  

  将 service 部署到集群以后,可以通过命令弹性扩缩容 service 中的容器数量。在 service 中运行的容器被称为 task(任务)。

  通过 docker service scale 服务名称|服务ID=n 可以将 service 运行的任务扩缩容为 n 个。

  通过 docker service update --replicas n 服务名称|服务ID 也可以达到扩缩容的效果。

  将 mynginx service 运行的任务扩展为 5 个:

[root@manager1 ~]# docker service scale mynginx=5
mynginx scaled to 5
overall progress: 5 out of 5 tasks 
1/5: running   [==================================================>] 
2/5: running   [==================================================>] 
3/5: running   [==================================================>] 
4/5: running   [==================================================>] 
5/5: running   [==================================================>] 
verify: Service converged

  通过 docker service ps 服务名称|服务ID 查看服务运行在哪些节点上。

Docker Swarm 集群环境搭建及弹性服务部署

  

  我们再来一波缩容的操作,命令如下:

[root@manager1 ~]# docker service update --replicas 3 mynginx
mynginx
overall progress: 3 out of 3 tasks 
1/3: running   [==================================================>] 
2/3: running   [==================================================>] 
3/3: running   [==================================================>] 
verify: Service converged

  通过 docker service ps 服务名称|服务ID 查看服务运行在哪些节点上。

Docker Swarm 集群环境搭建及弹性服务部署

  在 Swarm 集群模式下真正意义实现了所谓的弹性服务,动态扩缩容一行命令搞定,简单、便捷、强大。

  

删除服务

  

  通过 docker service rm 服务名称|服务ID 即可删除服务。

[root@manager1 ~]# docker service rm mynginx
mynginx
[root@manager1 ~]# docker service ls
ID                NAME              MODE              REPLICAS          IMAGE             PORTS

  

滚动更新及回滚

  

  以下案例将演示 Redis 版本如何滚动升级至更高版本再回滚至上一次的操作。

  首先,创建 5 个 Redis 服务副本,版本为 5,详细命令如下:

# 创建 5 个副本,每次更新 2 个,更新间隔 10s,20% 任务失败继续执行,超出 20% 执行回滚,每次回滚 2 个
docker service create --replicas 5 --name redis \
--update-delay 10s \
--update-parallelism 2 \
--update-failure-action continue \
--rollback-monitor 20s \
--rollback-parallelism 2 \
--rollback-max-failure-ratio 0.2 \
redis:5
  • --update-delay:定义滚动更新的时间间隔;
  • --update-parallelism:定义并行更新的副本数量,默认为 1;
  • --update-failure-action:定义容器启动失败之后所执行的动作;
  • --rollback-monitor:定义回滚的监控时间;
  • --rollback-parallelism:定义并行回滚的副本数量;
  • --rollback-max-failure-ratio:任务失败回滚比率,超过该比率执行回滚操作,0.2 表示 20%。

  

  然后通过以下命令实现服务的滚动更新。

docker service update --image redis:6 redis

Docker Swarm 集群环境搭建及弹性服务部署

  

  回滚服务,只能回滚到上一次操作的状态,并不能连续回滚到指定操作。

docker service update --rollback redis

Docker Swarm 集群环境搭建及弹性服务部署

  

常用命令

  

docker swarm

  

命令说明
docker swarm init初始化集群
docker swarm join-token worker查看工作节点的 token
docker swarm join-token manager查看管理节点的 token
docker swarm join加入集群

  

docker node

  

命令说明
docker node ls查看集群所有节点
docker node ps查看当前节点所有任务
docker node rm 节点名称\节点ID删除节点(-f强制删除)
docker node inspect 节点名称\节点ID查看节点详情
docker node demote 节点名称\节点ID节点降级,由管理节点降级为工作节点
docker node promote 节点名称\节点ID节点升级,由工作节点升级为管理节点
docker node update 节点名称\节点ID更新节点

  

docker service

  

命令说明
docker service create创建服务
docker service ls查看所有服务
docker service inspect 服务名称\服务ID查看服务详情
docker service logs 服务名称\服务ID查看服务日志
docker service rm 服务名称\服务ID删除服务(-f强制删除)
docker service scale 服务名称\服务ID=n设置服务数量
docker service update 服务名称\服务ID更新服务

  

参考资料

  

Docker Swarm 集群环境搭建及弹性服务部署

本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议

大家可以通过 分类 查看更多关于 Docker 的文章。

  

🤗 您的点赞转发是对我最大的支持。

📢 扫码关注 哈喽沃德先生「文档 + 视频」每篇文章都配有专门视频讲解,学习更轻松噢 ~

Docker Swarm 集群环境搭建及弹性服务部署

Docker Swarm 集群环境搭建及弹性服务部署

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Network
Network
Lv1
惊鸿一瞥而后不知所踪,这大概就是晚霞的美之所在。
文章
11
粉丝
0
获赞
0