微服务实践专题系列(二):基于Docker swarm mode集群的consul集群部署
发布于 3 个月前 作者 m3shine 612 次浏览 来自 分享

consul简介

consul是微服务治理方案,提供注册/发现、k/v存储、健康检查以及多数据中心部署的能力。

单节点安装如下:

    docker pull consul:0.9.2

启动consul:

    docker run -it -p 8500:8500 consul:0.9.2

浏览器访问:localhost:8500,可以看到consul的web UI。

consul可以作为server或client模式运行。

  • consul server:consul server之间彼此通信并选举一个leader。
  • consul client:集群中的每个节点都有自己的consul client,它负责监控运行在该节点上的服务的健康、与consul server通信。通常和应用服务运行在一个节点中,一个consul client仅仅和某一个consul server通信。
  • 集群中的所有client和server共享状态信息:即当一个应用服务注册到一个client,这个信息将在所有与它连接的client和server上都共享可用了。

本文着重描述consul集群方式部署,不熟悉docker也没关系,本文也有很多docker概念讲解。

基础准备

1、docker安装包

docker for linux/mac ,此安装包包含:

  • docker引擎

  • docker-machine:虚拟机管理

  • swarm mode:docker引擎内置的容器编排功能,包括容器集群化和调度。

    不要混淆swarm mode和docer swarm。

    swarm mode是1.12版提供的能力,集成在docker引擎中,没有和machine、compose集成,内置了k/v存储,并集成了overlay networks支持。

    而docker swarm是1.12版之前的集群方案,是独立的工具。在docker1.12之前,创建docker集群是需要用docker swarm的,并且需要额外的k/v存储(consul、etcd等)同步网络配置,保证节点在一个容器中。

  • docker-compose:服务编排组件

2、virtualbox

虽然macOS自带HyperKit虚拟解决方案,但因为docker 没有HyperKit driver,所以需要用virtualbox,手动下载安装或者docker早期解决方案Toolbox安装过也可。

架构设计

最初的架构设计是这样的:

consul.png

这种架构也能建成功,但考虑到对swarm集群的理解不要太狭隘,重新设计了另外的架构。

虽然不是所有的服务都适合部署到swarm集群,但是consul是适合的,部署的方式是swarm 的manager节点和consul server重合,swarm的worker节点和consul client重合。

重新设计架构如下:

consul2.png

实施

1、创建4个虚拟机

写一个shell脚本crete_vms.sh批量创建:

    #!/bin/sh
    #创建4个虚拟机
    set -e
    
    vms=("vm1" "vm2" "vm3" "vm4")
    
    for vm in ${vms[@]}
    do
      docker-machine create \
        -d virtualbox \
        --virtualbox-memory "1024" \
        --virtualbox-cpu-count "1" \
        --virtualbox-disk-size "2000" \
        ${vm}
    done
    
    docker-machine ls   

给这个脚本授权:sudo chmod a+x create_vms.sh,并执行后可以看到虚拟机创建完成。

1.png

小提示:

docker-machine 会自动加载一个Boot2Docker ISO用于构建docker容器运行环境。

2、构建swarm集群

2.1 用swarm mode方式将这4台虚拟机构建成一个集群

首先需要在一台机器上初始化swarm,这里在vm1上进行初始化,先绑定vm1环境:

eval $(docker-machine env vm1)

然后初始化:

docker swarm init --advertise-addr $(docker-machine ip vm1)

这时,vm1变成一个集群中的manager节点了。

2.2 接下来将vm2作为一个manager节点加入这个swarm 先查询加入命令:

docker swarm join-token manager 

To add a manager to this swarm, run the following command: docker swarm join --token SWMTKN-1-64eiwxk3wzoau20f7iv56fw0apgsxsk0gnzwb1e6okbezd373b-eyhb3sbu3fkcj8uyzw1bigayj 192.168.99.100:2377

然后绑定vm2环境:

eval $(docker-machine env vm2)

执行加入命令:

docker swarm join --token SWMTKN-1-64eiwxk3wzoau20f7iv56fw0apgsxsk0gnzwb1e6okbezd373b-eyhb3sbu3fkcj8uyzw1bigayj 192.168.99.100:2377

2.3 将vm3和vm4作为worker节点加入这个swarm 先查询加入命令:

docker swarm join-token worker

To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-64eiwxk3wzoau20f7iv56fw0apgsxsk0gnzwb1e6okbezd373b-8ern27gy685jifwq7b9cjvhcn 192.168.99.100:2377

绑定vm3环境:

eval $(docker-machine env vm3)

执行加入命令:

docker swarm join --token SWMTKN-1-64eiwxk3wzoau20f7iv56fw0apgsxsk0gnzwb1e6okbezd373b-8ern27gy685jifwq7b9cjvhcn 192.168.99.100:2377

绑定vm4环境:

eval $(docker-machine env vm4)

执行加入命令:

docker swarm join --token SWMTKN-1-64eiwxk3wzoau20f7iv56fw0apgsxsk0gnzwb1e6okbezd373b-8ern27gy685jifwq7b9cjvhcn 192.168.99.100:2377

至此,swarm集群创建完成! 切换到manager 节点查看集群信息:

eval $(docker-machine env vm1)
docker node ls

2.png

MANAGER STATUS显示为Reachable表示该节点是一个manager,空表示是一个worker。

可以在swarm manager节点环境下查看网络信息:

docker network ls

3.png

可以看到ingress的网络是属于swarm的,其他的都是本地(local)。swarm集群中的节点是自动加入overlay网络的。

小提示:

