一、Consul简介

Consul是基于GO语言开发的开源工具,主要面向分布式,服务化的系统提供服务注册、服务发现和配置管理的功能。Consul的功能都很实用,其中包括:服务注册/发现、健康检查、Key/Value存储、多数据中心和分布式一致性保证等特性。Consul本身只是一个二进制的可执行文件,所以安装和部署都非常简单,只需要从官网下载后,在执行对应的启动脚本即可。

二、Consul特性

基础特性
1.服务注册/发现
为什么微服务架构下就需要做服务注册和服务发现呢?微服务的目标就是要将原来大一统的系统架构,拆分成细粒度的按功能职责分成的小系统,这样就会出现很多小的系统,部署的节点也会随之增加。试想一下,如果没有一个统一的服务组件来管理各系统间的列表,微服务架构是很难落地实现的。
Consul提供的服务注册/发现功能在数据强一致性和分区容错性上都有非常好的保证,但在集群可用性下就会稍微差一些(相比Euerka来说)。

2.数据强一致性保证
Consul采用了一致性算法Raft来保证服务列表数据在数据中心中各Server下的强一致性,这样能保证同一个数据中心下不管某一台Server Down了,请求从其他Server中同样也能获取的最新的服务列表数据。数据强一致性带来的副作用是当数据在同步或者Server在选举Leader过程中,会出现集群不可用。

3.多数据中心
Consul支持多数据中心(Data Center),多个数据中心之间通过Gossip协议进行数据同步。多数据中心的好处是当某个数据中心出现故障时,其他数据中心可以继续提供服务,提升了可用性。

4.健康检查
Consul支持基本硬件资源方面的检查,如:CPU、内存、硬盘等

5.Key/Value存储
Consul支持Key/Value存储功能,可以将Consul作为配置中心使用,可以将一些公共配置信息配置到Consul,然后通过Consul提供的 HTTP API来获取对应Key的Value。

三、实验环境准备

主机名 IP地址 所需组件
docker01 192.168.45.129 consul,consul-template,nginx
docker02 192.168.45.141 consul, registrator
docker03 192.168.45.142 consul, registrator

注:实验环境关闭防火墙、禁用SElinux
所需的安装包:链接:https://pan.baidu.com/s/1R9ms2y0j5cdFmBvtcvMqiA
提取码:olcy

一)、在Docker01上执行二进制命令部署consul服务

[root@docker01 ~]# rz                  //上传压缩包
[root@docker01 ~]# unzip consul_1.5.1_linux_amd64.zip   //解包,解压后会得到一个命令
[root@docker01 ~]# mv consul /usr/local/bin/        // 移动到命令存放路径
[root@docker01 ~]# chmod  +x /usr/local/bin/consul  //赋予执行权限 
[root@docker01 ~]# nohup consul agent -server -bootstrap -ui -data-dir=/var/lib/consul-data -bind=192.168.45.129 -client=0.0.0.0 -node=master &
[1] 3904
[root@docker01 ~]# nohup: 忽略输入并把输出追加到"nohup.out"
//执行命令后,会提示该信息,并占用终端,按两下回车键即可,
//运行上述命令后,会在当前目录下生成一个名为“nohup.out”的文件,其存放的是consul服务的运行日志
//执行上述命令后,consul就放到后台运行了,并返回其PID号,可以通过“jobs -l”命令进行查看
上述命令的相关参数解释如下:
* -server:添加一个服务;
* -bootstrap:一般在server单节点的时候使用,自选举为leader;
* -ui:开启内部的web界面;
* -bind:指定开启服务的IP(就是本机IP咯);
* -client:指定服务的客户端(一般此处为任意);
* -node:在集群内部通信使用的名称,默认是主机名。
* 开启的端口作用如下:
* 8300:集群节点;
* 8301:集群内部访问的端口;
* 8302:跨数据中心之间的通信;
* 8500:http_ui;
* 8600:DNS
[root@docker01 ~]# consul info    //可以看到这个群集的leader及版本信息
//如:leader_addr = 192.168.45.129:8300
[root@docker01 ~]# consul members          //查看consul集群内成员的信息

