为了账号安全,请及时绑定邮箱和手机立即绑定

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

标签:
Docker


我们先来看一下服务发现常用的框架有哪些:

zookeeper

eureka

etcd

consul

这里就不挨个来介绍它们了,本文中主要以consul为主,如果你在大量接触或使用微服务的话,你可能会碰到一个问题?当你创建的服务数量越来越多时,这些服务之间的通信便越难管理,而且维护代价会越来越高。consul可以给你答案,我们一起来了解一下consul:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

1.了解consul

Consul是一个分布式,高度可用且支持多数据中心的服务发现,配置和编排工具。 Consul支持大规模部署,配置和维护面向服务的体系结构。 欲了解更多官方信息,请参阅:

consul 文档

consul github

1.1 架构设计

在现实中,我们一直渴望着追求提供高质量、高可用的服务架构体系,同时减少不必要的部署和维护代价,减少容错率。面对如此高的要求,可以有两种架构方案:

Docker+Etcd+Confd+Nginx

Docker+Consul+Nginx

本文中我们主要来介绍 Docker+Consul+Nginx方案,此方案更加高效、快捷,并且维护代价和容错率更低,分布式支持力度更强,如下图所示:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

使用Docker将Consul、Consul Template、Registrator和Nginx组装成一个值得信任且可扩展的服务框架,这套架构让你在这个框架中添加和移除服务,不需要重写任何配置,也不需要重启任何服务,一切都能正常运行,工作流程很简单:

docker节点 ---------> consul ---------> nginx.conf

1.2 架构优势

Docker+Consul+Nginx虽然看起来是三个组件的运用,但却证明是一个有机的整体。它们互相联系、互相作用,完全满足我们对高可用、高效服务架构方案的需求,是Docker生态圈中最理想的组合之一,具有以下优势:

自动发现与注册组件consul使用 Raft 算法来保证一致性,比复杂的Paxos 算法更直接。相比较而言,zookeeper 采用的是 Paxos,而 etcd 使用的则是 Raft;

支持多数据中心,多数据中心集群可以避免单数据中心的单点故障,zookeeper 和 etcd 均不提供多数据中心功能的支持;

自动、实时发现及无感知服务刷新,具备资源弹性,伸缩自如;

支持健康检查,负载能动态在可用的服务实例上进行均衡,etcd 不提供此功能;

支持足够多台Docker容器(前提架构资源足以保证性能支撑);

支持http 和dns 协议接口,zookeeper 的集成较为复杂,etcd 只支持 http 协议;

服务规模方便进行快速调整,官方提供web管理界面,etcd 无此功能;

Consul template 搭配consul使用,支持多种接入层,如Nginx、Haproxy。

2.环境说明

本文所用的环境均按1.1中的架构图来部署,nginx用1台服务器、consul用1台服务器、docker host用2台服务器,共用4台服务器来部署,当然如果你的服务器紧张,用3台也一样,减少1台docker host就行:

服务器IP 服务器名  角色

172.18.18.32  nginx 运行nginx服务、consul-template守护进程

172.18.18.33  consul  运行consul服务

172.18.18.34  docker01  运行registrator容器、运行nginx容器(映射端口81、82)

172.18.18.35  docker02  运行registrator容器、运行nginx容器(映射端口83、84)

3.部署nginx

在nginx服务器上操作

3.1 安装nginx

1、下载并解压nginx:

你可以用docker的方案运行nginx、也可以用源码包编译安装nginx。在本文中nginx用源码包的方式安装

[root@nginx /]# cd /usr/src/

[root@nginx src /]# tar -zxvf nginx-1.12.1.tar.gz

2、编译安装nginx:

[root@nginx src]# yum -y install gcc gcc-c++ make openssl-devel pcre-devel

[root@nginx src]# cd nginx-1.12.1/

[root@nginx nginx-1.12.1]# ./configure --prefix=/usr/local/nginx   --with-http_stub_status_module --with-http_realip_module --with-pcre  --with-http_ssl_module

[root@nginx nginx-1.12.1]# make -j 2

[root@nginx nginx-1.12.1]# make install

