【编者的话】作者讲述了如何将服务发现(Consul.io与Consul-Template)与负载均衡(Nginx)相结合,实现灵活的配置和自动化重载,降低运维难度。当你还执着于给容器分配固定IP这件事上时,也许服务发现才是正道。
这是关于我们如何在IIIEPE的生产环境中使用Docker的系列文章的最后一部分。如果你还没看过第一(译文)、第二(译文)和第三(译文)部分,请先前往阅读再继续。本文中,我将讨论如何配置服务发现和负载均衡的。
服务发现
市面上有不少服务发现方案,不过我们只测试过etcd和Consul.io。Etcd是CoreOS的一部分,虽然你可以脱离CoreOS使用它,但你很快就会发现你需要学习的不仅仅是etcd。Consul.io使用非常简单,通过Docker运行,并且拥有一个不错的生态系统。
在细说之前,如果你不知道什么是服务发现,我得说明一下,它与负载均衡无关,只是一款知晓运行在基础设施上的容器当前状态的软件。也就是说,服务发现跟你如何发送信息给它无关。
与其它服务发现工具一样,Consul.io解决了一个问题,它会存储应用的IP、端口和状态。要将应用注册到Consul.io里(正确的说法是服务),我们使用了Registrator。一旦Consul.io感知到应用,就需要做点什么,在我们的案例中,要重新载入负载均衡配置,因此我们使用了Consul-Template。
因为Consul.io和Registrator都运行在Docker容器里,实现起来比我们想象的要简单得多。
对于Consul-Template,最困难的部分是弄明白模板的语法。
负载均衡
我们使用Nginx作为负载均衡器,因为我们已使用多年,知道如何配置它,而像HAProxy这样的方案只会给整个工作流增加复杂度。因为这是所有事情的最后一块,我们选择了简单的方式来完成它。最终,我们想用HAProxy取代Nginx,不过这得再等几个星期。
在一个正常的负载均衡场景中,你会这样配置Nginx:
upstream myapp { ip_hash; server 10.10.10.10:14001 fail_timeout=0; keepalive 64; } server { listen 80; server_name example.com; location / { proxy_pass http://myapp; } }
当你想在upstream块里动态分配一系列的IP和端口时,问题就出现了。使用consul-template,我们创建了一个模板文件/etc/nginx/templates/template,每个使用该负载均衡器处理的应用都会有一个区块:
upstream myapp { ip_hash; {{range service "myapp"}} server {{.Address}}:{{.Port}} fail_timeout=0; {{end}} keepalive 64; } server { listen 80; server_name example.com; location / { proxy_pass http://myapp; } }
对于使用SSL的网站,模板会长一点:
# this part handles the list of IPs and ports upstream myapp { ip_hash; {{range service "myapp"}} server {{.Address}}:{{.Port}} fail_timeout=0; {{end}} keepalive 64; } # this section handles requests to port 80, which we'll redirect to the port 445 server { listen 80; server_name example.com; return 301 https://$host$request_uri; } server { listen 443 ssl spdy; server_name example.com; keepalive_timeout 75 75; ssl on; ssl_certificate /etc/nginx/cert/path_to_cert.crt; ssl_certificate_key /etc/nginx/cert/path_to_key.key; ssl_session_cache builtin:1000 shared:SSL:10m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; ssl_prefer_server_ciphers on; add_header Strict-Transport-Security max-age=31536000; location / { proxy_pass http://myapp; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 150; proxy_send_timeout 100; proxy_read_timeout 90; proxy_buffers 4 32k; client_max_body_size 500m; client_body_buffer_size 128k; proxy_redirect http:// https://; } }
每次Consul-Template运行时,它会向Consul.io查询“myapp”的服务,并将发现的每个容器的IP和端口添加到upstream块中。
因为Consul.io和Consul-Template需要在服务器重启时启动,我们创建了一个Upstart作业来处理:
description "Consul Template" author "Luis Elizondo" start on filesystem or runlevel [2345] stop on shutdown script echo $$ > /var/run/consul-template.pid exec consul-template \ -consul IP_OF_CONSUL:PORT_OF_CONSUL \ -template "/etc/nginx/templates/template:/etc/nginx/sites-enabled/default:service nginx restart" end script pre-start script echo "[`date`] Consul Template Starting" >> /var/log/consul-template.log end script pre-stop script rm /var/run/consul-template.pid echo "[`date`] Consul Template Stoping" >> /var/log/consul-template.log end script Consul.io也一样: description "Consul" author "Luis Elizondo" start on filesystem or runlevel [2345] stop on shutdown script echo $$ > /var/run/consul.pid exec docker start consul end script pre-start script echo "[`date`] Consul Starting" >> /var/log/consul.log end script pre-stop script rm /var/run/consul.pid exec docker stop consul echo "[`date`] Consul Stoping" >> /var/log/consul.log end script Registrator也需要,不过Registrator不是运行在LB上的,而是在每个web节点上: description "Registrator" author "Luis Elizondo" start on filesystem or runlevel [2345] stop on shutdown script echo $$ > /var/run/registrator.pid exec docker start registrator end script pre-start script echo "[`date`] Registrator Starting" >> /var/log/registrator.log end script pre-stop script rm /var/run/registrator.pid exec docker stop registrator echo "[`date`] Registrator Stoping" >> /var/log/registrator.log
在2014年11月我们开始这趟旅程之前,我们找不到可以采纳或适应我们条件的完整工作流的足够信息,这也是我在此与大家分享的主要动机。作为完成这件事的二人小组成员之一,我意识到我们的工作流还远远不够完善,随着时间的推移,可能会出现我们未预料到的情况。现在我们有很多想改进的事情,迁移到HAProxy(不针对Nginx)是其中这一。不过,我们的工作流和基础设施是以帮助我们完成工作的方式来配置的(我的主要职责是作为开发人员,不是系统管理员),而不是把我们的存在复杂化。
测试、安装和实现新的工作流,然后迁移所有应用总共花费了我们2个半月时间,但这是值得的。在迁移之前,我们使用Digital Ocean来预演大多数的问题和情况,这对我们而言是个很棒的方案,因为它非常便宜(我们花了大概5美元),这么做让我们可以将每一步都记录下来。
原文:http://dockerone.com/article/283
未经允许不得转载:SRE空间 » Docker Workflow(四):服务发现与负载均衡
评论前必须登录!
注册