至此,客户端可以访问docker01的8500端口进行验证:
Docker服务配置+ Consul + registrator实现服务发现
二)、docker02、docker03,加入consul集群

docker02配置如下:
[root@docker02 ~]# docker run -d --name consul -p 8301:8301 -p 8301:8301/udp -p 8500:8500 -p 8600:8600 -p 8600:8600/udp --restart=always progrium/consul -join 192.168.45.129 -advertise 192.168.45.141 -client 0.0.0.0 -node=node01
//上述命令中,“-join”是指定leader的IP地址(也就是docker01);“-advertise”是指定自己本身的IP地址
docker03配置如下:
[root@docker03 ~]# docker run -d --name consul -p 8301:8301 -p 8301:8301/udp -p 8500:8500 -p 8600:8600 -p 8600:8600/udp --restart=always progrium/consul -join 192.168.45.129 -advertise 192.168.45.142 -client 0.0.0.0 -node=node02
//上述命令中,“-join”是指定leader的IP地址(也就是docker01);“-advertise”是指定自己本身的IP地址
//注意:node名称在consul群集中,必须唯一

至此,执行“consul members”命令即可查看到docker02及docker03的信息

[root@docker01 ~]# consul members 
Node    Address              Status  Type    Build  Protocol  DC   Segment
master  192.168.45.129:8301  alive   server  1.5.1  2         dc1  <all>
node01  192.168.45.141:8301  alive   client  0.5.2  2         dc1  <default>
node02  192.168.45.142:8301  alive   client  0.5.2  2         dc1  <default>

浏览器访问consul服务,验证集群信息:
Docker服务配置+ Consul + registrator实现服务发现
三)、docker02及docker03主机上以容器的方式运行registrator服务
注:registrator是一个能自动发现docker container提供的服务,并在后端服务注册中心注册服务或取消服务的工具,后端注册中心支持conusl、etcd、skydns2、zookeeper等。

docker02配置如下:
[root@docker02 ~]# docker run -d --name registrator -v /var/run/docker.sock:/tmp/docker.sock --restart always gliderlabs/registrator consul://192.168.45.141:8500
//上述命令的作用是将收集的容器信息发送给本机的8500端口来显示
docker03配置如下:
[root@docker03 ~]# docker run -d --name registrator -v /var/run/docker.sock:/tmp/docker.sock --restart always gliderlabs/registrator consul://192.168.45.142:8500
//上述命令的作用是将收集的容器信息发送给本机的8500端口来cha显示

浏览器测试访问,这里我只访问了node1,这里就不访问node2了:
Docker服务配置+ Consul + registrator实现服务发现
Docker服务配置+ Consul + registrator实现服务发现

四)、在主机docker01上部署Nginx服务,以便提供反向代理

[root@docker01 ~]# yum -y install gcc openssl openssl-devel zlib zlib- devel pcre pcre-devel
[root@docker01 ~]# rz  
[root@docker01 ~]# tar zxf nginx-1.14.0.tar.gz  -C /usr/src/
[root@docker01 ~]# useradd -M -s /sbin/nologin nginx
[root@docker01 ~]# cd /usr/src/nginx-1.14.0/
[root@docker01 nginx-1.14.0]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
[root@docker01 nginx-1.14.0]# nginx    //开启nginx服务
[root@docker01 nginx-1.14.0]# netstat -anput | grep nginx   //确认nginx服务已开启
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      7232/nginx: master  

五)、在docker01安装consul-template命令工具,并编写模板
注:consul-template的作用就是将收集到的信息(把registrator收集到容器的信息)写入template模板中,并且最终写入Nginx的配置文件中。

