Puppet 4 性能提升超 2 倍,升级前应该你知悉的变化

阅读数:1526 2017 年 3 月 22 日

话题:性能调优语言 & 开发架构DevOps运维

1、激动人心的改进

Puppet4 的第一个正式版本于 2015 年 4 月 15 日发布截止到 2016 年 12 月 28 日 Puppet 已正式发布了 4.8.1 版本。Puppet4 与 3.x 版本相比有两点不同:很多的变化,很大的变化。毫不夸张地说 Puppet4 是一个全新的项目!

1.1 速度,速度,还是速度

Puppet4 使用函数式编程语言 Clojure 对 Puppet Master 进行了重写,Puppetlabs 公司并为此新建了一个项目:puppetserver。此外,PuppetDB 也使用 Clojure 进行了重写。如此脱胎换骨的变化,最主要的目的是为了提升性能,官方给出的数据是: 相比 Puppet3,Puppet4 有 2~3 倍的性能提升。

这是一个非常吸引人的提升!要知道从 Puppet2 到 Puppet3 所带来约 50% 的性能提升,就让我们感动不已了!

在以往的实际生产中,我们遇到过多次来自于 master 端的性能瓶颈,在一个数千台规模有近百个 OpenStack 集群的环境中,我们使用了多台物理 + 虚拟服务器来作为 Puppetmaster 节点,管理着大量的服务,一旦遇到高并发的编排任务时,master 端的 CPU 几乎处于 100% 的状态,超时时间设置为 120 秒的情况下,仍然会出现不少由于编译 catalog 超时而导致 agent 报错的情况。即使我们通过改进代码,水平扩展,组件拆分,参数调优,更换硬件等多种组合办法,但是受 Puppet3 所使用的 Ruby 语言性能瓶颈,对于 Puppetmaster 的性能我们并不满意。而 Puppet4 从根本上改进了性能问题。PuppetDB 也是另一个主要瓶颈,像 resource export,virtualresource 等高级特性,以及 facts,catalog 的缓存都会使用到 PuppetDB,虽然这些高级特性很炫酷而且也很实用,但是非常非常消耗资源。这使得我们在过去非常地谨慎甚至刻意去削减 Puppet 高级特性的使用,这也是 PuppetOpenstack 社区禁止提交含有这些高级特性的代码的原因之一(另一个原因是有些高级特性无法在 Standalone 模式下使用)。

1.2 稳定性和鲁棒性的提升

此外,Puppet4 一开始就拥有面向服务的架构:

  • 由于 Clojure 语言的天生优势,拥有良好的并发和互斥控制能力,而且可以使用丰富的 JavaLibrary,是作为后端服务开发的理想选择。
  • Puppetlabs 公司开发了一个 Clojure 框架 Trapperkeeperframework:为了支撑长期运行的应用和服务而生,从而保证 Puppet 服务的稳定性和鲁棒性。

1.3 全新的 Parser

新的 Parser 支持 lambdas 和 iteraion!再也不用使用 tricky 的 creates_resources 函数了:

全新的 parser 还直接支持数据类型检查,再也不用 stdlib 里的 validate_string 等函数了:

另外一个亮点是直接支持插值式函数调用:

支持链式赋值,代码可以变得更简洁了:

除了以上几点,还有其他诸多特性,不再一一举例。

2、“不变”的 agent

目前,puppet-agent 仍然使用 Ruby 来维护。不过 JVM 可以支持 Ruby 的 Java 版本:JRuby。因此在未来,puppet-agent 不排除可能会从 JRuby 过渡到 Clojure。

3、不兼容的改动

Puppet4 既然做了重写,因此有大量与 Puppet3 不兼容的变化。这些细节对于 Puppet3 用户来说是最关心的地方。

3.1 包管理方式的变化

过去,我们需要在服务器上单独安装 Puppet,Facter,Hiera,Mcollective 等多个组件才能获得相应的功能和特性。在 Puppet4 中,安装 Puppet 不再需要安装多个软件包,而是采用 AIO(All-in-One) 的方式来简化软件包的管理,例如 puppet-agent 中包含以下组件:

  • Facter 3.4.x
  • CFacter 0.4
  • Hiera 1.3.x
  • Mcollective 2.9.x
  • Ruby 2.1.5
  • OpenSSL 1.0.0r

Puppetlabs 将这种 AIO 的包管理方式称之为 PuppetCollections(PC),每个 PC 其实对应着一个软件仓库 (repo),为用户提供了 Facter/Ruby/Puppet 等组件的匹配矩阵。下表给出了 PC 中主要软件包中整合的组件。

要在服务器上启用新版本的 Puppet4,只需要执行一行简单的命令:在基于 RPM 的系统下使用以下命令:

(点击放大图像)

在基于 Deb 的系统下使用以下命令:

(点击放大图像)

通过这种集中式的软件仓库管理方式,用户可以移除过去 puppetlabs-release 中的 production,dependencies,devel 等多个仓库。注意:puppet-agent 不会自动升级旧版本的 puppet 软件包 (建议使用 deb 或 rpm 来管理软件包的升级)

