ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
### 指定资源的依赖关系 > Remove wrapper, open mouth, insert muffin, eat. > > — Instructions on 7-11 muffin packaging 为确保事物以正确的顺序发生,你可以在 Puppet 中指定一个资源依赖另一个资源, 例如:你必须先安装软件包 X 然后再启动它提供的服务,因此应该标记这项服务依赖于软件包 X。 Puppet 会按要求的顺序排出它遇到的所有依赖。 在一些配置管理系统中,资源按照你的书写顺序被应用,换句话说,资源被应用的顺序是隐式的。 Puppet 则不是这种情况,资源或多或少以一种随机(但一致)顺序被应用, 除非你明确地使用依赖关系指出应用的顺序。 一些人更喜欢隐式的方式,因为你可以按照你需要的执行顺序书写资源定义, 并且这就是它们被执行的方式。 另一方面,许多情况下资源的顺序无关紧要。使用隐式风格的系统时, 你不能明确地告诉系统,资源 B 是否被写在了资源 A 之后,由于资源 B 依赖于 A; 或者说书写的顺序是否正确,即资源 A 写在了资源 B 之前。 这使得重构更加困难,因为移动资源有可能会打破一些隐式的依赖关系。 虽然 Puppet 会让你多做一点儿工作,就是预先指定依赖关系, 但是这样产生的代码会更清晰且更易于维护。让我们看一个例子。 #### 操作步骤 1. 使用如下的内容创建一个新文件 /etc/puppet/modules/admin/manifests/ntp.pp: ``` class admin::ntp { package { "ntp": ensure =&gt; installed, } service { "ntp": ensure =&gt; running, require =&gt; Package["ntp"], } file { "/etc/ntp.conf": source =&gt; "puppet:///modules/admin/ntp.conf", notify =&gt; Service["ntp"], require =&gt; Package["ntp"], } } ``` 2. 复制已经存在的 ntp.conf 文件到 Puppet 的如下目录: ``` # cp /etc/ntp.conf /etc/puppet/modules/admin/files ``` 3. 在 nodes.pp 中将 admin::ntp 类添加到你的服务器: ``` node cookbook { include admin::ntp } ``` 4. 现在删除系统中已存在的 ntp.conf 文件: ``` # rm /etc/ntp.conf ``` 5. 运行 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 参数的同样效果 (-&gt; 表示 require,~&gt; 表示 notify)。然而,我更喜欢使用 require 和 notify, 因为依赖关系被定义成了资源的一部分,因此更容易看清将会发生什么。 不过,对于复杂的依赖关系链,你可能想使用 -&gt; 符号来代替。 #### 更多用法 你也可以指定一个资源依赖于某个类: ``` require => Class["my-apt-repo"] ``` 你不仅可以指定资源和类之间的依赖关系,甚至可以指定 **collections** 之间的依赖关系: ``` Yumrepo <| |> -> Package <| provider == yum |> ``` 这是一种功能强大的表达方式,所有 provider 是 yum 的 package 资源被应用之前, 所有的 yumrepo 资源首先都应该被应用。 > ![注记](https://box.kancloud.cn/2016-05-12_5733eec619643.png) 历史说明: > 在 Puppet 2.7 版本之前, 所有资源编目都以非确定性的方式被应用, 这意味着每次 Puppet 运行资源的顺序都会不同。这可能会导致一些有趣的问题, 比如一个 Puppet 配置清单在一台机器上能运行成功而在另一台机器上却运行失败。 经过 Puppet Labs 的努力,现在这种情况已经不会发生。现在 Puppet 既保证可靠成功,又保证可靠失败("either succeed reliably, or fail reliably")。 如果你还在使用早期版本并且遇到了这种问题,请更新到新版本。