最佳实践:管理和部署应用程序和说明书 - AWS OpsWorks

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

最佳实践:管理和部署应用程序和说明书

重要

AWS OpsWorks Stacks不再接受新客户。在 2024 年 5 月 26 日之前,现有客户将能够照常使用 OpsWorks 控制台、API、CLI 和 CloudFormation 资源,届时这些工具或资源将停用。为准备此过渡,我们建议您尽快将堆栈过渡到AWS Systems Manager。有关更多信息,请参阅 AWS OpsWorks Stacks 生命周期终止常见问题解答将 AWS OpsWorks Stacks 应用程序迁移到 AWS Systems Manager Application Manager

AWS OpsWorks Stacks 将应用程序和说明书从远程存储库部署到各个新实例。在实例的生命周期内,您经常必须在堆栈的联机实例上更新应用程序和说明书,以添加功能、修复错误等。管理堆栈的应用程序和说明书的方法有很多种,但您使用的方法应满足以下一般要求:

  • 所有生产堆栈实例应具有相同的应用程序和自定义说明书代码,除非出于 A/B 测试目的等有限的例外情况。

  • 即使出现问题,部署更新也不应中断站点的操作。

本部分介绍管理和部署应用程序和自定义说明书的推荐做法。

维持一致性

一般来说,您需要对您的生产堆栈上运行的应用程序或说明书代码保持严密的控制。通常,所有实例都应运行当前已获批准的代码版本。如下文所述,在更新您的应用程序或说明书时会出现例外,在适应特殊情况 (例如,执行 A/B 测试) 时也会出现例外。

通过两种方式将应用程序和说明书代码从指定的源存储库部署到您的堆栈的实例:

  • 当您启动某个实例时,AWS OpsWorks Stacks 会自动将当前应用程序和说明书代码部署到该实例。

  • 对于联机实例,您必须通过运行部署命令 (对于应用程序) 或更新自定义说明书命令 (对于说明书) 来手动部署当前应用程序或说明书代码。

由于有两种部署机制,因此请务必仔细地管理您的源代码,以避免在不同实例上意外地运行不同的代码。例如,如果您从某个 Git 主分支部署应用程序或说明书,则 AWS OpsWorks Stacks 会部署当时在该分支中的内容。如果您更新主分支中的代码,然后启动一个新实例,则该实例的代码版本将比原来的实例更新。更新的版本可能甚至不会被批准用于生产。

建议:Amazon S3 存档

要确保您的所有实例均具有已批准的代码版本,我们建议您从 Amazon Simple Storage Service (Amazon S3) 存档部署您的应用程序和说明书。这可确保代码是必须是显式更新的静态构件 (.zip 或其他存档文件)。此外,Amazon S3 高度可靠,因此您无法访问存档的情况将极少 (如果有的话)。为了进一步确保一致性,请使用命名约定或使用 Amazon S3 版本控制(提供审计跟踪记录并提供一种简单的方式来转换为之前的版本)来对每个存档文件进行显式版本管理。

例如,您可以使用一个工具 (如 Jenkins) 创建部署管道。提交并测试您要部署的代码之后,创建一个存档文件并将其上传到 Amazon S3。所有应用程序部署或说明书更新都将安装该存档文件中的代码,且每个实例将具有相同的代码。

建议:Git 或 Subversion 存储库

如果您倾向于使用 Git 或 Subversion 存储库,请勿从主分支部署。应改为标记已批准的版本并将该版本指定为应用程序说明书源。

将代码部署到联机实例

AWS OpsWorks Stacks 不会自动将更新的代码部署到联机实例。您必须手动执行该操作,这会带来以下挑战:

  • 高效地部署更新,而不影响站点在部署过程中处理客户请求的能力。

  • 处理不成功的部署,不论是因为部署的应用程序或说明书的问题还是因为部署过程本身的问题。

