1.5.4 不可变基础设施

如果你对一位开发工程师说:“你的软件有 bug”,他大概率这样回:“我本地跑好好的,怎么到你那就不行?”,或者你是个运维工程师,维护线上系统时,肯定吐槽过:“谁又改了配置文件...”。

本节,我们讨论上述问题的根源 —— 基础设施的“可变”与“不可变”。

1.可变的基础设施

从管理基础设施的层面看,“可变”的基础设施与传统运维操作相关。例如,有一台服务器部署的是 Apache,现在想换成 Nginx。传统运维手段是先卸载掉 Apache,重新安装一个 Nginx,再重启系统让这次变更生效。

上述的过程中,装有 Apache 的 Linux 系统为了满足业务需求,进行了一次或多次变更,该 Linux 系统就是一个可变的基础设施。

可变的基础设施通常会导致以下问题:

  • 重大故障时,难以快速重新构建服务:持续过多的手动操作并且缺乏记录,会导致很难由标准初始化的服务器来重新构建起等效的服务;
  • 不一致风险:类似于程序变量因并发修改而带来的状态不一致风险。服务运行过程中,频繁的修改基础设施配置,同样会引入中间状态,导致出现无法预知的问题。

可变的基础设施带来的运维之痛,引得业内技术专家 Chad Fowler 这样吐槽:

要把一个不知道打过多少个升级补丁,不知道经历了多少任管理员的系统迁移到其他机器上,毫无疑问会是一场灾难。

2.不可变基础设施

2013 年 6 月,Chad Fowler 撰写了一篇名为 《Trash Your Servers and Burn Your Code: Immutable Infrastructure and Disposable Components》的文章,提出了 Immutable Infrastructure(不可变基础设施)的概念[1]。这一前瞻性的构想,伴随着 Docker 容器技术的兴起、微服务架构的流行,得到了事实上的检验。

不可变基础设施的核心思想是任何基础设施的运行实例一旦创建之后就变成只读状态。如需修改或升级,应该先修改基础设施的配置模版(例如 yaml、Dockerfile 配置),之后再使用新的运行实例替换。例如上面提到的 Nginx 升级案例,应该准备一个新的装有 Nginx 的操作系统,而不是在原有的基础上原地更新。


图 1-25 基础设施可变与不可变对比

此刻,读者是否灵光一现想起前面介绍的容器技术。构建镜像运行容器之后,如果出现问题,我们不会在容器内修改解决,而是修改 Dockerfile 在容器构建阶段去解决。

从容器的角度看,镜像就是一个不可变基础设施。工程师交付的产物从有着各种依赖条件的安装包变成一个不依赖任何环境的镜像文件,当软件需要升级或者修改配置时,我们修改镜像文件,新起一个容器实例替换,而不是在运行容器内修改。有了镜像之后,本地与测试环境不一致、测试环境与正式环境不一致问题消失殆尽了。

相比可变基础设施,不可变基础设施的最大的优势是一致性。所有的基础设施通过标准化描述文件(如 yaml、dockerfile 等)统一定义,同样的配置拉起的服务,绝对不可能出现不一致的情况。

从此,我们可以快速拉起成千上万一模一样的服务,服务的版本升级、回滚也成为常态。


  1. 参见 http://chadfowler.com/2013/06/23/immutable-deployments.html ↩︎

总字数:987
Last Updated:
Contributors: isno