由于blog各种垃圾评论太多,而且本人审核评论周期较长,所以懒得管理评论了,就把评论功能关闭,有问题可以直接qq骚扰我

consul 服务注册发现以及与nginx联动

常用服务 西门飞冰 1693℃
[隐藏]

1.Consul介绍

ConsulHashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。使用起来也较为简单。

2.Consul 安装

Consul 用 golang实现,因此具有天然的可移植性,安装包仅包含一个可执行文件,方便部署。

下载地址:https://www.consul.io/downloads.html

下载完成后,按照如下命令进行安装

[root@service1 ~]# unzip consul_1.0.0_linux_amd64.zip
[root@service1 ~]# mv consul /usr/bin/

安装完成进行验证

[root@service1 ~]# consul -v
Consul v1.0.0
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

3.环境介绍

四台服务器

IP地址 主机名 操作系统
server(Leader) 192.168.28.71 Service1 Centos 7.2
server(Follower) 192.168.28.72 Service2 Centos 7.2
agent1 192.168.28.61 Agent1 Centos 7.2
agent2 192.168.28.62 Agent2 Centos 7.2

4.建立集群

要想利用Consul提供的服务实现服务的注册与发现,我们需要建立Consul Cluster。在Consul方案中,每个提供服务的节点上都要部署和运行Consul的agent,所有运行Consul agent节点的集合构成Consul Cluster。Consul agent有两种运行模式:Server和Client。这里的Server和Client只是Consul集群层面的区分,与搭建在Cluster之上 的应用服务无关。以Server模式运行的Consul agent节点用于维护Consul集群的状态,官方建议每个Consul Cluster至少有3个或以上的运行在Server mode的Agent,Client节点不限。

1、启动一个server

[root@service1 ~]# consul agent -server -bootstrap-expect 2 -data-dir /tmp/consul -node=n1 -bind=192.168.28.71 -ui

参数说明:

-server:集群启动为service

-bootstrap-expect:期待加入service节点的数量

-data-dir:数据目录

-node:节点名称,集群中每个节点名称需唯一

-bind:指定一个consul运行时的监听地址

-ui:启动时启动ui

2、启动一个agent

[root@service2 ~]# consul agent -server -bootstrap-expect 2 -data-dir /tmp/consul -node=n2 -bind=192.168.28.72 -ui

3、通过consul members查看当前agent状态,可以看出server1和server2启动后并不知道其他节点的存在。

[root@service1 ~]# consul members
Node  Address             Status  Type    Build  Protocol  DC   Segment
n1    192.168.28.71:8301  alive   server  1.0.0  2         dc1  <all>

4、使用consul join命令触发Cluster bootstrap过程,将192.168.28.72服务器加入当前集群中

[root@service1 ~]# consul members
Node  Address             Status  Type    Build  Protocol  DC   Segment
n1    192.168.28.71:8301  alive   server  1.0.0  2         dc1  <all>
n2    192.168.28.72:8301  alive   server  1.0.0  2         dc1  <all>

5、join后,两台主机互相知道了对方,并进行了leader election过程,server1被选举为leader,server2为follower

[root@service1 ~]# consul info
……
	protocol_version_max = 3
	protocol_version_min = 0
	snapshot_version_max = 1
	snapshot_version_min = 0
	state = Leader
	term = 35
……

server2查看结果

[root@service2 ~]# consul info
……
	protocol_version_max = 3
	protocol_version_min = 0
	snapshot_version_max = 1
	snapshot_version_min = 0
	state = Follower
	term = 2
……

到这里server1和server2就成为了dc1这个数据中心consul cluster的两个节点,而且是用来维护集群状态的server node。Server1被选举为leader,server2是follower。

5.服务注册与发现

我们建立Consul Cluster是为了实现服务的注册和发现。Consul支持两种服务注册的方式,一种是通过Consul的服务注册HTTP API,由服务自身在启动后调用API注册自己,另外一种则是通过在配置文件中定义服务的方式进行注册。Consul文档中建议使用后面一种方式来做服务 配置和服务注册。

5.1.准备工作

服务准备,我已经在agent1和agent2安装了两台web服务器,提供web服务,我现在就把它注册到consul server上。