3.2 配置文件和目录的路径变化

  1. 软件包的安装目录变更为 /opt/puppetlabs
  2. 可执行文件已移动到 /opt/puppetlabs/bin
  3. confdir 从 /etc/puppet/ 变为 /etc/puppetlabs/puppet
  4. ssldir 从 vardir/sslconfdir/ssl
  5. puppetserver 的配置文件放置在 /etc/puppetlabs/puppetserver
  6. mcollective 的配置文件放置在 /etc/puppetlabs/mcollective
  7. 所有的 module/manifest/data 从 confdir 移到 codedir
  • codedir 默认路径是 /etc/puppetlabs/code
  • 包含 environments 目录
  • 包含全局的 modules 目录(可选)
  • 包含 hiera.yaml 配置文件
  • 包含 hieradata 目录

3.3 其他路径变化

  • puppet agent 的 vardir 已经移动到 /opt/puppetlabs/puppet/cache
  • rundir 已经移动到 /var/run/puppetlabs

3.4 Directory Environment 正式启用

过去多年的 Config File Environment 将被正式移除。默认的 environmentpath 是 $codedir/environments。以新建一个 production 环境为例:

  • 将 modules 放置到 $codedir/environments/production/modules
  • 将 main manifest 放置到 codedir/environments/production/manifests使codedir/modules 作为全局 modules,并用 default_manifest 设置来配置一个全局的 mainmanifest。

3.5 不再使用 Ruby1.8.7

由于使用了 AIO 的包管理方式,Puppet 不再使用系统自带的 Ruby 解释器,将直接使用 Ruby2.1.5 版本。

3.6 下一代 Puppet 语言的改动

重点来了,Puppet4 最重要的变化是重写了 parser 和 evaluator,在 Puppet3.x 中可以通过在 puppet 配置文件中开启 Future Parser 来使用,在 Puppet4 中该 parser 已经成为”present parser“,那么过去的 parser 正式退出舞台。新 parser 包含了迭代,变量类型检查等诸多新特性。并且,新 parser 对于数值,空字符串和'udenf/nil'比较提供更好的检查机制。除了核心模块的变动以外,还有一些炫酷的特性:

  • 在 PuppetMaster 加载新的 Puppet 代码不再需要重启 server 服务
  • EPP(Embeded Puppet) 将支持直接使用 Puppet 来编写 inline 和基于文件模,不再需要使用 ERB,避免用户在 Puppet 和 Ruby 之间来回切换。
  • 支持使用 Puppet 来编写 functions。

3.7 Puppet Kick 等将被移除

所有的项目在历史发展过程中,都会有很多的妥协和不良设计,Puppet 项目从 2 到 3 很多旧有的特性只是被标记为废弃,并没有从代码库中移除,借助 Puppet4 版本的重构,大约 60000 行"technicaldebt"类型的代码被移除。 较为熟知的有以下:

  • puppet kick 命令
  • inventory 服务
  • couchDBfacts terminus
  • ActiveRecordstored config
  • puppet.conf 中的 mastersection

3.8 HTTP API 的变化

Puppet4 中的另一个重要变化是 master 和 agent 通讯的 URLs 发生了变化。因此 Puppet3 的 agent 将无法和 Puppet4 的 server 端通信。例如:

3.9 puppet doc 和 tagmail 被移除

由于 puppet doc 命令依赖 RDoc,而 RDoc 与最新版本的 ruby 不兼容,因此在 Puppet4 代码中被移除,如果要继续使用,可以通过 puppetlabs-strings 模块来提供类似的功能。同理,tagmail 被移除,可以通过 puppetlabs-tagmail 模块来找到它。

3.10 Resource Type/Providers 的变化

列举一个比较重要的变化:

  • 在 Puppet3 中,若用户没有设置 allow_virtual 属性,会有废弃的警告信息,在 Puppet4 中该警告会被移除,allow_vritual 默认会从 false 变为 true。内部 API 和实现的变化
  • 这些变化只会影响到 Puppet 内部 ruby 方法和库的调用接口,对终端用户的使用没有任何影响。

4、被废弃的特性

Rack 和 WEBrick Web 服务器被废弃:Rack 和 WEBrick Web 服务器过去常用于开发和简单验证,目前已在 Puppet4.1 中标记为弃用,计划在 5.0 中移除。

5、主要配置参数

Puppet4 有多达 200 个配置参数,不过用户需要关心的参数大约为 30 个。这里我们只是简单介绍 puppet.conf 中的主要参数。

5.1 Agent 端

基础参数

  • server: Puppet Master 的地址,默认值是 puppet
  • ca_server: Puppet CA 的地址,仅在多 master 模式使用
  • report_server: Puppet report server 的地址,仅在多 master 模式使用
  • certname:node 的证书名称,默认使用 FQDN
  • environment:agent 向 master 端请求的 environment。默认是 prodcution

