写点什么

大规模零停机关键云基础设施升级

作者:Kiran Bhat

  • 2025-08-19
    北京
  • 本文字数:5121 字

    阅读完需:约 17 分钟

大小:2.53M时长:14:42
大规模零停机关键云基础设施升级

工程师们可以通过研究其他进行基础设施升级和迁移人员的经验来避免常见错误并减少意外的复杂情况。基础设施升级和迁移包括数据库版本更新、平台现代化、SDK 升级、数据中心迁移以及组件更换。所有这些对于在不断发展的技术环境中保持安全性、性能和合规性都至关重要。

 

引言

如今,不再只有专业的数据库管理员或发布工程师才能对基础设施进行修改。每个工程师在其职业生涯中都得应对更新和迁移的问题。我个人曾参与过这些公司无数次的升级工作,从 SDK 更新、Kafka 版本升级到大型数据中心迁移,再到从单体架构向微服务架构的转变。每次迁移都让我明白,大多数升级都能进行得很顺利,但那些不顺利的升级会给整个公司带来混乱。

 

当你要更新那些多年未曾改动过的代码,而最初的工程师也已离职时,情况会变得更加棘手。这些老旧系统成了令人恐惧的未知数。如果没有合适的测试框架,风险会呈指数级上升。一旦出现问题,看似简单的改造就会变成持续数个季度的噩梦。

 

现代分布式系统的工作规模前所未见,每天在从不停歇的基础设施上处理数十亿的任务。在易贝(eBay),我曾协助管理承载着网站 90%图片的平台;在 Snowflake,我们的团队每天要在超过 50 个地区准备数十万的虚拟机。事实很明确:这些系统需要不断变化,才能保持安全、快速和合规。风险之高不言而喻:停机时间会耗费数百万美元,并损害用户信任。

 

人们总是低估升级和迁移的难度。当一切顺利时,人们会说“这不过是一次升级”。但是当错误通过链接的系统传播时,它们就会演变成影响职业生涯和季度业绩的灾难。

 

这篇文章总结了从 eBay 和 Snowflake 等大型公司那里吸取到了艰难的教训,并将其简化。它不提供理论框架,而是为你提供真实的案例、实用的注意事项和经过验证的方法,帮助你对下一个基础设施项目充满信心。在当今的工程领域,问题不在于你是否需要一次重大升级,而在于何时需要。



大规模升级中的常见挑战及经验验证的解决方案

挑战 1:存在未知依赖关系的遗留系统

工程师们认为,对那些多年未受关注的系统进行代码升级是最具挑战性的任务。原开发人员已离职,文档要么稀少要么过时,系统成了一个“能用就行”的黑箱,直到需要对其进行修改。工程团队会推迟这些升级工作,因为尽管任务看似极其复杂,但实际情况会随着每一天的过去而变得更糟。升级过程拖延得越久,与现代标准的差距就越大,升级的风险也就越高。

 

解决遗留系统升级问题需要循序渐进的规划,而不是冲动行动。任何“快速的 SDK 升级”都可能引发多年累积的技术债以及暴露隐藏依赖关系。

 

解决方案:系统性发现与准备

在编写代码之前,第一步应当是全面了解系统组件。这个项目需要扎实的基础工作,因为这是基本的风险防范措施。

 

首先提出四个关键问题:

 

我们有足够的测试覆盖率吗?

遗留系统通常几乎没有或根本没有自动化测试。在开始升级流程之前,你的系统需要具备测试能力,因为它必须在系统出现故障时向你发出报警。初期工作应侧重于创建涵盖当前功能的测试基础设施,然后再开始升级流程。

 

监控和报警系统是否已就位?

系统健康监控应该在升级过程期间和之后持续运行。

 

你能检测到性能下降、错误率激增或功能故障吗?

当监控系统缺失时,你必须在开始流程之前创建基准指标。

 

团队是否具备调试专业知识?

工程师需要具备足够的系统知识才能进行诊断调查。在开始项目之前,你应该将知识传授给团队成员或创建文档,因为随着之前团队成员的流失,领域专业知识也已消失。

 

准备阶段似乎推迟了升级流程,但实际上它通过避免因未准备好的遗留系统修改而导致的长时间紧急处理期,从而加快了项目进度。

 