docker-machine env vm的作用是查看vm的环境变量,而eval $(docker-machine env vm)是执行,即将当前shell与指定的虚拟机配置环境进行绑定,关掉shell也就释放了这种绑定的环境。这个命令的最好使用场景就是:虚拟机中不需要安装docker compose、machine等、也不需要上传配置文件到虚拟机,就可以在当前shell中执行虚拟机中不存在的命令和文件来操作虚拟机容器和服务。

如果要解绑,执行解绑命令:

eval $(docker-machine env -u)

3、构建consul集群

3.1 先创建一个consul server leader,写个consul-server-init.yml文件:

version: '3.3'
services:
  consul-server:
    image: consul:0.9.2
    environment:
      - "CONSUL_LOCAL_CONFIG={\"disable_update_check\": true}"
      - "CONSUL_CLIENT_INTERFACE=eth0"
      - "CONSUL_BIND_INTERFACE=eth1" #容器启动时自动绑定eth1端口的IP
    entrypoint:
      - consul
      - agent
      - -server
      - -bootstrap #作为一个集群启动
      - -data-dir=/consul/data
      - -advertise={{ GetInterfaceIP "eth1" }}
      - -client=0.0.0.0 #consul服务侦听地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1,对外提供服务需改成0.0.0.0
      - -ui
    ports:
      - 8300:8300 #server rpc address
      - 8301:8301 #CLuster Serf Addr LAN
      - 8301:8301/udp
      - 8302:8302 #Cluster Serf Addr WAN
      - 8302:8302/udp
      - 8400:8400 #cli rpc endpoint
      - 8500:8500 #Web UI, http api
      - 8600:53/udp #DNS服务
    network_mode: host #此处指定host模式才能绑定到eth1

切换到vm1 manager节点

eval $(docker-machine env vm1)
docker-compose -f consul-server-init.yml up -d

如果启动报错,可以通过docker logs container_id来查看错误信息,然后再docker-compose -f consul-server-init.yml down掉它。

3.2 再写一个consul-server-join.yml用来创建consul server follower加入该集群。

version: '3.3'
services:
  consul-server:
    image: consul:0.9.2
    environment:
      - "CONSUL_LOCAL_CONFIG={\"disable_update_check\": true}"
      - "CONSUL_CLIENT_INTERFACE=eth0"
      - "CONSUL_BIND_INTERFACE=eth1" #容器启动时自动绑定eth1端口的IP
    entrypoint:
      - consul
      - agent
      - -server
      - -data-dir=/consul/data
      - -retry-join=192.168.99.100 #加入一个集群
      - -advertise={{ GetInterfaceIP "eth1" }}
      - client=0.0.0.0
      - -ui
    ports:
      - 8300:8300 #server rpc address
      - 8301:8301 #CLuster Serf Addr LAN
      - 8301:8301/udp
      - 8302:8302 #Cluster Serf Addr WAN
      - 8302:8302/udp
      - 8400:8400 #cli rpc endpoint
      - 8500:8500 #Web UI, http api
      - 8600:53/udp #DNS服务
    network_mode: host #此处指定host(宿主机)模式才能绑定到eth1

切换到vm2环境

eval $(docker-machine env vm2)
docker-compose -f consul-server-join.yml up -d

3.3 写一个consul-client.yml来创建consul client并加入集群

version: '3.3'  #第三版开始支持swarm mode集群的compose-file编排
services:
  consul-agent:
    image: consul:0.9.2
    environment:
      - "CONSUL_LOCAL_CONFIG={\"disable_update_check\": true}"
      - "CONSUL_CLIENT_INTERFACE=eth0"
      - "CONSUL_BIND_INTERFACE=eth1" #容器启动时自动绑定eth1端口的IP
    entrypoint:
      - consul
      - agent
      - -data-dir=/consul/data
      - -advertise={{GetInterfaceIP "eth1"}}
      - -retry-join=192.168.99.100 #consul server的地址,以便使该client与            server组成同一个集群
      - -retry-join=192.168.99.101
    network_mode: host #此处指定host(宿主机)模式才能绑定到eth1

分别切换到vm3和vm4环境执行创建:

eval $(docker-machine env vm3)
docker-compose -f consul-client.yml up -d

eval $(docker-machine env vm4)
docker-compose -f consul-client.yml up -d

到此为止,consul集群创建完成,查看集群信息:

docker exec -t <vm1容器id> consul members

4.png

这里我故意把vm3服务离开了。

小结:

consul不适合用1.13的deploy部署,还是写运维shell方式部署最省事,我上面为了讲清楚很多概念一步一步描述的。 deploy部署的话默认会虚拟出一个集群vip,多个相同服务绑定到这个共同的vip上对外提供服务。

访问http://192.168.99.100:8500,可以看到consul管理界面:

6.png

下一篇文章演示Registrator和应用的部署。

10 回复

@i5ting 编辑器有待提高,写文章真心累。markdown标准语法预览的时候显示不正确以至于一直耿耿于怀不敢发布。

@m3shine 感谢,辛苦,写的很详细嘛

@i5ting 你不会理解错了吧?我是说cnode的编辑器 😄

@m3shine 知道,没那么傻,哈哈

文章很给力,为什么不使用k8s而使用swarm,有什么考虑吗? 我们公司也是用consul来进行服务注册和心跳检查和用它的UI来设置k/v储存

@zy445566 部署成本相对比较低,适合小型团队。

swarm mode自带服务发现的

@zy445566 具体选型的考虑倒没有,实现微服务的技术很多,这只是其中一种。

@coordcn 太喜欢你了

@richenlin 你这一句话,我过几天再来答复你

回到顶部