使用 Drupal 实现持续集成
在 1990 年代初期,我的第一份大学毕业后的工作是在一家初创公司担任软件工程师。我们正在使用一个著名的开源网络安全项目构建商业产品。在那个年代,敏捷软件开发实践(更不用说万维网,甚至公众对互联网的广泛认知)还处于未来。我和我在那个项目中的工程师同事(他们和我一起毕业,直到今天仍然是我认识的最优秀的程序员)被教授了我们现在称之为瀑布模型的方法。我们认为我们是不可战胜的。
我们不知道接下来会发生什么。在咨询了潜在客户后,我们编写了一份需求文档,描述了产品需要做什么,一份功能规范,描述了产品的外观和行为,一份设计文档,描述了我们将如何构建产品的技术架构和内部结构,甚至还有一份测试计划,描述了我们将构建的自动化测试,以确保产品能够工作。我们有一个由管理层宣布的发布截止日期:“圣诞节前”。幸好我们还年轻!我们开始了我们的死亡行军。当地的中餐外卖店非常了解我们。我每天早上大约凌晨 1 点才到家,持续了好几个月。我们终于在 12 月 18 日完成了并发布了产品的 1.0 版本。我花了几周时间才想起正常人在不工作的时候会做什么。
我从这次经历中学到了什么?我们做错了什么: 基本上,我们使用的软件工程方法的一切都完全是愚蠢的。我们按时交付了一个可用的产品,但我们开始时受益于一个可用的开源项目。我们基本上犯了敏捷开发为了防止而发明的所有错误。
我们做对了什么: 我们实际上实施了我们的测试计划。由于测试是自动化的,构建过程也必须是自动化的。这当然给项目增加了很多“额外的工作”,但回报是巨大的。每天下班前,我们会启动构建脚本。当我们第二天早上来上班时,如果最后一行的输出显示 PASSED,我们就会感到自信并准备发货。我们当时并不知道,我们正走在最终被称为持续集成 (CI) 的道路上。
快进 20 年。我现在在 Acquia 工作,该公司为使用开源项目 Drupal 的公司生产商业产品。Drupal 是一个用于构建网站和服务的 LAMP 堆栈应用程序。我们很早就意识到,每个使用 Drupal 的人都需要在某个地方托管它,并且大多数使用 Drupal 构建网站的人也不想成为构建可靠、可扩展的基础架构来托管它的专家。不仅如此,他们还希望能够遵循软件开发、测试和部署的最佳实践;他们想使用持续集成。但是,他们通常没有时间、资源或管理层的支持来投资必要的基础设施。在过去的三年里,我一直在解决这个问题。
什么是持续集成?Web 上有许多优秀且有说服力的资源详细讨论了 CI 的原则。在本文中,我将讨论 Drupal 网站开发最有意义的最佳实践的简化列表
-
使用源代码存储库。 这是良好软件开发的第零步。大多数人都在这样做,使用 Git、SVN 或其他系统;如果您没有,请立即开始。
-
进行小而频繁的更改。 所有开发人员都应频繁提交更改。这减少了不可避免的冲突,并使问题更早地浮出水面。此外,小而频繁的更改可以实现小而频繁的发布,使所有其他原则更有价值。
-
自动化测试。 让您的存储库与测试环境自动集成,以便每次提交都会触发测试运行。这样,您就可以立即知道是否发生了故障。
-
在生产环境的克隆中进行测试。 在与生产环境不同的条件下测试您的软件没有任何好处;这样做是导致您在部署时使您的网站崩溃的秘诀。永远不要再听到有人说“但这在我的机器上可以工作!”。
-
使所有版本易于访问。 尽管尽了最大努力,生产版本仍然会崩溃,因此您需要一种简单的方法来重新部署之前的版本。然后,您需要比较工作版本和损坏版本,以找出问题所在。为此,您需要过去版本的参考副本。
-
拥有审计跟踪(即,责任清单)。 这不仅可以帮助您进行源代码控制,了解是谁提交的,还可以帮助您了解是谁部署的提交。这可以提供理由以及潜在的修复。
-
自动化网站部署。 为了容忍小而频繁的发布,推送发布需要是一个自动化的过程,以便它非常快速和容易。如果推送一个版本是一件很麻烦的事情,那么整个过程就会崩溃。
-
衡量结果并快速迭代。 这些更改有帮助吗?网站速度更快了吗?可用性增强是否带来了更多销售额?如果没有,您可以再次迭代。
实现持续集成需要一定数量的基础设施、工程团队使用它的文化和纪律,以及管理层的理解和承诺,以便它支持必要的投资。这是一篇关于技术的文章,而不是关于管理和文化的文章,因此我主要关注这里的基础设施。
自行构建许多商店构建了自己的 CI 系统,这些系统完全适合他们自己的需求。如果您有时间和资源来实现,这样做是完全合理的。当然,自己构建的最大危险是决定这样做——然后却一直没有时间去做。您最终以手动、缓慢且容易出错的方式做事,“直到我们有时间修复它”,这通常会变成“永远不会”。当您开始时,它可能会最终成为一个永久性的副项目,这可能会导致您偷工减料,最终在最糟糕的时候导致问题。
以下是一些您应该记住的事情。
使用源代码存储库。 您可能已经在使用了(对吧?)。您需要熟悉它的“提交后钩子”功能,以便根据它编写脚本操作。如果您使用的是托管存储库(例如 GitHub),您将需要与它的基于 Web 的钩子集成。
进行小而频繁的更改。 您的所有开发人员都将频繁提交,尽可能在本地解决冲突。为了保持事情向前发展,您需要有一个始终可用的正在运行的每个人最新代码的副本。一种方法是将您的主要开发分支的顶端自动部署到共享的开发环境,以便每个人始终可以看到它。您可以使用您的存储库的提交后钩子自己编写脚本。像 Jenkins 这样的构建自动化工具会有所帮助,但您仍然需要自己编写部署脚本。
自动化测试。 假设您为您的网站编写了自动化测试,您将希望在有人提交他们认为是准备发布的提交时运行它们。有很多工具可以做到这一点。一个流行的选择是 Jenkins(以前称为 Hudson),它非常出色。它可以直接与您的代码存储库集成,并在每次提交时触发“作业”,或者按计划运行作业。
然而,测试本身并不是全部。因为您的应用程序是一个 Drupal 网站,所以您需要在 Web 环境中对其进行测试。您肯定需要一个正在运行的数据库服务器。如果您想测试像浏览器会看到的实际页面加载,您还需要一个正在运行的 Web 服务器。您可能希望将您的应用程序与相当新的生产数据库一起测试;如果您不自动化该过程,总有一天您会发现自己正在针对一年旧的数据进行测试。但是,您可能还希望在针对当前生产数据库运行测试之前“清理”您的当前生产数据库,以免您意外地从您的测试服务器向所有客户发送垃圾邮件,或者更糟。这都是您的测试工具脚本的责任,由 Jenkins 运行。
如果您自欺欺人地认为您可以“模拟”这些依赖项,并拥有可以在任何地方运行的纯粹独立的单元测试,那么现实会嘲笑您。您会发现测试没有准确地模拟您的实时环境,并且您将不得不回滚一个“通过了所有测试”但在生产环境中失败的版本。
在生产环境的克隆中进行测试。 这是事情真正变得有趣的地方。我已经谈到了需要一个正在运行的 Web 和数据库服务器。如果您的网站使用其他服务,如 memcached、Varnish 或 Apache Solr,您需要确保这些服务也到位。如果您的生产站点使用 SSL,您要么需要在您的测试环境中运行 SSL,要么需要关闭强制执行 SSL 的检查或重定向。最终,维护您的测试环境与维护您的生产环境一样多的工作。
您在哪里运行所有这些东西?“简单”的答案是在与 Jenkins 相同的服务器上运行它。但是,Jenkins 可能没有在您的生产服务器上运行,因此您的测试环境立即与生产环境不同。您知道 当您通过您的发行版的软件包管理器安装 Jenkins 时,它不会拉入一些您的站点最终可能会在测试中使用的其他软件包,但随后会因为在生产环境中丢失而失败吗?
这指向了一个更深层次的问题。除非您确切地知道您的生产环境到底是什么,否则您无法创建生产环境的克隆。安装了哪些软件包?有哪些配置文件到位?有哪些守护程序正在运行?安装了哪些安全更新?运行生产网站会导致各种意想不到的问题和意外情况,即使是善意、有良好意愿的系统管理员也可能通过手动更改服务器上的某些配置来解决危机。您必须确保这些更改始终传播到您的测试环境。就此而言,您必须确保它们也永久维护在您的生产环境中。
这直接引出了 DevOps 和服务器配置管理的主题。确保您的生产环境符合您的期望的唯一方法是自动化其配置,确保您的测试环境是您的生产环境的克隆的唯一方法是使用完全相同的自动化配置来构建它。有一些很好的开源工具可以做到这一点;Puppet 和 Chef 是我熟悉的两个工具。但是,Puppet 和 Chef 本身就是编程语言。一旦您走上这条道路,您现在就维护着两个完全不同的软件:您的 Web 应用程序和运行它的基础设施自动化。此时,您需要进行递归调用,从头开始重新阅读本文,因为您需要在您的基础设施自动化上使用持续集成,就像您对您的 Web 应用程序所做的那样。因此,您的 Web 应用程序需要一个生产环境和测试环境,所有这些都运行在您的生产基础设施环境中;现在您需要一个测试基础设施环境,在将更新部署到生产环境之前在其中测试对您的基础设施代码的更新。如果您使用 Jenkins 来运行您的 CI 流程,并且 Jenkins 是作为您正在开发的基础设施的一部分部署的,那么...您的大脑刚刚遇到堆栈溢出并爆炸了。糟糕。
需要明确的是,这一切都是可以实现的,并且可能有一些简化的假设可以减少工作量。但是,如果您错误地认为您的服务器配置是可以构建一次就忘记的事情,那么您的网站最终会因此而受苦。
使所有版本易于访问。 当需要推送到生产环境时,您希望在您的版本控制系统中创建一个符号标签,说明您何时发布了什么。如果您频繁发布,您最终会得到很多标签,但这没关系;它们很便宜。您可能会在您创建的脚本中创建这些标签以自动化部署。
维护审计跟踪。 您的 VCS 为您的源代码提供了提交历史记录,但您需要的不仅仅是这些。当出现问题时,您应该能够轻松地指出参与其中的日期/时间/个人,并快速获得您需要的信息。谁在今天早些时候将版本推送到生产环境?谁向 Apache 虚拟主机配置添加了新的域名?您可以验证上周离职的员工的 SSH 密钥是否已删除吗?大多数更改将在您的网站源代码中,但有些将在您的基础设施配置代码中,因此您需要对更改进行统一查看。
自动化网站部署。 好的,所以您正在使用小批量和频繁提交进行工作,每次都在生产环境的克隆中进行测试。现在需要很容易地将您的新应用程序推送到实时环境。如果您已经按照描述自动化了您的基础设施,并且已经有一个系统可以用于将新的代码提交部署到您的测试环境,那么这应该是一个很小的额外步骤。它必须简单、快速且可靠;您希望能够推送一个版本,然后在五分钟后去吃午饭,而不用担心它。
衡量结果并快速迭代。 有许多很棒的监控和测量工具可用于检查诸如错误日志、页面加载性能、服务器性能、A/B 测试等内容。因为您已经自动化了您的基础设施配置,所以将这些工具集成到您的服务器上并不是那么多额外的工作,但您仍然必须决定使用哪些工具、如何最好地安装它们以及如何最有效地从中获取您需要的数据。
使用现有系统哇!好的,老实说。您的公司实际上有多大可能进行投资来构建和部署如上所述的自动化 CI 基础设施?我猜也是。事实是,基础设施不是您的专长。(如果是,我们可以聘请您吗?)您构建了出色的网站,您不应该花费那么多时间和精力也构建运行它的服务器。
您的替代方案是使用其他人为您构建的系统。有几个系统存在,每个系统都有不同的属性,并且随着时间的推移会有更多系统出现。我碰巧是 Acquia Cloud 的首席工程师,所以让我快速演示一下 Acquia Cloud 如何提供您为您的网站实施 CI 所需的一切。