挑战 2:在高容量系统升级期间保持性能

 在大型分布式系统中,性能至关重要,因为哪怕是很小的性能下降也会对用户造成重大影响,并导致收入损失。每秒处理数百万次操作或每天处理数十亿次请求的系统升级,必须提升性能,而不能造成性能下降。性能倒退是基础设施变更带来的最危险也是最常见的负面影响之一。

 

开发测试在实验室条件下能够成功,但在面对真实世界的流量模式、用户并发和分布式系统的时序依赖时却会失败。

 

解决方案:全面的性能验证

实施严格的性能和压力测试。当你的系统处理关键流量时,性能测试是强制性的要求。每次升级的第一步都需要在执行详细的压力测试的同时收集基准性能数据,这些测试应模拟实际工作负载场景。测试过程应包括典型的正常路径执行、边缘情况以及高峰流量条件和故障场景,以检测性能瓶颈。

 

此时你应当建立一个强大的性能测试框架,因为你的团队目前还没有。在此期间所做的投入将在所有即将到来的系统升级过程中带来收益。你的安全网将是一个可靠的性能测试套件,让你在前进时充满信心,同时为成功提供客观验证。

 

系统需要经历渐进部署阶段。无论升级看起来多么微小,都必须分阶段实施,而不能一次性部署到整个系统。

 

常见的渐进部署方法包括金丝雀部署(将一小部分流量路由到新版本)、蓝绿部署(维护并行环境以实现即时切换)和滚动更新(逐步替换实例)。

 

渐进部署的顺序从质量保证环境开始,接着是预生产环境,然后是受控的生产测试,最后才全面部署。每个环境都会让你了解到升级在不同条件下的表现情况。这个过程包含内置检查点,如果出现任何问题,你可以暂停部署。遵循从 1%开始部署,然后逐步推进到 10%,再继续到 50%,最后达到 100%的流程,能在问题波及全部用户之前提供多次发现它们的机会。

 

在整个过渡期间,系统需要持续的性能监控。整个升级过程需要完整的监控系统,以追踪关键图表、图形和仪表板数据。团队成员在关键阶段需要实时关注关键指标,而不能只是设置报警然后离开。自动化报警可能无法检测到初期的性能下降,而人类观察者则能通过细微的趋势提前发现这些问题。

 

挑战 3:回滚策略——在进入之前了解你的退出选项

团队使用回滚策略作为一种保护机制,在部署失败时将系统恢复到已记录的安全版本。大多数组织及其团队都会维护某种形式的版本恢复机制,包括点击按钮实现自动系统恢复,或者需要在多个组件间协调步骤。许多团队通过痛苦的经历认识到,不是每一次修改都是可逆的。

 

认为回滚总是可行的错误观念会让人对系统的安全性产生危险的错觉。回滚过程对于无状态的应用程序部署和配置更改很有效,但在升级包含数据转换、安全更改或持久状态修改时,回滚会变得复杂甚至不可能。

 

解决方案:了解你的回滚现实

每个组织都应制定正式的回滚程序。所有迁移和升级操作都必须有明确的回滚方案,无论其未来的使用计划如何。否则,这样的系统就相当于一个单向入口系统,没有退出计划,这会让你面临风险。回滚程序需要有恰当的文档记录和验证,有时还应接受独立测试。

 

我所合作过的最先进的一些工程组织将回滚测试作为其升级程序中不可或缺的一部分。在这一阶段进行测试能够显示出实际的回滚时长以及在压力情况下出现的特定困难。在生产事故中发现原本预计五分钟的回滚时间延长到了两小时,其价值是巨大的。

 

永久性修改的识别应在初始阶段进行。某些升级构成了无法逆转的绝对障碍。从未加密数据升级到加密数据的过程变得棘手,因为回退到未加密数据会带来安全风险。数据库模式变更、卷加密、安全策略更新以及数据格式转换都属于此类永久性修改。

 

升级计划应包含所有已记录为风险的回滚限制和约束条件,这些限制在回滚可能性受限时会被提及。所有具有回滚限制的变更都需要额外的预防措施以及小规模的首次部署。验证过程需要对最小流量部署或小范围部署进行广泛检查,然后逐步扩大受控范围。由于变更的不可更改性,首次部署时必须完美执行,因为无法回滚。

 

