这篇文章改编自 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 | 例子: NGINX 厨师 |
安装、配置和调优 | |
路由 API 流量 | |
9:46 | 现实世界的厨师示例 |
10:08 | 版本 2: 部署应用程序 |
10:40 | 版本 3: SOA 一切 |
随后发生了 Heartbleed 事件 | |
SSL 的一切 | |
12:25 | 版本 4: Docker |
好处 | |
部署容器 | |
15:45 | 部署策略 |
17:43 | 服务发现选项 |
18:33 | Consul 架构 |
19:30 | Consul 功能 |
22:07 | Consul 模板 |
启动 Consul 模板的命令 | |
使用 Consul 模板配置 NGINX | |
使用 Consul 模板进行配置管理 | |
24:35 | 使用 Chef 部署 Consul |
25:44 | 专业提示 |
Chef 部分搜索 | |
DNS | |
避免过时的配置 | |
30:35 | 问题 |
36:31 | 联系信息 |
大家早上好。 我叫 Kevin Reedy,在芝加哥的一家名为 Belly Card 的公司工作。 我们有大约一百名员工和二十名工程师。 今天我将和大家讨论我们如何实现负载均衡,特别是在不断变化的动态基础设施中。
所以首先我要向你介绍我们的基础设施堆栈随时间的变化,从版本 0 开始,我称之为黑暗时代。 然后我们将介绍如何使用 Chef 配置 NGINX。之后,我们将讨论如何从 Chef 转变为使用名为 Consul 服务发现平台的数据来配置 NGINX。如果时间允许,我有一些关于配置 NGINX 的专业提示,尤其是在配置管理方面。
因此,尽管我要和你们谈论 Chef 和 Consul,但我要声明的是,本次谈话中没有任何内容是专门针对他们的。 Chef、Puppet、Ansible、Salt、CFEngine 以及其他所有产品都是很棒的产品,您应该使用其中之一。 我们喜欢 Chef,我相信很多人也喜欢。
服务发现也是如此。 Consul、etcd 和 ZooKeeper 都很棒,因此使用适合您的即可。
Belly 是什么? 本质上它是咖啡店打卡的数字替代品,买十杯饮料可免费获赠一杯。 我们在商店里放置一台 iPad,顾客使用手机或带有二维码的实体卡进行扫描,我们跟踪他们的积分,给予奖励,并且我们实际上在此基础上构建了营销工具。
但我在这里并不是要跟你们谈论 Belgian 公司。 如果您对此感兴趣,可以访问我们的网站。 我将和你讨论我们的基础设施堆栈。
所以版本为 0。 在我工作之前,Belly 只有三名开发人员,它是一个单体式 Ruby on Rails应用,这意味着我们网站的每个 API 调用和部分内容都转到单个 Rails 应用程序。它由 MySQL、MongoDB 和 Memcached 支持,我们将它部署在 Heroku 上,这是一个很好的起点。
所以版本 1 – 新希望。 我们认为 Heroku 不再能满足我们的需求,因此我们开始部署一种名为 Capistrano 的东西,它本质上“比用 Ruby 编写的 shell 脚本更好”。 它可以帮助您部署事物。
我们在 Amazon Web Services EC2 上有大约六台服务器。 这是一个静态数字,但如果我们知道有大事发生,我们就会提高它,如果需要,我们就会降低它。 前面我们有 AWS Elastic Load Balancer。
因此,我们想将主页与 API 的其余部分分开,于是就有一个项目诞生了。我们希望这样做,以便能够更快地改进主页,并让不同的开发人员共同开发主页。
当时——直到今天——最流行的术语是面向服务的架构。
因此,我们的堆栈的第二个版本是为了实现面向服务的架构。 我们的第一个计划是将主页与 API 分开。这看起来非常简单 - 我们只有www.bellycard.com和api.bellycard.com 。
但事实证明它真的很复杂,一点也不简单,因为我们的一些移动应用是静态编写的,使用www.bellycard.com/api和/api‑assets 。 我们的电子邮件提供商和所有已通过电子邮件发送给人们的点击链接均以/eo表示“电子邮件打开”,以/ec表示“电子邮件点击”。 我们的 Facebook 应用程序配置为/facebook/callback 。
这意味着 AWS Elastic Load Balancer 不再为我们提供将流量路由到不同应用所需的灵活性。 所以 NGINX 来拯救我们了。 具体来说,我们可以有多个上游并重写规则以将流量路由到我们的不同应用。
在这个非常基本的例子中,我们为 API 定义了一个包含六个服务器的上游
块,并为主页定义了一个包含两个服务器的块。
还有两个服务器
块 [定义虚拟服务器]。 一方面,我们监听api.bellycard.com ,并将所有流量路由到 API 服务器。 另一方面,我们通过www.bellycard.com监听,并据此安排事宜。
效果很好。 它使我们的开发人员能够快速行动。 我们的前端人员正在处理一个项目,并且不会被我们的 API 所阻碍。因此,我们部署了第三项服务。 我相信它是为了与苹果的 Passbook 集成。 第四,我们将所有 Facebook 功能都移出。 第五个目标是处理我们网站上的用户事件。
后来有人认为用 Node.js 编写这个是个好主意,所以现在我们用两种语言编写了五种不同的服务。 它们都是独立部署的,不需要太多的配置管理,而且我们手动编辑 NGINX,我相信很多人都是从这样做的。
我们需要一种更好的方法来扩展这个过程,所以我们使用了 Chef。
Chef 是一个配置管理套件。 它是用 Ruby 编写的,您可以用 Ruby 编写实际的配置管理,因此对开发人员来说非常有用。learnchef.com 是学习Chef 的绝佳资源;它可以在 45 分钟内教给您比我所能教的更多的有关 Chef 的知识。
我将介绍一些基本知识,以便我们能够达成共识。
Chef 中的第一个构建块是菜谱。 厨师使用了很多巧妙的名字,例如刀子作为工具、菜谱以及所有东西都在菜谱书中。 这使得它变得有趣和容易理解,并提供了一个很好的比喻,但也使得任何东西都很难在 Google 上找到。
这是我能想到的最基本的食谱。 安装软件包nginx
并启动和启用nginx
服务。
您还可以拥有文件资源。 例如我想将内容Hello
World!
写入文件/usr/share/NGINX/html/index.html 。
您还可以将其构建到模板系统中。 这里我有几个变量g
和w
代表Hello
和Kevin
,我可以将这些变量传递到模板文件中,该模板文件是 ERB 格式(Ruby 模板脚本)。
因此,我们不必仅仅手动写出内容,还可以编写一个供阅读和问候的模板。
最后一个主要组成部分是食谱,它是菜谱、文件和模板的集合。 还有资源、提供者和库,这些都是更复杂的资源。 https://supermarket.getchef.com上有大量开源和其他食谱,包括 NGINX、MySQL、Java、 apt
和yum
的食谱,甚至可以管理你的ssh_known_hosts文件。 您在配置管理中尝试执行的操作的大部分主要构建模块都可以在烹饪手册中找到。
我们将通过 Chef 进行一个非常快速的 NGINX 示例,其中我们将安装 NGINX 并通过更改几个变量来对其进行配置。 我们将使用 Chef 来发现我们的应用在哪里运行,然后配置 NGINX 将流量路由到我们的应用。
所以在这个例子中,我们做的第一件事是设置一些节点属性。 对于每个节点,您可以通过附加 JSON 文档来设置属性值。 我们将使用第三方 NGINX cookbook 来查找这些属性的设置。 我们将worker_connections
设置为某个值、 worker_rlimit_nofile
指令、我们将在 NGINX 中使用的事件
类型,甚至client_max_body_size
。
之后,我们从 NGINX 食谱中引入了两个菜谱。 第一个是nginx::repo ,它根据您的操作系统设置apt
或yum
存储库。 然后 [ nginx配方] 安装 NGINX。您也可以从源代码安装 NGINX,但使用软件包速度更快。
接下来我们利用 Chef 的搜索功能。 运行 Chef 时,您可以将其作为机器上的代理运行,也可以以单独模式运行它,该模式本质上像脚本一样运行它。 当机器上有代理时,您可以向 Chef 服务器查询节点和其他属性。
在这里,我们要求 Chef 为我们提供所有附加了食谱belly‑api的节点的列表。 之后,我们模板化一个名为/sites‑enabled/api 的站点文件。 它的来源是我接下来将向您展示的模板 [名为api.erb的文件]。 我们传入的变量是我们刚刚搜索的节点。
这里的最后一个新内容是用于重新加载nginx服务的通知
语句。 这说明每当这个模板发生变化时,我希望你重新加载这个服务。
所以这里的模板文件非常简单。 我们有一个名为api的上游,在 ERB 中,我们将通过的所有服务器作为变量进行迭代,并通过 IP 地址和端口 8080 指定服务器。 我们甚至添加了带有服务器名称的注释。 当操作员正在寻找这项服务的运行情况时,这对他们来说将是一个很好的评论。
我们还定义了一个服务器
块来监听api.bellycard.com 。 我只是将所有流量传递到api上游。
我还想提供一个现实世界的例子。 它可能太小了,你们无法阅读,但你们可以大概了解一下 Chef 食谱可以有多复杂。 这是我们今天的一些生产服务器的实际模板和配方。
现在回到我们的堆栈。 我告诉过你,我们已经部署了大约 5 个应用,而且进展顺利。 我们现在有一种将流量路由给他们的方法,因此我们的开发人员只需掌握这一点,今天我们就有大约 40 个 Ruby应用使用 Chef 部署到我们的服务器上。 流量通过 NGINX 完全动态地路由。
我们的开发人员实际上不需要做任何事情,只需编辑一个配方以包含他们的新服务的名称即可。 所有流量均由 NGINX 路由并通过 Chef 进行动态配置。
我们还有大约十个前端 JavaScript应用,它们只是静态文件,我们将它们部署在 S3 上,并在其前面使用 CDN [Amazon] CloudFront。 我们从 S3 存储桶中提供index.html ,其余资产则通过 CloudFront 提供。 我们还有另外五个应用程序,开发人员刚刚将其推送到 Heroku,因为这是一次性的事情,最终投入生产,而且没有人真正被告知。
[Heroku 上的五个应用程序] 是分开的 - 完全在我们的基础设施之外 - 直到四月的一个美好的日子,Heartbleed 漏洞被宣布。 很多人都争先恐后。 Heartbleed是 OpenSSL 的一个漏洞,它可能导致他人提取您的私钥。
由于我们使用 Chef,因此一旦有补丁可用,我们就能够在所有设备上升级 OpenSSL 基础设施。 我相信它在大约 20 分钟内就部署到了我们整个基础设施的各个地方。 然而,AWS(以及 Heroku)花了大约 24 小时来修补其弹性负载均衡器。
这促使我们将所有负载均衡和SSL 终止实际上移到 NGINX 中,无论它部署在何处 - S3 和 Heroku。 这样做会受到一点惩罚,但至少在四月的那一天,这对我们来说是值得的。
因此,我们的堆栈的第 3 版从“SOA 所有事物”变成了“SSL 所有事物”。 我们到bellycard.com及其子域的所有流量都会通过我们的负载均衡器。 为了提高性能,我们的资产实际上仍然由不同域上的 CloudFront 提供服务。 我们不想承担 SSL 的开销,而且我们在东海岸只有一个数据中心。
版本 4——今年大家都在谈论的流行词是 Docker。 由于 Docker 的版本为 0.5,我们的开发人员很高兴开始使用它。
使用 Docker 的原因很简单。
它大大简化了应用的部署。 沒有菜谱可寫。 您不需要担心如何进行资产汇编。 当其他人使用 Python 编写应用程序时,您是否使用 Ruby 编写应用程序并不重要。
本质上它将开发和运营的职责分开。 您的开发人员可能要担心代码、要使用什么库、甚至要安装哪些 Linux 包。 运营可能会担心更多的事情,例如:我要将它部署在哪里? 我要如何从中捕获日志? 我该如何监控它? 一旦解决了这些问题和操作,每个应用都可以运行,无论它是用什么编写的。
这样做的好处是,它允许我们的开发人员在自己的笔记本电脑上轻松启动相关服务。 正如我提到的,我们有大约 55 种不同的应用,其中许多现在都在 Docker 容器中。
假设您正在开发一项用于发送电子邮件活动的新服务。 它依赖于电子邮件服务。 因此,在您的开发机器上,您通常会下载代码,运行bundle
install
,在后台启动它,然后“哦 - 但实际上它依赖于另一项服务,即用户服务”。
该服务依赖于其他东西和其他东西。 因此实际上,新的电子邮件营销服务依赖于大约五种其他服务以及 MySQL、Elasticsearch、Redis 等等。
使用 Docker,我们实际上可以根据生产中使用的相同 Chef 配方构建这些容器,并为我们的开发人员提供他们可以极快下载的容器。
从而加快了部署和开发。
因此在版本 4 中,我们从使用 Chef 部署应用转变为在容器中部署它们。 有很多解决方案可以解决这个问题,而且我相信还会有更多。
第一个是CoreOS和Fleet。 CoreOS 是一个精简的 Linux 操作系统,它在其上运行一个名为etcd 的服务发现引擎。 Fleet 是一种让您定义诸如“我希望一个容器运行五次,并且我不希望它与其他服务在同一台机器上运行”之类的方式。
还有另一个名为 Deis 的版本,它与 Heroku 类似,因为它有一个 Git Push 界面。 有 Apache 的 Mesos 和 Google 的 Kubernetes;Flynn 是另一个最近才推出的。 实际上,我们编写了自己的工具,因为当我们开始这次航行时,大多数工具还没有到可以使用的地方。
我们的系统被称为 Jockey,它的效果非常好,因为我们的部署过程非常有主见。 Docker 的优点在于它本质上提供了一组用于容器化的通用 API。 如果我们只是使用 Linux 的 LXC 容器,我们就不必担心很多事情。
我们计划将其开源,但正如我提到的那样,部署确实是主观的,对我们有用的东西可能并不适合你。
当我们转向 Docker 时,我们的部署策略也发生了变化。 以前,我们通过部署新版本的应用来实现零停机部署。 这意味着如果我们在四台机器上都有该用户传真服务,我们将使用 Chef 下载新版本,将其安装在 [旧版本] 之上,然后向 Web 服务器发送信号以重新加载。 Unicorn 是一个出色的 Ruby 引擎,可以实现这一功能。
然而,容器是不可变的。 一旦您有一个正在运行的容器,如果您想进行新的构建,您就应该创建一个新的容器。 您可以附加它,运行额外的命令,然后保存它 - 就像在 Git 中一样。 但实际上,如果您想充分利用 Docker,您的容器应该是完全不可变的。
所以这意味着我们必须制定一个新的部署策略,因为我们不再能够就地部署。 那里有几个。 蓝绿色很有趣。 如果您已经在四台机器上运行一个应用,则可以将其启动到四台新机器上,并让负载均衡器指向新机器。 一旦你确定它确实按照你预期的方式工作,你可以拆掉你的蓝色,你的绿色就会变成蓝色。 亚马逊有一些非常棒的工具可以利用 AWS 来实现这一点。
还有“金丝雀”部署,我可以部署新机器的一个版本,对其进行监控,如果它通过指标检查和健康检查,那么我就可以继续部署。
这里的容器的不同之处在于,你实际上要拆除它们并启动新的容器,因此你需要某种系统来跟踪基础设施中运行的每个应用的位置。
Chef 实际上开始成为实现这一目标的一种非常好的方法。 有一本正在合并的食谱叫做 Chef Metal,它允许您像在 Chef 基础设施中处理任何其他资源一样处理容器。
还有服务发现。 ZooKeeper是一款非常流行的工具,在 Hadoop 中得到广泛使用。[Airbnb] 有一款名为SmartStack的出色产品,可让您在 ZooKeeper 中进行部署并跟踪部署情况。
我提到过etcd ,它本质上是一个具有 REST 接口的分布式键值存储。 与 ZooKeeper(更像是一个 Java 客户端库)相比,这非常棒,因为您现在可以从任何应用与 etcd 进行通信。 我之前提到的很多开源平台即服务——比如 Deis 和 Flynn 甚至谷歌的 Kubernetes——都使用 etcd。 如果您正在使用 CoreOS,etcd 已经内置于其中。
另外一个也已经问世的,也是基于 REST 的,叫做Consul 。 它是由 HashiCorp 的人员发布的,他们制作了 Vagrant 和 Packer 以及大量其他出色的工具。 实际上,我们决定使用 Consul。
下面是 Consul 的基本结构图。 您可以看到有多个数据中心,每个中心有三台服务器。 数据中心 1 中也有客户端。 有趣的是,在您的服务器代理中,您将选出一个主要代理,然后您的所有客户端实际上不仅了解所有服务器,还了解所有其他客户端。 然后,他们使用八卦协议与所有其他代理进行通信。
这让我想起了 AT&T 的一则老广告,广告中你告诉了两个朋友,这两个朋友又告诉了两个朋友,消息就这样传遍了整个节点网络。[编辑 – 嗯,很接近:这是Faberge Organics 洗发水的广告。 ] 这与 etcd 或 ZooKeeper 相比,在 etcd 或 ZooKeeper 中,你基本上只需要服务器代理,然后你的客户端就可以连接到它们。
通过 Consul 的做事方式,您实际上可以在几乎每台服务器、部署 Docker 的所有地方以及运行负载均衡器的所有地方运行 Consul 客户端。 因此您始终可以通过本地主机端口 8500 与该 API 通信。
与 etcd 一样,[Consul] 是一个分布式键值存储。 您可以设置和获取密钥,它们将保持线性化,以便您可以确保它们始终一致。 其中存在一些问题,但他们对这些问题所在提供的文档非常出色。 然而,与 etcd 不同的是,他们将服务发现视为一等公民。
除了键值对之外,您还可以注册服务,例如 API。注册服务时,您会告诉 Consul 它在哪个节点上运行。 这意味着当我们部署一个容器时,我们也会告诉 Consul 也在这个主机上注册这个服务 API。
最重要的是,Consul 具有分布式健康检查,因此现在您可以在服务发现平台内定义 Nagios 风格的健康检查。 当您决定查询 Consul 时,您可以要求提供 API 服务正在运行的所有位置的列表。 您可以发送“全部”或“仅通过”或“仅不健康”的标志。
它还支持多个数据中心。 我提到过你应该在任何地方运行那个 Consul 客户端。 当启动它的时候,你传入一个指定数据中心的参数。 如果您有一个东数据中心和一个西数据中心,您可以查询本地 Consul 客户端,而无需了解数据中心,也不需要询问地址或其他信息。
我们实际上使用数据中心作为我们的暂存和生产环境的边界。 我们对暂存应用的配置可能会说“问我MySQL.services.consul在哪里”。 无论它实际上是在暂存节点还是生产节点上运行,您都将获得正确的值,而无需了解数据中心或了解多环境。
它(以及 etcd)的另一个优点是它的 HTTP 接口有长轮询。 这意味着您可以查询并请求运行此服务的所有服务器的列表,同时保持连接打开 60 秒,并在发生任何变化时立即收到通知。 投票时间实际上可以长达 10 分钟。 这意味着您可以立即收到有关基础设施的任何变化的通知。
我已经提到的另一件事是,您可以通过在任何地方拥有客户来构建扩展代理的能力。 这非常棒,因为您可以随时与本地主机对话。
然而,最大的问题是:既然我已经将这些数据存储在分布式服务发现平台中,那么我该如何根据这些数据配置 NGINX?
值得庆幸的是,有一个名为Consul Template的工具。 它实际上是昨天发布的,这让我从此刻开始改变了今天的幻灯片。 它曾经被称为“Consul HAProxy”,这是一个糟糕的名字,因为它实际上并不是特定于 HAProxy 的。
Consul Template 为您提供了一个非常简单的界面来构建模板来订阅服务的变化、这些服务的健康检查,甚至是键值存储。 这样,您就可以将诸如 NGINX 工作器的数量之类的设置存储在键值存储中,并在发生变化时重新生成配置。
这里最大的功能是从模板生成文件,这听起来与我们之前使用 Chef 所做的事情非常相似。 这里最大的区别是它使用 Golang 模板语言而不是 ERB(Ruby)。 一旦更改了文件,您就可以选择调用更改的命令,例如service
nginx
reload
。
这是一个在命令行运行 Consul Template 的示例。 您将其指向您的实际 Consul 主机,在本例中为consul‑prod.example.com 。 在实际的生产环境中,我建议在任何地方运行 Consul 并连接到本地主机。
然后传入一个模板文件,这是一个 Golang 模板。 在我们的例子中,我们传递的是/etc/consul‑templates/api 。 然后,您传入实际要写出的文件,在我们的例子中是/etc/NGINX/sites‑enabled/api 。 然后调用命令: service
nginx
reload
。
Consul 模板看起来与我之前的幻灯片非常相似,只不过不是 ERB 而是 Golang。 因此我们在这里定义两个上游。 一个叫做api ,一个叫做homepage 。 我们有一个针对服务 API 的范围
语句,并且有内置变量用于获取该服务实际运行的 IP 和端口。
Consul Template 的优点在于,以这种方式使用它可以使服务变化的收敛速度很快。 在使用 Docker 部署之前,我们根据机器的情况每 5 或 10 分钟运行一次 Chef。 对于我们来说这已经足够快了,因为我们已经部署到位。
现在我们正在构建更先进的部署系统,我们需要在几秒内而不是几分钟内收到这些变化的通知。 我们实际上在几毫秒内就能得到它,平均大概是 200 毫秒。
但是,仍然需要配置管理来生成模板。 我们不能简单地用 Consul 来代替 Chef。 我们还需要弄清楚如何部署 Consul 和 Consul Template 等等。
因此,我们实际上是使用 Chef 模板来部署我们的 Consul 模板,这看起来有点复杂。 我们在 Chef 配方中首先要做的事情是查询 Consul 主机以获取所有服务的列表。 然后我们生成一个 Consul 模板 [使用 模板
和 来源
语句],我们传入 SSL 证书和密钥位置并重新加载 consul‑template
。[编辑——Reedy 先生最初提到 consul‑haproxy
,出现在第一个 通知
幻灯片上的声明。 随后他自我纠正并澄清说该幻灯片的发布时间早于 Consul Template 的发布。 ]
我们还为 Consul Template 编写了一个配置文件,并传入 [指定的变量] Consul 主机、源、目标和重新加载命令。 这实际上是我们如何结合使用 Chef 和 Consul 来即时更新我们的 NGINX 配置的核心。
接下来我有一些关于 Chef、Consul 和 NGINX 配置的专业技巧。
第一个提示是,如果您使用 Chef 搜索来查找您的服务运行的位置,您应该查看 Chef 部分搜索。 Chef 搜索的问题在于它会复制整个节点,包括所有属性。 如果您将很多内容保存到节点的属性中,那么您必须在与 Chef 服务器通信时通过网络提取这些信息,并将它们存储在内存中。
如果 Chef 搜索返回数百或数千台服务器,您很容易就会发现实际配方可能会耗尽内存。 部分搜索允许您仅返回您关心的键。
例如,我们首先有
节点 = 搜索(:节点,'recipe:belly-api')
该搜索将返回有关每个对象的每一条信息。 这包括其磁盘空间、RAM、CPU 以及所有已写入其自身节点属性的应用的信息。
相反,我们可以使用部分搜索,其中我们创建一个名为search_keys
的新哈希并为其提供我们关心的键列表 - 在本例中只有名称和IP地址。 然后我们点击非常相似的 API,称为partial_search
,并传入额外的 [ keys
] 参数。
当我们转移到 S3 和 Heroku 前面的负载均衡时,困扰我们的第二件事是 NGINX 仅在重新加载配置时使用 DNS 来解析上游
块中的主机名。 这意味着如果您将上游服务器设置为s3.amazonaws.com或anything.herokuapp.com并且它发生变化,您的负载均衡器直到下次重新加载才会知道新的 IP 地址。
我们解决这个问题的方法实际上是在 Chef 中执行 DNS 解析,然后当 DNS 发生变化时触发 NGINX 重新加载。 这导致了第二个问题:[DNS 响应中的地址顺序] 并不总是相同的,因此在将响应写入模板之前,请确保对其进行排序。
当您开始部署大量服务时,另一个问题是您要避免陈旧的配置。[编辑 – Reedy 先生暂停演讲以回答观众的问题。 ] 在 Apache、NGINX 和其他 UNIX 事物中,一种常见的配置模式是拥有一个conf.d文件夹,然后从中加载所有内容。 因此,如果我部署服务 A、B 和 C,我会创建service-a.conf 、 service-b.conf和service-c.conf 。
然后我决定用 D 替换服务 B,现在 NGINX 配置文件夹中有四个配置,但服务 B 不再存在。 由于 B 和 D 具有相似的主机名,因此最终可能会发生冲突。
过去,我们曾采用两种方法来实现这一目标(删除陈旧的配置)。 使用模板您可以添加:delete
功能,但这很快变得有点笨重。 我们基本上有一个旧服务列表,如果它们存在,我们总是会尝试删除它们。 这实际上并没有实现。
您可以做的另一件事是将所有站点配置呈现为一个文件。 很多人将此称为“将幂等性向上移动”。 本质上,您不需要从多个来源加载 NGINX 配置,而是将其全部放入nginx.conf中。
当您实际登录到框时,这确实会有点笨拙,但希望我们能够达到您不会在生产中实时对配置文件进行故障排除的程度。 如果您的 Chef 配方仍然有点难以处理,我们所做的是使用一个nginx.conf来加载一系列不同的站点。 例如,我们的一个站点配置文件列出了大约 30 个服务,然后我们有一个用于 Heroku 的服务,一个用于所有 S3 的服务,等等。
因此,如果您将所有站点配置呈现为单个或少量文件,则无需担心清理工作。 如果从 Chef 的角度来看某项服务消失了,Chef 就会停止将其渲染为实际文件。
问: 到目前为止,Consul 给您带来了什么帮助?
一个: 我们喜欢 Consul,与 etcd 相比,我真正喜欢它的一点是,可以在它的基础上继续构建服务。 我不需要担心服务发现。 事实上,如果您有遗留应用并且使用 Consul 部署(假设)MySQL 服务器,Consul 还提供 DNS 接口。
您的应用不需要知道 Consul;它只需查询“我从mysqldb.services.consul获得什么地址?”。 在这种情况下,Consul 是 DNS 服务器。 您设置 DNS 基础设施,以便如果 TLD [顶级域名] 以.consul
结尾,则查询将被路由到 Consul。
对于我们来说,它的扩展非常好。 我们在生产环境中运行大约 3 个服务器代理节点和大约 60 个客户端。 我们没有遇到任何问题。 他们只是不断添加功能并且不会破坏向后兼容性,因此升级一直很棒。
问: 您使用 NGINX Plus 吗?
一个: 我们没有。 当我们开始与 Consul 合作时,我们就已经对此进行了研究。 如果我们不需要模板系统,那就太好了,因为我们只需要一个脚本来监听 HTTP 长轮询,然后代表您与 NGINX API 对话。 唯一的问题是,您可能还需要一个模板系统,以防 NGINX 重新启动。 它会立即重新加载您的上游配置。
其他人也在 NGINX Lua 中做了一些工作来直接查询 Consul。 我还没有看到很好的实施方案,因为它们往往分为两类。 首先,它们对每个 HTTP 请求都查询 Consul,这很慢。 第二种是他们在配置运行时加载它,最终您会遇到与 DNS 相同的问题。 因此,模板目前是最好的,但如果我们将来看到使用 NGINX Lua 来实现它的方法,我不会感到惊讶。
问: 您会离开 Chef 吗?
一个: Consul 中没有很好的内置方法来维护这些模板,而且我们已经使用 Chef 部署了 NGINX。 目前,我们的方案有数百行甚至数千行,涵盖了我们使用 NGINX 进行的所有其他操作,包括日志记录、跟踪和一些 OAuth。 我并不认为我们会在基础设施中抛弃 Chef 并替换它,但它是一种很好的增强,也是获取快速通知的好方法。
问: Chef 提供了多少开销?
一个: 因为我们的大多数机器都在执行单一任务,所以我们实际的 Chef 开销非常低。 空闲时 RAM 使用率较低。 它实际上位于一个计时器中并且可以分叉。 如果不关心它的收敛速度,其他人也会在cron
中运行它。 我们发现一些较重的配方中的 CPU 出现了小幅波动,但我们无法通过部署另一台服务器来解决这个问题。
问: 您使用 CloudFormation 做了多少工作?
一个: 我们尚未使用 CloudFormation。 它已经在我们的关注范围内,但我们做出的一项改变是利用更多的 Auto Scaling 组。 其工作方式是,当一个实例启动时,它将有一个包含其 Chef 运行列表的用户数据。
一台新机器将加入集群,并且已经拥有基于其映像的密钥,因此它能够与我们的 Chef 服务器对话、自行注册并获取所需的食谱。 这为我们解决了大部分 CloudFormation 问题,因为我们没有使用很多与之配合使用的其他 AWS 工具。
问: 服务器被毁了怎么办?
一个: 如果 Auto Scaling 组中的某个服务器消失,您可以使用 Amazon SNS [简单通知服务] 获取通知。 我们有一个非常简单的服务,可以监听这些通知,然后清理 Chef 服务器。
问: 您使用过 AWS 的 OpsWorks 吗?
一个: 我们没有。 我们从一开始就使用托管 Chef,它对我们来说非常有用。 我对此并不确定,但我相信 OpsWorks 更像 Chef Solo,您只需使用它来进行配置。 我们仍然在几乎所有的机器上运行 Chef Agent,并使用相同的 Chef 配方来生成用于开发的 Docker 容器。
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”