基于 Docker 的高可用 Rails 集群方案探索

基于 Docker 的高可用 Rails 集群方案探索

作者:长洪 2015-07-29 13:21:58

云计算 本文是暴走漫画团队关于自动化高可用集群方案的探索。主要目的是减少人工接入,实现自动化。主要是用了consul和registrator两个工具。

0x0 问题

运维从来都是一个“不起眼”的大问题。运维工作还特别琐碎,一般要花去工程师大量的时间,同时还有突发性,对工程师机动性要求比较高。所以运维自动化一直在困扰暴走漫画团队。

虽说大部分运维工作都交给第三方云服务提供商了,但是平时还是有一些机器的维护之类的,繁琐的事情。

我 做的最多的应该就是加减服务器了。暴漫的流量趋势非常规律,每年寒暑假是访问的高峰期,一般会比平时流量高出2倍。所以每年寒暑假之前都要添加足量的服务 器以应对马上到来的流量高峰,而在寒暑假结束之后,要去掉一部分机器,以节省开支。刚开始完全是人肉运维,我一个人先去开5台机器,然后一个个上去改配置 文件之类的,感觉好傻。后面就用了ansible作为自动化运维工具,这个要比puppet和chef轻量很多,对付我们这些简单的运维工作绰绰有余。 于是现在就变成了开完机器,用ansible同步配置,代码,启动app server,然后手动更新nginx配置。

使用ansible之后其实已经轻松很多了,但是还不够,我想象中的自动化集群,应该可以随意增加删除node,node不可用的时候自动删除,当然这些都不能影响服务的访问。

下面介绍一种自动化的Rails集群方案

