前言
之前在测试环境,已经有进行集群部署了: webrtc 的 signal 服务器 VerneMQ 的集群设置。但是这种部署方式不够灵活,尤其是像后面生产环境要在全球多个点部署好几台,其实很不方便。再加上如果有版本迭代的话,就更不方便了。所以后面考量了一下,决定还是用docker来进行集群部署。
虽然 VerneMQ 有使用docker搭建的教程: 传送门, 但是在使用中,使用 VerneMQ 原生镜像,修改测试文件无效,只能在 run 命令中指定参数,这个就非常长了,所以就使用自定义 Dockerfile ,自己创建镜像。
而且这个 docker 部署集群,会分别在中国区,新加坡,美区,欧洲 四个区域部署。
Docker 安装
这个就没啥好说,肯定服务器要先装docker: 参考链接
镜像制作
Dockerfile 构建镜像, 创建一个文件 Dockerfile, 内容如下:
1 | FROM centos:latest |
接下来 build 镜像,进入 Dockfile 所在目录,命令如下:
1 | docker build -t airdroid/vernemq:1.6.1 . |
通过docker images 查看镜像:
1 | [root@VM_16_14_centos ~]# docker images |
运行容器
既然镜像已经创建了,那么接下来就是将容器跑起来了。以中国区为例,其他区相同,–name修改为对应区域即可:
1 | docker run -dit \ |
参数解释:
- -dit: 以交互式的方式在后台运行
- -p:端口映射,将容器的服务端口映射到容器外部,mqtt 我们需要将 1883 1889 1900 44053 映射
- –name: 容器别名,便于后续识别和操作便利
- -v: 交容器内的日志和配置文件映射到宿主机,便于在容器外操作
- f5514b4637e7: 镜像 vernemq id
容器启动后,可以通过docker ps 查看容器是否正常:
1 | [root@VM_16_14_centos ~]# docker ps |
可以看到已经在运行了,用ping命令试一下:
1 | [kbz@VM_16_14_centos docker]$ sudo docker exec vernemq-release-cn-1 vernemq ping |
修改 vernemq.conf 配置文件,每个区的配置文件都会有一些差别,比如 nodename,webhook地址,clustering 等等。以中国区为例:
1 | allow_anonymous = off |
可以直接进去容器里面修改配置文件: sudo docker exec -it vernemq-release-cn-1 /bin/bash
1 | [kbz@VM_16_14_centos docker]$ sudo docker exec -it vernemq-release-cn-1 /bin/bash |
当然还有一种更简单的方式,前面在run容器的时候,已经通过-v参数将配置文件映射到宿主机了,这样我们就可以直接在容器外进行操作了:
1 | [kbz@VM_16_14_centos log]$ cd /etc/vernemq/ |
修改配置文件之后,接下来重启 vernemq 服务,容器不用重启,只需要重启容器里面的 vernemq 服务即可:
1 | docker exec vernemq-release-cn-1 vernemq restart |
配置其他三个区
这样子中国区 VerneMQ 服务就配置好了。接下来就配置其他三个区的:
首先要先把当前的容器镜像导出来,然后通过香港中转服务上传分发到其他三台服务器:
1 | docker export -o vernemq.tar 容器ID |
接下来就在其他区的服务器上,导入这个镜像:
1 | docker import vernemq.tar airdroid/vernemq:1.6.1 |
这样子镜像也就有了,接下来就跟之前中国区的操作一样, run -> edit config -> vernemq restart
我们可以看下log (之前run的时候,也已经把log的路径也映射到宿主机了,因此不用进入容器,直接在宿主机上访问即可):
1 | [kbz@VM_16_14_centos vernemq]$ cd /data/server/docker/vernemq/log/ |
weave 网络设置
通过上面的步骤,我们已经在4台机子上用docker部署了VerneMQ服务了,所以接下来要设置集群了。 而集群有一个前提就是各个服务器的容器之间的通信问题。
当容器分布在多个不同的主机上时,这些容器之间的相互通信变得复杂起来。容器在不同主机之间都使用的是自己的私有IP地址,不同主机的容器之间进行通讯需要将主机的端口映射到容器的端口上,而且IP地址需要使用主机的IP地址。
虽然 Docker 1.9 Overlay Network 已经可以实现跨主机网络互通,但是在使用 Dockerfile 原生网络,处理容器间通信的时候,不仅配置复杂,而且稳定性差。
容器间通信,我们采用开源的weave 容器网络解决方案,可以简单的理解,把weave 当作一个交换机,把各个区域的容器接入到weave,达到网络通信 和数据传输的目的。
Weave介绍
Weave是Github上一个比较热门的Docker容器网络方案,具有非常良好的易用性且功能强大。Weave通过创建虚拟网络使Docker容器能够跨主机通信并能够自动相互发现。通过weave网络,由多个容器构成的基于微服务架构的应用可以运行在任何地方:主机,多主机,云上或者数据中心。应用程序使用网络就好像容器是插在同一个网络交换机上一样,不需要配置端口映射,连接等。在weave网络中,使用应用容器提供的服务可以暴露给外部,而不用管它们运行在何处。类似地,现存的内部系统也可以接受来自于应用容器的请求,而不管容器运行于何处。
一个Weave网络由一系列的’peers’构成—-这些weave路由器存在于不同的主机上。每个peer都由一个名字,这个名字在重启之后保持不变.这个名字便于用户理解和区分日志信息。每个peer在每次运行时都会有一个不同的唯一标识符(UID).对于路由器而言,这些标识符不是透明的,尽管名字默认是路由器的MAC地址。
Weave路由器之间建立起TCP连接,通过这个连接进行心跳握手和拓扑信息交换,这些连接可以通过配置进行加密。peers之间还会建立UDP连接,也可以进行加密,这些UDP连接用于网络包的封装,这些连接是双工的而且可以穿越防火墙。Weave网络在主机上创建一个网桥,每个容器通过veth pari连接到网桥上,容器由用户或者weave网络的IPADM分配IP地址。
简单的来说就是:weave 就是相当于以docker 容器的形式,启动一个新的虚拟网卡,每个区域的主机通过这个交换机连接起来, 然后再给容器分配子网,达到通信的目的。
下载安装
1 | wget https://github.com/zettio/weave/releases/download/latest_release/weave |
1 | chmod +weave |
1 | cp weave /usr/local/bin/ |
启动容器并创建虚拟网络
执行 weave launch, 拉取镜像,并开启容器:
1 | [root@VM_16_14_centos ~]# docker ps |
这样子第一台宿主机的weave就部署成功了,接下来部署第二台宿主机。第二台宿主机部署步骤稍微有点不同,我们需要为这台宿主机的 weave 路由器指定第一台宿主机的 IP 地址,命令如下:
1 | weave launch <first-host-IP-address> |
比如,在新加坡的服务器执行:
1 | weave launch 172.xx.16.14 |
依次类推,在美区执行新加坡的IP,在欧洲执行美区IP。 这样子就通过 weave 将整个虚拟网络都串起来了。
最后,通过weave status peers ,查看路由表,四个区域的主机都已建立了连接,如下图:
1 | [root@VM_16_14_centos ~]# weave status peers |
给容器分配网段
既然四个区域的宿主机都建立了连接,但是容器如果通信,还需要给各个区域的容器分配ip,这里分配的是10.0.0.0/24 的网段,命令如下:
1 | 中国: weave attach 10.0.0.1/24 vernemq-release-cn-1 |
接下来查看容器分配的ip有没有生效,以中国区为例,如下图:
1 | [root@VM_16_14_centos ~]# docker exec vernemq-release-cn-1 ifconfig |
可以看 10.0.0.1 已经是了。
建立连接
默认情况下,容器间都是相互ping不通的。需要使用weave connect命令在weave的路由器之间建立连接,连接方式如下:
1 | weave connect 宿主机ip |
比如,在中国区执行:
1 | # 注意,因为虚拟网络已经建立起来了,因此只需要在一台执行即可实现全部通信,也就是说在中国区这一台,就可以直接执行 connect 这4台 |
测试 ping 的情况,在中国区(10.0.0.1)测试如下,其他区域类似:
1 | [root@VM_16_14_centos ~]# docker exec vernemq-release-cn-1 ping 10.0.0.2 |
这样子就可以实现不同主机之间容器的通信了。
集群部署
各个区域的容器建正常通信以后,就可以建立mqtt cluster 了。直接在中国区这一台执行:
1 | docker exec vernemq-release-cn-1 vmq-admin cluster join discovery-node=VerneMQ@10.0.0.2 |
1 | docker exec vernemq-release-cn-1 vmq-admin cluster join discovery-node=VerneMQ@10.0.0.3 |
1 | docker exec vernemq-release-cn-1 vmq-admin cluster join discovery-node=VerneMQ@10.0.0.4 |
当然如果嫌弃前缀太长的话,也可以进入到容器里面再执行。
接下来测试集群是否正常:
1 | [root@VM_16_14_centos ~]# docker exec vernemq-release-cn-1 vmq-admin cluster show |
正常work,至此,集群搭建完成。
部署过程中遇到的问题总结
使用vernqmq 原生镜像,修改测试文件无效
解决方式: 自定义Dockerfile ,创建镜像
使用Dockerfile 原生网络,处理容器间通信,配置复杂,稳定性差
解决方式: 使用docker 容器网络 weave 组件,处理
配置欧洲docker时,和欧洲宿主机的ip冲突
配置欧洲docker时,和欧洲宿主机的ip冲突,欧洲的宿主机ip 为 172.17.0.0 网段,而docker 虚拟网络的IP也是172.17.0.0 网段,造成了冲突。
解决方案: 修改docker 默认的虚拟网卡IP,这里我们设置的是192.168.0.0/24 网段,配置如下:
修改docker daemon.json 文件,内容如下:
1 | [root@VM_16_14_centos ~]# cat /etc/docker/daemon.json |
重启docker 服务
1 | systemctl restart docker |
查看docker 默认虚拟网卡的IP,是否更改
1 | [root@VM1614_centos ~]# ifconfig |
但是还有一个问题存在: 如果后面重启docker 或重启容器时,容器的ip会消失。 所以解决方法就是 重新执行 weave 绑定ip:
1 | weave attach ip 容器名 |
举个例子,比如中国区,这个由于意外原因,重启系统或重启容器了,需要执行如下命令:
1 | weave attach 10.0.0.1/24 vernemq-release-cn-1 |
这个 weave ip 是及时生效的,附加后,马上生效,不需要重启容器。
(这个很容易漏掉,如果有脚本维护的话,那么就要写入到shell中,不然很容易忘记)
其他补充
容器的操作可以通过2种方式试下,一种是在容器外,一种是容器内:
1 | 容器内: docker exec -it 容器id 或容器名 /bin/bash |
常用指令:
1 | 查看当前镜像: docker images |
文件映射到宿主机:
启动容器时,已经将容器内的配置文件目录和log 映射到容器外,具体路径如下:
查看及修改配置配置文件:
1 | cat|vim /etc/vernemq/vernemq.conf |
查看日志文件:
1 | cat /data/server/docker/vernemq/log/*.log |
最后感谢树礼的整理。