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

1. 使用到的框架或者组件

  • Consul:分布式的、高可用的、 可横向扩展的,用于实现分布式系统的服务发现与配置。
  • Registrator:可以用来做服务发现。
  • Consul Template:搭配Consul使用,支持多种接入层,如Nginx、Haproxy。可以动态添加和移除服务,不需要重写任何服务。
  • Docker:利用容器化,简化部署,节省资源。
  • Supervisor: 是基于Python 的进程管理工具,可以帮助我们更简单的启动、重启和停止服务器上的后台进程,是Linux 服务器管理的效率工具。

2. 架构设计

de11c5f722122d7f4f64b27c0d56a7a3.png

3. 环境说明

我们需要部署nginx、consul、consul-template、registrator、webservice1(nginx)/webservice2(nginx)等服务。

需要注意的是:consul-template必须和nginx部署在一台机器上(因为consul-template动态更新nginx的配置后,需要通过自动触发的方式,来reload nginx的配置信息,否则是没法自动生效。这个reload就需要保证consul-template和nginx处于同一机器才行)

我们测试机器有限,而且有Docker这么方便的容器化工具,所以我们打算把所有服务都通过docker容器来运行。这样的话,我们只要一台安装了docker的机器就行,这里使用一台安装了docker的centos机器

但是我们刚才讲到了consul-template和nginx必须要在一台机器上,这个时候我们不得不要违背一个Docker容器运行一个服务的建议了。我们考虑使用Supervisor来让一个Docker容器同时运行consul-template和nginx服务。

服务器IP 容器名 容器IP 角色
192.168.1.92 consultemplate 172.10.0.2 通过Supervisor运行consul-template,nginx服务
192.168.1.92 consulserver 172.10.0.3 运行consul服务
192.168.1.92 registrator -- 运行registrator服务
192.168.1.92 nginx_81 -- 运行webservice1(nginx,使用端口81)服务
192.168.1.92 nginx_82 -- 运行webservice2(nginx,使用端口82)服务

4. 制作服务镜像

4.1 制作Nginx和Consul-template镜像

4.1.1 创建目录nginx-consultemplate

    mkdir -p nginx-consultemplate
    cd nginx-consultemplate

4.1.2 创建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 upsteam的一个简单模板,第二段则是定义了一个server,监听8000端口,反向代理到upstream。