0x1 相关技术

  • docker
  • hashicorp/consul(https://github.com/hashicorp/consul)
  • hashicorp/consul-template(https://github.com/hashicorp/consul-template)
  • hashicorp/registrator(https://github.com/gliderlabs/registrator)

0X2 整体架构

0x3 实践

由于不是科普帖,各种工具的详细信息就不自己介绍了。

  consul & registrator

这两个工具是集群中每个节点的基础服务。我在一台机器上,所以把consul cluster给省掉了,只用了一个consul节点。下面是docker-compose配置。

consul:

hostname: node1

image: progrium/consul

command: -server -bootstrap -advertise 172.17.42.1

ports:

– “8400:8400”

– “8500:8500”

– “8600:53/udp”

registrator:

image: gliderlabs/registrator

command: consul://consul:8500

hostname: registrator1

volumes:

– /var/run/docker.sock:/tmp/docker.sock

links:

– consul

需要注意的是consul的启动参数里的advertise。应该声明为host机器的docker0的ip。如果不声明的话会默认使用容器ip,这样registrator注册的设备ip都是不可访问的。

以上配置启动之后一套自动服务器发现功能就算完工了。

#p#

接下来,我们配置一个web应用测试一下。

web:

image: nginx

volumes:

– ./sites-enabled:/etc/nginx/conf.d

ports:

– “80:80”

links:

– rails

rails:

image: tutum/hello-world

ports:

– “80”

这个配置生成了nginx和rails,并且挂载了本地的sites-enabled文件夹作为nginx的配置来源。注意rails的ports是随机的。

在sites-enabled中配置nginx server已rails作为backend。

  1. upstream backend { 
  2. server { 
  3.     server_name "10.0.2.15"
  4.     location / { 
  5.             proxy_pass http://backend; 
  6.     } 
  7. }  

对你并没有看错, upstream并没有定义可用的backend node。这个配置将会有consul-template根据服务列表自动填充。

让我们启动这个web应用,访问80端口是无法访问的 应为没有backend node。

接下来需要安装consule-template, 在github下载对应的release。

然后创建一个配置文件ct-nginx.conf

  1. consul = "127.0.0.1:8500" 
  2. log_level = "warn" 
  3.  
  4. template { 
  5.     source = "/home/vagrant/nginx.ctmpl" 
  6.     destination = "/home/vagrant/sites-enabled/backend.conf" 
  7.     command = "docker-compose -f /home/vagrant/docker-compose.yml restart web" 
  8. }  

我有映射consul的端口,所以直接使用了127.0.0.1。source就是我们配置文件的模板。如下

  1. upstream backend { 
  2.     {{range service "hello-world"}} 
  3.     server {{.Address}}:{{.Port}};{{end}} 
  4. server { 
  5.     server_name "10.0.2.15"
  6.     location / { 
  7.             proxy_pass http://backend; 
  8.     } 

consul-template提供了方便的模板查询语句,可以直接从consul中查询并渲染出配置文件。这个模板中就找出了所有名字为“hello-world”的service,并且循环输出service对应的Address,也就是服务ip,Port。

接着看ct-nginx.conf,destination代表模板生成完毕之后的位置, 这里直接放在nginx的配置文件夹,***command是生成配置后的动作,可以重启各种服务。我们这里在更新nginx之后重启生效。

OK,配置已经妥当,consul和registrator也已经启动, 让我们看看当前的服务列表。

  1. $ curl localhost:8500/v1/catalog/service/hello-world?pretty 
  2. $ [] 

当前并没有注册名为hello_world的服务。

#p#

稍微提一下registrator注册服务的命名机制,registaor默认是通过提取容器各种参数来生成的的服务参数

比如

  1. docker run -d --name nginx.0 -p 4443:443 -p 8000:80 progrium/nginx 

生成的服务信息如下

  1.     "ID""hostname:nginx.0:443"
  2.     "Name""nginx-443"
  3.     "Port": 4443, 
  4.     "IP""192.168.1.102"
  5.     "Tags": [], 
  6.     "Attrs": {}, 
  7. }, 
  8.     "ID""hostname:nginx.0:80"
  9.     "Name""nginx-80"
  10.     "Port": 8000, 
  11.     "IP""192.168.1.102"
  12.     "Tags": [], 
  13.     "Attrs": {} 

当然也可以通过环境变量来指定

  1. $ docker run -d --name nginx.0 -p 4443:443 -p 8000:80 \ 
  2.            -e "SERVICE_443_NAME=https" \ 
  3.            -e "SERVICE_443_ID=https.12345" \ 
  4.            -e "SERVICE_443_SNI=enabled" \ 
  5.            -e "SERVICE_80_NAME=http" \ 
  6.            -e "SERVICE_TAGS=www" progrium/nginx 
  1.     "ID""https.12345"
  2.     "Name""https"
  3.     "Port": 4443, 
  4.     "IP""192.168.1.102"
  5.     "Tags": ["www"], 
  6.     "Attrs": {"sni""enabled"}, 
  7. }, 
  8.     "ID""hostname:nginx.0:80"
  9.     "Name""http"
  10.     "Port": 8000, 
  11.     "IP""192.168.1.102"
  12.     "Tags": ["www"], 
  13.     "Attrs": {} 

接下来我们启动consul-template

  1. $ consul-template -config=./ct-nginx.conf 

会直接根据模板生成一个nginx配置 虽然现在并没有backend node。

  1. $ cat /home/vagrant/sites-enabled/backend.conf 
  2. upstream backend { 
  3. server { 
  4.     server_name "10.0.2.15"
  5.     location / { 
  6.             proxy_pass http://backend; 
  7.     } 
  8. }  

然后启动我们的web应用。

启动之后,请求服务列表就可以看到helle-world服务,说明已经实现自动服务发现。

  1. $ curl localhost:8500/v1/catalog/service/hello-world?pretty 
  2.     "Node""node1"
  3.     "Address""172.17.42.1"
  4.     "ServiceID""registrator1:vagrant_rails_1:80"
  5.     "ServiceName""hello-world"
  6.     "ServiceTags"null
  7.     "ServiceAddress"""
  8.     "ServicePort": 32783 
  9. ]  

浏览器中可以正常访问了,Yeah!

#p#

OK, 让我们更进一步,scale我们的rails node。

  1. $ docker-compose scale rails=4 
  2.  
  3. $ curl localhost:8500/v1/catalog/service/hello-world?pretty 
  4.     "Node""node1"
  5.     "Address""172.17.42.1"
  6.     "ServiceID""registrator1:vagrant_rails_1:80"
  7.     "ServiceName""hello-world"
  8.     "ServiceTags"null
  9.     "ServiceAddress"""
  10.     "ServicePort": 32783 
  11. }, 
  12.     "Node""node1"
  13.     "Address""172.17.42.1"
  14.     "ServiceID""registrator1:vagrant_rails_2:80"
  15.     "ServiceName""hello-world"
  16.     "ServiceTags"null
  17.     "ServiceAddress"""
  18.     "ServicePort": 32784 
  19. }, 
  20.     "Node""node1"
  21.     "Address""172.17.42.1"
  22.     "ServiceID""registrator1:vagrant_rails_3:80"
  23.     "ServiceName""hello-world"
  24.     "ServiceTags"null
  25.     "ServiceAddress"""
  26.     "ServicePort": 32785 
  27. }, 
  28.     "Node""node1"
  29.     "Address""172.17.42.1"
  30.     "ServiceID""registrator1:vagrant_rails_4:80"
  31.     "ServiceName""hello-world"
  32.     "ServiceTags"null
  33.     "ServiceAddress"""
  34.     "ServicePort": 32786 
  35. ]  

