第 2 章:在生产环境中运行云原生应用程序

本章系统分析了云原生应用在生产环境运行面临的挑战,阐述持续交付、自动化运维和最终一致性等关键实践,帮助开发者和运维团队实现高效、稳定的生产部署。

本章要点

  • 认识到为什么开发人员应该关心运维
  • 了解影响成功部署的障碍
  • 消除这些障碍
  • 实现持续交付
  • 云原生架构模式对运维的影响

作为开发人员,你最想做的事情就是创造用户喜欢、能为他们提供价值的软件。当用户需要新功能或你有新想法时,你希望能轻松构建并交付它,同时保证软件在生产环境中始终可用和响应。

然而,现实中将软件部署到生产环境充满挑战。许多流程本意是降低风险、提高效率,结果却适得其反,变得缓慢且繁琐。部署后的运维也同样困难,系统不稳定让支持人员长期处于“救火”状态。

即使代码优秀、功能完备,依然很难做到:

  • 顺利部署软件
  • 保持软件稳定运行

很多开发者认为这些是运维的责任,但生产环境的脆弱并非某个团队或个人的错,而是普遍存在的组织行为和运维实践导致的。团队分工、沟通方式、软件架构等都在影响着行业的健康。

解决方案是:设计新的系统,将开发实践和架构模式与生产运维紧密结合。

面临的困难

生产环境运维是一项艰巨且常常吃力不讨好的工作。发布或故障时,运维人员常常需要加班。开发团队与运维团队之间的冲突频发,互相指责对方影响了产品体验。

实际上,这些挑战源于一系列阻碍成功的行为方式。几乎所有组织都存在以下常见问题,如下图所示:

  • 碎片化的变化:开发生命周期中的不断变化影响初次部署和后续稳定性,导致环境与构件不一致。
  • 有风险的部署:复杂环境和紧耦合组件使部署充满风险,降低发布频率。
  • 认为变化是个例外:传统认为底层系统稳定,实际高度分布式环境变化频繁。
  • 生产环境不稳定:不稳定环境进一步增加部署难度,限制发布频率。

下图展示了这些问题的结构化总结。

图 2.1 导致软件难以部署和无法在生产环境中保持良好运行的原因
图 2.1 导致软件难以部署和无法在生产环境中保持良好运行的原因

碎片化的变化

“在我的机器上是好的”是运维团队常听到的说法。许多企业从软件准备发布到用户可用,往往有长达数周的延期。主要原因是开发生命周期中的环境和构件变化。

  • 环境变化:如依赖包版本不一致,开发环境和生产环境更新频率不同。
  • 构件变化:如属性文件配置被编译进可部署构件,导致不同环境需不同构件。

这些变化不仅影响首次部署,也加剧运维不稳定。例如,UAT 测试通过但生产环境因文件描述符限制导致故障,根源在于环境差异。

此外,环境配置如服务器名称、URL 或 IP 变化,若硬编码在构件中,需重新打包和部署,增加风险。

有风险的部署

许多公司选择在“休息时间”发布软件,原因是部署充满危险。停机代价高昂,客户流失直接影响收入。

为降低风险,组织制定了复杂流程和测试环境,但这些措施增加了部署负担。搭建与生产一致的测试环境成本高,协调多团队测试也极为复杂。

下图展示了依次测试两个应用程序的流程。

图 2.2 在所有测试通过的情况下,依次测试两个应用程序是很简单的。
图 2.2 在所有测试通过的情况下,依次测试两个应用程序是很简单的。

如果测试失败,环境恢复和协调变得更复杂。实际发布往往因风险而推迟,导致已知 bug 长期存在,甚至需要定期重启应用应急。

低频发布导致每次部署包含更多变更,风险更高。

图 2.3 一个失败的测试,会立刻增加在预发布环境中进行测试的复杂性。
图 2.3 一个失败的测试,会立刻增加在预发布环境中进行测试的复杂性。

认为变化是个例外

许多 IT 组织长期认为变化是例外,导致团队长期处于“救火”模式。新产品部署后,开发团队退出运维,知识只留给运维手册,假设所有失败场景已知,实际远非如此。

变化才是唯一不变的,尤其在云环境下,系统持续经历不稳定。

生产环境的不稳定性

所有上述因素都阻碍了软件的稳定运行。不稳定环境进一步增加部署难度,形成恶性循环。IT 团队长期救火,部署时机极少,影响整体效率。

综上,编写软件只是客户体验的开始。碎片化变化、有风险部署、错误的变化观念,使生产运维极为困难。要优化运维,需借鉴云计算公司的实践,形成贯穿开发到运维的优化系统。

解决的办法

新一代互联网公司(如 Google)已找到更优方法。下图展示了理想系统的结构:

  • 易于频繁发布
  • 运维稳定、可预测

与前述问题相反:

  • 可重复性提升发布速度和稳定性
  • 安全部署提升敏捷性和稳定性
  • 预期环境变化减少救火时间

持续交付(Continuous Delivery, CD)成为核心驱动力,显著简化部署并带来诸多好处。