图 1. 工作流页面是 Acquia Cloud 的 CI 系统的核心。
使用源代码存储库。 Acquia Cloud 同时提供 Git 和 SVN 存储库。URL 显示在顶部。
进行小而频繁的更改。 Acquia Cloud 为您的网站提供开发、暂存和生产环境。您可以将存储库中的任何分支或标签部署到其中任何一个环境中。当您在环境中部署分支时,对该分支的每次提交都会部署到该环境。这使得 Dev 环境非常适合初始集成测试。将其设置为部署“master”(Git)或“trunk”(SVN)分支,每个开发人员的提交都可以立即用于初始实验。
自动化测试。 每次您部署代码或执行各种其他操作时,Acquia Cloud 都会运行“Cloud Hooks”。这些是您放入代码存储库中的简单脚本,用于执行您想要的任何操作。每个钩子都与特定环境中的特定操作相关联——例如,当您将代码部署到生产环境时,存储库的 hooks/post-code-deploy/prod 目录中的所有脚本都会运行。钩子脚本按排序顺序运行,直到第一个脚本失败,并且所有钩子脚本的输出都可以在最后获得。这是运行您的测试脚本、清理数据库、执行负载测试或任何其他操作的完美方式。
在生产环境的克隆中进行测试。 这是 Acquia Cloud 最大的回报。我们为您维护这些环境中的每一个——Dev、Stage 和 Prod。您可以选择它们是在同一服务器上还是在不同的服务器上,以及它们是冗余的和负载均衡的还是在单个 VM 上运行,但我们确保就您的 Web 应用程序而言,配置是相同的。当然,我们还提供 24/7 监控、备份、安全更新和关键修复——所有这些都是您必须在自己的服务器上完成的事情。
使所有版本易于访问。 正如您在图 2 中看到的,您始终可以恢复到任何环境中任何特定的标记版本或分支。