此时nginx已经重启,我们可以看到4个backend都开始处理请求。

你可以看到,rails服务器只要启动之后就自动加入集群,如果一台节点挂掉之后,会自动从集群里去掉,基本上没有任何影响。

肯定有不足的地方,欢迎讨论, 发出来就是为了学习。

博文出处:http://dev.baozou.com/ye-tan-ji-yu-dockerde-railsji-qun/
 

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/295461.html<

(0)
管理的头像管理
上一篇2025-05-21 13:36
下一篇 2025-05-21 13:37

相关推荐

  • 骨干网络体系结构能干什么?骨干网络体系结构的作用

    骨干网络体系结构是现代信息社会的“超级高速公路网”,它通过分层设计、冗余备份和智能调度,确保海量数据在全球范围内高速、稳定、安全地传输,是支撑云计算、物联网及人工智能应用的底层基石,想象一下,如果你把互联网比作一个巨大的城市交通系统,那么骨干网络就是连接各个城市的主干道和立交桥,没有它,你的每一次微信发送、每一……

    2026-06-18
    0
  • 高io数据库可以干什么用?高io数据库适合什么场景

    高IO数据库的核心价值在于通过极高的读写吞吐量,解决海量数据场景下的性能瓶颈,是支撑高并发交易、实时分析及大规模内容分发的关键基础设施,在数字化转型的深水区,数据不再仅仅是静态的记录,而是流动的资产,传统的机械硬盘或普通SSD早已无法满足现代应用对速度的极致追求,高IO(Input/Output)数据库,就是那……

    2026-06-18
    0
  • 高io服务器性能如何?高io服务器适合什么场景

    高IO服务器并非单纯指代某种硬件,而是指在随机读写、高并发连接及小文件处理场景下,具备极致IOPS(每秒输入输出操作次数)和低延迟特性的计算资源,它是支撑现代高并发应用稳定运行的核心基石,在2026年的数字化浪潮中,业务负载早已从简单的静态页面展示演变为复杂的实时数据处理,许多开发者在排查系统瓶颈时,往往忽略了……

    2026-06-18
    0
  • 隔离网络空间哪里便宜?国内隔离网络空间价格

    隔离网络空间并没有统一的“便宜”标准,其成本高度取决于物理隔离等级、带宽需求及安全合规要求,通常物理网闸方案初期投入较高但长期运维成本低,而逻辑隔离方案虽初期便宜但存在潜在安全风险,建议根据业务敏感度选择混合隔离架构以平衡成本与安全,在数字化时代,企业构建独立网络环境的需求日益增长,但“隔离网络空间哪里便宜”这……

    2026-06-18
    0
  • 骨干网络体系结构设备为何故障?常见原因有哪些

    骨干网络体系结构设备故障的核心原因通常归结为硬件老化、配置错误、物理链路中断及外部攻击四大类,其中电源模块失效与光模块性能衰减是占比最高的隐性故障源,骨干网作为数字经济的“大动脉”,其稳定性直接关乎国计民生,当核心路由器或交换机出现丢包、震荡甚至宕机时,运维人员往往面临巨大的压力,很多人第一反应是检查软件配置……

    2026-06-18
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注