[root@service1 ~]# curl http://192.168.28.61:10000
service1
[root@service1 ~]# curl http://192.168.28.62:10000
service2
[root@service1 ~]# curl http://192.168.28.61:10000/health
ok
[root@service1 ~]# curl http://192.168.28.62:10000/health
ok

5.2.服务注册

Consul agent在启动时可以通过-config-dir来指定配置文件所在目录,比如以agent1为例,我们可以如此启动agent1:

[root@agent1 ~]# consul agent -data-dir /tmp/consul -node=n3 -bind=192.168.28.61 -config-dir=./conf

这样在./conf下的所有配置文件扩展名为.json的文件都会被consul agent作为配置文件读取

我们在agent1的consul agent的配置文件目录下创建server1.json文件。

{
  "service": {
    "name": "service1",
    "tags": ["master"],
    "address": "192.168.28.61",
    "port": 10000,
    "checks": [
      {
        "http": "http://localhost:10000/health",
        "interval": "10s"
      }
    ]
  }
}

这个配置就是我们在agent1节点上为service1这个服务做的服务定义,定义中包含,name、address、port,还包含一个服务检测的配置,这里我们每隔10秒对服务进行一次健康检查。

上述操作完成之后,我们只需要在service1节点把agent1节点加入集群,agent1就可以自动把服务注册到集群。

我们可以通过集群提供的web页面来查看注册到的服务。(web页面访问端口为8500,需要在server启动时指定ui参数)。

consul-ui-1

我们可以使用同样的方式吧agent2节点加入到集群,加入后ui显示如下:

consul-ui-2

5.3.服务发现

Consul提供了两种发现服务的方式,一种是通过HTTP API查看存在哪些服务;另外一种是通过consul agent内置的DNS服务来做。两者的差别在于后者可以根据服务check的实时状态动态调整available服务节点列表。

在agent1和agent2配置和部署完service1服务后,我们就可以通过DNS命令来查询服务的具体信息了。consul为服务编排的内置域名为 “NAME.service.consul”,这样我们的service1的域名为:service1.service.consul。我们在service1通过dig工具来查看一 下,注意是在service1上,service1上并未定义和部署web3服务,但集群中服务的信息已经被同步到n1上了,信息是一致的。

[root@service1 ~]# dig @127.0.0.1 -p 8600 service1.service.consul SRV

; <<>> DiG 9.9.4-RedHat-9.9.4-37.el7 <<>> @127.0.0.1 -p 8600 service1.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18460
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;service1.service.consul.	IN	SRV

;; ANSWER SECTION:
service1.service.consul. 0	IN	SRV	1 1 10000 n3.node.dc1.consul.
service1.service.consul. 0	IN	SRV	1 1 10000 n4.node.dc1.consul.

;; ADDITIONAL SECTION:
n3.node.dc1.consul.	0	IN	A	192.168.28.61
n3.node.dc1.consul.	0	IN	TXT	"consul-network-segment="
n4.node.dc1.consul.	0	IN	A	192.168.28.62
n4.node.dc1.consul.	0	IN	TXT	"consul-network-segment="

;; Query time: 5 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: 五 11月 03 15:33:49 CST 2017
;; MSG SIZE  rcvd: 232

可以看到在ANSWER SECTION中,我们得到了两个结果:n3和n4上各有一个service1的服务。在dig命令中我们用了SRV标志,那是因为我们需要的服务信息不仅有ip地址,还需要有端口号。

现在我们停掉agent1上的service1服务,10s后,我们再来查一下,我们可以到consul agent故障的service1从结果列表中剔除了,这样service1服务的客户端在服务发现过程中就只能获取到当前可用的service1服务节点了。另外consul agent DNS在返回查询结果时也支持DNS Server常见的策略,至少是支持轮询。你可以多次执行dig命令,可以看到n3和n4的排列顺序是不同的。还有一点值得注意的是:由于考虑DNS cache对consul agent查询结果的影响,默认情况下所有由consul agent返回的结果TTL值均设为0,也就是说不支持dns结果缓存。

[root@service1 ~]# dig @127.0.0.1 -p 8600 service1.service.consul SRV

; <<>> DiG 9.9.4-RedHat-9.9.4-37.el7 <<>> @127.0.0.1 -p 8600 service1.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48138
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;service1.service.consul.	IN	SRV

