
本文改编自Belly Card的Kevin Reedy于2014年10月在nginx.conf上所作的演讲。虽然演讲已过去数年,但其内容如今仍极具参考价值。可在YouTube上观看演讲录像。
目录
0:00 简介 概述 免责声明1:16 什么是Belly? Belly的技术栈1:44 版本0:黑暗时代2:04 版本1:新的希望2:35 版本2:分离主页和API 今日热词:面向服务的架构! 启用SOA 使用NGINX替代ELB 上游和虚拟服务器配置 结果4:43 使用Chef进行配置 配方 文件 模板 说明书6:49 示例:使用Chef配置NGINX 安装、配置和调优 路由API流量9:46 实际应用中的Chef示例10:08 版本2:部署应用10:40 版本3:全面采用SOA 随后发生了Heartbleed漏洞事件 全面启用SSL12:25 版本4:Docker 优势 部署容器15:45 部署策略17:43 服务发现选项18:33 Consul架构19:30 Consul功能22:07 Consul Template 启动Consul Template的命令 使用Consul Template配置NGINX 使用Consul Template进行配置管理24:35 使用Chef部署Consul25:44 实用技巧 Chef部分搜索 DNS 避免配置过期30:35 问答36:31 联系信息
0:00 简介

大家早上好。我叫Kevin Reedy,就职于总部位于芝加哥的Belly Card公司。公司约有100名员工,其中包括20名工程师。今天,我将介绍我们如何在不断变化的动态基础设施中实现负载均衡。
0:21 概述

首先,我会从版本0讲起,介绍我们的基础设施堆栈如何随时间演变。我把版本0称为“黑暗时代”。接下来,我们会介绍如何使用Chef配置NGINX。然后,我们会讨论如何改用Consul服务发现平台中的数据来配置NGINX。如果时间允许,我还会分享一些配置NGINX的实用技巧,尤其是配置管理方面的技巧。
0:49 免责声明

虽然接下来我要介绍Chef和Consul,但需要先说明,本次演讲的内容并不局限于这两款产品。Chef、Puppet、Ansible、Salt、CFEngine以及其他同类产品都很出色,建议从中选择一款使用。我们很喜欢Chef,相信很多人也一样。
服务发现也是如此。Consul、etcd和ZooKeeper都很出色,请选择适合自己的产品。
1:16 什么是Belly?