通过这种方法,你可以在潜在灾难演变成严重问题之前将其转化为可管理的风险,促使你在问题出现之前就解决回滚限制。即使对于不可逆的变更,若能掌握诸如数据恢复策略、并行系统维护或分阶段迁移方法之类的应急计划,也能减轻故障带来的影响。虽然这些并非真正的回滚手段,但在出现问题时确实能提供替代路径。

 

挑战 4:范围蔓延——当“改进”使升级脱轨

工程师们常犯的一个错误——无论是初级工程师还是高级工程师都会犯——就是在进行迁移和升级时想要改进一些东西。乍一看这似乎合情合理:“既然我们已经在处理这段代码了,为什么不顺便解决那个性能问题呢?”或者“在迁移这个系统的时候,我们顺便把 API 现代化一下吧”。这种想法听起来挺有道理,但其实是个陷阱,它会把原本简单的升级变成令人头疼的调试噩梦。

 

当事情没有按计划进行时,问题就显现出来了。如果升级过程中出现了问题,就很难将改进相关的问题和迁移相关的问题区分开来。原本清晰的回滚决定会变成复杂的调查取证:性能下降是迁移本身造成的,还是我们添加的“改进”导致的?错误是来自系统升级,还是我们偷偷加的新功能?

 

现实世界的教训

我曾参与过一次系统迁移,其中包含了内存相关的改动。在同一个迁移窗口期间,团队决定实施一些性能优化。当时觉得同时处理这两件事挺高效。迁移完成后出现问题时,我们面临着极其艰难的调试挑战。系统表现异常,但我们无法确定这些问题是由迁移过程引起的,还是我们预期的性能改进导致的。

 

这种不确定性使决策陷入僵局。我们是应该回滚整个变更,从而可能失去性能提升?还是应该尝试隔离并仅回滚改进的部分?由于我们同时引入了多个变量,复杂性呈指数级增长。

 

解决方案:先原样迁移,再进行改进

在升级或迁移过程中,切勿添加任何额外的改进——哪怕只是一行日志。这种严格要求可能看起来有些过分,但对于在故障排查期间保持清晰思路至关重要。先将系统原封不动地迁移过去,然后在后续的单独部署中再进行改进。

 

这种方法提供了清晰的关注点分离。如果在迁移过程中出现问题,就知道是迁移相关的;如果在改进阶段出现问题,就知道是改进相关的。这种清晰性加快了调试速度,也让回滚决策变得简单明了。

 

改进仍会进行,但会具备恰当的隔离性和可测试性。当你在生产事故中无需费力理清多项变更时,未来的你会感谢现在的你。

 

成功升级的战略框架

成功的大规模变更并不会凭空发生,而是经过精心规划并以严谨的方式实施的。以下框架基于多年从事基础设施项目的经验,并提供了一种结构化的方法来规划和执行升级,从而降低风险并增强信任。无论你是更新数据库、迁移服务还是使平台更现代化,都可以使用这些建议。这些步骤是成功升级策略的基础。

 

制定全面的测试/部署计划,以识别所有差距并涵盖所有测试类型(压力测试、代理测试、回归测试、集成测试等)

 

  • 投资于测试框架基础。根据升级的风险和频率,确保强大的测试框架让你充满信心。

  • 尽早与利益相关者进行沟通协调,让可观测性团队、经理、项目经理(PM)以及多级领导参与其中,并在整个项目过程中随时向他们通报情况

  • 清晰地记录风险和计划,列出所有风险,并制定详细的测试计划、上线计划和回滚测试策略

  • 制定一个分阶段部署计划,以确定缓慢的推出策略,其中包含明确的日期并团队时间线对齐

  • 制定并测试回滚计划,在产品上线前进行回滚测试,以增强对退出策略的信心

  • 制定明确的成功/失败标准,并设定可衡量的指标,以确定何时继续进行,何时回滚

  • 预留充足的缓冲时间,始终在初始估算的基础上为意外问题增加百分之二十到三十(具体比例视风险而定)的时间

  • 定义升级后的监控期,确定在宣布成功之前需要监控多长时间

 

结论

成功实施零停机大规模升级需要的不仅仅是技术技能,还需要系统性的准备和清晰的沟通,以及对潜在问题基于经验的理解。

 

