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

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

集群搭建

环境准备

  • 五台安装了 Docker 的 CentOS 机器,版本为:CentOS 7.8.2003
  • Docker Engine 1.12+(最低要求 1.12,本文使用 19.03.12)
  • 防火墙开启以下端口或者关闭防火墙:
    • TCP 端口 2377,用于集群管理通信;
    • TCP 和 UDP 端口 7946,用于节点之间通信;
    • UDP 端口 4789,用于覆盖网络。

机器分布

角色 IP HOSTNAME Docker 版本
Manager 192.168.10.101 manager1 19.03.12
Manager 192.168.10.102 manager2 19.03.12
Manager 192.168.10.103 manager3 19.03.12
Worker 192.168.10.10 worker1 19.03.12
Worker 192.168.10.11 worker2 19.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 中内置的集群模式自带了公钥基础设施(PKI)系统,使得安全部署容器变得简单。集群中的节点使用传输层安全协议(TLS)对集群中其他节点的通信进行身份验证、授权和加密。

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

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

Manager

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

docker swarm join-token manager

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

Worker

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

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

查看集群信息

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

查看集群节点

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

docker node ls

* 代表当前节点,现在的环境为 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 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 ps 可以查看该服务对应容器的相关信息。

调用服务

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

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

弹性服务

将 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 查看服务运行在哪些节点上。

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

[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 查看服务运行在哪些节点上。

在 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 service update --rollback redis

常用命令

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 更新服务

参考资料

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

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


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

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


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335