最简单的方法是运行默认部署命令 (针对应用程序) 或者运行用于将更新同时部署到每个实例的更新自定义说明书命令 (对于说明书)。此方法简单快捷,但不允许犯错误。如果部署失败或更新的代码有任何问题,则您的生产堆栈中的每个实例都将受到影响,可能会中断或禁用您的站点,直到您解决问题或回滚到之前的版本。

建议:使用一个健壮的部署策略,允许运行旧版本代码的实例继续处理请求,直到您确认部署已成功并且可以放心地将所有传入流量转移到新版本。

以下部分提供了两个健壮的部署策略的示例,然后讨论了如何在部署期间管理后端数据库。为简洁起见,它们只介绍了应用程序更新,但您可以对说明书使用类似的策略。

使用滚动部署

滚动部署将分多个阶段在堆栈的联机应用程序服务器实例上更新应用程序。在每个阶段中,您将更新联机实例的一个子集,并在开始下一个阶段之前确认更新已成功。如果您遇到问题,仍在运行旧的应用程序版本的实例可以继续处理传入流量,直到您解决该问题。

以下示例假设,您正在使用建议做法跨多个可用区分配堆栈的应用程序服务器实例。

执行滚动部署
  1. “Deploy App”页面上,选择 Advanced,选择单个应用程序服务器实例,并将应用程序部署到该实例。

    如果您想要保持谨慎,可以从负载均衡器中删除该实例,然后再部署应用程序。这可以确保在您确认应用程序正常运行之前,用户不会遇到更新的应用程序。如果您使用 Elastic Load Balancing,请使用 Elastic Load Balancing 控制台、CLI 或 SDK 从负载均衡器中删除实例

  2. 确认已更新的应用程序运行正常,且实例具有可接受的性能指标。

    如果您从 Elastic Load Balancing 负载均衡器移除了该实例,请使用 Elastic Load Balancing 控制台、CLI 或 SDK 来还原它。更新后的应用程序版本现在正在处理用户请求。

  3. 将更新部署至可用区中剩余的实例,并验证它们是否正常运行,以及是否具有可接受的指标。

  4. 对堆栈的其他可用区重复第 3 步,一个可用区重复一次。如果您需要特别小心,请重复步骤 1~3。

注意

如果您使用 Elastic Load Balancing 负载均衡器,则可以使用其运行状况检查来验证部署是否成功。但是,将 ping 路径部署为一个用于检查依赖项并确认一切正常的应用程序,而不是一个只是用于确认应用程序服务器正在运行的静态文件。

使用单独的堆栈

管理应用程序的另一种方法是对应用程序生命周期的每个阶段使用单独的堆栈。不同的堆栈有时称为环境。这种安排使您能够对不可公开访问的堆栈进行开发和测试。当您准备好部署更新时,将用户流量从托管当前应用程序版本的堆栈切换到托管更新后的版本的堆栈。

使用开发、暂存和生产堆栈

最常见的方法使用以下堆栈。

开发堆栈

将开发堆栈用于实现新功能或修复错误等任务。开发堆栈实质上是一个原型生产堆栈,具有与生产堆栈上相同的层、应用程序和资源等。由于开发堆栈通常不必处理与生产堆栈相同的负载,因此您通常可以使用更少或更小的实例。

开发堆栈不是面向公众的;您可按如下方式控制访问权限:

  • 通过配置应用程序服务器或负载均衡器的安全组入站规则来限制网络访问权限,以便仅接受来自指定的 IP 地址或地址范围的传入请求。

    例如,限制 HTTP、HTTPS 和 SSH 访问您的公司地址范围内的地址。

  • 使用堆栈的AWS OpsWorks权限页面控制对 Stacks 堆栈管理功能的访问。

    例如,向开发团队授予管理权限级别,并向所有其他员工授予显示权限级别。

暂存堆栈

使用暂存堆栈测试并最终确定更新后的生产堆栈的候选项。完成开发后,可通过克隆开发堆栈来创建一个暂存堆栈。然后,在该暂存堆栈上运行您的测试套件并将更新部署到该堆栈,以修复出现的问题。