在本文中,我们学习了以下与升级相关的要点:

 

  • 提前投入时间来发现遗留系统的未知依赖关系,因为在修改多年未更新的代码之前,你需要了解测试覆盖范围以及监控和调试功能。

  • 性能验证是绝对必要的,因为组织需要实施全面的测试框架和渐进部署策略,以确保系统升级能提升性能,而不是导致性能下降。

  • 回滚策略需要规划,因为你必须提前了解你的退出选项,并明确哪些更改是不可逆的,以便制定合适的计划。

  • 必须坚决抵制范围蔓延,因为将改进与升级混杂在一起,会在问题出现时使故障排除的难度呈指数级增加。

 

战略准备优于快速执行,因为它包括全面的规划、利益相关者的协调以及测试框架,这些可以避免在无准备升级期间出现长达数周的疲于应付的情况。

 

各种升级和迁移策略之所以独立存在,是因为没有一种方法能适用于所有情况。我所描述的策略源于我在大型公司长达十年的工作经验,这些公司运营的系统每天处理数十亿次操作。

 

每个升级和迁移项目带给我们的核心启示是,你将从中汲取新知识。请欣然接受这一学习过程,因为从每个项目中获得的知识都将为应对未来的挑战奠定重要基础。

 

本文提供了实用的建议和具体的指导方针,以支持平滑的升级流程。本文中概述的经过实战检验的方法将帮助你在处理意外情况的同时,保持系统和用户的稳定性。

 

原文链接:

https://www.infoq.com/articles/zero-downtime-cloud-upgrades/

2025-08-19 10:323912

评论

发布
暂无评论

云原生 go-zero 微服务框架

万俊峰Kevin

微服务 microservice go-zero Go 语言

商业通识 : 商业到底是什么?

Walker

学习 得到 个人成长 商业

首个数字银行卡明年发行,广州出台区块链措施支持大湾区

CECBC

区块链 金融科技 社会

职场求生攻略答疑篇之 3 —— 数据是土地

臧萌

数据 职场成长

Google鼓励的13条代码审查标准 [建议收藏]

简爱W

【MySQL】我这样分析MySQL中的事务,面试官对我刮目相看!!

冰河

MySQL 面试 事务 隔离级别 冰河

为什么Java二维数组不用指定列的长度

Rayjun

Java 数组

Python 为什么要在 18 年前引入布尔类型?且与 C、C++ 和 Java 都不同?

Python猫

Python 编程

拥抱K8S系列-04-基于docker部署更多应用

张无忌

Docker 标准化 vsftpd

持续集成有什么好处?快来看鸭

清菡软件测试

jenkins

[翻译]Defer,Panic,and Recover

卓丁

defer panic recover Go 语言

oeasy教您玩转linux010206toilet

o

java安全编码指南之:声明和初始化

程序那些事

安全编码 java安全编码 编码指南 对象初始化

2020-09-03-第十三周作业

路易斯李李李

JavaScript 深拷贝与浅拷贝

梁凤波

妈妈,今天您几点下班?

脑极体

Flink从保存点启动应用-18

小知识点

scala 大数据 flink

2020-09-03-第十三周学习总结

路易斯李李李

Python 函数为什么会默认返回 None?

Python猫

Python 编程

区块链技术应用于链接智慧医疗

CECBC

区块链 社会保险 智能医疗

智能商业时代的思考(一)从在线化到网络化

刘旭东

拼多多 淘宝 智能商业 网络协同

人生革命由自律发起

胡迪伦

自学编程 拖延症 懒惰 死循环

Elasticsearch之mapping

北漂码农有话说

SpringBoot 缓存之常用注解

hepingfly【gzh:和平本记】

Java 缓存 springboot 注解

怎么向女朋友解释什么叫区块链?

艾小仙

比特币 区块链 以太坊 defi

如何将VSCode变成绿色版本

lmymirror

vscode 教程

一个在交流群里讨论过两轮的问题,答案竟然跟一个 PEP 有关

Python猫

Python 编程

区块链技术破解数字版权保护难题

CECBC

区块链 版权保护 数字技术

为稳外贸保驾护航 区块链交易平台显身手

CECBC

区块链 银行 福费廷

Python 为什么能支持任意的真值判断?

Python猫

Python 编程

宁波新基建之路 基于制造优势破题智慧发展

CECBC

新基建

大规模零停机关键云基础设施升级_软件工程_InfoQ精选文章