运行相关

  • noop: agent 仅在模拟运行并输出运行结果
  • nice: 指定 agent 运行的 nice 值,防止 agent 在应用 catalog 时占用过多的 CPU 资源
  • report: 是否发生 report,默认为 true。
  • tags: 限制 Puppet 只运行含有指定 tags 的 resources。
  • trace, profile, graph,show_diff:用于 debugagent 运行结果
  • usecacheonfailure: 在 master 端无法返回一个正确的 catalog 时,是否回退执行上一个正确的 catalog。默认是 true,如果是开发环境,建议修改为 false。
  • prerun_command 和 postrun_command:在 Puppet 执行前后运行的命令,若返回值非 0,则 Puppet 执行失败。

服务相关

  • runinterval: Puppet 的运行间隔
  • waitforcert: Puppet 请求证书签名的频率。当 agent 端第一次启动时,agent 会提交一个 CSR(certificatesigning request) 到 ca server,该证书可能是自动签名 (autosign),或者需要人工批准,而这段时间无法预估,因此需要设置一个时间段,默认是 2m。
  • splay 和 splaylimit:为每次 Agent 的定时执行添加一个随机数时间,用于避免惊群效应的发生。
  • daemonize: 是否以进程方式运行,配合 cron 使用时,应设置为 false。
  • onetime: 是否执行完成后退出,配合 cron 使用时,应设置为 true。

5.2 Server 端

多数参数对于单机模式运行的 Puppet 同样适用。在 CS 模式下,这些参数应该放置在 [master] 下;在单机模式下,这些参数应该放置在 [main] 下。

主要参数

  • dns_alt_names: Puppet Master 可以使用的 DNS 主机名列表 (alt 表示 alist)。agent 用到的 server 参数值必须和此参数或者 server 端的 certname 匹配。注:该参数仅适用于初始化生成 Puppet master 证书阶段。
  • environment_timeout: master 从 environment 加载数据的缓存时长。设置为 0,禁用缓存,为了更好的性能,可以将其设置为 unlimited,直到下次重启 master 才会重新加载 environment 配置。
  • enviromentpath: environment 的查找路径,默认值:$codedir/environments
  • basemodulepath: 所有环境的模块路径,会被所有的环境使用,默认值是:$codedir/modules:/opt/puppetlabs/puppet/modulesreports: 选择处理 report 的 hander, 默认值是 store。

Server 其他配置

pupept server 除了 puppet.conf 之外,还有拥有其他的配置文件,其默认的配置文件路径是:/etc/puppetlabs/puppetserver/conf.d。这些配置文件使用 HOCON 格式,可以在保留 JSON 语义格式的前提下,提高可读性。在 conf.d 目录下包含以下配置文件:

  • global.conf
  • webserver.conf
  • web-routes.conf
  • puppetserver.conf
  • auth.conf
  • master.conf (deprecated)
  • ca.conf (deprecated)

例如,常见的几个参数配置有以下:

  • puppet-admin:授权可以访问 admin 接口的 client
  • jruby-puppet: 调优 JRuby 时提供更多细节信息
  • JAVA_ARGS: 设置 Puppet Server 的内存分配

6. 总结和建议

相比 Puppet2 到 Puppet3 的版本升级,Puppet4 不仅是纯粹的新功能和性能提升,更像是对 Puppet 的全新重构,摒弃了过去留下来的历史负担和诟病。但是,Puppet4 所带来的不兼容性,导致对于 Puppet3 用户,尤其是 Puppet 3.3 版本之前的用户,若想要把线上的业务代码升级到 Puppet4,需要花费不少的精力。分享我们的升级经验:约在 2016 年初,云极星创将线上的 Puppet 版本从 3.3 升级到了 3.7,并提前使用了 future parser 特性(Puppet4 中的 parser)。2016 年 9 月,我们使用了半周时间完成了对 Puppet4 升级调研并给出调研报告,在 Jira 上列出计划和任务分工,实际使用了一周时间完成了 96 Puppet Module 代码更新和测试,并在生产环境上线。因此我们的建议是:即使 Puppet4 令人激动人心,但配置管理系统的升级一定要谨慎对待,提前做好计划和回滚方案,充分测试,分步骤操作。

7、参考文档

  1. https://docs.puppet.com/puppet/4.0/reference/whered_it_go.html
  2. https://docs.puppet.com/puppet/4.0/reference/release_notes.html
  3. https://puppet.com/blog/welcome-to-puppet-collections
  4. http://www.infoworld.com/article/2687553/devops/puppet-server-drops-ruby-for-clojure.html
  5. https://docs.puppet.com/puppet/latest/reference/puppet_collections.html

作者简介

余兴超,云极星创联合创始人兼平台开发部总监,目前负责智能运维平台和安全。Puppet OpenStack 项目 Core reviewer,《深入理解 OpenStack 自动化部署》主要作者。从 2011 年至今一直坚守在云计算研发一线,是中国第一批云计算的落地工程师,曾参与 OpenStack 落地新浪云的全过程,并主导了国内众多 OpenStack 案例的落地和运维。


感谢木环对本文的审校。

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们。