3.2 安装consul-template

安装consul-template非常简单,下载二进制包即可使用

1、下载consul-template

下载地址:https://releases.hashicorp.com/consul-template/0.19.3/consul-template_0.19.3_linux_amd64.zip

[root@nginx ]# wget https://releases.hashicorp.com/consul-template/0.19.3/consul-template_0.19.3_linux_amd64.zip

2、解压并安装到/usr/bin目录

[root@nginx ]# unzip consul-template_0.19.3_linux_amd64.zip

[root@nginx ]# mv consul-template /usr/bin/

4.部署consul

在consul服务器上操作

4.1 安装consul

有两种方式安装consul(容器、二进制包),在本文中选使用二制包的方式。

1、下载consul二进制包

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

2、解压、安装

[root@consul ~]#unzip consul_0.9.2_linux_amd64.zip

[root@consul ~]#mv consul /usr/bin/

3、部署consul

[root@consul ~]#consul agent -server -bootstrap -ui -data-dir=/var/lib/consul-data -bind=172.18.18.33 -client=0.0.0.0 -node=server01

参数说明:

agent:运行一个consul代理。

-server :切换代理到服务器模式。

-bootstrap :将服务器设置为引导模式。

-ui:启用内置的静态web UI服务器。

-data-dir:路径到数据目录存储代理状态。

-bind:设置集群通信的绑定地址。

-client:设置用于绑定客户端访问的地址。这包括RPC、DNS、HTTP和HTTPS(如果配置)。

-node:此节点的名称。 在集群中必须是唯一的,如果你运行第2台consul,可以写server02、server03等。

consul启动后它会在前台显示,如果你想让它在后台运行,可以加上nohup &来运行它:

[root@consul ~]#nohup consul agent -server -bootstrap -ui -data-dir=/var/lib/consul-data -bind=172.18.18.33 -client=0.0.0.0 -node=server01 &

4、查看consul启动后的情况:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

启动consul后默认会监听5个端口:

8300: replication、leader farwarding的端口

8301: lan cossip的端口

8302: wan gossip的端口

8500: web ui界面的端口

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

可参考下图查看端口的意思:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

4.2 查看consul集群信息

[root@consul ~]#consul members

[root@consul ~]#consul info |grep leader

[root@consul ~]#consul catalog services

4.3 通过http api获取集群信息

# 集群server成员

[root@consul ~]#curl 127.0.0.1:8500/v1/status/peers

# 集群Raft leader

[root@consul ~]#curl 127.0.0.1:8500/v1/status/leader

# 注册的所有服务

[root@consul ~]#curl 127.0.0.1:8500/v1/catalog/services

# 服务信息

[root@consul ~]#curl 127.0.0.1:8500/v1/catalog/services/nginx

# 集群节点详细信息

[root@consul ~]#curl 127.0.0.1:8500/v1/catalog/nodes

一般我们通过 http://consul服务器:8500 web界面来访问查看:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

从上图可以看到,consul 界面有5个菜单项(SERVICES、NODES、KEY/VALUE、ACL、DC1)。在SERVICES中,目前因为没有任何服务加入进来,只显示了consul它自己的服务状态。

我们在来看下NODES,从图中很好理解, 在server01这台节点上有个consul :8300的服务:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

接下来,我们去nginx服务器上配置一下nginx模板,并在两台docker主机上运行registrator服务进行测试。

5.配置nginx

在nginx服务器上操作

在步骤3中nginx已经安装好了,这一步只是配置nginx,大概配置的思路为:

在/usr/local/nginx/conf中创建目录consul,目录名自定义;

在consul目录中创建nginx.ctmpl模板;

在nginx.conf配置中添加include项并指向consul目录 ;

重启nginx服务;

5.1 创建nginx.ctmpl模板

[root@nginx /]#mkdir /usr/local/nginx/consul/

[root@nginx /]#cd /usr/local/nginx/consul/

[root@nginx consul]#vim nginx.ctmpl

upstream http_backend {

    {{range service "nginx"}}

    server {{ .Address }}:{{ .Port }};

    {{ end }}

}

