docker+consul+registrator实现服务发现

什么是服务发现?

百度百科是这样说的: 服务发现是指使用一个注册中心来记录分布式系统中的全部服务的信息,以便其他服务能够快速的找到这些已注册的服务

举个架构环境的中的栗子:

docker 微服务 dns 服务发现 docker的服务发现有哪些_docker

这是网站架构最常见的一种方式,前边nginx做反向代理负载均衡,来把请求转交到后端apache处理

不过,docker轻量化我们都知道,如果我们后端部署了50台甚至上百台apache或者nginx,我们不可能记住所有的地址和映射端口,所以我们采用到服务发现,帮我们自动发现这些服务器的ip和地址映射的端口,并且可以实现实时添加等减少工作压力

consul作用

Consul包含多个组件,但是作为一个整体,为你的基础设施提供服务发现和服务配置的工具.他提供以下关键特性:

  • 服务发现: Consul的客户端可用提供一个服务,比如 api 或者mysql ,另外一些客户端可用使用Consul去发现一个指定服务的提供者.通过DNS或者HTTP应用程序可用很容易的找到他所依赖的服务.
  • 健康检查: Consul客户端可用提供任意数量的健康检查,指定一个服务(比如:webserver是否返回了200 OK 状态码)或者使用本地节点(比如:内存使用是否大于90%). 这个信息可由operator用来监视集群的健康.被服务发现组件用来避免将流量发送到不健康的主机.
  • Key/Value存储: 应用程序可用根据自己的需要使用Consul的层级的Key/Value存储.比如动态配置,功能标记,协调,领袖选举等等,简单的HTTP API让他更易于使用.
    多数据中心: Consul支持开箱即用的多数据中心.这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域

实验环境

服务

主机

备注

consul

172.16.46.111

consul集群,收集所有容器的信息并处理

consul,registrator,httpd

172.16.46.112

收集dockerhost容器信息

consul,registrator,httpd

172.16.46.113

收集dockerhost容器信息

nginx,consul-template

172.16.46.114

负载均衡调度器,生成nginx模板文件

各组件流程

docker 微服务 dns 服务发现 docker的服务发现有哪些_docker服务发现_02

consul集群server数量建议是3-5台,node节点数量随便

docker01上部署consul服务

[root@docker01 ~]# unzip consul_1.5.1_linux_amd64.zip 
Archive:  consul_1.5.1_linux_amd64.zip
  inflating: consul                  
  
[root@docker01 ~]# mv consul /usr/local/bin/
[root@docker01 ~]# chmod +x /usr/local/bin/consul
#启动服务
consul agent -server -bootstrap -ui -data-dir=/var/lib/consul-data -bind=172.16.46.111 -client=0.0.0.0 -node=master

PS:启动以后会占用一个终端界面,可是使用nohup放到后台运行

nohup consul agent -server -bootstrap -ui -data-dir=/var/lib/consul-data -bind=172.16.46.111 -client=0.0.0.0 -node=master &

参数说明:

-bootstrap:加入这个选项时,一般都在server单节点的时候用,自选举为leader

-ui:开启内部的web界面

-data-dir:key/volume数据存储位置

-bind:指定开启服务的IP

-client:指定访问的客户端

-node:指定集群内通信的名称

//查看consul集群内的成员的信息

[root@docker01 ~]# consul members
Node    Address             Status  Type    Build  Protocol  DC   Segment
master  172.16.46.111:8301  alive   server  1.5.1  2         dc1  <all>

docker02,docker03加入集群

以容器的方式运行consul客户端服务

#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:latest -join 172.16.46.111 -advertise 172.16.46.112 -client 0.0.0.0 -node=node01
#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:latest -join 172.16.46.111 -advertise 172.16.46.113 -client 0.0.0.0 -node=node02

PS:开启的端口

8300:集群节点

8301:集群内部的访问

8302:跨数据中心的通信

8500:web的ui界面

8600:使用dns协议查看节点信息的端口

在docker01查看consul集群成员

docker 微服务 dns 服务发现 docker的服务发现有哪些_docker服务发现_03

web界面访问

docker 微服务 dns 服务发现 docker的服务发现有哪些_nginx_04

部署consul-template

解压consul-template的压缩包

# unzip consul-template_0.19.5_linux_amd64.zip 
# mv consul-template /usr/local/bin/ 
# chmod +x /usr/local/bin/consul-template