Belly是什么?本质上,它以数字化方式取代了咖啡店的纸质集点卡,也就是买10杯赠1杯的那种。我们在店内放置一台iPad,顾客使用手机或带有二维码的实体卡扫码;我们记录积分、发放奖励,并在此基础上构建营销工具。
1:36 Belly的技术栈
不过,我今天不是来介绍belly这家公司的。如果对此感兴趣,可以直接访问我们的网站。接下来,我要介绍的是我们的基础设施技术栈。
1:44 版本0:黑暗时代
先说版本 0。当时团队只有三名开发人员,我还没有加入。Belly 是一个单体式 Ruby on Rails 应用,也就是说,每个 API 调用和网站的各个部分都由同一个 Rails 应用处理。它使用 MySQL、MongoDB 和 Memcached 作为后端,并部署在 Heroku 上;对于起步阶段而言,Heroku 是一个很不错的平台。
2:04 版本1:新的希望
于是有了版本1:《新希望》。我们认为Heroku已无法再满足需求,因此开始使用一款名为Capistrano的部署工具。它使用Ruby编写,本质上“比shell脚本更好”,可帮助部署应用。
我们在Amazon Web Services EC2上部署了大约6台服务器。服务器数量通常固定,但如果预知会有重大事件发生,我们会增加服务器,并在需要时再减少。前端使用AWS Elastic Load Balancer。
2:35 版本2:将主页与API分离
后来有一个项目需要将主页与API的其余部分分离。这样可以加快主页的迭代速度,并由不同的开发人员负责开发。
2:47 今日热词:面向服务的架构!
当时广受关注的热门术语是面向服务的架构,时至今日依然如此。
2:50 实施SOA
因此,我们的第2版技术栈旨在支持面向服务的架构。最初的计划是将主页与API分离。这看起来很简单,只需使用www.bellycard.com和api.bellycard.com。
但事实证明,这件事非常复杂,一点也不简单,因为我们的一些移动应用已在代码中固定使用www.bellycard.com/api和/api‑assets。我们的电子邮件服务提供商以及此前已通过电子邮件发送给用户的所有点击链接,都使用/eo表示“邮件打开”,使用/ec表示“邮件点击”。我们的Facebook应用配置为使用/facebook/callback。
3:28 NGINX取代ELB
这意味着,AWS Elastic Load Balancer已无法再提供我们所需的灵活性,不能将这些流量路由到不同的应用。因此,我们转而使用NGINX来解决这一问题。具体而言,我们可以配置多个上游和重写规则,将流量路由到不同的应用。
3:44 上游和虚拟服务器配置
在这个非常基础的示例中,我们定义了一个包含6台API服务器的upstream块,以及一个包含2台主页服务器的块。
此外,还有两个server块[用于定义虚拟服务器]。其中一个侦听api.bellycard.com,并将其所有流量路由到API服务器。另一个侦听www.bellycard.com,并相应地路由流量。
4:02 结果
这种方式效果很好,让开发人员能够快速推进工作。前端人员可以专注于一个项目,不会因API而受阻。因此,我们部署了第三项服务,我记得是用于与Apple Passbook集成。随后又部署了第四项服务,将所有Facebook功能迁移了出去。第五项服务则用于处理网站上的用户事件。
后来,有人觉得用Node.js来编写这个服务是个好主意,于是我们有了5个使用两种语言编写的独立服务。它们都是独立部署的,几乎没有配置管理,而且我们还在手动编辑NGINX配置。我相信很多人一开始也是这样做的。
4:43 使用Chef进行配置
我们需要一种更好的方式来扩展这一流程,因此采用了Chef。
Chef是一套配置管理工具。它使用Ruby编写,您也可以使用Ruby编写实际的配置管理代码,因此非常适合开发人员。learnchef.com是学习Chef的优质资源;通过它,您可以学到远超我在45分钟内所能讲授的Chef知识。
不过,我还是会介绍一些基础知识,以便大家理解一致。
5:17 配方
Chef中的第一类构建块是配方。Chef使用了许多巧妙的名称,例如将工具称为刀具,还有配方,并将所有内容都放在食谱中。这种命名方式既有趣又容易理解,也提供了一个很贴切的比喻,但同时也让人很难通过Google搜索到相关内容。
下面是我能想到的最基本的recipe:安装软件包nginx,然后启动并启用nginx服务。
5:56 文件
还可以使用文件资源。例如,我想将内容“Hello World!”写入文件“/usr/share/NGINX/html/index.html”。
6:08 模板
也可以将其集成到模板系统中。这里有两个变量g和w,分别表示Hello和Kevin。可以将这些变量传入采用ERB格式的模板文件(Ruby模板脚本)。
因此,我们不必手动写出内容,而是可以编写一个模板,用于读取内容并确定问候对象。
6:19 Cookbook
最后一个主要构建模块是 cookbook,它由 recipe、文件和模板组成,还包括 resource、provider 和 library 等更复杂的资源。以下网站提供了大量开源及其他 cookbook:https://supermarket.getchef.com。其中包括适用于 NGINX、MySQL、Java、apt 和 yum 的 cookbook,甚至还有用于管理 ssh_known_hosts 文件的 cookbook。配置管理所需的大多数主要构建模块,基本都能在现有 cookbook 中找到。
6:49 示例:用于NGINX的Chef
下面快速介绍一个结合使用NGINX和Chef的示例。我们将安装NGINX,并通过更改几个变量进行配置。我们会使用Chef发现应用程序的运行位置,然后配置NGINX,将流量路由到该应用程序。
7:14 安装、配置和调优
在此示例中,首先要设置一些节点属性。对于每个节点,可以通过附加JSON文档来设置属性值。我们将使用第三方NGINX cookbook,它会查找这些属性的设置。我们将把worker_connections设置为特定值,并设置worker_rlimit_nofile指令、NGINX中要使用的event类型,甚至还会设置client_max_body_size。
之后,我们会引入NGINX cookbook中的两个recipe。第一个是nginx::repo,它会根据操作系统设置apt或yum软件仓库。然后,[nginx recipe]会安装NGINX。也可以从源代码安装NGINX,但使用软件包安装速度更快。
接下来,我们将利用Chef的搜索功能。运行Chef时,可以将其作为代理在计算机上运行,也可以采用solo模式运行;solo模式本质上是像执行脚本一样运行Chef。在计算机上运行代理后,可以查询Chef服务器中的节点及其他属性。
这里,我们要求Chef列出附加了配方belly‑api的所有节点。然后,我们根据模板生成名为/sites‑enabled/api的站点文件。其源文件是接下来将介绍的模板[名为api.erb的文件]。我们传入的变量就是刚才搜索到的节点。
这里最后一个新增内容是使用notifies语句重新加载nginx服务。也就是说,每当此模板发生更改时,就重新加载该服务。
8:54 路由API流量
这里的模板文件很简单。我们有一个名为api的上游,并在ERB中遍历通过变量传入的所有服务器,使用IP地址和端口 8080 指定服务器。我们还添加了一条包含服务器名称的注释。当运维人员查看此服务的运行情况时,这条注释会很有帮助。
我们还定义了一个server块,用于侦听api.bellycard.com。我只需将所有流量传递到api上游。
9:46 Chef 实际应用示例
我还想提供一个实际案例。这里的内容可能太小,大家看不清,但可以大致感受一下Chef配方会有多复杂。这是目前我们部分生产服务器实际使用的模板和配方。
10:08 版本 2:部署应用
现在回到我们的技术栈。前面提到,我们已经部署了大约5个应用,而且运行得很顺利。现在有了将流量路由到这些应用的方法,开发人员便充分利用了这一点。如今,我们已使用Chef在服务器上部署了大约40个Ruby应用,并通过NGINX以完全动态的方式路由流量。
我们的开发人员只需编辑一个recipe,加入新服务的名称即可。所有流量均由NGINX路由,并通过Chef进行动态配置。
10:40 版本3:全面采用SOA
我们还有大约10个前端JavaScript应用,它们只是静态文件,部署在S3上,并在前端使用CDN,即[Amazon] CloudFront。我们直接从S3存储桶提供index.html,其余资源则通过CloudFront提供。此外,还有大约5个应用,开发人员原本只是将其作为一次性项目推送到Heroku,后来却投入了生产环境,而且几乎没有人收到相关通知。
11:10 随后发生了“心脏出血”漏洞事件
[Heroku上的5个应用]彼此独立,完全位于我们的基础设施之外。直到4月的一天,Heartbleed漏洞被公布,许多人都开始仓促应对。Heartbleed是OpenSSL中的一个漏洞,可能会让他人提取您的私钥。
由于我们使用Chef,因此补丁一经发布,我们就能升级所有服务器上的OpenSSL基础设施。我记得整个基础设施大约在20分钟内就完成了部署。不过,AWS(因此也包括Heroku)花了大约24小时才为其Elastic Load Balancer打上补丁。
这促使我们将所有负载均衡和SSL终止都迁移到NGINX,无论应用部署在何处,包括S3和Heroku。这样做会略微影响性能,但至少在4月的那一天,对我们来说是值得的。
11:57 全面启用SSL
因此,我们的第3版技术栈从“全面采用SOA”转向了“全面采用SSL”。所有发往bellycard.com及其子域名的流量都会经过我们的负载均衡器。为提升性能,我们的静态资源实际上仍通过另一个域名上的CloudFront提供。我们不希望承担SSL带来的额外开销,而且我们在美国东海岸只有一个数据中心。
12:25 版本4:Docker
版本4:今年大家都在谈论的热门词是Docker。早在Docker大约处于0.5版时,我们的开发人员就已经迫不及待地想开始使用它了。
12:38 优势
使用Docker的理由很简单。
它极大地简化了应用部署。无需编写配置脚本,也不必操心如何编译静态资源。无论您的应用使用Ruby编写,而其他人的应用使用Python编写,都不会有影响。
从本质上说,它将开发与运维的职责分离开来。开发人员可以专注于代码、要使用的库,甚至要安装哪些Linux软件包。运维人员则可以关注其他问题,例如:要将应用部署到哪里?如何采集应用日志?如何监控应用?解决这些问题并完成相关运维工作后,无论应用使用哪种语言编写,都可以正常运行。
这样做还有一个好处:开发人员可以轻松地在自己的笔记本电脑上启动依赖服务。如前所述,我们目前已有约55个不同的应用,其中许多现已部署在Docker容器中。
假设您正在开发一项用于发送电子邮件营销活动的新服务。该服务依赖电子邮件服务。因此,通常需要在开发计算机上下载代码,运行bundle install,在后台启动该服务,然后发现:“等等,其实它还依赖另一项服务,也就是用户服务。”
该服务又依赖其他服务,而这些服务还会依赖更多服务。因此,这个新的电子邮件营销活动服务实际上依赖大约5项其他服务,以及MySQL、Elasticsearch、Redis等。
借助 Docker,我们可以使用生产环境中相同的 Chef 配方构建这些容器,并为开发人员提供可快速下载的容器。
因此,这可以加快部署和开发。
14:23 部署容器
因此,在版本 4 中,我们不再使用 Chef 部署应用,而是改为在容器中部署。实现这一目标的解决方案有很多,而且未来肯定还会出现更多。
第一种方案是CoreOS和Fleet。CoreOS是一种精简的Linux操作系统,其上运行着一个名为etcd的服务发现引擎。通过Fleet,可以定义类似这样的要求:“我希望一个容器运行5个实例,并且不希望它与另一个服务运行在同一批计算机上。”
另一个名为Deis的工具与Heroku类似,也提供Git Push接口。此外还有Apache的Mesos和Google的Kubernetes;Flynn则是最近刚推出的另一个工具。实际上,我们自行开发了一套工具,因为在我们开始这段探索之旅时,这些工具大多还不具备可用条件。
我们开发的工具名为Jockey,实际效果非常好,因为我们的部署流程有一套非常明确的规范。Docker的优势在于,它实际上为容器化提供了一组通用API。相比仅使用Linux的LXC容器,我们无需再操心许多问题。
我们计划将其开源,但正如我之前提到的,我们的部署流程非常固化,适合我们的方案未必适合您。
15:45 部署策略
此外,迁移到Docker后,我们的部署策略也有所改变。此前,我们会直接在原位置部署应用的新版本,以实现零停机部署。也就是说,如果用户传真服务运行在4台计算机上,我们会使用Chef拉取新版本,将其覆盖安装到[旧版本]上,然后向Web服务器发送信号以重新加载。Unicorn是一款非常适合执行此类操作的Ruby引擎。
不过,容器是不可变的。容器运行后,如果要创建新的构建版本,就应创建一个新容器。也可以连接到现有容器,运行其他命令,然后将其保存,这有点类似于在Git中的操作。但要充分发挥Docker的优势,容器应保持完全不可变。
这意味着我们必须采用新的部署策略,因为无法再进行原地部署。目前有几种可选策略,其中蓝绿部署值得关注。假设应用正在4台机器上运行,可以在另外4台新机器上启动该应用,并让负载均衡器将流量转发到新机器。确认应用确实按预期运行后,即可停用蓝色环境,绿色环境则成为新的蓝色环境。Amazon为在AWS上实施这种部署提供了非常实用的工具。
还有一种“金丝雀”部署:先部署一个新版本的机器并进行监控,如果通过指标检查和运行状况检查,就可以继续部署。
容器的不同之处在于,您实际上需要销毁现有容器并启动新容器,因此需要某种系统来跟踪基础设施中运行的每个应用所在的位置。
Chef实际上正逐渐成为实现这一目标的有效方式。目前正在合并一个名为Chef Metal的cookbook,借助它,可以像管理Chef基础设施中的其他资源一样管理容器。
17:43 服务发现选项
此外还有服务发现。ZooKeeper是一款非常流行的工具,广泛应用于Hadoop。[Airbnb]有一款出色的产品,名为SmartStack,可用于执行部署并在ZooKeeper中跟踪部署情况。
我之前提到过etcd,它本质上是一个提供REST接口的分布式键值存储。相比更偏向Java客户端库的ZooKeeper,etcd的一大优势是任何应用都可以与它通信。我之前提到的许多开源平台即服务(PaaS),例如Deis、Flynn,甚至Google的Kubernetes,都使用etcd。如果使用CoreOS,则已内置etcd,可直接使用。
另一个新推出的工具也基于REST,名为Consul。它由HashiCorp团队发布,该团队开发了Vagrant、Packer以及许多其他出色的工具。我们最终决定使用Consul。
18:33 Consul架构
下图展示了Consul最基本的架构。可以看到,其中有多个数据中心,每个数据中心包含3台服务器。数据中心1中还有客户端。值得注意的是,服务器代理会选举出一个主代理,而所有客户端不仅知道所有服务器,还知道其他所有客户端。随后,它们通过gossip协议与其他所有代理通信。
这让我想起AT&T以前的一则广告:你告诉两个朋友,他们再各自告诉两个朋友,接着这些朋友又各自告诉两个朋友,消息就这样传遍整个节点网络。[编辑注:差不多,但那其实是Faberge Organics洗发水的广告。]相比之下,etcd或ZooKeeper基本上只有服务器代理,客户端连接到这些代理。
采用Consul的方式时,几乎每台服务器上都会运行Consul客户端,包括部署Docker和运行负载均衡器的所有位置。因此,始终可以通过localhost的8500端口访问该API。
19:30 Consul功能
与etcd一样,[Consul]也是一种分布式键值存储。您可以设置和获取键,它会保持线性一致性,从而确保数据始终一致。这里有一些需要注意的问题,但其文档对这些问题可能出现的位置说明得非常出色。不过,与etcd不同的是,Consul将服务发现视为核心功能。
除了键值对之外,还可以注册服务,例如API。注册服务时,需要告知Consul该服务在哪个节点上运行。这意味着部署容器时,还要让Consul在该主机上注册此服务API。
此外,Consul还提供分布式运行状况检查,因此可以直接在服务发现平台中定义Nagios式运行状况检查。查询Consul时,可以请求获取API服务所有运行位置的列表,并传入“全部”“仅通过”或“仅不健康”标志。
它还支持多个数据中心。前面提到过,应在所有位置运行Consul客户端。启动客户端时,需要传入一个参数来指定数据中心。如果有东部数据中心和西部数据中心,则无需感知数据中心,即可查询本地Consul客户端,获取地址等信息。
实际上,我们以数据中心作为预发布环境与生产环境的边界。预发布环境中的应用配置可能会要求:“告诉我 MySQL.services.consul 在哪里。”无论它实际运行在预发布节点还是生产节点上,都能获得正确的值,而无需感知数据中心或多个环境。
它(以及etcd)的另一个优势是,其HTTP接口支持长轮询。这意味着,您可以查询运行此服务的所有服务器列表,同时将连接保持打开60秒;如有任何变化,系统会立即通知您。轮询时间最长可达10分钟,因此您可以即时获知基础设施的任何变化。
我之前还提到,可以通过在各处部署客户端来实现代理的横向扩展。这样做的好处是,始终可以与localhost通信。
不过,关键问题是:既然这些数据现在存储在分布式服务发现平台中,如何利用这些数据配置NGINX?
22:07 Consul Template
好在有一款名为Consul Template的工具。它昨天才刚刚发布,所以我不得不从这里开始修改今天的演示文稿。它以前叫“Consul HAProxy”,这个名字很不合适,因为它实际上并非专用于HAProxy。
Consul Template提供了一个非常简单的界面,可用于构建模板,以订阅服务变更、这些服务的运行状况检查结果,甚至键值存储的变更。这样,您就可以将NGINX工作进程数量等设置存储在键值存储中,并在设置发生变化时重新生成配置。
这里的主要功能是根据模板生成文件,这与我们之前使用Chef所做的工作非常相似。更大的区别在于,它使用Golang模板语言,而不是基于Ruby的ERB。文件发生更改后,可以选择调用命令,例如service nginx reload。
22:59 启动Consul Template的命令
下面是一个通过命令行运行Consul Template的示例。将其指向实际的Consul主机,本例中为consul‑prod.example.com。在实际生产环境中,建议在所有位置运行Consul并连接到localhost。
然后传入一个模板文件,即Golang模板。在本例中,我们传入的是/etc/consul‑templates/api。接着传入实际要写入的文件,在本例中为/etc/NGINX/sites‑enabled/api。然后传入要调用的命令:service nginx reload。
23:32 使用Consul Template配置NGINX
Consul模板看起来与我之前展示的一张幻灯片非常相似,只不过这里使用的是Golang,而不是ERB。因此,我们在这里定义了两个上游。一个名为api,另一个名为homepage。我们为服务API使用了range语句,并通过内置变量获取该服务实际运行位置的IP地址和端口。
23:54 使用Consul Template进行配置管理
Consul Template以及这种使用方式的优势在于,服务变更可以快速收敛。在使用Docker部署之前,我们会根据机器的不同,每隔约5或10分钟运行一次Chef。由于当时采用原地部署,这样的速度对我们来说已经足够快。
现在,我们正在构建更先进的部署系统,因此需要在数秒内而不是数分钟内收到这些变更的通知。实际上,通知可在毫秒级送达,平均大约为200毫秒。
不过,生成模板仍然需要配置管理。我们不能直接用Consul取代Chef。我们仍需确定如何部署Consul、Consul Template及其他所有相关组件。
24:35 使用Chef部署Consul
实际上,我们使用Chef模板来部署Consul模板,这似乎有点复杂。首先,我们会在Chef配方中查询Consul主机,获取所有服务的列表。然后,我们生成一个Consul模板[使用template和source语句],传入SSL证书和密钥的位置,并重新加载consul‑template。[编者注:Reedy先生最初提到的是 consul‑haproxy,即幻灯片上第一个 notifies 语句中显示的名称。随后他更正了这一说法,并说明该幻灯片制作于Consul Template发布之前。]
我们还会为Consul Template写入一个配置文件,并传入[用于指定]Consul主机、源、目标和重新加载命令的变量。这正是我们结合使用Chef和Consul来即时更新NGINX配置的核心机制。
25:44 专业技巧
接下来,我将分享一些关于Chef、Consul和NGINX配置的实用技巧。
25:52 Chef 部分搜索
第一条建议是,如果您使用Chef search查找服务的运行位置,可以考虑使用Chef partial search。Chef search的问题在于,它会复制整个节点,包括所有属性。如果在节点属性中保存了大量内容,与Chef服务器通信时,就必须通过网络传输这些内容,并将其存储在内存中。
如果Chef搜索返回数百甚至数千台服务器,实际运行recipe时很容易耗尽内存。使用部分搜索,可以只返回所需的键。
例如,我们最初使用的是
nodes = search(:node, 'recipe:belly-api')该搜索会返回每个对象的全部信息,包括其磁盘空间、RAM、CPU,以及所有已写入自有节点属性的应用程序的相关信息。
我们可以改用部分搜索,创建一个名为“search_keys”的新哈希,并为其提供所需键的列表,在本例中仅包括名称和IP地址。然后调用一个非常相似的API“partial_search”,并传入额外的[keys]参数。
26:53 DNS
当我们改为在S3和Heroku前端使用负载均衡时,遇到的第二个问题是,NGINX仅在重新加载配置时使用DNS解析upstream块中的主机名。这意味着,如果将上游服务器设置为s3.amazonaws.com或anything.herokuapp.com,而其IP地址发生变化,则负载均衡器要到下次重新加载时才会获知新的IP地址。
我们的解决方法是在Chef中执行DNS解析,并在解析结果发生变化时触发NGINX重新加载。这又带来了另一个问题:[DNS响应中的地址顺序]并不总是相同,因此在将响应写入模板之前,还要确保对其进行排序。
27:36 避免配置过期
开始部署大量服务时,还需要避免配置过时。[编者注:Reedy先生短暂停下演示,回答听众提出的问题。]在Apache、NGINX和其他UNIX类系统中,一种常见的配置模式是创建conf.d文件夹,然后加载其中的所有内容。因此,如果部署服务A、B和C,我会创建service-a.conf、service-b.conf和service-c.conf。
然后,我决定用服务 D 替换服务 B。此时,NGINX 配置文件夹中有4个配置,但服务 B 已不存在。由于 B 和 D 的主机名相似,两者可能会发生冲突。
过去,我们主要采用两种方式来执行此操作[删除过时配置]。使用模板时,可以添加一个:delete函数,但这种方式很快就变得难以管理。实际上,我们维护了一份旧服务列表,只要这些服务存在,就会尝试将其删除。这种方式难以扩展。
另一种方法是将所有站点配置渲染到一个文件中。很多人将这种做法称为“将幂等性上移”。也就是说,不要让NGINX配置从多个来源加载,而是将所有配置都放入nginx.conf。
这样一来,实际登录服务器时确实会有些不便,但希望我们正在逐步实现不再直接在生产环境中排查配置文件问题。如果在Chef配方中仍然有些难以管理,我们的做法是使用一个nginx.conf来加载一系列不同的站点。例如,我们有一个站点配置文件列出了大约30项服务,此外还有一个用于Heroku的配置文件、一个用于所有S3服务的配置文件,等等。
因此,如果将所有站点配置渲染到一个或少量文件中,就不必担心后续清理。如果从Chef的角度来看某项服务已不存在,Chef只需停止将其渲染到实际文件中。
30:35 问答
问: 到目前为止,Consul的使用效果如何?
答:我们非常喜欢Consul。与etcd之类的工具相比,我尤其喜欢的一点是,Consul之上不断有新的服务构建起来。我不必担心服务发现。事实上,如果您有旧版应用,并使用Consul部署MySQL服务器,Consul还会提供DNS接口。
应用无需感知Consul,只需查询“从mysqldb.services.consul可以获取什么地址?”。在这种情况下,Consul充当DNS服务器。配置DNS基础设施后,如果TLD[顶级域]以.consul结尾,查询就会路由到Consul。
它的横向扩展效果非常好。我们的生产环境中运行着约3个服务器代理节点和约60个客户端,目前没有遇到任何问题。他们不断增加新功能,同时保持向后兼容,因此升级过程一直很顺利。
问: 您是否使用NGINX Plus?
答:我们没有使用。开始使用Consul时,我们正是出于这一需求研究过NGINX Plus。如果不需要模板系统,那会很方便,因为只需用一个脚本监听HTTP长轮询,再由该脚本调用NGINX API即可。唯一的问题是,可能仍需要模板系统,以便在NGINX重启时立即重新加载上游配置。
还有一些人尝试使用NGINX Lua直接查询Consul。目前我还没有看到很好的实现,因为这些实现通常分为两类。第一类是在每次HTTP请求时查询Consul,速度较慢。第二类是在加载配置时载入数据,最终会遇到与DNS相同的问题。因此,目前使用模板系统更合适,但未来很可能会出现使用NGINX Lua实现这一功能的方法。
问: 您以后会考虑不再使用Chef吗?
答:Consul没有提供很好的内置方式来维护这些模板,而且我们已经在使用Chef部署NGINX。目前,为了实现日志记录、跟踪和部分OAuth等其他NGINX相关功能,我们编写的recipe已有数百行,甚至数千行。我认为我们不会在基础设施中弃用并替换Chef,但Consul是很好的补充,也有助于快速获取通知。
问: Chef会带来多少开销?
答:由于我们的大多数机器只执行一项任务,因此Chef的实际开销很低。空闲时,RAM占用量也很低。它实际上由定时器控制,并可派生子进程。如果不在意收敛速度,也有人通过cron运行它。执行一些负载较重的配方时,CPU使用率会略有上升,但只需再部署一台服务器即可解决。
问: 您在多大程度上使用过CloudFormation?
答:我们尚未使用CloudFormation。我们已在考虑采用它,但目前做出的一项改变是更多地使用Auto Scaling组。具体来说,实例启动时,其用户数据中会包含Chef运行列表。
新机器启动并加入集群时,会根据其镜像预先配置好密钥,因此能够与我们的Chef服务器通信、完成注册,并拉取所需的cookbook。由于我们并未使用很多通常与CloudFormation配套的其他AWS工具,这种方式已经满足了我们对CloudFormation的大部分需求。
问: 如何处理服务器被销毁的情况?
答:如果Auto Scaling组中的服务器被销毁,可以使用Amazon SNS[简单通知服务]接收相关通知。我们有一项非常简单的服务,用于侦听这些通知,然后清理Chef服务器。
问: 您使用过AWS的OpsWorks吗?
答: 没有。我们从一开始就一直使用托管式Chef,效果很好。我不太确定,但我认为OpsWorks更像Chef Solo,只用于预置。我们仍在几乎所有计算机上运行Chef Agent,并使用相同的Chef配方生成用于开发的Docker容器。
36:31 联系信息
相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