4.1.3 创建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 /etc/nginx/consul/*.conf;
}

我们后面运行consul-template的时候,会使用nginx.ctmpl模板,解析之后生成.conf文件到/etc/nginx/consul目录下,所以nginx.conf文件的最后一条内容是include /etc/nginx/consul/*.conf;

4.1.4 创建supervisord.conf配置文件

[supervisord]
nodaemon=true

[program:consul-template]
command=consul-template -consul-addr 172.12.0.3:8500 -template "/etc/nginx/consul/nginx.ctmpl:/etc/nginx/consul/vhost.conf:nginx -s reload" -log-level=info

[program:nginx]
command=nginx

运行consul-template的时候,通过-consul-addr参数来指定consul服务的IP和端口号,-template参数来指定模板的解析,规则是:冒号第一段是模板文件路径,第二段是生成的配置文件路径,第三段是额外指令(这里特别重要:如果我们没有nginx -s reload这个,配置更新之后,无法自动生效。这个代表每次配置改变之后,都会自动执行此指令,用来reload nginx的配置,以便自动生效

4.1.5 创建Dockerfile文件

# 基于nginx基础镜像创建
FROM nginx:1.12.1
# 设置作者信息
MAINTAINER zwffff "[email protected]"

# 设置环境变量,用于更新时,更改此信息来忽略缓存
ENV REFRESHED_AT 2019-05-26

# 安装net-tools(用于调试的时候,打印网络信息),supervisor(进程管理工具),wget,unzip
RUN apt-get update -yqq && apt-get install -yqq net-tools supervisor wget unzip

# 下载安装consul-template
RUN wget https://releases.hashicorp.com/consul-template/0.19.3/consul-template_0.19.3_linux_amd64.zip
RUN unzip consul-template_0.19.3_linux_amd64.zip
RUN mv consul-template /usr/bin/

RUN mkdir -p /etc/nginx/consul/
# 将模板文件nginx.ctmpl拷贝到/etc/nginx/consul目录下
ADD nginx.ctmpl /etc/nginx/consul/
# 将nginx.conf配置文件拷贝到/etc/nginx配置下进行覆盖
ADD nginx.conf /etc/nginx/

# 将supervisord.conf配置文件拷贝到/etc/supervisor/目录
ADD supervisord.conf /etc/supervisor/supervisord.conf

# 运行supervisord时,指定上一条语句的配置文件
ENTRYPOINT [ "/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf" ]

4.1.6 编辑好Dockerfile文件之后,我们可以通过以下命令来生成nginx-consultemplate镜像文件

docker build -t zwffff/nginx-consultemplate .

4.2 制作Consul镜像

4.2.1 创建目录consul

mkdir -p consul
cd consul

4.2.2 创建Dockerfile文件

FROM centos:7.4.1708
MAINTAINER zwffff "[email protected]"

#配置consul版本
ENV CONSUL_VERSION=1.0.6
ENV HASHICORP_RELEASES=https://releases.hashicorp.com

#创建用户
RUN groupadd consul && useradd -g consul consul

RUN yum upgrade -y
RUN yum install -y net-tools
#RUN yum install -y firewall firewalld-config
RUN yum install -y wget unzip
RUN  wget ${HASHICORP_RELEASES}/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip && \
        unzip consul_${CONSUL_VERSION}_linux_amd64.zip && \
        rm -rf consul_${CONSUL_VERSION}_linux_amd64.zip && \
        mv consul /usr/local/bin

#创建consul数据目录和配置目录
RUN mkdir -p /consul/data && \
        mkdir -p /consul/config && \
        chown -R consul:consul /consul

#设置匿名卷
VOLUME /consul/data

#开放端口
EXPOSE 8300
EXPOSE 8301 8301/udp 8302 8302/udp
EXPOSE 8500 8600 8600/udp
EXPOSE 80

4.2.3 生成镜像

docker build -t zwffff/consul .

我们只需要用到以上两个自定义镜像,至此镜像就都制作完成了。下面我们考虑把所有镜像通过docker-compose
进行编排到一起执行。

5. 利用Docker-Compose进行容器编排

docker-compose怎么使用,这里不做具体的介绍,它主要使用YAML文件进行配置。有version、services和networks三部分组成。特别留意的是:version版本为2和3的时候,有一些配置是有区分的,不一样的。 services就是我们需要定义的容器集合,networks则是我们需要定义的网络集合。

我们需要启动以下容器:

  • web:使用zwffff/nginx-consultemplate镜像启动,会运行consul-template和nginx服务,依赖consul服务

  • consul:使用zwffff/consul镜像启动,运行consul服务

  • registrator:使用docker hub上的gliderlabs/registrator镜像启动,运行registrator服务,依赖web服务

  • nginx1:使用nginx镜像启动,用来作为webservice1调用测试,依赖registrator服务

  • nginx2:使用nginx镜像启动,用来作为webservice2调用测试,作为webservice1服务的同级服务,用来进行负载均衡测试,依赖registrator服务

  • 创建自定义网络
    docker network create --subnet=172.12.0.0/16 consul_testconsul

  • 创建 docker-compose.yml文件

version: "2"
services:
 web:
  image: zwffff/nginx-consultemplate  # 指定容器所使用的镜像
  container_name: consultemplate  # 指定容器名称
  networks:                        #指定容器所使用的网络
   consul_testconsul:        # 自定义网络的名称,这个与第一步创建的网络名称一致,同时下面的networks必须进行定义
    ipv4_address: 172.12.0.2   #指定当前容器所使用的IP地址
  depends_on:    #指定该容器依赖的容器
   - consul
  ports:    #指定容器绑定的端口号
   - "8000:8000"

 consul:
  image: zwffff/consul
  # -bind指定了当前consul服务所绑定的IP地址
  command: consul agent -server -bootstrap -ui -data-dir=/var/lib/consul-data -bind=172.12.0.3 -client=0.0.0.0 -node=server01  
  networks:
   consul_testconsul:
     ipv4_address: 172.12.0.3
  container_name: consulserver
  ports:
    - "8300"
    - "8301"
    - "8301/udp"
    - "8302"
    - "8302/udp"
    - "8500"
    - "8602"
    - "8600/udp"
    - "80"

 registrator:
  image: gliderlabs/registrator:latest
  container_name: registrator
  network_mode: host      # 这里要把宿主机注册到consul上去,所以网络模式必须要使用host模式
  command: --ip 192.168.1.92 consul://172.12.0.3:8500
  depends_on:
    - web
  volumes:
      -  /var/run/docker.sock:/tmp/docker.sock
  restart: always

 nginx1:
   image: nginx
   container_name: nginx_81
   depends_on:
     - registrator
   ports:
     - "81:80"

 nginx2:
   image: nginx
   container_name: nginx_82
   depends_on:
     - registrator
   ports:
     - "82:80"

networks:
 consul_testconsul:
  external: true     #使用外部已创建的网络时,external属性必须设置为true

这样,我们五个容器都已经通过docker-compose编排好了。
通过执行docker-compose up指令即可一键运行整个集群服务了。

参考文章:
基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架: https://blog.51cto.com/ganbing/2086851
consul官网:https://www.consul.io
consul github:https://github.com/hashicorp/consul
consul-template:https://github.com/hashicorp/consul-template
registrator:https://github.com/gliderlabs/registrator

你可能感兴趣的:(Docker+Consul+Registrator+Nginx实现容器服务自动发现的集群框架)