server {

    listen 8000;

    server_name localhost;

    location / {

    proxy_pass http://http_backend;

    }

}

nginx.ctmpl模板中的内容就是两段意思,熟悉nginx的朋友一看也能明白:第1 定义nginx upstream一个简单模板,第2 定义一个server,监听8000端口,反向代理到upstream。

5.2 修改nginx.conf

[root@nginx consul]# vim /usr/local/nginx/conf/nginx.conf

worker_processes  1;

events {

    worker_connections  1024;

}

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {

        listen       80;

        server_name  localhost;

        location / {

            root   html;

            index  index.html index.htm;

        }

        error_page   500 502 503 504  /50x.html;

        location = /50x.html {

            root   html;

        }

    }

        #添加这一行

    include /usr/local/nginx/consul/*.conf;

}

添加好了在重载nginx服务:

[root@nginx consul]# /usr/local/nginx/sbin/nginx  -s reload

5.3 运行consul-template进程

1、启动consul-template

[root@nginx consul]#consul-template --consul-addr 172.18.18.33:8500 --template "./nginx.ctmpl:vhost.conf" --log-level=info

2018/03/14 08:08:06.933447 [INFO] consul-template v0.19.3 (ebf2d3d)

2018/03/14 08:08:06.933459 [INFO] (runner) creating new runner (dry: false, once: false)

2018/03/14 08:08:06.933779 [INFO] (runner) creating watcher

2018/03/14 08:08:06.933858 [INFO] (runner) starting

2018/03/14 08:08:06.933873 [INFO] (runner) initiating run

2018/03/14 08:08:06.935387 [INFO] (runner) initiating run

注意:它这个日志是一直在前台输出,通过ctrl+c停止consul-template进程。

参数说明:

--consul-addr:指定consul服务的ip和端口;

./nginx.ctmpl:这是用nginx.ctmpl这个模板来启动进程,这是写的相对路径,也可以写绝对路径;

vhost.conf:nginx.ctmpl模板生成后的文件名,这也可以写绝对路径,如果不写绝对路径,这个文件就在当前目录生成(/usr/local/nginx/consul/)

2、验证consul-template

由于consul-template在前台运行,所以我们在打开一个nginx终端验证。

#查看下进程

[root@nginx ~]# ps -ef | grep consul-template

root     22954 22794  0 16:08 pts/0    00:00:00 consul-template --consul-addr 172.18.18.33:8500 --template ./nginx.ctmpl:vhost.conf --log-level=info

#查看下consul目录下的文件

[root@nginx ~]# cd /usr/local/nginx/consul/

[root@nginx consul]# ls

nginx.ctmpl  vhost.conf

在consul目录下,是不是发现多了一个文件vhost.conf,就是刚才启动consul-template进程时生成的。

在来查看下vhost.conf的内容,目前upstraem配置为空,还没有docker主机加入进来:

[root@nginx consul]# cat vhost.conf 

upstream http_backend {

}

server {

    listen 8000;

    server_name localhost;

    location / {

    proxy_pass http://http_backend;

    }

}

接下来去配置下docker主机。

6.部署docker

在docker01和docker02上操作

先来说一下在docker服务器上操作的大概思路:

分别在两台docker服务器上都创建registrator容器,注意到consul服务中心;

在docker01上运行两台nginx容器(端口81、82),在docker02上运行两台nginx容器(端口83、84);

修改这4台nginx容器中的index.html页面内容为(docker01:81、docker01:82、docker02:83、docker02:84)

访问consul web界面验证

访问nginx服务器地址 http://172.18.18.32:8000 进行验证;

6.1 安装docker服务

安装过程省略,可参考笔者这篇文章进行安装 《docker环境安装(Ubuntu、Centos)》

6.2 创建registrator容器

分别在docker 01 和docker 02 上都创建:

[root@docker01 /]# docker run -d --name registrator --network=host -v /var/run/docker.sock:/tmp/docker.sock --restart=always gliderlabs/registrator:latest --ip 172.18.18.34 consul://172.18.18.33:8500

[root@docker02 /]# docker run -d --name registrator --network=host -v /var/run/docker.sock:/tmp/docker.sock --restart=always gliderlabs/registrator:latest --ip 172.18.18.35 consul://172.18.18.33:8500

参数说明:

--network:把运行的docker容器设定为host网络模式;

-v /var/run/docker.sock:把宿主机的Docker守护进程(Docker daemon)默认监听的Unix域套接字挂载到容器中;

--ip : 刚才把network指定了host模式,所以我们指定下IP为宿主机的IP;

consul:j最后这个选项是配置consul服务器的IP和端口。

### 6.3 启动nginx容器

1、先在docker01上启动第1台nginx,也就是端口为81的容器:

[root@docker01 /]#docker run -itd --name nginx_81 -p 81:80 nginx

进入容器修改index.html:

[root@docker01 /]# docker exec -it nginx_81 bash

root@272533504ab0:/# cd /usr/share/nginx/html/

root@272533504ab0:/usr/share/nginx/html# echo  "docker01:81" > index.html 

在去nginx服务器上验证下vhost.conf,从下面可以看到docker01的nginx 81注册进来了:

[root@nginx consul]# cat vhost.conf 

upstream http_backend {

    server 172.18.18.34:81;

}

server {

    listen 8000;

    server_name localhost;

    location / {

    proxy_pass http://http_backend;

    }

}

然后访问一下nginx服务器的IP地址,http://172.18.18.32:8000 ,从下图可以看出是可以访问的:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

2、在docker01上启动第2台nginx,也就是端口为82的容器,并修改好index.html:

[root@docker01 /]# docker run -itd --name nginx_82 -p 82:80 nginx

[root@docker /]# docker exec -it nginx_82  bash

root@b66febfa0753:/# cd /usr/share/nginx/html/

root@b66febfa0753:/usr/share/nginx/html# echo  "docker01:82" > index.html 

在去nginx服务器上验证下vhost.conf,从下面可以看到docker01的nginx 82也注册进来了:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

接着,我们访问下consul服务的web界面,http://172.18.18.33:8500 ,从下图可以看出,在SERVICE中是不是发现多了个nginx 服务:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

然后,在看看NODES,从下图可以看出,刚才创建的两个nginx容器(81、82)都注册到了server01这台consul服务器,如果我们的consul是集群环境的话,可以分别注册到server02或server03中:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

3、把docker02服务器上的nginx容器83和84也创建了

创建nginx:83

[root@docker02 /]# docker run -itd --name nginx_83 -p 83:80 nginx

[root@docker02 /]# docker exec -it nginx_83 bash

root@5c21ba694829:/# cd /usr/share/nginx/html/

root@5c21ba694829:/usr/share/nginx/html# echo  "docker02:83" > index.html

创建nginx:84

[root@docker02 /]# docker run -itd --name nginx_84 -p 84:80 nginx

[root@docker02 /]#docker exec -it nginx_84  bash

root@0f9d72ff453b:/# cd /usr/share/nginx/html/

root@0f9d72ff453b:/usr/share/nginx/html#  echo  "docker02:84" > index.html

4、去nginx服务器上验证vhost.conf:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

从上图可以看出,docker02服务器上的83和84也自动注册进来了。

5、在来看看consul服务器上的web界面:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

从上图可以看出,SERVICE中的nginx已经有了4个,并且还多了些其它的服务,这些服务是我docker02上跑的其它应用容器,也都会自动注册进来。

6、访问nginx服务器做最后的验证,http://172.18.18.32:8000 ,记得用f5刷新验证:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

F5刷新一下页面:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

在刷新一下,是不是访问到了docker02这台主机了:

基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架

到此,自动注册服务的过程就完成了,想到详细了解consul的朋友可以参考官方文档:

consul 官方下载:https://www.consul.io/downloads.html

consul官方集群安装:https://www.consul.io/intro/getting-started/join.html

consul github :https://github.com/hashicorp/consul

consul官方镜像: https://hub.docker.com/_/consul/

喜欢我的文章,请点击最上方右角处的《关注》支持一下!

©著作权归作者所有:来自51CTO博客作者甘兵的原创作品,如需转载,请注明出处,否则将追究法律责任


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消