Puppet 简介
每个IT专家都遭受过代码在生产环境上不能正常运行的困境。有经验的开发者耗费几个小时、几天、乃至几个星期的时间进行应用程序开发,但在应用发布之后就不得不持续不断地为它打各种补丁。质量保证工程师能够确保应用达到了高性能和低磁盘占用的各种指标……但只限于他们的测试系统环境。运维工程师在进行每次部署操作都得逐字逐句地仔细对照检查表,结果发现他们还是得整日整夜地加班工作,才能够让应用能够在生产环境上正常运行(或者说苟延残喘)。
与此同时,公司的执行长官们则是暴跳如雷。因为他们认为自己已经花了这么多钱,却依然得不到满意的结果。“为什么新的特性要这么长时间才能发布,连改一个bug都要这么久?”客户们在远离我们的产品,竞争者的技术已经远远领先我们,就连华尔街也留意到了我们的颓势。
陷入以上这种困境的IT组织通常极度缺乏组织纪律。开发、运维和测试人员的管理各行其是,各自遵循不同的衡量标准和工作目标,他们或许在不同的大楼里工作,有些人甚至从来没有见过面。这些团队很可能使用不同的技术栈进行工作,各自使用不同的配置。应用程序的代码或许还算稳健,但除此之外就是一团散沙了。能够在开发者的笔记本、或是在QA环境下正常工作的代码,往往在部署到生产环境后就会出现问题。最糟糕的是:没人知道问题的根源在哪里。
Puppet的创始人Luke Kanies曾经也是那些在数据中心中彻夜加班的运维人员之一。正是出于对现状的不满,促使他编写了这套如今被称为Puppet的软件。
等一下——我们刚才谈论的不是组织的问题吗?一套软件怎么能够解决组织文化的问题,并促进团队的协作呢?答案是,软件确实做不到这一点,至少它本身是做不到的。Puppet是一个优秀的基础设施管理平台,可以让每个系统管理员更高效地完成工作,哪怕是一个封闭的运维团队也能够掌握。而对于那些准备提高团队的协作能力的组织来说,Puppet能够为共享的代码库提供一种强力的粘合剂,以统一不同团队的工作。请耐心地听我介绍Puppet的工作原理,以及它是如何帮助处于各种不同状况的团队增强协作能力,以进行软件开发和发布的——这种工作方式的演变通常被称做DevOps。
Puppet是什么?
“Puppet”这个词实际上包括了两层含义:它既代表编写这种代码的语言,也代表对基础设施进行管理的平台。
Puppet语言
Puppet是一种简单的建模语言,使用它编写的代码能够对基础设施的管理实现自动化。Puppet允许对整个系统(我们称之为节点)所希望达到的最终状态进行简单地描述。这与过程式的脚本有明显的不同:编写过程式的脚本需要你清楚地知道如何将某个特定的系统转变至某种特定的状态,并且正确地编写所有这些步骤。而使用Puppet时,你不需要了解或指定达到最终状态的步骤,你也无需担心因为错误的步骤顺序,或是细微的脚本错误而造成错误的结果。
与过程式的脚本的另一点不同在于,Puppet的语言能够跨平台运行。Puppet将状态进行了抽象,而不依赖于具体实现,因此你就可以专注在你所关心的那一部分系统,而将实现的细节,例如命令的名称、参数及文件格式等等交给Puppet自己负责。举例来说,你可以通过Puppet对所有的用户以相同的方式进行管理,无论该用户是用NetInfo或是/etc/passwd方式进行存储的。
这种抽象的概念正是Puppet功能的关键所在,它允许使用者自由选择最适合他本人的代码对系统进行管理。这意味着团队之间能够更好地进行协作,团队成员也能够对他们所不了解的资源进行管理,这种方式促进了团队共同承担责任的意识。
Puppet这门建模语言的另一个优势在于:它是可重复的。通常来说,要继续执行脚本文件,必须对系统进行变更。但Puppet可以被不断地重复执行,如果系统已经达到了目标状态,Puppet就会确保停留在该状态上。
资源
Puppet语言的基础在于对资源的声明。每个资源都定义了系统的一个组件,例如某个必须运行的服务,或是某个必须被安装的包。以下是一些其它类型资源的示例:
- 某个用户帐号
- 某个特定的文件
- 某个文件夹
- 某个软件包
- 某个运行中的服务
可以将资源想象为构建块,他们将结合在一起,对你所管理的系统的目标状态进行建模。
接下来,我们将接触到Puppet中更深入核心的定义,这些定义允许你以一种经济的方式将资源进行结合,而经济正是Puppet的关键特色之一。
类型与提供者
Puppet将类似的资源以类型的方式进行组织。举例来说,用户是一种类型,文件是另一种类型,而服务又是一种类型。当你正确地对某个资源的类型进行描述之后,接下来只需描述该资源所期望的状态即可。比起传统的写法:“运行这个命令,以启动XYZ服务”,你只需简单地表示:“保证XYZ处于运行状态”就可以了。
提供者则在一种特定的系统中,使用该系统本身的工具实现各种资源类型。由于类型与提供者的定义被区分开来,因此某个单一的资源类型(例如“包”)就能够管理多种不同的系统中所定义的包。举例来说,你的“包”资源能够管理Red Hat系统下的yum、基于Debian的系统下的dpkg和apt,以及BSD系统中的端口。
管理员通常来说不大有机会对提供者进行定义,除非管理员打算改变系统的默认值。Puppet中已经精确的写入了提供者,因此你无需了解如何对运行在基础设施中的各种操作系统或平台进行管理。再次声明,由于Puppet将细节进行了抽象,因此你无需担心各种细节问题。如果你确实需要编写提供者,那也通常能够找到一些简单的Ruby代码,其中封装了各种shell命令,因此通常非常简短,同时也便于创建。
类型和提供者使得Puppet能够运行在各种主流平台上,并且允许Puppet不断成长与进化,以支持运算服务器之外的各种平台,例如网络与存储设备。
下面的一个示例将为你展现Puppet语言的便捷性,它首先演示了如何用shell脚本添加一个新用户以及一个新的组,这与Puppet中始终一致的操作形成鲜明对比。而在使用Puppet的示例中,“用户”和“组”都是类型,Puppet能够自动找到适用于你的平台的提供者。相比之下,特定于平台的过程式脚本无论是编写还是理解都要困难得多。
类、清单与模块
Puppet语言中的其它元素的主要作用是为资源的声明提供更多的灵活性和便捷性。类在Puppet中的作用是切分代码块,将资源组织成较大的配置单元。举例来说,一个类能够包括所有安装和配置NTP时必须的Puppet代码。类的创建与调用可以在不同的地方完成。
不同的类集合可以应用在扮演不同角色的节点上。我们将其称之为“节点分类”,这是一项非常强大的能力,它允许你根据节点的能力,而不是根据节点的名称对他们进行管理。这种“别把家畜当宠物”的机器管理方式,得到了许多快速发展的组织的偏爱。
Puppet语言文件被称为清单,最简单的Puppet部署方式就是一个单独的清单文件加上一些资源。如果我们为以上示例中的基础Puppet代码命名为“user-present.pp”文件,那它就成为了一个清单。
模块是一系列类、资源类型、文件和模板的结合,他们以一某个特定的目的,并按照某种特定的、可预测的结构组织在一起。模块可以为了各种目的而创建,可以是对Apache实例进行完整的配置以搭建一套Rails应用程序,也可以为各种其它目的进行创建。通过将各种复杂特性的实现封装在模块中,管理员就能够使用更小、可读性更好的清单文件对模块进行调用。
Puppet模块的一个巨大优势在于模块的重用性。你可以自由使用他人编写的模块,并且Puppet有一个参与者数量巨大的活跃社区,除了Puppet Labs的员工所提编写的模块之外,社区成员们也会免费地分享他们所编写的模块。你能够在Puppet Forge上找到超过3000个可以免费下载的模块,其中有许多模块是系统管理员的工作中最常见的一些任务,因此这些模块能够节约你大量的时间。比方说,你可以使用模块进行各种管理任务,包括简单的服务器构建块(NTP、SSH)管理,乃至复杂方案(SQL Server或F5)的管理。
类、清单和模块都是纯粹的代码,与组织中所需要的其它任何在代码一样,它们能够、也应该被签入到版本控制系统当中,稍后我们将对这一点展开讨论。
Puppet平台
完整的Puppet解决方案不仅仅是指这门语言。使用者需要在不同的基础设施中部署Puppet代码、时不时地对代码及配置进行更新、纠正不恰当的变更、并且时时对系统进行检查,以保证每个环节的正常运行。为了满足这些需求,大多数使用者会在某个主机-代理结构中运行Puppet解决方案,由一系列组件所组成。根据不同的需求,使用者可以选择运行一个或多个主机。每个节点上都会安装一个代理,通过一个经过签名的安全连接与主机进行通信。
采取主机-代理这一结构的目的是为了将Puppet代码部署在节点上,并长期维护这些节点的配置信息。在对节点进行配置之前,Puppet会将清单编译为一个目录(catalog),目录是一种静态文档,在其中对系统资源及资源间的关系进行定义。根据节点的工作任务,以及任务的上下文不同,每个目录将对应一个单独的节点。目录定义了节点将如何工作,Puppet将根据目录的内容对节点进行检查,判断该节点的配置是否正确,并且在需要时应用新的配置。
在常规Puppet运行期间,每个基于节点的代理会定期与某个主机进行检查工作,Puppet会根据不同结果进行以下各种操作:
- 对于产生了偏差的配置进行纠正
- 仅报告节点的状态,而不进行任何改动
- 使用Puppet的操作工具进行必需的配置改动
- 收集节点与事件的相关数据,并加以保存,以便重试
Puppet Lab还提供了一个商用版本的解决方案,名为Puppet Enterprise,其中包括了客户支持服务,并提供了一系列高级且重要的功能:
- 节点管理高级功能
- 基于角色的访问控制
- 运维性指标,以及一个报表控制台
结合语言与平台
现在,你对Puppet的工作原理有一个基本的了解了,但你可能仍然会感到疑惑:Puppet怎样帮助你的组织解决深层次的问题,并简化人们的协作方式呢?
一切重点在于:在你使用Puppet时,你是在对你的基础设施进行建模,正如对代码建模一样。你能够像对待代码一样的方式处理Puppet,或者从更广的意义上说,是对基础设施的配置进行同样的处理。Puppet代码能够方便地进行保存和重用,能够与运维团队的其他成员,以及其他任何需要对机器进行管理的团队成员进行分享。无论是在笔记本上的开发环境,还是在生产环境上,开发人员和运维人员都能够使用相同的清单对系统进行管理。因此当代码发布到生产环境时,各种令人不快的打击就会少很多。 这将大大改善部署的质量,尤其是在我们所见到的组织中更是如此。
将配置作为代码处理,系统管理员就能够为开发人员提供独占的测试环境,开发人员也不再将系统管理员视为碍事的人了。你甚至可以将Puppet代码交付给审记,如今有许多审记都接收Puppet清单,以进行一致性验证。这些都能够提升组织的效率,并点燃员工的热情。
最重要的一点或许在于,你能够将Puppet代码签入到某个共享的版本控制工具中,这将为你的基础设施提供一个可控的历史记录。你可以实行在软件开发者中十分常见的结对审查实践,让运维团队也能够不断地对配置代码进行改善、变更和测试,直到你有信心将配置提交至生产环境。
由于Puppet支持在模拟环境或noop模式下运行,你就可以在应用改动之前预先检查改动会造成的影响。这将大大缓解部署的压力,因为你可以随时选择回滚。
通过在Puppet使用中结合版本控制,以及之前我们所提到的各种优秀实践,许多客户实现了持续集成方面的最高境界,能够更频繁地将代码提交至生产环境,并且产生的错误更少。如果你能够以更小的增量部署应用,你就能够更早、更频繁地获得用户的反馈,它将告诉你你是否正处在正确的前进方向上。这样就可以避免在经过6到12个月开发工作,提交了大量代码之后,却发现它并不符合客户的需要,或是对客户没有吸引力这种悲惨情形的发生了。
我们的客户会选择与开发人员的应用程序代码同步对开发、测试以及生产环境上的配置进行变更,这就让开发者能够在一个非常接近于真实环境,甚至与生产环境完全相同的环境中进行工作。再也不会发生由于在开发与测试环境中的配置的不同,导致应用程序在生产环境上崩溃的情况出现了。开发者和QA能够部署更优秀的软件、运维人员不再需要整夜无眠、而执行官们……好吧,就算他们谈不上有多高兴,至少也能够对结果感到满意,从而将关注点转移到IT团队的效率以外的事情上了!
迈出第一步
不可否认,我们所见过的多数组织在持续协作方面都远远没有达到一个高水准,更不用说持续交付了。而Puppet的一个优点在于,随着你的团队的成长和基础设施的规模增加,Puppet也能够随之成长。或许你还没有准备好在整个公司范围内推行DevOps的实践,这不要紧。许多客户都在保守的、循规蹈矩的行业,例如银行业与政府项目中成功地将Puppet作为配置管理工具进行应用。这些组织或许对持续交付方面的需求很低,但不管怎样,能够将基础设施作为代码进行保存与版本化,这就极大地改善了这些组织的变更控制,以及安全实践了。
我们建议你首先对某个能够简化你工作的任务开始实现自动化。举例来说,许多管理员首先会对NTP、DNS、SSH、防火墙、用户和组等实现自动化管理,这些都是日常工作,但又经常会产生各种问题的任务。
当人们逐渐熟悉了Puppet之后,他们就会更进一步,开始编写更复杂的模块对服务进行管理,例如Tomcat的监控服务,或JBoss的应用服务器管理,还有一些人会开始采用Forge模块。当你做好进一步探索的准备,你就能够确保数据中心、乃至云端的所有机器都正确配置了各种任务、并确保这些任务运行正常,而且整个系统也处于正常运行状态中,以保证你的核心业务的应用程序正常运转。
你要记住的一点是,并非所有基础设施的代码都要你来编写,这一点非常重要。在你之前已经有人解决了这些问题,因此你只需对这些工作成果善加利用!我们之前提到了Puppet Forge上提供了几千个模块,你也可以在Puppet社区中寻求帮助,其中的模块更达到几万个之多。你也可以订阅Google上的Puppet用户组,或是查看ask.puppetlabs.com论坛上的内容,并与论坛中的活跃人士混熟。你也可以参加当地的Puppet Camp或Puppet用户小组,与小组成员进行面对面的交流。你还可以利用Puppet Labs上的学习资源,包括免费和付费的版本。在YouTube频道上和我们的官方文档中也可以学到各种知识。
当你进入了Puppet的生态系统后,以上这些只是全部学习资源的一小部分。我们期待与你相会,帮助你学习如何使用Puppet改善你的基础设施、业务和工作生活。
----------------------------------------------------------------------------------------------------------------------------