[root@docker01 ~]# rz           //上传我提供的包
[root@docker01 ~]# unzip consul-template_0.19.5_linux_amd64.zip     //解包
[root@docker01 ~]# mv consul-template /usr/local/bin/   //移动到命令搜索路径
[root@docker01 ~]# chmod +x /usr/local/bin/consul-template    //赋予执行权限
[root@docker01 ~]# cd /usr/local/nginx/
//在Nginx安装目录下,编写模板供consul-template命令工具使用,并且配置Nginx反向代理
[root@docker01 nginx]# mkdir consul
[root@docker01 nginx]# cd  consul/
[root@docker01 consul]# vim nginx.ctmpl
upstream http_backend {
        {{range service "nginx"}}            //这里的“Nginx”是基于docker镜像进行搜索的,而不是容器的名称
        server {{ .Address }}:{{ .Port }};
        {{ end }}
}
server {
        listen 8000;                         //监听地址可任意指定,不要冲突即可
        server_name localhost;
        location / {
                proxy_pass http://http_backend;
        }
}
//编辑完成后,保存退出即可
[root@docker01 consul]# vim ../conf/nginx.conf    //在主配置文件中进行调用生成的vhost.conf文件
include /usr/local/nginx/consul/*.conf;
}             //在配置文件末尾的花括号上方写入“include”配置,进行调用vhost.conf文件
[root@docker01 consul]# nginx -s reload   //重启nginx服务
[root@docker01 consul]# nohup consul-template -consul-addr 192.168.45.129:8500 -template "/usr/local/nginx/consul/nginx.ctmpl:/usr/local/nginx/consul/vhost.conf:/usr/local/sbin/nginx -s reload" &
[2] 64430
[root@docker01 consul]# nohup: 忽略输入并把输出追加到"nohup.out"

[root@docker01 consul]# 
//同样也是将这条命令放入后台执行,否则会占用前台的终端
//这条命令的作用就i是将本机收集到的信息,生成一个vhost.conf的文件,将命令放入后台才能保证实时发现同步并更新

注:这里附加了一张图
Docker服务配置+ Consul + registrator实现服务发现
六)、验证服务的实时发现功能
配置至此,docker02或者docker03上一旦有任何Nginx相关的容器以后台“-d”的运行方式运行,都会被添加到反向代理中来,进行调度,一旦容器发生意外关闭,则可以自动从反向代理配置文件中剔除。

现在可以在docker02、和docker03上分别运行两台Nginx容器,其容器名称依次为web01、web02.......,其网页文件依次为:this is web01 test、this is web02 test..........

为其准备不同的网页文件的目的就是方便客户端访问时区分访问的是哪台容器。

由于其配置过程类似,我这里就写出一个运行Nginx容器的过程,其他照做即可。

配置示例如下(运行web01并修改其首页文件):

[root@docker02 ~]# docker run -d -P --name web01 nginx
[root@docker02 ~]# docker exec  -it web01  /bin/bash
root@1aaf578ec6f7:/#  echo "this is a web01 test." > /usr/share/nginx/html/index.html

注:在docker02及docker03运行四个Nginx容器后(必须以后台运行的方式,也就是说在运行时必须有“-d”选项),那么,此时访问docker01的8000端口,就会循环访问到这四个容器提供的网页文件,如下:

[root@docker01 consul]# curl 192.168.45.141:8000
this is a web01 test.
[root@docker01 consul]# curl 192.168.45.141:8000
this is a web02 test.
[root@docker01 consul]# curl 192.168.45.141:8000
this is a web03 test.
[root@docker01 consul]# curl 192.168.45.141:8000
this is a web04 test.
[root@docker01 consul]# curl 192.168.45.141:8000
this is a web01 test.
[root@docker01 consul]# curl 192.168.45.141:8000
this is a web02 test.
//并且查看以下文件,会看到其中的配置
[root@docker01 consul]# pwd
/usr/local/nginx/consul
[root@docker01 consul]# cat vhost.conf     //以下web池中的server都是基于编写的模板自动生成的
upstream http_backend {

  server 192.168.45.141:32768;

  server 192.168.45.141:32769;

  server 192.168.45.142:32768;

  server 192.168.45.142:32769;

}

server {
  listen 8000;
  server_name localhost;
  location / {
  proxy_pass http://http_backend;
  }
}
//由于consul-template是在后台运行的,所以,只要检测到容器的变化,就会动态修改上述文件
//并且重启Nginx服务,使更改生效

至此,consul+registrator+docker实时服务发现就配置完成了