不可变服务器

2013年6月13日

自动化配置工具(例如 CFEnginePuppetChef)允许您指定服务器的配置方式,并将新机器和现有机器纳入合规性管理。这有助于避免 雪花服务器 的问题。此类工具可以创建可以随意拆除和重建的 凤凰服务器。不可变服务器是这种方法的逻辑结论,即一旦部署,就永远不会被修改,而只是被一个新的更新实例所取代。

自动化配置工具通常与 配置同步 一起使用,在配置同步中,您让服务器运行相当长的时间,反复应用配置以使其与最新规范保持一致。从理论上讲,服务器可以无限期地运行,并且它们将保持完全一致和最新。但在实践中,不可能完全管理服务器的配置,因此配置漂移和运行中服务器的意外更改有相当大的空间。

这就是 凤凰服务器 发挥作用的地方。

通过频繁地从基础镜像销毁和重建服务器,服务器的 100% 元素都会重置为已知状态,而无需花费大量时间来指定和维护详细的配置规范。

一旦您使用凤凰服务器,配置管理的重点就会转移到基础镜像的管理上。修复、更改和更新将应用于基础镜像,而不是运行的系统。每次您想要进行新的更新时,您都要修改基础实例并通过自动化测试工具运行它。只有当它们通过这些步骤时,您才会创建新的服务器。

因此,凤凰服务器的完整状态是由基础镜像 + 自动化配置管理 + 数据 [1] 的组合构建的,这减少了自动化配置管理服务器 100% 内容的压力。

但是,虽然我们可以在服务器短暂的生命周期内继续对其运行配置管理更新,但这样做的好处较少。事实上,*不* 这样做有相当大的价值,因为对运行中的系统进行任何更改都会带来风险。

这自然而然地导致了不可变服务器 [2]

一旦您从经过良好测试的基础镜像启动了一个服务器实例,您就不应该运行配置管理工具,因为它们会为实例带来未经测试的更改。任何需要的更改都可以对基础镜像进行,然后进行测试,最后再进行推广。没有更改的服务器将被拆除和替换。

如果这听起来很熟悉,那是因为它遵循了 持续集成持续交付 的实践。使用软件的持续交付,将给定版本的应用程序编译成可部署的工件只有一次,并且知道您在所有环境中部署和运行的是一致构建的应用程序,这样会更安全。使用不可变服务器,您可以对基础镜像进行每次更改,然后您就知道从该镜像创建的所有实例都是一致的。

服务器角色实例之间的主要区别在于配置设置,这些设置应该来自服务器外部。例如,大多数虚拟化和云平台都提供了一种在配置新实例时设置元数据值的方法,然后运行中的服务器可以读取这些值。新服务器也可以从像 Zookeeper 这样的中央注册表中提取配置值。

建议尽量减少不可变服务器的每个实例配置项的数量和范围,并在可行的情况下通过自动化测试来运行对这些配置项的更改。

处理数据

如果服务器是一次性的,那么存储在服务器上的数据通常就不是一次性的。在实现凤凰服务器或不可变服务器时,您应该考虑在销毁和创建服务器时需要持久化哪些数据,以及为了通过添加其他服务器来扩展而必须复制哪些数据。

当数据有价值但在运行时不需要时,您可以将数据从实例中移出,例如将日志文件发送到中央系统日志服务器。像 NFS 这样的共享文件系统可以让服务器访问文件,这些文件可能位于 SAN 上。云平台通常提供可挂载的存储设备,例如 AWS EBS 卷,当旧服务器实例被销毁时,可以将其附加到新的服务器实例上,或者在扩展集群时快速复制并附加到副本上。通常,您可以将责任推卸给其他人维护的服务,例如亚马逊的 RDS 数据库服务。

延伸阅读

Netflix 一直走在使用不可变服务器模式的最前沿,尽管我不知道他们是否使用过这个术语。他们已经开源了他们开发的 Aminator 工具,用于管理在亚马逊的 AWS 云上使用的 AMI 实例,并 在其博客中介绍了他们对这种模式的使用如何随着经验的积累而演变。有趣的是,实例化新实例的速度一直是他们的一个关键驱动因素,因为这有助于他们自动扩展和恢复。

注释

1: 数据涵盖了各种内容,包括数据库文件和其他应用程序管理的数据、运行时状态、其他运行时生成的数据(如日志文件)以及外部提供的配置。

2: 我的同事 Ben Butler-Cole 在 Thoughtworks 内部邮件列表中创造了“不可变服务器”一词来描述这种模式。