docker02,docker03上面部署registrator服务

registrator是一个能自动发现docker container提供的服务,并在后端服务注册中心注册服务或取消服务的工具,后端注册中心支持conusl、etcd、skydns2、zookeeper等。

#docker02
docker run -d --name registrator -v /var/run/docker.sock:/tmp/docker.sock --restart always gliderlabs/registrator consul://172.16.46.112:8500
#docker03
docker run -d --name registrator -v /var/run/docker.sock:/tmp/docker.sock --restart always gliderlabs/registrator consul://172.16.46.113:8500

在docker02和docker03上面部署httpd

docker02:web01 ,web02

docker03:web03 ,web04

以docker02为例

[root@docker02 ~]# docker run -d --name web01 -P httpd
[root@docker02 ~]# docker run -d --name web02 -P httpd
[root@docker02 ~]# docker exec -it web01 /bin/bash
root@0142ffed48ff:/usr/local/apache2# pwd
/usr/local/apache2
root@0142ffed48ff:/usr/local/apache2# echo web01 > htdocs/index.html 
root@0142ffed48ff:/usr/local/apache2# read escape sequence
[root@docker02 ~]# docker exec -it web02 /bin/bash
root@20f696970a84:/usr/local/apache2# echo web02 > htdocs/index.html 
root@20f696970a84:/usr/local/apache2# read escape sequence

部署nginx服务

有脚本的话可以直接执行nginx 安装脚本。这里就不列出了。

安装完成以后更改nginx服务配置文件,添加以下模板文件,然后使用consul-template就可以生成新的配置文件

mdkir /usr/local/nginx/consul
cd /usr/local/nginx/consul
vim nginx.ctmpl
upstream http_backend {
        {{range service "httpd"}}
        server {{ .Address }}:{{ .Port }};
        {{ end }}
}

server {
        listen 8000;
        server_name localhost;
        location / {
        proxy_pass http://http_backend;
        }
}

修改nginx.conf,添加

docker 微服务 dns 服务发现 docker的服务发现有哪些_docker 微服务 dns 服务发现_05

// nginx主配置文件可以识别模板产生的新配置文件

重新加载服务

[root@localhost consul]# nginx -s reload

//使用consul-template 命令,根据模板生产新的配置文件 ’ vhost.conf ’ ,并重新加载nginx的配置文件

consul-template -consul-addr 172.16.46.111:8500 -template "/usr/local/nginx/consul/nginx.ctmpl:/usr/local/nginx/consul/vhost.conf"

会占用终端,当然,可以使用nohup保持后台运行

nohup consul-template -consul-addr 172.16.46.111:8500 -template "/usr/local/nginx/consul/nginx.ctmpl:/usr/local/nginx/consul/vhost.conf" &

//此时,应该能够看到,新生产的vhost.conf配置文件已经生效,访问本机8000端口可以得到不同容器提供的服务。

[root@localhost ~]# cd /usr/local/nginx/consul/
[root@localhost consul]# ls
nginx.ctmpl  vhost.conf
[root@localhost consul]# cat vhost.conf

docker 微服务 dns 服务发现 docker的服务发现有哪些_docker服务发现_06

curl连接测试前,最后提前再重新加载一遍nginx服务再访问

[root@localhost consul]# nginx -s reload
[root@localhost consul]# curl 127.0.0.1:8000
web01
[root@localhost consul]# curl 127.0.0.1:8000
web02
[root@localhost consul]# curl 127.0.0.1:8000
web03
[root@localhost consul]# curl 127.0.0.1:8000
web04
[root@localhost consul]# curl 127.0.0.1:8000
web01

再添加一台httpd服务器,验证是否会添加进来

docker 微服务 dns 服务发现 docker的服务发现有哪些_运维_07

[root@localhost consul]# nginx -s reload
[root@localhost consul]# curl 127.0.0.1:8000
web01
[root@localhost consul]# curl 127.0.0.1:8000
web02
[root@localhost consul]# curl 127.0.0.1:8000
web03
[root@localhost consul]# curl 127.0.0.1:8000
web04
[root@localhost consul]# curl 127.0.0.1:8000
web05
[root@localhost consul]# curl 127.0.0.1:8000
web01

经过多次的验证,都可以实时的添加进来,不过我们每次访问前都要重新加载一遍nginx服务,因为重新刷新nginx的vhost.conf配置文件。