图 2. 代码选择器允许您将任何分支或之前的发布版本部署到任何环境。
拥有审计跟踪(即,责任清单)。 我们的任务日志是您的审计跟踪。它显示代码提交,但也显示对您的 Web 环境的所有更改:域名、SSH 密钥、服务器启动等等。它向您显示每个操作发生的具体日期和时间,并可以选择显示命令的完整详细信息。

图 3. 任务日志显示对您的网站的任何环境的所有更改。

图 4. 每个任务都有详细信息。
自动化网站部署。 要将一个环境的版本部署到另一个环境,只需在 UI 上拖放(或使用我们的 API 或 Drush CLI 执行相同的操作)。如果您从部署分支的环境中拖动代码,它会在该分支的顶端创建一个符号标签,并将该标签部署到目标环境中。如果您拖动部署标签的环境,它只会将相同的标签部署到相同的环境中。您始终可以通过从下拉列表中选择任何分支或任何以前的标签(或者,再次,通过我们的 API 或 CLI)来部署到任何环境中的任何分支或任何以前的标签。

图 5. 部署代码是一个简单的拖放操作(API 和 CLI 也可用)。
衡量结果并快速迭代。 本文主要介绍了 Acquia Cloud,但 Acquia Cloud 本身只是 Acquia Network 的一项功能,Acquia Network 提供了各种各样的工具来改进您的网站,例如专家 Drupal 配置建议、SEO 优化、分面搜索、性能监控、负载测试和垃圾邮件阻止,以及教育、培训和支持等服务。Acquia Network 是每个 Cloud 订阅的一部分,并包含所有这些工具,其中大多数是免费的。

图 6. Acquia Network 提供资源来了解和改进您网站的结果。
要观看视频概述,展示如何使用 Acquia Cloud 为您的 Drupal 网站进行开发,我有一个关于此主题的网络研讨会,网址为 http://ow.ly/cUNlL。要注册完全免费版本的 Acquia Cloud,请访问 http://network.acquia.com/freecloud。