指定资源的依赖关系
为确保事物以正确的顺序发生,你可以在 Puppet 中指定一个资源依赖另一个资源, 例如:你必须先安装软件包 X 然后再启动它提供的服务,因此应该标记这项服务依赖于软件包 X。 Puppet 会按要求的顺序排出它遇到的所有依赖。
在一些配置管理系统中,资源按照你的书写顺序被应用,换句话说,资源被应用的顺序是隐式的。 Puppet 则不是这种情况,资源或多或少以一种随机(但一致)顺序被应用, 除非你明确地使用依赖关系指出应用的顺序。 一些人更喜欢隐式的方式,因为你可以按照你需要的执行顺序书写资源定义, 并且这就是它们被执行的方式。
另一方面,许多情况下资源的顺序无关紧要。使用隐式风格的系统时, 你不能明确地告诉系统,资源 B 是否被写在了资源 A 之后,由于资源 B 依赖于 A; 或者说书写的顺序是否正确,即资源 A 写在了资源 B 之前。 这使得重构更加困难,因为移动资源有可能会打破一些隐式的依赖关系。
虽然 Puppet 会让你多做一点儿工作,就是预先指定依赖关系, 但是这样产生的代码会更清晰且更易于维护。让我们看一个例子。
操作步骤
使用如下的内容创建一个新文件
/etc/puppet/modules/admin/manifests/ntp.pp
:class admin::ntp { package { "ntp": ensure => installed, } service { "ntp": ensure => running, require => Package["ntp"], } file { "/etc/ntp.conf": source => "puppet:///modules/admin/ntp.conf", notify => Service["ntp"], require => Package["ntp"], } }
复制已经存在的
ntp.conf
文件到 Puppet 的如下目录:# cp /etc/ntp.conf /etc/puppet/modules/admin/files
在
nodes.pp
中将admin::ntp
类添加到你的服务器:node cookbook { include admin::ntp }
现在删除系统中已存在的 ntp.conf 文件:
# rm /etc/ntp.conf
运行 Puppet:
# puppet agent --test info: Retrieving plugin info: Caching catalog for cookbook.bitfieldconsulting.com info: Applying configuration version '1302960655' notice: /Stage[main]/Admin::Ntp/File[/etc/ntp.conf]/ensure: defined content as '{md5}3386aaad98dd5e0b28428966dac9e1f5' info: /Stage[main]/Admin::Ntp/File[/etc/ntp.conf]: Scheduling refresh of Service[ntp] notice: /Stage[main]/Admin::Ntp/Service[ntp]: Triggered 'refresh' from 1 events notice: Finished catalog run in 2.36 seconds
工作原理
在本例中演示了两种类型的依赖: require
和 notify
。在第一种情况中, ntp
服务要求 ntp
包资源首先被应用:
service { "ntp": ensure => running, require => Package["ntp"], }
在第二种情况中,NTP 的配置文件设置成了 notify
(通知)ntp
服务;换句话说, 一旦发现配置文件有变化,Puppet 就应该使用新的配置文件重新启动 ntp
服务:
file { "/etc/ntp.conf": source => "puppet:///modules/admin/ntp.conf", notify => Service["ntp"], require => Package["ntp"], }
这意味着服务依赖于配置文件以及所安装的软件包,Puppet 会按照如下的正确顺序来应用这三个资源:
Package["ntp"] -> File["/etc/ntp.conf"] ~> Service["ntp"]
事实上,这是指定相同依赖关系链的另一种方法。添加上面这行到你的配置清单中, 就会产生和上例中使用 require
和 notify
参数的同样效果 (->
表示 require
,~>
表示 notify
)。然而,我更喜欢使用 require
和 notify
, 因为依赖关系被定义成了资源的一部分,因此更容易看清将会发生什么。 不过,对于复杂的依赖关系链,你可能想使用 ->
符号来代替。
更多用法
你也可以指定一个资源依赖于某个类:
require => Class["my-apt-repo"]
你不仅可以指定资源和类之间的依赖关系,甚至可以指定 collections 之间的依赖关系:
Yumrepo <| |> -> Package <| provider == yum |>
这是一种功能强大的表达方式,所有 provider
是 yum
的 package
资源被应用之前, 所有的 yumrepo
资源首先都应该被应用。
历史说明: 在 Puppet 2.7 版本之前, 所有资源编目都以非确定性的方式被应用, 这意味着每次 Puppet 运行资源的顺序都会不同。这可能会导致一些有趣的问题, 比如一个 Puppet 配置清单在一台机器上能运行成功而在另一台机器上却运行失败。 经过 Puppet Labs 的努力,现在这种情况已经不会发生。现在 Puppet 既保证可靠成功,又保证可靠失败("either succeed reliably, or fail reliably")。 如果你还在使用早期版本并且遇到了这种问题,请更新到新版本。 |