图 2.4 对这四个因素的明确关注形成了一个有效的、可预测的和稳定的系统。
图 2.4 对这四个因素的明确关注形成了一个有效的、可预测的和稳定的系统。

持续交付

持续交付并非每次代码变更都部署到生产,而是让新版本随时可部署。每次功能开发后,自动化测试和打包,确保软件随时可交付。

下图展示了持续交付的迭代周期。

图 2.5 每个开发 / 测试周期都不会进行一次部署,相反,每个周期都会生成一个可以交付的软件。随后,是否部署就是一个业务上的决定了。
图 2.5 每个开发 / 测试周期都不会进行一次部署,相反,每个周期都会生成一个可以交付的软件。随后,是否部署就是一个业务上的决定了。

与传统流程相比,持续交付让业务部门而非 IT 决定何时发布,提升市场响应速度。

图 2.6 传统的软件交付生命周期,在创建可以发布到生产环境中的构件之前,会提前进行大量的开发工作和一个长时间的测试周期。
图 2.6 传统的软件交付生命周期,在创建可以发布到生产环境中的构件之前,会提前进行大量的开发工作和一个长时间的测试周期。

持续交付带来灵活选择,能根据反馈快速调整,降低风险。

图 2.7 持续交付允许业务部门(而不是由 IT 部门)来决定何时交付软件。
图 2.7 持续交付允许业务部门(而不是由 IT 部门)来决定何时交付软件。

开发延迟时,持续交付让企业可选择按计划发布功能有限版本,或稍作延期,提升灵活性。

图 2.8 当开发进度延期后,你必须在两个都不让人满意的选择中决定一个。
图 2.8 当开发进度延期后,你必须在两个都不让人满意的选择中决定一个。

可重复性

可重复性是系统部署和运维稳定的关键。通过标准化环境、单一可部署构件和自动化流程,实现部署过程的可预测性。

  • 控制环境:使用标准化机器镜像和基础设施即代码,确保每次环境一致。
  • 控制可部署构件:属性文件不包含环境值,参数在部署时注入,实现构件一致。
  • 控制流程:自动化组合标准镜像、受控配置和单一构件,贯穿开发到生产。

下图展示了标准化环境和构件的一致性。

图 2.11 我们期望的结果,是能够让运行在标准化环境中的应用程序保持一致。注意,应用程序在所有环境中都是相同的,运行时环境在生命周期的各个阶段中都是标准的。
图 2.11 我们期望的结果,是能够让运行在标准化环境中的应用程序保持一致。注意,应用程序在所有环境中都是相同的,运行时环境在生命周期的各个阶段中都是标准的。

自动化是实现一致性的唯一途径。

图 2.12 自动化组合标准的基础镜像、受控的环境配置和单一可部署构件。
图 2.12 自动化组合标准的基础镜像、受控的环境配置和单一可部署构件。

安全部署

云时代公司在生产环境中安全试验。安全网由运维实践和软件设计模式构成,配合测试驱动开发,降低失败影响。

安全部署核心实践:

  • 并行部署和版本化服务:新旧版本并行,流量逐步切换,遇故障可回退。
  • 远程监控:收集运行数据,分析新版本效果。
  • 灵活路由:按需分流,支持地理位置、用户类型等多维度路由。

下图展示了并行部署的核心流程。

图 2.13 数据会告诉你如何并行部署应用程序的多个版本。你可以通过数据对访问应用程序的流量进行控制,从而可以在生产环境中安全地部署新的软件。
图 2.13 数据会告诉你如何并行部署应用程序的多个版本。你可以通过数据对访问应用程序的流量进行控制,从而可以在生产环境中安全地部署新的软件。

A/B 测试实现要点:

  • 构件版本可见,便于流量切分和数据分析
  • 指标与版本关联,便于对比
  • 路由算法灵活,支持多种业务场景
  • 组件化部署,降低风险

变化是一定的

现代系统需拥抱变化,采用最终一致性模型。系统不断比较期望状态与实际状态,自动修复偏差,实现自愈。

  • 期望状态:系统设计目标,如服务器数量、服务分布
  • 实际状态:当前运行状态,随时监控和调整

下图展示了期望状态与实际状态的对比。

图 2.14 所部署软件的期望状态
图 2.14 所部署软件的期望状态

当实际状态与期望状态不符时,系统自动修复。

实际状态与期望状态不符时的修复
实际状态与期望状态不符时的修复

最终一致性是云环境下系统弹性和稳定性的基础。

总结

  • 代码实现价值需轻松、频繁部署,并保持生产环境稳定运行。
  • 系统失败源于定制化难维护方案、环境风险和错误的变化观念。
  • 部署风险导致频率降低,反而加剧风险。
  • 关注可重复性、确保安全部署、拥抱变化,创建支持部署的系统。
  • 自动化是优化运维的核心,贯穿构建、环境和部署流程。
  • 云环境下,设计模式和运维实践持续变化。
  • 新系统依赖持续交付和高度迭代的软件开发生命周期。
  • 细粒度系统和微服务架构提升敏捷性和弹性。
  • 最终一致性是变化环境下系统可靠性的基础。

文章导航

独立页面

这是书籍中的独立页面。

书籍首页

评论区