不可变基础设施:拒绝SSH
【编者的话】同一套软件系统在部署与运行过程中,常常会因为依赖组件版本、运行时间及人工干预等多种因素引发运行结果差异,造成不必要的损失。要消除这种影响,其中之一就是推行“不可变基础设施”保证其一致性。
什么是不可变基础设施
在开始本文之前,先介绍下什么是不可变基础设施。不可变基础设施(Immutable Infrastructure)是由Chad Fowler于2013年提出的一个很有前瞻性的构想:在这种模式中,任何基础设施的实例(包括服务器、容器等各种软硬件)一旦创建之后便成为一种只读状态,不可对其进行任何更改。如果需要修改或升级某些实例,唯一的方式就是创建一批新的实例以替换。这种思想与不可变对象的概念是完全相同的。(来自InfoQ)
当然在很多年以前这个概念是得不到技术支持的,我们很难在不同的物理机上实现软件的不可变。不过随着虚拟化技术以及云计算的发展,现在这已经变得可能了。我们更多的时候,面对的不是一台台的物理主机,更多的是云主机实例。安装一个操作系统也不需要几小时,而只需要鼠标点几下,等上两三分钟即可。重装系统这个概念已经不存在,删掉一个主机实例我们也不会心疼(来自个人博客)。
实现这种模式的好处是显而易见的,这意味着配置工作可实现重复性,减少了配置管理工作的负担,让持续集成与持续部署过程变得更流畅。同时它也更易于应对部署环境间的差异及版本管理,包括在部署出错时可进行快速回滚 —— 只要旧版本的镜像文件还有备份,就可以快速地生成旧版本的实例进行替换。否则的话,就只能老老实实地重新构建旧版本的实例,并且祈祷能够赶在老板掀桌之前完成回滚。
不可变基础设施令人兴奋的事情之一是:它让我们有机会重新审视一些旧的方式,并改进它们。其中之一是“漂移”——不同机器间的差异。造成这一问题主因有两个:延迟配置与更新。二者都会随着时间加剧。不同机器被设置的时间越久、存在的越久,就越有可能碰到漂移的问题。让我们依次来看看这些问题。
为什么漂移是个问题?
首先要回答的是:为什么漂移自身是个问题?或者换个说法:为什么拥有一模一样的机器很重要?
在软件系统中,减少风险的主要方式之一是测试。手工和自动测试都依赖于相同的三个步骤:
· 将系统置于一个已知状态
· 执行一个动作
· 将结果与预期做比较
将系统置于一个已知状态不仅适用于数据,也适用于所有安装的软件组件版本。一旦系统被正确设置,测试将验证X版本代码运行于Y版本平台且具有Z版本库的正确性。所有其他组合都是未知的,必须单独验证。也就是说,无法保证同一版本代码与旧版或新版平台和库组合时能同样工作,因为旧版本可能存在BUG,而新版本可能有回归或细微的变化。
为了让测试中的投入有所价值,必须保证系统及所有组件版本处于已知状态,以便能简单且安全地在机器和环境间复制。
简单而言,要保证东西能工作,必须在生产环境中运行在测试环境中所测试的东西。
这同样适用于单一环境。如果在负载均衡器后有多台机器为客户端提供服务,要保持工作正常,这些机器必须完全一致。
延迟配置的问题
你可能会觉得这很容易通过使用一些可靠的配置机制来解决。不管你喜欢什么脚本或配置管理工具,这并没有看起来那么容易。问题在于包管理器的常见使用模式及中央仓库的更新时机。当你使用类似这样的命令时,问题就出现了:
> sudo apt-get install mypkg
为了更好的展示为什么这是个问题,请看这个简单的例子:三台机器在不同时间使用同一配置脚本进行设置:
正如你所见,虽然所有机器都安装了A和B包,配置时间的不同造成了同一脚本将同一个包的不同版本拉取到不同机器上。系统的稳定性与中心仓库里每个包的更新计划密切相关!
镜像是解决之道
解决这个问题的办法之一是将所有包及其依赖项固定到一个特定版本上。虽然这让你得以重新控制系统的更新计划,也带来了高昂的维护成本。
一个更简单、更可靠的办法是听从真言:只做一次构建。
要消除环境间的差异(即造成失败的潜在因素),构建的产物应在尽可能低的层次上捕获应用及其依赖项。在虚拟基础设施中,尽可能低的层次可以简单的是整个机器的镜像。然后,你就能创建出你所需要的完全一致的实例:
镜像使得创建相同主机变得简单,但并没有解决所有问题。一旦有机会登录,你就失去了这些主机不随时间发散的保证:
这些主机存在的越久,东西被修改的可能性就越高,也就越难被完全的重建。这在很大程度上消减了其带来的益处。
强制不可变性
那么,如何弥补这点?那就是禁止登录。这不仅解决了漂移问题,还能减少受攻击面从而提高安全性。在此之上,它还强制你遵循一个干净的以镜像为基础的工作流,杜绝后门。欢迎加入拒绝SSH的运动来推广所有这些优势:
现在,你的基础设施已经不可变了。所有的修改都要求通过常规的自动化构建与部署管道来重新构建新的镜像。作为回报,系统的简单性和可靠性将大幅提升。非常值得一试。
结论
漂移通过侵蚀测试中得到的保证,降低了系统的可靠性。而这点在依赖传统配置工具时非常容易发生。
迁移到能在尽可能低层次捕获应用及其依赖的构建与部署管道上,你将重获这种信心。在处理虚拟硬件时,达成这点最好的方式是产出整个系统的镜像。要保证这个过程的可靠性,你需要消除SSH和登录能力。镜像和基础设施不再可变。所有的修改都会触发新镜像的产生,且针对所有环境只构建一次。
原文链接:Immutable Infrastructure: No SSH(翻译:梁晓勇)