
如果你正在学习或刚开始接触DevOps和基础设施自动化,这篇文章将帮助你详细了解不可变基础设施(Immutable infrastructure)模型。
在进入技术解释之前,首先,你应该对可变和不可变这两个词的字面意思有一个清晰的认识。
- 可变的(Mutable): 可以被改变的东西。意味着你可以在它被创建后继续对它进行修改。
- 不变的(Immutable): 不能改变的东西。一旦它被创建,你就不能改变其中的任何东西。
现在让我们看一个真实世界的例子,即一所房子。在一所房子里,有一些你可以改变的对象(可变的),也有一些必须被替换的对象(不可变的),如果它们发生了什么变化。例如,你可以给一扇门涂上不同的颜色,更换门把手,给它一个不同的外观。在这里门是一个可变的对象。同时,一个洗脸盆是一个不可变的对象。如果你想改变脸盆的颜色,你需要用一个新的脸盆来替换它。这一点也适用于地砖。
在IT界,我们在软件工程和DevOps中都有可变性和不可变性的概念。在软件工程中,这一概念被应用于面向对象的编程,而在DevOps中,它被应用于基础设施自动化。在本指南中,我们将从DevOps的角度重点讨论不可变的基础设施。
核心要点
- 可变基础设施是在服务器创建后继续登录修改;不可变基础设施是在镜像阶段完成配置,运行后不再原地变更。
- 不可变模式的核心动作是“替换”,不是“修补”:要升级、打补丁或改配置,就构建新镜像并替换旧实例。
- CI/CD 中的可部署工件通常是虚拟机镜像或容器镜像,而不是一组登录服务器后执行的命令。
- 蓝绿发布和金丝雀发布都适合与不可变基础设施结合使用。
- 镜像生命周期管理是不可变基础设施能否落地的关键,尤其是基础镜像、黄金镜像、安全补丁和应用镜像的协同。
什么是不可变的基础设施?
要理解不可变的基础设施,首先,你应该知道服务器的生命周期。
下面是一个带有应用程序的服务器的简略的生命周期(仅供参考,各组织的流程有所不同)。
- 部署一个服务器。
- SSH进入服务器。
- 安装所需的工具。
- 配置安全代理、防火墙和实用程序以保证安全。(安全加固)
- 安装和配置所需的应用程序。
- 修改应用程序和服务器配置,以提高应用程序的性能。
- 使服务器用于生产工作。
- 每个月登录服务器,为服务器打上安全补丁(服务器更新)。
- 在应用程序可用时进行升级。
正如你所看到的,上面提到的步骤是一个可变的模型。这是因为我们正在根据要求对服务器进行修改。因此,当你使用Ansible、Puppet或Chef等配置管理工具来管理服务器时,你遵循的是可变模式。
「不可变」,就像它的字面意思一样,不可变的基础设施是一个概念,在你部署服务器之后,你不会对它做任何改变。意思是说,服务器在部署的时候已经预先配置好了配置、安装好了工具和应用程序。服务器出现的那一刻,应用程序就开始运行。
如果您想进行任何更改,则应销毁现有服务并用新服务替换。更改可能是打补丁、应用程序升级、服务器配置更改等。

