引导阶段
在过去的 6 年里,我有着独一无二的机会观察我们公司是如何由几个只想着出租教科书的应届毕业生发展成一个大而成熟的公司。当我回头看时,我会将我们的成长分成两个不同阶段:A 轮融资之前和 A 轮融资之后,与你听到或读到的大部分创业公司不同,我们经历了相当长一段时间的 A 轮融资(大概有 3 年)。
在这一发展阶段,我们并没有花费大量的资源或人力在 DevOps 上,相反我们主要关注产品的构建。在刚开始几年的大部分时间里,我把自己定位为一软件工程师,每月只需几天时间花费在系统管理上。
我们经常开玩笑说,我是那个抽到下签,被“困于”服务器管理的那个人。但是,实际上,我自己特别享受。尽管如此,我也从来没想过我对软件开发的热情居然会用在服务器管理上。
尽量简单(在你能控制的范围)
我们初期之所以能不在 DevOps 上花费力气是有几个原因的。首先,很大程度上是因为我们是小公司,变化也比较少。我们选择了一个简单的架构,应用程序数量也比较少。所以尽管我们的产品不断发展,但是需要对底层的基础架构进行修改的地方却比较少。
过度投资
第二,早期我们在服务器硬件上投资过度了。我们可能只需要两台服务器就可以运行我们整个网站,而我们却买了 10 台。但这允许我们之后花很少的时间去担心那些性能或基础架构发展等问题,而我们也是在几年之后才耗尽初期购买的服务器的性能。当然,配置这些服务器是有前期成本的,但是一旦设置好了,就不需要大的改动。
选择好的工具
最后,我们采用 Ruby on Rails 作为应用程序框架,及其关联的工具,比如:Git、Capistrano 和 Teamcity,允许我们在早期就采用那些良好的发布和部署实践。与此同时,我们也构建于那些行之有效且稳定的开源解决方案之上,比如:nginx、MySQL 和 memcached。
也正因为对这些工具和框架的采用,从而让我们避免了采用不必要的复杂且专有的解决方案。很多时候我觉得这些方案会随着公司的成长,降低其开发速度。
成长
随着我们公司进入第二个成长阶段,我们的工程师和产品团队也稳步增长。只有两个开发人员的日子已经一去不复返了,一眨眼间,我们就有 10 个,甚至 20 个人为现有的以及新产品工作。可想而知,我们需要引进的变化数量也会稳步增加。我们的硬件上需要承载的应用绝对数量也直线上升,先是以前的两倍,然后三倍。同时开发人员也想使用新的应用框架、编程语言、数据库、排队系统及缓存服务器等。
随着这些复杂性的增加,错误和停机的成本也增加了。很快我们发现旧的手动配置基础架构已不再适用,而我们基础架构层对成熟性和灵活性的缺乏也将给我们带来以下问题:减缓新产品和功能的发布,危害我们的稳定性。认识到这一点,我停止了在产品上的工作,并将重点全部放在研究开发自动化、监控和发布流程上。
引进 Chef
幸运的是,我们认识到我们需要实行 DevOps 实践。而当时,我们遇到了 OpsCode Chef,以及它所倡导的“基础架构即代码”原则。最初,我们花费了几个月时间为现有基础框架的每一部分编写自动化脚本。一旦完成,我们就可以利用这些自动化脚本重构所有服务器,这将大大减轻我们肩上的负担。现在我们所有服务器都已设置一致,而我们最终也有一个地方能让团队所有人都可以看到每块基础架构到底是如何建立和设置的。同样重要的是,它允许我们快速地将额外资源添加进来。
DevOps 团队的成立
DevOps 开始在公司内担负起独特的责任,为我们的产品线提供关键支持,并保证我们的基础架构可以持续拓展。除了这些重点之外,我们也在不断开发工具和产品,用于管理这些需要持续支持和改进的基础架构。尤其在前期,通常来说如果往基础架构中引进新的应用,就要求对底层自动化脚本进行修改。由于越来越多人开始依赖我们的工作,内部用户(开发人员和运维人员)也随之提出了更多与 DevOps 相关的需求。
由于我们的开发团队已经分为不同的产品团队,且每个团队都关注不同的业务,我们决定设定一个单独的 DevOps 团队。这样我们就有一个专门的团队全职解决基础架构问题。另外,应用平台的可用性和稳定性对我们的业务来说也是及其重要的,宕机或别的问题对我们的服务都会有很大的影响。我们需要随时保证有专门的、训练有素的工程师来协助和调查问题,尤其当问题的归属可能跨越多个团队或无法当时就明了时。
自动化果实
按需配置
在采用 Chef 和自动化我们产品的基础架构之后,我们立马着手做的事情就是改善我们的测试和 staging 系统,给它们配上同等程度的自动化。我们经常听到的抱怨之一就是开发人员无法简单快速地给业务人员展示他们当前所做的工作。为此,我们开发了一个 100% 自助服务的门户,这样公司里的任何人都可以启动一个预配置服务器在 EC2 上运行完整的程序。
用户可以自己选择要在服务器上安装哪个版本的哪些应用程序,他们也可以选择使用测试数据库或使用产品数据库某一时间的快照。该系统的最大优点就是可以重用我们构建产品服务器时的 Chef 脚本。这允许我们在发布到产品服务器之前,就把很多潜在问题给过滤掉了。我们的开发和 QA 团队也会更自信,因为他们测试新特性的环境与产品环境上的设置及运行的版本是一致的。
现在在我们公司,此 Staging 系统尤其受欢迎。很多员工都说到他们之前所在的公司如果想要搭建一个模拟服务器,需要数周的时间及大量的文本工作。在我们这里,所有人都可以在 15 分钟内构建出一个 Staging 系统。当然创建这样的系统肯定离不开健壮的自动化基础。
数据中心故障恢复只需几分钟
在 Rafter,数据中心故障恢复是 DevOps 自动化帮助我们解决的另外一个难题。大概在两年前,我们决定我们需要有能力在任意时候都能切换到辅助数据中心,以减少停机所带来的影响和损失。由于我们面向的是教育行业,我们的业务有季节性,如果在返校季遭受长时间的停机,其代价是昂贵的。同时,我们的运维人员也从中获利极大,他们可以在数据中心无实时数据时,执行那些具有风险的维护。
正因为有了自动化的基础架构,我们可以相对比较容易地完成这个难题。要换在最初,如果有人告诉我有天我们能在几分钟内对整个数据中心进行故障恢复,我肯定会非常震惊。但是现在我们完全可以依靠自动化,设计出相应的基础架构来支持这一目标。
共享部署
另外一块需要我们 DevOps 团队重点工作的地方是改进部署流程。从一开始,我们就使用 Capistrano 这一优秀工具管理部署,并对其非常满意。我们需要做出的改进就是让 Campfire bot(又名为 Reginald)通过 Capistrano 部署。现在我们的产品开发人员只要通过 Reginald 来发布应用就可以了。
其实这里最大的胜利就是让部署变成一个共享的经验。 Campfire 聊天室的任何人都可以查看部署是否正在进行,如果有问题,马上就可以有人参与解决。所有的错误和部署日志都存储于我们的数据库中,并且可以从 Reginald 给开发人员指定的 web 应用上查看。这样一来,就更容易分享那些潜在的问题。在以前,当开发人员在服务器上部署时更多的是私人操作,而现在我们采用公开部署,让团队中每个人都能看到具体情况,这样部署起来就更简单。
自助工具
对于我们 DevOps 团队构建并使用的产品,我们都秉持着尽可能使其可自助化这一宗旨。自动化的成功在于移除人为的障碍,尤其是来自我们自己的。为相应人员提供工具和平台用于管理他们在乎的那部分基础架构,会让整个组织更有效地执行起来。尤其是在那些别人可以为你工作的领域(有可能他们会比你做得更好),你的工具应该允许他们去这么做。在我们采用的工具和实践中,我们也保持这个原则。
我们的团队构成
我发现,行业里很大范围内趋向于将DevOps 结构定义为:开发vs 运维。我们的DevOps 团队出自于产品开发团队,所以一直由传统软件开发人员组成。我们所有现有团队成员在成为DevOps 的一员前,都为我们主要产品做过开发。我们非常幸运拥有这样一个出色的运维团队,照顾和改善我们的硬件和数据中心,允许我们全心全意地关注于软件开发。
关注开发
我相信对“开发”这一层面的极大关注对我们来说非常行之有效。随着我们需要构建和支持更加复杂的应用基础架构,我们对传统软件开发的需要将不断增加。这样说来,我们发现招聘工作越来越难,因为很多软件工程师对运维/ 基础架构相关领域并没有太多兴趣,而很多运维工程人员也对传统软件开发的各个角色没有太多经验。可以肯定的是,我们需要特殊人员来填补该空缺。在Rafter,我注意到DevOps 似乎引起那些对某一领域有很深造诣的人员,而非那些通才。现在我们的DevOps 团队包含有三个工程师,同时我们也一直在寻找更多的优秀人才。
使我们DevOps 团队独特的一点是我们经常会接受那些可能需要正常产品团队或网站稳定性工程师来完成的任务。比如:我们领导完成过将我们的应用升级到能在Ruby 及Ruby on Rails 各主要新版本上运行的项目。如果你曾参与过大型应用针对重要的Rails 更新的话,你就会明白这并非易事,它需要对Rails 及底层代码库有很深的了解。同时,我们也经常帮助产品团队调试和解决他们产品上的性能及可拓展性问题。正因为这些工作,我们团队不断地接触那些我们需要支持的软件平台的各部分。
日常工作
支持
我们DevOps 团队成员典型的一天是由以下几部分组成:解决支持请求、调查告警和从事长期项目。通常,我们会花费大概50% 的时间在支持和告警上,50% 的时间在项目上,但是支持请求和告警会占更多,因为一般情况下它们都具有时间紧迫性。其中支持请求往往涉及各种各样的问题,但主要还是围绕着应用支持相关领域。举个例子,工程师希望往平台上添加一个新的应用,又或想给现有应用拓展更多服务器。有时,这些请求可以是大范围的,需要很多修改和测试的,比如:支持一种新的编程语言或新的数据库。
监控和告警
另外一组常见请求是调查应用告警(有自动的,也有工程师报告出来的)。通常,DevOps 扮演警报协调员的角色,进行着初步调查,并寻找出解决问题的最佳团队。这样说来,我们并不会亲自处理所有的应用告警。我们会调查那些影响基础架构的告警(如涉及对网络、IO、CPU 和内存过度使用的情况),或那些由各团队共享的职责和使用的领域(如共享的库、数据库和遗留应用程序)。
项目工作
很多情况下,我们在工程支持请求和调查告警上所做的工作,会帮助我们发现那些我们需要进一步改进的地方。具体说来,这些领域里,我们往往没有为工程师提供足够的工具或信息去解决问题。我们现在就面临着这样一个问题:我们还没有能力让工程师自己部署自己的cronjob 改动。因此,当需要为应用修改cronjob 时,他们就需要开一个支持请求。当每周有10 个这样请求的时候,很显然我们需要为工程师们开发出一工具以允许他们部署自己的cronjob。因此,我们的项目工作很大一部分来自处理支持和告警请求时发现的缺陷。
我们还花费大量时间在系统更新,及为提升对更新的信心所做的测试上。我需要花上好几页才能列全我们平台上所支持的服务器、数据库、应用程序、库及操作系统。保证所有东西都以其最新最安全的版本运行着,其本身就够多位工程师忙碌上一整年。
我们另外一个项目工作源自直接的外部请求。例如:管理层要求我们能够故障恢复到另外一个数据中心,或审计上要求一个特定安全功能,又或是个由工程师发出的可能影响多个应用的基础架构修改请求。
DevOps 即平台
随着公司的不断壮大,DevOps 也在我们的产品工程团队和运营团队间找到了自己的位置。我把这个结构设想成三层蛋糕:底层是我们的运维团队,负责获取和建立物理硬件;然后中间是我们的 DevOps 团队,负责提供一个平台,以便大家使用这些硬件资源;最上面一层是我们的产品工程团队,他们使用 DevOps 平台部署、监控和管理他们的应用。
当讨论 DevOps 时,我认为“平台”是个关键概念。当我第一次开始 DevOps 时候,我曾认为我们的工具是些独立的项目。但是,一旦你开始构建这些独立部分,你会意识到各个组件都能构成更大平台的一部分,并且它们都要接触到共用的信息集。所有的工具都需要集成起来,否则其复杂度和重复性就会慢慢增加。
构建 DevOps 平台
将我们的 DevOps 工具转变成服务平台是当前也是未来需要不断进行的一个工程。这听起来,可能会很奇怪。但是你想想,我们会有不同的客户想要了解我们的基础架构信息。比如:本文提到的某些应用可能需要通过以下方式访问 DevOps 平台:
- 我们的 Staging 服务器门户需要知道哪些应用可以安装在它上面。
- 我们的部署框架需要知道哪些应用可以部署,及部署在哪里。
- 为了切换数据中心,我们需要知道如何在另外的数据中心启动这些应用。
- Chef 脚本需要知道如何根据我们要安装的应用要求,正确配置服务器。
从这些例子中可以看出,通过服务发布那些通用的信息集可以用来回答关于基础架构的基本问题。
我们可以设想得更远,开发出更多影响基础架构中变化的服务。比如:让服务器或应用进入维护模式的服务;往平台中添加新应用服务等等。有的 DevOps 组织可能会通过特定脚本来执行这些功能。但是它的缺点在于一般情况下只能有一个 DevOps 工程师执行这类脚本。服务的好处在于其它工具和应用可以通过共享方式与其交互。为了更大的灵活性,我们也可以在这些服务上面开发出相应的应用。这也支持了“任何时候都可以构建能自我服务的工具”这一想法。
Chef 即数据库
我们看待 Chef 在整个系统中的角色也发生了转变。它不仅仅是个自动化服务器的工具。我们把它当作 DevOps 平台中的数据层。通过引用 Chef 平台和 APIs 的优点,我们可以保存和查询所有关于基础架构里的服务器和应用的信息。在 Chef 提供数据存储层的同时,我们也在建立自己的服务集以访问这些数据和提供灵活的交互方式。
我们的工作永远不会结束
所有的这些都是为了确保我们依然可以持续拓展,且基础架构不会成为新产品发布的障碍。就算有大量的自动化就绪,我们仍然需要在现有自动化基础上进行持续迭代。
有个例子很快就呈现在我脑海里。我们的团队曾花费很多精力构建一个如何在每个服务器上设置应用的框架。以前我们只需要编写一个小的 JSON 文件,描述下应用及依赖的基本信息。然后就可以拍拍手去解决下一个问题了。
但是我们开始意识到我们需要添加很多新应用,并要花费很大一块时间编写这些配置,因为通常需要与产品工程师多次来回沟通,其效率比较低。很快成为自动化的一个瓶颈。因此自动化工作永远不会结束,就算你今天有足够的自动化,很可能明天它就会阻碍你的发展。
关于作者
Chris Williams是 BookRenter.com ,首家在线教科书租赁服务提供商,是于 2012 年成立的 Rafter Inc 联合创始人之一。现在他在管理 Rafter 的 DevOps 团队,并负责其基础架构自动化、部署和发布流程、及平台可用性。
参考英文原文: DevOps @ Rafter
感谢陈菲对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。
评论