暂存堆栈也不是面向公众的;您可以使用与开发堆栈相同的方式控制堆栈和网络访问权限。请注意,当您克隆开发堆栈以创建暂存堆栈时,您可以克隆 AWS OpsWorks Stacks 权限管理授予的权限。但是,克隆不会影响用户的 IAM 策略所授予的权限。您必须使用 IAM 控制台、CLI 或开发工具包来修改这些权限。有关更多信息,请参阅管理用户权限

生产堆栈

生产堆栈是面向公众的堆栈,可支持您当前的应用程序。在暂存堆栈通过测试后,您可以将其提升到生产环境并停用旧的生产堆栈。有关如何执行此操作的示例,请参阅 使用蓝-绿部署策略

注意

您可以为每个堆栈创建一个 AWS CloudFormation 模板,而不必使用 AWS OpsWorks Stacks 控制台手动创建堆栈。这种方法有以下优势:

  • 速度和便利性:当您启动模板时,AWS CloudFormation 会自动创建堆栈,包括所有必需的实例。

  • 一致性:将每个堆栈的模板存储在您的源存储库内,以确保开发人员出于相同目的使用相同堆栈。

使用蓝-绿部署策略

蓝-绿 部署策略是高效利用不同的堆栈将应用程序更新部署到生产的一种常见方式。

  • 蓝色环境是生产堆栈,用于托管当前的应用程序。

  • 绿色环境是暂存堆栈,用于托管更新后的应用程序。

在您准备好将更新的应用程序部署到生产之后,便可以将用户流量从蓝色堆栈切换到绿色堆栈,后者将成为新的生产堆栈。然后,您可以停用原来的蓝色堆栈。

下面的示例介绍了如何结合 Route 53Elastic Load Balancing 负载均衡器池,使用 AWS OpsWorks Stacks 堆栈执行蓝绿部署。进行切换之前,您应确保以下内容:

  • 绿色堆栈上的应用程序更新通过了测试且可用于生产。

  • 绿色堆栈与蓝色堆栈相同,只是它包含更新后的应用程序且不面向公众。

    这两个堆栈的权限相同、每层中的实例的数量和类型相同、基于时间和基于负载的配置相同,等等。

  • 绿色堆栈的所有全天候实例和基于计划时间的实例均处于联机状态。

  • 您有一个 Elastic Load Balancing 负载均衡器池,您可将它动态地挂载到任一堆栈中的层,也可以对它进行预热以处理预期的流量。

  • 您已使用 Route 53 加权路由功能来在包括您的合并负载均衡器的托管区域中创建一个记录集。

  • 您已将一个非零加权分配给挂载到您的蓝色堆栈的应用程序服务器层的负载均衡器,并将零加权分配到未使用的负载均衡器。这可以确保蓝色堆栈的负载均衡器处理所有传入的流量。

将用户切换到绿色堆栈
  1. 将一个池的未使用的负载均衡器挂载到绿色堆栈的应用程序服务器层。在某些情况下,例如当您预计有闪现的流量时,或者如果您不能将负载测试配置为逐步增加流量,请对负载均衡器进行预热以处理预期的流量。

  2. 在绿色堆栈的所有实例均通过 Elastic Load Balancing 运行状况检查后,更改 Route 53 记录集中的权重,以便绿色堆栈的负载均衡器具有非零权重,而蓝色堆栈的负载均衡器的权重相应减少。我们建议您开始时让绿色堆栈处理小部分请求,例如 5%,让蓝色堆栈处理剩余请求。现在您有两个生产堆栈,其中绿色堆栈处理部分传入请求,蓝色堆栈处理剩余请求。

  3. 监控绿色堆栈的性能指标。如果它们是可接受的,则增加绿色堆栈的权重,让它处理约 10% 的传入流量。

  4. 重复步骤 3,直至绿色堆栈处理约一半的传入流量。此时任何问题都应该已经浮现,因此,如果绿色堆栈的性能表现可接受,则可以通过将蓝色堆栈的权重减少到零来完成此过程。现在,绿色堆栈成为了新的蓝色堆栈,处理所有传入流量。

  5. 从原来的蓝色堆栈的应用程序服务器层分离负载均衡器并将其退回到池。

  6. 尽管原来的蓝色堆栈不再处理用户请求,我们仍然建议将其保留一段时间,以防新的蓝色堆栈出现问题。在这种情况下,您可以通过反向执行上述过程,将传入流量直接引导回原来的蓝色堆栈,从而回滚更新。当您确信新的蓝色堆栈的工作情况可接受之后,关闭原来的蓝色堆栈