| 对比项 | 可变基础设施 | 不可变基础设施 |
|---|---|---|
| 变更方式 | 登录现有服务器修改 | 构建新镜像并替换旧实例 |
| 常见工具 | Ansible、Puppet、Chef 等配置管理工具 | Docker、Packer、镜像仓库、编排平台 |
| 风险 | 长期运行后容易产生配置漂移 | 依赖镜像构建和发布流程质量 |
| 回滚方式 | 再次修改服务器状态 | 回退到旧镜像或旧实例组 |
| 适合场景 | 传统服务器运维、低频变更 | 云、容器、自动伸缩和标准化发布 |
你可以为大多数现代应用遵循不可变的基础设施模型,包括数据库集群。
例如,如果你有应用程序在自动缩放组中运行,而你遵循的是不可变的服务器部署模型。每当你想部署新的代码时,你需要销毁现有的虚拟机,这样由自动缩放启动的新虚拟机就会下载最新的代码。另一种方法是,你需要用带有代码的最新镜像来改变启动模板。
在一个不可变的模型中,在配置方面应遵循标准的最佳实践。
例如,使用配置存储或服务发现工具,将经常改变的配置外部化。一个典型的例子是Nginx的upstream配置。
这样一来,你就不必为小的变化和配置而重新生成服务器。
如果你知道容器,它是不可变基础设施的最好例子。除了外部化的配置,对容器的任何改变都会导致重建。
用于CI/CD的不可变的基础设施模型
那么,不可变的基础设施模式如何用在CI/CD过程?
当你在虚拟机环境的CI管道中遵循不可变的基础设施模式时,可部署的工件将是一个虚拟机镜像或一个docker镜像。
例如,一旦CI完成,利用Docker或packer等工具,你可以把程序代码塞到容器或虚拟机镜像(AWS AMI)中,并使用它在相关环境中进行部署。
当涉及到部署时,你可以遵循蓝绿部署或金丝雀部署。让我们来看看这两种方法。
- 蓝绿模式: 在这种模式下,使用最新的应用程序镜像,你将一组新的服务器(蓝色)与生产服务器(绿色)一起部署,但它不会提供流量。当蓝色服务器被验证OK之后,流量将被重定向到新的(蓝色)服务器组,旧的(绿色)服务器将被销毁。
- 金丝雀模型: 在这个模型中,不是将全部流量导到新的服务器集上,而是只将流量的一个子集导到新的服务器上。流量切换是根据团队制定的时间节奏逐渐发生的。一旦流量完全切换到新的服务器集,旧的服务器就会被删除。
从发布视角看,不可变基础设施减少了“这台服务器和那台服务器配置不一样”的风险。团队发布的是镜像版本,验证的也是镜像版本,回滚时也可以回到上一个镜像版本。
镜像生命周期管理和补丁
在不可改变的基础设施模型中,虚拟机或容器镜像的创建和修补起到了关键作用。你需要利用CI/CD工具,制定良好的镜像生命周期管理。
在云和容器环境中,首先我们需要一个基础镜像。之后基于这个基础镜像创建应用镜像。在实际的项目环境中,这个过程会比较复杂。
下面我们来聊一下这一切在实际项目环境中是如何发生的,以及如何根据公司的安全策略建立应用程序镜像。
因此,这里列出了在安全的项目环境中遵循的通用镜像生命周期管理(虚拟机和容器)步骤。
注意:该列表是为了给你一个关于镜像生命周期管理的总体情况。它在每个组织中都是不同的。

- 在一个安全、合规的环境中,你不允许使用云提供商提供的基础镜像或docker hub等公共容器注册处提供的docker基础镜像。
- 每个组织都会用标准的安全工具(各种agent)、DNS/Proxy、LDAP配置等创建虚拟机/容器基础镜像(它根据每个组织的安全政策而改变)。通常,这种镜像是由中央平台团队或安全团队创建和维护的。你可以叫它黄金镜像。
- 经过批准和认证的基本镜像将与组织中的所有团队共享。它可以是一个单一的云账户或与组织内的多个子账户共享。
- 然后,每个团队可以在批准的基础镜像上创建自己的应用镜像。(这里使用像Docker和Packer这样的工具)。
- 团队创建的新镜像将被测试并部署到生产中。
- 现在,当基础镜像得到新的更新或补丁时,平台或企业安全团队会发布新版本的基础镜像并通知所有项目团队。
- 每个组织都有一个打补丁的生命周期。意思是说,安全团队对VMS的更新和补丁的应用有一定的准则。例如,它可能是一个月或三个月一次。
- 对于虚拟机,补丁可以是 “就地” 的,也就是对现有实例进行补丁,也可以是不可更改的,也就是用新的镜像替换现有的镜像。容器在本质上是不可变的。
- 基于补丁的生命周期,每个团队都会用新的基础镜像更新现有的应用镜像,并将其部署到生产中,而不管应用的代码是否有变化。这同时适用于虚拟机和容器。
实践中的注意事项
不可变基础设施不是“永远不改配置”,而是把变更前移到构建和发布流程中。真正运行中的实例尽量不做手工变更。
落地时要注意几件事:
- 经常变化的配置应外部化,例如配置中心、环境变量、服务发现或密钥管理系统。
- 镜像构建过程要可重复,避免不同人本地构建出不同结果。
- 基础镜像和应用镜像要有版本管理和漏洞修复流程。
- 发布系统要支持快速回滚到上一个可用镜像。
- 监控和日志要能按镜像版本、实例批次和发布时间定位问题。
FAQ
Q1:不可变基础设施是不是不能修改任何配置? 不是。它强调不要登录运行中的服务器做临时修改。经常变化的配置应该外部化,由配置存储或服务发现工具管理。
Q2:容器天然就是不可变基础设施吗? 容器镜像很适合不可变模式。除了外部化配置,对容器内容的变更通常应通过重建镜像完成。
Q3:补丁怎么打? 不可变模式下,补丁通常进入基础镜像或应用镜像的新版本,然后通过部署新实例替换旧实例,而不是逐台登录修改。
结论
我们已经看了不可变的基础设施的关键概念。
作为一名DevOps工程师,你应该在构建和部署不可变镜像时遵循标准最佳实践,以减少攻击面,降低配置漂移,并让发布和回滚更可控。
如果你正在使用容器或容器编排工具(如Kubernetes),你已经在遵循应用程序部署的不可变模式。
扩展阅读
