谈 DevOps 与雪花式架构
如今在 IT 圈里,几乎甩不开关于 DevOps 的议论。DevOps 是业界炙手可热的新话题,承接了云计算热度的余温;听人们谈论它,你或许会以为传统的系统管理早已入土为安。
首先我们必须谈谈我们所说的 DevOps 究竟指什么。这一点可能令人困惑,因为与云计算一样,一个较老的术语常常被借用来表示某种不同的、或者充其量是与某种已经存在的事物相关的含义。传统的 DevOps 是开发与运维角色的合并。从 1960 年代到 1990 年代,这是运行系统的标准方式。在那个世界里,编写软件的人通常就是部署和维护它的人。于是便有了“开发者”(developer)与“运维”(operations)的合并,operations 是系统管理员这一角色的半标准化称谓。直到 1990 年代和 2000 年代“IT 部门”的兴起,这两种角色才普遍被分开。自那以后,回归这两种角色合并的做法又开始重新流行起来,主要是因为这两者能够协同运作,并在许多现代的、托管的 Web 应用场景中带来巨大价值。
如今人们谈论 DevOps,往往并不是指开发者与运维人员的严格合并,而是指对运维人员的一种改造——大大加重对编码的侧重,但编码的对象不是应用本身,而是把应用基础设施定义为代码,作为云架构的自然延伸。这一点起初可能颇为令人困惑。需要注意的重点是,传统的 DevOps 并不是当今普遍发生的情况,当今发生的是一种新的“伪” DevOps:开发者仍然是开发者,运维仍然是运维,但运维已经演变为一种新的“重代码”角色,继续专注于管理运行开发者所提供代码的服务器。
当今具有重要意义的是,系统管理员这一角色已经开始分化为两种相关但显著不同的角色,其中之一被当今业界大多数人不恰当地称为 DevOps(业界大多数人太年轻,记不得 DevOps 曾经是常态而非例外、当然也绝非什么新奇之物的年代)。我在此把系统管理员角色的这两个方面分别称为 DevOps 方法和雪花式(Snowflake)方法。
我使用雪花(Snowflake)这个词来指代传统的系统架构,因为每一台单独的服务器都可以被看作一片“独一无二的雪花”。它们各不相同,至少就它们没有以某种方式被管理得彼此完全一致而言是如此。这并不意味着它们必须全都各不相同,而只是说它们保留了各不相同的可能性。在传统环境中,系统管理员会逐台登录每一台服务器去对其进行操作。为简化管理任务,一定程度的脚本编写很常见,但这一角色的核心在于花大量时间在单台系统上工作。
简化雪花式架构的管理,往往涉及以合理的方式尽量减少系统之间差异的种种尝试。这通常从诸如选择单一标准操作系统及版本(Windows 2012 R2 或 Red Hat Enterprise Linux 7)这类事情开始,而不是允许每一次服务器安装都采用不同的操作系统或版本。这种标准化看似基础,但即便在今天,许多机构也仍然缺乏这种标准化。
下一步通常是创建一套标准的部署方法或一个黄金母盘镜像(gold master image),用于制作所有系统,从而使基础操作系统和所有基础软件包——往往包括系统定制、监控软件包、安全软件包、认证配置及类似的修改——都是标准的并被统一部署。这为所有系统提供了一个共同的起点,以尽量减少差异。但从技术上讲,它们只能确保一个标准的起点,而随着时间推移,配置上的差异必须被预见到。
除这些步骤之外,雪花式环境通常会使用定制的、专门编写的管理脚本或管理工具,以随时间推移在系统之间维持某种标准化。系统之间存在的共性越多,它们就越易于维护和排障,管理人员所需的知识也就越少。更高的标准化意味着更少的意外、更少的未知,以及好得多的测试能力。
在一个由单个系统管理员、配有良好实践和工具的环境中,雪花式环境可以达到很高程度的标准化。但在有许多系统管理员的环境中——尤其是那些由来自多个地区的人员全天候支持、并拥有大量系统的环境——标准化即便配以非常勤勉的实践,也会变得非常困难。而这还是在我们着手处理一个显而易见的问题之前:执行不同角色的系统需要不同的软件包,并且可能需要不同的软件包版本。
DevOps 方法是从云架构模型中有机生长出来的。云架构是围绕着自动创建和自动销毁的、大体相同的(至少在分组内如此)、通过编程接口或 API 来控制的系统而设计的。这一模型显然适合通过一个管理系统进行集中控制,而不是依靠系统管理员的手工操作。在这一模型下,手工管理实际上是不可能的,也完全不切实际。单个系统并不像雪花模型那样独一无二,任何差异都会造成严重问题。
从云架构世界中涌现出来的观念是:系统架构应当集中地“以代码形式”定义,而不是在服务器本身上定义。这起初听起来令人困惑,但当我们更深入地审视它时便会发现颇有道理。为了支持这一模型,一种新型的系统管理工具开始涌现,它尚未拥有一个真正标准的名称,但常被称为系统自动化工具、DevOps 框架、IT 自动化工具,或干脆称为“基础设施即代码”(infrastructure as code)工具。这一领域中常见的工具集包括 Puppet、Chef、CFEngine 和 SaltStack。
这些自动化工具集背后的理念是,使用一个中央服务来管理和控制所有系统。这一中央权威机构通过基于代码的、关于系统应当呈现何种样貌和行为的描述来管理单台服务器。在 Chef 的世界里,为了显得俏皮,这些被称为“菜谱”(recipes),但这个类比很贴切。每个系统的代码可能包含诸如以下信息:应当安装哪些软件包及软件包版本的清单、应当修改哪些系统配置,以及要复制到该机器上的文件。在许多情况下,关于这些部署或修改的决策是通过可能颇为复杂的逻辑来处理的,因此需要真正的代码,而不是诸如标记语言或模板之类更简单的东西。随后,系统按角色分组并作为组进行管理。“Web 服务器”角色可能会告诉一组系统去安装 Apache 和 PHP,并将内存配置为极少使用交换。“SQL Server”角色可能会安装 MS SQL Server 以及仅供该应用使用的特殊备份工具,并将内存配置为按一组 SQL Server 机器所需的方式进行调优。这些只是示例。通常一个机构会拥有非常多的角色,有些可能是通用的,比如“Web 服务器”,另一些则更专门,用于支持非常特定的应用。角色通常可以分层,因此一个系统既可以是“Web 服务器”又可以是“Java 服务器”,使两者的综合需求都得到满足。
这些标准化的定义意味着,系统一旦被指定归属于某个角色或另一个角色,就可以自动“自我构建”。一个新系统可能由管理员请求一台系统而创建,或者一套容量监控系统可能判定某个角色需要额外容量,并在完全没有任何人工干预的情况下自动派生出新的服务器实例。在该系统被请求之时——无论是由人还是自动地——角色即被指定,而该系统将通过自动化框架把自身转变为一个完全配置好且最新的“节点”(node)。无需任何人工的系统管理干预。这一过程快速、简单,而最重要的是,完全可重复。
以代码形式定义系统会带来一些不那么显而易见的后果。其一是,不再需要对完整系统进行备份。既然你能够以最小的努力近乎瞬时地重新创建一个系统,又何必去备份它呢?来自数据库系统的本地数据仍需备份,但只需备份数据库数据,而非整个系统。这可以大大减轻备份基础设施的负担,并使恢复过程更快、更可靠。
对于已经以代码形式定义的系统,所需的文档数量极少。在雪花式环境中,系统管理员需要维护针对每一台主机的特定文档,并手动维护这些文档。这非常耗时且容易出错。而通过中央代码定义的系统几乎不需要任何文档,并且文档可以在组的层面而非单个节点的层面来处理。
测试以代码形式定义的系统同样很容易做到。你可以通过代码创建一个系统,对其进行测试,并且知道当你把那份定义投入生产环境时,生产系统将会被可重复地、与测试中创建时一模一样地创建出来。在雪花式环境中,非常常见的做法是采取试图做到这一点的测试实践,但却是通过手工操作来进行的,容易出现马虎且并非精确可重复的情况,而且政治因素常常会要求:与其真正力求可重复,不如更快地模拟出可重复的样子。代码定义的系统绕开了这些问题,使测试的价值大大提升。
除了需要为每个角色定义一定数量的节点之外,该系统可以从零开始自动地重新供给整套架构。灾后重建或启用第二站点都可以非常迅速、轻松地完成。此外,在本地托管系统与远程托管系统之间迁移,包括迁移到 Amazon、Microsoft、IBM、Rackspace 等公司所提供的系统,也极为容易。
当然,在 DevOps 的世界里,使用云架构以实现最极致水平的自动化具有巨大价值,但使用云架构对于发挥这类工具的作用并非必需。而且,当然,可以部分地使用代码定义的架构,同时也实施手工管理以采取一种混合方法,但在单个系统上这种做法很少被推荐。当两种方法都被要求采用时,通常远好得多的做法是拥有两套环境,一套作为雪花式来管理,另一套作为 DevOps 来管理。这构成一种远更优越的混合方式。我曾见过这种做法在一个企业环境中运作得极为出色:其中有数以万计的“雪花式”服务器,每一台都非常独特,但另有一个由数以万计的节点组成的专用环境,以 DevOps 方式进行管理,因为所有这些节点都是相同且可互换的,使用两种可能配置之一。这种混合方式非常有效。
然而,DevOps 方法也伴随着重大的告诫。以这种方式管理系统所需的技能组合远远超过传统系统管理所需的技能,因为至少所有传统系统管理知识仍然是需要的,外加扎实的编程知识——通常是 Python 和 Ruby 等现代语言的知识——以及对所涉及具体框架的了解。这种对扩展知识库的要求意味着,DevOps 从业者不仅稀缺,而且昂贵。它还意味着,本就远远谈不上为系统管理员或开发者步入职场做好准备的大学教育,如今距离让毕业生胜任 DevOps 模式下的工作就更加遥远了。
在这两个阵营中各自工作的系统管理员,往往倾向于认为所有系统都需要套进他们自己的模子里。新晋的 DevOps 从业者常常相信雪花式系统是遗留产物、需要被更新。雪花式(传统)管理员则往往把“基础设施即代码”这一潮流视为愚蠢、充满不必要的开销、过于复杂且非常小众。
现实情况是,两种方法都具有巨大的价值,而且两者都将继续保持极强的生命力。两者分别适用于截然不同的工作负载,而我猜想,大型机构通常会通过某种形式的混合方式看到两者并存。在 SMB 市场中,通常只有极少量的服务器、没有足以证明云架构合理性的规模杠杆,且系统之间差异很大;我猜想,DevOps 将几乎无限期地处于常态之外,因为使其运转所必需的开销和额外技能不切实际,甚至无法获得。较大型的机构则必须审视它们的工作负载。许多传统工作负载和大量传统软件并不太适合 DevOps 方法,尤其是云自动化,要么需要混合方式,要么需要在每个系统层面上达到不切实际的高编码水平,从而使 DevOps 模型无从证明其合理性。但构建于 Web 架构之上、或能够极好地横向扩展的工作负载,将在规模化时从 DevOps 模型中获益良多。这可能适用于大型企业公司,或者更小型的、很可能为外部消费而生产托管应用的公司。
这种方法上的差异意味着,以美国为例,美国大部分地区由那些将继续专注于雪花式管理模型的公司构成,而东海岸的一些公司则可能切实评估 DevOps 模型并开始朝那个方向迈进。但在西海岸,更现代的架构以及对托管应用和面向外部消费的应用大得多的侧重是驱动经济的因素,DevOps 已经在从新来者向成熟、确立的常态转变。DevOps 方法与雪花式方法很可能会像这样在很大程度上按地区分隔开来,正如 IT 总体上会看到不同的技能组合迁移到不同的地区一样。看到 DevOps 开始在诸如 Austin 这样传统 IT 表现相当糟糕的市场扎根,也不足为奇。
两种方法并无优劣之分,它们是服务于两种截然不同的系统供给方式、以及这些系统两种不同根本需求的两种不同方法。然而,随着云架构和 DevOps 模型的兴起,至关重要的是现有的系统管理员要理解 DevOps 模型意味着什么以及它何时适用,以便他们能够正确地评估自身的工作负载和独特需求。传统雪花式系统管理世界的很大一部分将随着时间推移迁移到 DevOps 模型。就这两种模型的平衡而言,我们距离这个行业达到一种稳态还非常遥远。
最初发表于 StorageCraft 博客。

