一、      目的

在服务在容器中部署时,外部调用服务需要知道服务接口ip及端口号,这样导致部署时需要配置,从而增加部署的困难。本文档主要介绍如何使用ningx反向代理和consul进行自动化服务发现与部署,从而使外部访问服务只需要访问nginx代理即可解决,同时也可以解决分布式服务及大访问量负载问题。

场景说明:如有一个数据服务data-service,如果在docker集群中部署的话,ip和port都可能变化,这时线上服务必须更改配置,才能访问到data-service服务。而采用本方案的话,只需要配置好ningx负载均衡的ip与地址,数据服务可随时重新部署调整,不需要重新配置。


 

二、     
概述

Nginx是常用的轻量级反向代理插件,使用Ningx可以让服务统一入口,通过Ningx配置服务路径请求转发路径,将对应的请求路由到对应的服务中处理。使用Ningx可以使后端服务部署更加灵活。

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

服务发现 Consul的客户端可用提供一个服务,比如 api 或者mysql ,另外一些客户端可用使用Consul去发现一个指定服务的提供者.通过DNS或者HTTP应用程序可用很容易的找到他所依赖的服务.

健康检查 Consul客户端可用提供任意数量的健康检查,指定一个服务(比如:webserver是否返回了200
OK 状态码)或者使用本地节点(比如:内存使用是否大于90%). 这个信息可由operator用来监视集群的健康.被服务发现组件用来避免将流量发送到不健康的主机.

Key/Value存储
应用程序可用根据自己的需要使用Consul的层级的Key/Value存储.比如动态配置,功能标记,协调,领袖选举等等,简单的HTTP API让他更易于使用.

多数据中心 Consul支持开箱即用的多数据中心.这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域.

Consul面向DevOps和应用开发者友好.是他适合现代的弹性的基础设施.


 

三、     
部署方案

  i.  部署图

图1 部署图

 

ii.  部署过程

  1. 部署consul server

    docker run -d --name=consul_server -p : -p : -p :/udp -h docker_server progrium/consul -server -bootstrap
  2. 部署consul registrator
    docker run -d --name=consul_registrator --net=host --volume=/var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator:latest  -ip="192.168.1.60" consul://192.168.1.60:8500

    -ip:使用主机ip,因为nginx转发可能涉及到跨主机的服务请求转发,所以需要绑定主机ip;

    consul://192.168.1.60:8500:为consul server的ip和端口。

  3. 部署consul template&nginx
  •   部署容器

    docker -d run liberalman/nginx-consul-template:latest
  •   配置Nginx

    Nginx配置存储路径为:/etc/nginx/conf.d,使用的是分文件,该文件是由consul template自动更新的,不需要进行配置。

  •   配置Consul template

    配置文件存储的路径为:/etc/consul-templates/nginx.conf.ctmpl,该文件为consul template在监控consul server服务有改动时,进行配置修改,并存储到/etc/nginx/conf.d/app.conf当中。

示例配置:

upstream solr {

  least_conn;

  {{range service "solr"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;

  {{else}}server 127.0.0.1:65535; # force a 502{{end}}

}

upstream data_service {

  least_conn;

  {{range service "data_service"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;

  {{else}}server 127.0.0.1:65535; # force a 502{{end}}

}

server {

  listen 80 default_server;

  location /solr {

    proxy_pass http://solr;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_set_header Host $host;

    proxy_set_header X-Real-IP $remote_addr;

  }

  location /data {

    proxy_pass http://data_service;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_set_header Host $host;

    proxy_set_header X-Real-IP $remote_addr;

  }

}

配置一个服务需要俩个地方进行配置修改。

upstream solr {

  least_conn;

  {{range service "solr"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;

  {{else}}server 127.0.0.1:65535; # force a 502{{end}}

}

1)      upstream配置

    •   upstream solr:该solr为定义的服务别名,在后面server节点中需要用到;
    •   {{range service "solr"}}:其中solr为该服务在注册时到服务时的服务名称,该名称在容器启动时设置环境变量SERVICE_NAME得到,如果需指定某端口对应某服务,使用SERVICE_80_NAME,80替换为端口号即可,下图是配置了80端口的服务名为data_service

2)      server配置

  location /solr:配置路由进行转发

  proxy_pass http://data_service:配置对应的路由转发到哪个upstream上。

  

location /solr {

    proxy_pass http://solr;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_set_header Host $host;

    proxy_set_header X-Real-IP $remote_addr;

  }

该段代码表示将请求路径/solr的请求转发到服务名为solr的地址上。

以app.conf为例:

upstream solr {

  least_conn;

  server 192.168.1.60:8080 max_fails=3 fail_timeout=60 weight=1;

}

upstream data_service {

  least_conn;

  server 192.168.1.60:5000 max_fails=3 fail_timeout=60 weight=1;

}

server {

  listen 80 default_server;

  location /solr {

    proxy_pass http://solr;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_set_header Host $host;

    proxy_set_header X-Real-IP $remote_addr;

  }

  location /data {

    proxy_pass http://data_service;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_set_header Host $host;

    proxy_set_header X-Real-IP $remote_addr;

  }

}

假设nginx部署在192.168.1.112服务器上,那么访问 http://192.168.1.112/solr,该请求会被转发到http://192.168.1.60:8080/solr

    4. 启动服务

1)      如果需要忽略不注册到consul上,则在创建容器时添加环境变量SERVICE_IGNORE=true

2)      如果需要注册到consul上,则需要设置服务名,使用SERVICE_NAME=[服务名]进行设置,也可将容器对应的不同端口设置为不同的服务名,例如需要将容器暴露的端口8088设置为bussiness服务名,则使用SERVICE_8088_NAME=[服务名],即在中间加上端口号即可

3)      如果需要对服务加上标签,可使用环境变量SERVICE_TAGS进行设置,多个标签以英文逗号隔开

            iii.          采用docker compose部署

 Docker compose部署可以解决容器先后启动顺序问题    

version: '2'
services:
load_balancer:
image: nginx-consul-template:latest
hostname: lb
container_name: consul-nginx-template
links:
- consul_server
depends_on:
- consul_server
ports:
- "80:80"
environment:
- SERVICE_IGNORE=true consul_server:
image: progrium/consul
hostname: consul_server
container_name: consul_server
ports:
- "8300:8300"
- "8301:8301"
- "8302:8302"
- "8400:8400"
- "8500:8500"
- "8600:8600"
environment:
- SERVICE_IGNORE=true
command: -server -bootstrap registrator:
image: gliderlabs/registrator:latest
hostname: registrator
container_name: consul_registrator
links:
- consul_server
depends_on:
- consul_server
volumes:
- "/var/run/docker.sock:/tmp/docker.sock"
environment:
- SERVICE_IGNORE=true
command: -ip 192.168.1.60 consul://192.168.1.60:8500

    

四、      常见问题

  待补充...

Docker容器服务发现方案的更多相关文章

  1. 基于 Consul 的 Docker Swarm 服务发现

    Docker 是一种新型的虚拟化技术,它的目标在于实现轻量级操作系统的虚拟化.相比传统的虚拟化方案,Docker 虚拟化技术有一些很明显的优势:启动容器的速度明显快于传统虚拟化技术,同时创建一台虚拟机 ...

  2. Docker Kubernetes 服务发现原理详解

    Docker Kubernetes  服务发现原理详解 服务发现支持Service环境变量和DNS两种模式: 一.环境变量 (默认) 当一个Pod运行到Node,kubelet会为每个容器添加一组环境 ...

  3. docker容器日志收集方案汇总评价总结

    docker日志收集方案有太多,下面截图罗列docker官方给的日志收集方案(详细请转docker官方文档).很多方案都不适合我们下面的系列文章没有说. 经过以下5篇博客的叙述简单说下docker容器 ...

  4. Docker 容器优雅终止方案

    原文链接:Docker 容器优雅终止方案 作为一名系统重启工程师(SRE),你可能经常需要重启容器,毕竟 Kubernetes 的优势就是快速弹性伸缩和故障恢复,遇到问题先重启容器再说,几秒钟即可恢复 ...

  5. Ocelot + Consul + Registrator 基于Docker 实现服务发现、服务自动注册

    目录 1. Consul集群搭建 1.1 F&Q Consul官方推荐的host网络模式运行 2. Registrator服务注册工具 2.1 F&Q Registrator悬挂服务 ...

  6. docker容器日志收集方案(方案N,其他中间件传输方案)

    由于docker虚拟化的特殊性导致日志收集方案的多样性和复杂性下面接收几个可能的方案 ​ 这个方案各大公司都在用只不过传输方式大同小异 中间件使用kafka是肯定的,kafka的积压与吞吐能力相当强悍 ...

  7. docker容器日志收集方案(方案一 filebeat+本地日志收集)

    filebeat不用多说就是扫描本地磁盘日志文件,读取文件内容然后远程传输. docker容器日志默认记录方式为 json-file 就是将日志以json格式记录在磁盘上 格式如下: { " ...

  8. Docker容器日志清理方案

    Docker容器在运行过程中会产生很多日志,久而久之,磁盘空间就被占满了,以下分享docker容器日志清理的几种方法 删除日志 在linux上,容器日志一般存放在 /var/lib/docker/co ...

  9. docker容器日志收集方案(方案二 filebeat+syslog本地日志收集)

    与方案一一样都是把日志输出到本地文件系统使用filebeat进行扫描采集 不同的是输出的位置是不一样的 我们对docker进行如下设置 sudo docker service update  --lo ...

随机推荐

  1. 阿里P9架构师讲解从单机至亿级流量大型网站系统架构的演进过程

    阶段一.单机构建网站 网站的初期,我们经常会在单机上跑我们所有的程序和软件.此时我们使用一个容器,如tomcat.jetty.jboos,然后直接使用JSP/servlet技术,或者使用一些开源的框架 ...

  2. Java中IO流中的装饰设计模式(BufferReader的原理)

    本文粗略的介绍下JavaIO的整体框架,重在解释BufferReader/BufferWriter的演变过程和原理(对应的设计模式) 一.JavaIO的简介 流按操作数据分为两种:字节流与字符流. 流 ...

  3. Hadoop2源码分析-YARN 的服务库和事件库

    1.概述 在<Hadoop2源码分析-YARN RPC 示例介绍>一文当中,给大家介绍了YARN 的 RPC 机制,以及相关代码的演示,今天我们继续去学习 YARN 的服务库和事件库,分享 ...

  4. S0到S5状态讲解

    ACPI(高级配置和电源管理接口)的六种工作状态Advanced Configuration and Power Management InterfaceACPI表示高级配置和电源管理接口( Adva ...

  5. c time类型详解

    linux下存储时间常见的有两种存储方式,一个是从1970年01月01日 0:00:00到现在经过了多少秒,一个是用一个结构来分别存储年月日时分秒的.time_t 这种类型就是用来存储从1970年到现 ...

  6. ruby Enumerator::lazy

    当一个很大的数组或集合需要做循环操作的时候,一次性把数据放到内存会有很大弊端.这时lazy就派上用场了.Float::INFINITY 是无穷大意思 举个例子 取出1到无穷大对7整除余数为0的前10个 ...

  7. numpy使用指南

    numpy.array numpy.array是numpy中用于处理n阶数组的对象,是其类族中的重要基类. numpy.array可以表示任意维的数组,可以使用构造函数初始化: arr = numpy ...

  8. Scala面向对象编程与类型系统

    Scala支持面向对象编程, 其面向对象特性与Java有共同之处并添加了很多新的特性. 类定义 scala使用class关键字定义类: class MyComplex(real0:Double, im ...

  9. 浅谈c#的三个高级参数ref out 和Params

    c#的三个高级参数ref out 和Params 前言:在我们学习c#基础的时候,我们会学习到c#的三个高级的参数,分别是out .ref 和Params,在这里我们来分别的讲解一下,在这里的我们先不 ...

  10. opoa介绍

    一 定义      One Page, One Application(后面缩写为OPOA,或者1P1A), 含义很简单:一个页面就是一个应用.不再使用iframe, 页面提交不能再使用submit方 ...