管理后端数据库

如果您的应用程序依赖于后端数据库,则您将需要从旧的应用程序过渡到新的应用程序。AWS OpsWorksStacks 支持以下数据库选项。

Amazon RDS 层

借助 Amazon Relational Database Service (Amazon RDS) 层,您可以单独创建 RDS 数据库实例,然后将它注册到您的堆栈。您一次仅可以将 RDS 数据库实例注册到一个堆栈,但您可以将 RDS 数据库实例从一个堆栈切换到另一个堆栈。

AWS OpsWorks Stacks 以您的应用程序可以轻松使用的格式在您的应用程序服务器上安装一个包含连接数据的文件。AWS OpsWorksStacks 还会将数据库连接信息添加到可由配方访问的堆栈配置和部署属性。您也可以使用 JSON 向应用程序提供连接数据。有关更多信息,请参阅连接到数据库

更新依赖于数据库的应用程序带来了两个基本挑战:

  • 在过渡期间要确保每个事务都得到正确记录,同时避免新旧应用程序版本之间出现竞用情况。

  • 以限制对站点的性能影响且最大程度减少或消除停机时间的方式执行过渡。

当您使用本主题中所述的部署策略时,您不能只是将数据库从旧的应用程序分离并将它重新连接到新的应用程序。在过渡期间,两个版本的应用程序并行运行,且必须有权访问相同数据。下面介绍了管理过渡的两种方法,这两种方法各有优势和挑战。

方法 1:将这两个应用程序连接到同一数据库
优点
  • 过渡期间没有停机时间。

    一个应用程序逐步停止访问数据库,而另一个应用程序逐步接管。

  • 您不必在两个数据库之间同步数据。

挑战
  • 两个应用程序均访问相同数据库,因此您必须管理访问权限,以防止数据丢失或损坏。

  • 如果您需要迁移到新的数据库架构,旧的应用程序版本必须能够使用新的架构。

如果您使用单独的堆栈,这种方法可能最适合 Amazon RDS,因为实例没有与特定堆栈永久关联,并且可以通过在不同堆栈上运行的应用程序进行访问。但是,您不能将 RDS 数据库实例一次注册到多个堆栈,因此您必须为两个应用程序提供连接数据,例如,使用 JSON。有关更多信息,请参阅使用自定义配方

如果您使用滚动升级,则旧的和新的应用程序版本均在相同堆栈上托管,因此您既可以使用 Amazon RDS 层,也可以使用 MySQL 层。

方法 2:为每个应用程序版本提供各自的数据库
优点
  • 每个版本均有各自的数据库,因此架构不必兼容。

挑战
  • 过渡期间在两个数据库之间同步数据,而不会丢失或损坏数据。

  • 确保您的同步过程不会导致严重停机或显著地降低站点的性能。

如果您使用不同的堆栈,则每个堆栈均有各自的数据库。如果您使用滚动部署,则可以将两个数据库挂载到堆栈,每个数据库针对一个应用程序。如果旧的和更新的应用程序的数据库架构不兼容,则此方法更好。

建议:一般来说,我们建议使用 Amazon RDS 层作为应用程序的后端数据库,因为它更灵活,并且可用于任何过渡场景。有关如何处理过渡的更多信息,请参阅《Amazon RDS 用户指南》。