Docker Swarm 集群初探 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hansonwang99
V2EX    Docker

Docker Swarm 集群初探

  •  
  •   hansonwang99
    hansonwang99 2018-03-07 09:17:47 +08:00 2918 次点击
    这是一个创建于 2842 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Desktop


    前言

    相信 Docker 技术大家都有所了解,单个 Docker 能发挥的作用毕竟有限,也不便于管理,所以 Docker 得组集群来使用才能发挥强大的技术优势。既然要组集群那就涉及诸如 Docker 的资源调度、管理等等一系列问题。目前涉及 Docker 集群的三个主要的技术无外乎 Swarm、Kubernetes、Mesos 三种。从本文开始作者将会一一实践这几种主要的 Docker 集群技术,话不多说,现在开始。

    注意:作者的 kubernetes 相关实践在此


    环境准备

    • Mac OS X 10.13.2
    • Docker 17.09.1-ce-mac42 (21090)
    • virtualbox (虚拟集群中节点时需要)
    • boot2docker v1.8.0 (在虚拟节点中起 docker 环境时需要)

    环境搭建

    节点规划如下:

    集群节点规划图

    我们需要 4 个节点( 1 个 master + 3 个 slave ),由于没有真实地 4 台物理机,所以下文中是靠docker-machinevirtualbox以及boot2docker来虚拟出 4 个独立 IP 地址的带 docker 环境的节点,大家注意!

    环境安装:

    • Docker 环境安装:

    Tips: 以前 Mac 上一般是使用boot2docker这个专门为 OS X 上运行 Docker 而开发的一个轻量级的虚拟主机管理工具来安装 docker,现在boot2docker这种安装方式官方已经 deprecated 了(当然下文中还是需要boot2docker.iso的镜像来帮助我们在虚拟的节点上起 docker 环境),可以直接下载 docker 的 dmg 安装包双击进行安装即可

    我们选择 docker CE 版安装即可,下载链接如下: https://store.docker.com/search?type=edition&offering=community

    注意:选择官方 docker dmg 包安装完成以后,docker-machine已经天然地集成于其中了,该工具在下文中创建虚拟节点时需要,它是一个可以在虚拟主机节点上安装 docker engine 的工具

    • virtualbox 安装

    由于我们搭建集群需要具备多个不同 IP 地址的节点,然而我们手上仅一台电脑,所以需要借助 virtualbox 来虚拟出多个不同 IP 地址的节点供我们使用需要

    去官方下载 virtualbox 的 dmg 安装包,双击安装即可: https://www.virtualbox.org/

    • boot2docker 安装 Boot2Docker 是一个专为 Docker 而设计的轻量级 Linux 发型包,解决 Windows 或者 OS X 用户不能安装 Docker 的问题。Boot2Docker 完全运行于内存中,体积小,启动快。Boot2Docker 需要运行在 VirtualBox 中。

    我使用的是 brew 这个 mac 上的包管理器安装的,非常方便,只需一行命令: brew install boot2docker

    除此之外我们还需要下载 boot2docker.iso 镜像在后文中进行使用: https://github.com/boot2docker/boot2docker/releases/tag/v17.07.0-ce 我们先把boot2docker.iso下好后面备用


    Docker Swarm 集群实验

    先创建 4 个虚拟节点( 1 个 master + 3 个 slave )

    首先要将之前下载的boot2docker.iso放到/Users/你的用户名 /.docker/machine/cache/目录下,然后执行如下命令:

    docker-machine create --virtualbox-boot2docker-url ~/.docker/machine/cache/boot2docker.iso master docker-machine create --virtualbox-boot2docker-url ~/.docker/machine/cache/boot2docker.iso slave1 docker-machine create --virtualbox-boot2docker-url ~/.docker/machine/cache/boot2docker.iso slave2 docker-machine create --virtualbox-boot2docker-url ~/.docker/machine/cache/boot2docker.iso slave3 

    注意:上面若不指定 boot2docker 的路径:--virtualbox-boot2docker-url ~/.docker/machine/cache/boot2docker.iso,直接执行docker-machine create master创建节点时,可能会报No default Boot2Docker ISO found locally, downloading the latest release...这种错误!所以最好自己指定 boot2docker.iso 镜像路径

    docker-machine 命令创建虚拟机过程细节如下: docker-machine 命令创建虚拟机过程

    创建完 4 个节点以后,可以用docker-machine ls命令查看一下各个节点的情况,可以看到自动为其分配了独立的 IP 地址: docker-machine ls 查看虚拟节点创建情况

    ssh 接入虚拟节点

    开启 4 个独立的 terminal 终端,分别执行:

    docker-machine ssh master docker-machine ssh slave1 docker-machine ssh slave2 docker-machine ssh slave3 

    执行后的效果如下图: 3 个 slave1 个 master 概览.jpg

    接下来在 master 上初始化一个 docker swarm 集群

    执行命令:

    docker swarm init --advertise-addr 192.168.99.100 

    效果如下: 在 master 节点上初始化集群

    上述命令执行成功后,提示中会告知用户在 slave 节点上执行命令 docker swarm join --token SWMTKN-1-1uzft9zcrd5cl7eva4gr4ptgrs1gc252483ey19xfphcuxc8ta-evsmmj7b7kleh7yoezjutzuu2 192.168.99.100:2377 可以加入到该集群中,把命令都告诉你了,你说智不只能!

    将 3 个 slave 节点加入集群

    分别去三个 slave 上,输入上面提示中的命令:

    docker swarm join --token SWMTKN-1-1uzft9zcrd5cl7eva4gr4ptgrs1gc252483ey19xfphcuxc8ta-evsmmj7b7kleh7yoezjutzuu2 192.168.99.100:2377 

    执行效果如下: master 上初始化集群以及 3 个 slave 加入集群

    注意:如果忘了 docker swarm join 命令中的 token 命令的话,可以使用命令docker swarm join-token worker来 get 之

    好,到此为止应该说 docker swarm 集群的搭建工作已经完成了,那下面在这个集群上做点实际的任务吧!

    开始在 master 节点上创建服务

    我们计划在该 docker 集群上部署高可用的 nginx 容器任务来作为演示: 在 master 节点上执行如下命令来创建名为 mynginx 的 service,让其有 2 份 nginx 容器副本分配到集群中去,起在 8080 端口: docker service create --replicas 2 -d -p 8080:80 --name mynginx registry.docker-cn.com/library/nginx 然后使用如下两条命令查看效果:

    docker service ls docker service ps mynginx 

    执行效果如下: 在 master 节点上刚创建 mynginx service

    此处有两点需要注意:

    1. 我们使用了registry.docker-cn.com/library/nginx作为加速镜像,不然可能在 slave 上 pull 镜像的时候 timeout
    2. 注意此处创建了 service 之后并不是 nginx 容器立马都在 slave 上起起来了,是需要等一段时间的(如,我等了近 8 分钟),因为在 slave 上还要去 pull nginx 镜像,再启动 nginx 容器等,没有那么快

    等待若干分钟以后,我们再看效果,发现此时任务顺利地分发到 slave1 和 slave2 上了:

    经过若干分钟后在 master 上查看 service 的效果

    分别用浏览器访问: http://192.168.99.101:8080 和 http://192.168.99.102:8080,会得到如下结果: 192.168.99.101 ( slave1 )上 nginx 容器访问结果

    192.168.99.102 ( slave2 )上 nginx 容器访问结果

    成功访问到了 slave 节点中起起来的 nginx 服务!

    此时分别去 slave1 和 slave2 上查看容器运行情况,结果如下: slave1 和 slave2 上查看容器运行情况

    进一步实验:扩容 service 中的任务

    我们想将 nginx 容器平滑地扩容到 3 份,在 master 上执行:

    然后在 master 上查看 service,发现新增的一个容器任务分配到 slave3 上了,当然此时 slave3 上正在 preparing: 扩容为 3 份后任务被分到 slave3 上).jpg

    等若干分钟后在 master 上再次查看 service,发现 slave3 上的 nginx 容器任务成功启动了:

    成功扩容之后 master 节点上看集群信息

    去 slave3 节点上 docker ps 看一下,发现容器确实启动了: 扩容到 slave3 后 slave3 上的 docker ps 信息

    ####进一步实验:集群中 service 高可用 目前有 3 个运行的 nginx 容器保证服务的可用性,如果其中一个容器意外关闭将会是什么情况?接下来就来模拟

    我们关闭 slave1 上此时正在运行着的 nginx 容器,看服务有什么变化: 关掉 slave1 上的 nginx 容器

    此时去 master 节点上查看信息发现,被关掉的 nginx 被分配到 master 上重启了:

    关闭了 slave1 后,在 master 节点上恢复了 nginx 服务

    此时我又关闭 master 节点上启动的 nginx 容器,发现刚关闭不久后,nginx 容器又重新在 master 上恢复了:

    再次关闭 master 上的 ngix,结果在 master 上全部重启.jpg

    接下来我们来将 slave3 宕机(宕机和前文的关闭 nginx 容器不同,此处模仿的是物理宕机),我们在控制台中使用 docker-machine stop 来模拟宕机动作: 将 slave3 从集群中断开

    此时去 master 上查看 service 信息发现 slave3 宕机以后,nginx 任务又重启与 slave1 上来保持高可用:

    将 slave3 宕机后 nginx 重启在 slave1 上

    最后来把狠的,我们将 slave1,slave2,slave3 全部从集群中断开: 将所有节点全部宕机.jpg

    结果去 master 上查看 service 信息,发现 3 个容器副本全部迁移到 master 之上了:

    3 个 slave 全部宕机后任务全部重启在 master 上

    此时在 master 上执行docker ps查看容器信息如下:运行着 3 个 nginx 容器: slave 全部宕机后在 master 节点上看到的 nginx 容器进程

    总而言之,无论怎么操作集群都能保持制定数量的容器副本来实现高可用!


    [干货] 总结一下上文中的常用命令

    • 创建虚拟主机节点
    docker-machine create 虚拟主机名 
    • 查看虚拟机节点信息
    docker-machine ls 
    • 停止虚拟主机节点
    docker-machine stop 虚拟主机名 
    • 删除虚拟主机节点
    docker-machine rm 虚拟主机名 
    • 初始化 docker swarm 集群
    docker swarm init --advertise-addr master 的 IP 地址 
    • slave 节点加入集群
    docker swarm join --token [token] [master 的 IP]:[master 的端口] 
    • slave 节点主动离开集群
    docker swarm leave 
    • 在 master 上获取加入集群的 token
    docker swarm join-token worker 
    • master 上创建 service 举例:
    docker service create --replicas 2 -d -p 8080:80 --name 服务名 镜像名 
    • master 上查看 service 信息
    docker service ls docker service ps 你所创建的服务的 ID 
    • 在 master 上删除 service
    docker service rm 服务名 
    • 在 master 上进行服务扩容
    docker service scale 你的 service name=你要的副本数目 

    参考文献


    后记

    想要看作者关于 kubernetes 的相关实践? 请戳这里

    作者更多的原创文章在此

    mahone3297
        1
    mahone3297  
       2018-03-07 10:02:34 +08:00
    * 可以编写 docker-compose.yml ,然后用 docker stack deploy 直接一键部署
    * docker 的 load balance 是怎样的?我发现,用 nginx replicas=3 的话,你刷新,他每次直接轮询 n1,n2,n3 (假设 3 个 node ),而是 n1 处理了好多请求,才到 n2,n2 也是处理了好多请求,才到 n3.不知道这个策略是怎样的,请教。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1077 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 18:15 PVG 02:15 LAX 10:15 JFK 13:15
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86