Puppet的能与不能

Openstack云平台是一个复杂的软件栈,涉及到大量的配置,服务,软件包等等多种系统资源的管理,人工管理的方式必然带来最终不可维护,人工失误等诸多问题。因此,我们需要使用一套统一框架解决配置管理上的问题。我们在过去发现了一点就是,工程师们通常喜欢在一个系统/工具上去套所有的应用场景。

首先,我们要明白任何一个工具/语言/系统都不是万能的。我们在使用一个工具/语言/系统前,必须深刻理解它的能力和局限。我们既然选择了Puppet作为配置管理系统,就应知道它能做什么,不能做什么。

什么场景下选择使用Puppet?

Puppet适合用于以下场景:

  • network,host,dns等文件的配置管理
  • ssh,ntp,nscd等服务的状态管理
  • MySQL,Apache,RabbitMQ等软件的包管理
  • Openstack软件的包安装,配置文件管理以及服务状态的管理
  • Puppet原生resource type,如ssh,host等
  • Puppet第三方模块中的扩展resource,如keystone_user,mysql_database等

什么场景下不选择使用Puppet?

Puppet不适合使用以下场景:

  • 源码文件管理

    有人可能会使用fileresource来管理一些项目的脚本,比如zabbix的plugin scripts,这些代码文件通常作为静态文件放置在files/目录下,在agent应用catalog的阶段,从puppetserver下载到各个服务器上。这样做有好多缺点:

    • 首先, 每次代码文件的更新必须要更新相应模块,业务代码和部署代码完全耦合。
    • 其次,所有线上业务没统一的代码管理方式,在我们内部,所有项目必须使用RPM包的方式进行统一管理
    • 最后,每次执行Puppet Agent都会对每个文件单独计算hash值,并在服务器端做hash值比较,且会把旧文件备份到备份文件目录下,此操作会消耗客观的CPU和IO资源。
  • 软件包的依赖管理

    例如在计算节点上,nova-compute依赖bridge-utils包,有些工程师喜欢在nova::compute里去添加一个package资源来确保在计算节点上安装此包。正确的做法是在nova的spec文件里,对openstack-nova-compute组件新增一条包依赖关系。 我们应该明确包的依赖管理应该交给软件包管理工具去做。

  • 二进制文件的管理

    我们可能会为一个业务系统添加一下方便管理,查询,统计或者清理的脚本,一些工程师的做法是将这些二进制可执行文件也丢到了puppet module的file/目录下,随着项目的发展会出现大量的二进制文件,那么它们的归宿,要么放到该项目的tools目录,或者单独作为一个项目存在,例如openstack_tools。

  • 服务的初始化操作

    Puppet中有个exec资源,有些工程师拿它来写非常复杂的bash脚本。这就类似使用Python的subprocess去写非常复杂的bash脚本一样,实现方式非常丑陋,而且低效。例如Nova服务的db sync操作,复杂的实现逻辑已经封装到了Python脚本中,Puppet只是通过exec{'nova-db-sync'}去调用nova-manage db synccli接口。

    因此在遇到业务逻辑非常复杂或者代价太大就应该交给项目去实现,对外提供操作简单的接口,然后交给Puppet去调用,而不是由Puppet去实现。

 exec { 'nova-db-sync':
    command => "/usr/bin/nova-manage ${extra_params} db sync",
    refreshonly => true,
    logoutput => on_failure
 }
  • 服务状态的监控和恢复

    有些工程师认为可以把Puppet的runinterval改成60s,这样就可以使用Puppet做频繁的状态收敛来确保服务一直是处于运行状态,虽然在一定程度上,可以确保服务的运行状态,但这里有两个问题:

    • Puppet既不是监控系统也不是专业的服务状态管理,60s的执行间隔对于服务来说,简直是太长了
    • Server端每次编译catalog会消耗大量资源,在集群数量增长或者Puppet代码逻辑复杂度提高后,你将会发现catalog的编译时间都已经超过了60s的执行间隔。
  • 角色间或节点间的依赖管理处理

    Puppet本身没有编排能力,只能处理同个节点内类之间或者服务之间的依赖关系,这是Puppet最大的硬伤。因此,Puppet公司后来就收购了Mcollective来弥补编排的短板。我们这里推荐使用Ansible来做集群编排,Ansible作为后起之秀,提供了基于YAML格式的配置管理和编排能力。