;; ANSWER SECTION:
service1.service.consul. 0	IN	SRV	1 1 10000 n3.node.dc1.consul.

;; ADDITIONAL SECTION:
n3.node.dc1.consul.	0	IN	A	192.168.28.61
n3.node.dc1.consul.	0	IN	TXT	"consul-network-segment="

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: 五 11月 03 15:43:29 CST 2017
;; MSG SIZE  rcvd: 142

6.consul-template与nginx联动

6.1.方案概述

nginx提供的负载均衡服务同样支持高可用、可扩展的Web服务,但缺点是较依赖于人工。例如传统的nginx负载均衡的配置方式是,在nginx某个include的某个配置文件中配置一个upstream,upstream中配置多个服务节点,每一个服务节点就是一个web应用服务。nginx虽然可以做到对服务节点的健康检查,但是当服务节点增加、减少或者发生状态改变(如负载较大、网络故障、其他故障)时,nginx配置文件是固定写死的,不能动态的感知后端服务节点的服务状态信息,因此需要有一种解决方案能够帮助ngnix动态的感知后端服务节点的服务信息。

6.2.配置概述

nginx前端作为负载均衡器使用,它代理了三台能提供web服务的服务器,每一台服务器上均安装consul,并以agent的形式运行在服务器上,并将Consul Agent加入到Consul Cluster中。Consul-template与Consul Cluster的Server连接,动态的从Consul的服务信息库汇中拉取nginx代理的三台服务器的IP、端口号等信息,并将IP地址以及端口号写入到nginx的配置文件中,在完成一次写入后(即后台服务发生变更时),Consul-template将自动将nginx重启加载,实现nginx应用新配置文件的目的。

6.3.配置过程

在上文中,我们已经构建了一个consul集群了,我们需要在这个集群的基础上添加如下服务:
1、 在server1 节点安装并配置nginx服务
2、 在server1节点安装并配置consul-template服务
3、 验证与测试

环境安装

yum -y install nginx
wget -c https://releases.hashicorp.com/consul-template/0.12.0/consul-template_0.12.0_linux_amd64.zip
unzip -d . consul-template_0.12.0_linux_amd64.zip
cp consul-template '/bin'
rm -rf consul*

配置consul-template
准备一个nginx模版配置文件

[root@service1 ~]# cat nginx_service1.ctmpl
upstream service1 {
    ip_hash;
{{range service "service1"}}
    server {{.Address}}:{{.Port}} fail_timeout=0;
{{end}}
    keepalive 64;
}
server {
    listen 10000;
    server_name ipaddress;
    location / {
        proxy_pass          http://service1/;
    }
}

启动consul-template:consul-template将查询consul集群的服务注册信息,并自动更新到nginx配置文件,完成之后还能执行nginx重载命令。

[root@service1 ~]# consul-template -consul 127.0.0.1:8500 -template nginx_service1.ctmpl:/etc/nginx/conf.d/nginx_service1.conf:"/usr/sbin/nginx -s reload"

验证:在consul-template进程启动之后,查看nginx配置文件目录,可以看到server1的膜拜已经推送了过来,并且自动添加了已经注册的服务地址和端口。

[root@service1 ~]# cat /etc/nginx/conf.d/nginx_service1.conf
upstream service1 {
    ip_hash;

    server 192.168.28.61:10000 fail_timeout=0;
    server 192.168.28.62:10000 fail_timeout=0;
    keepalive 64;
}
server {
    listen 10000;
    server_name ipaddress;
    location / {
        proxy_pass          http://service1/;
    }
}

我们将192.168.28.62服务器下线,等10秒后再查看nginx配置文件,可以看到192.168.28.62服务器已经自动下线了。

[root@service1 ~]# cat /etc/nginx/conf.d/nginx_service1.conf
upstream service1 {
    ip_hash;

    server 192.168.28.61:10000 fail_timeout=0;

    keepalive 64;
}
server {
    listen 10000;
    server_name ipaddress;
    location / {
        proxy_pass          http://service1/;
    }
}

7.参考文档

http://dockone.io/article/1359

https://studygolang.com/articles/4476

http://www.techweb.com.cn/network/system/2016-01-28/2270190.shtml

转载请注明:西门飞冰的博客-专注于Linux运维 » consul 服务注册发现以及与nginx联动

喜欢 (2)or分享 (0)