我有大约 200 个或多或少相同的 Linux VM。所有常见配置都有一个类:
class my_packages {
class { "::ntp":
servers => [ "de.pool.ntp.org" ],
}
....
}
我将其包含在 site.pp 的每个节点中。
现在我想运行我自己的本地时间服务器,使用 puppetlabs/ntp 包很简单。我只需将 my_packages 中的 servers 条目替换为新时间服务器 VM 的 IP 地址,该 VM 现在具有与之前在 my_packages 中使用的相同的 ntp 类条目。
node 'mytime' {
# include my_packages
class { '::ntp':
servers => [
'de.pool.ntp.org',
'ptbtime1.ptb.de',
'ptbtime2.ptb.de',
'ptbtime3.ptb.de',
],
}
...
}
但是,由于现在在节点中定义了类“::ntp”条目,因此我无法在我的新时间服务器 VM 的节点条目中包含 my_packages,因为在这种情况下会出现“重复声明”错误。
使用本地名称服务器时也发生了类似的问题。每个 VM 都有一个指向本地名称服务器的 /etc/resolv.conf 文件,因此在 my_packages 中有一个文件资源。但是本地名称服务器本身必须有一个不同的 /etc/resolv.conf 文件——在安装完成之前它不能指向自己,而在安装过程中并非如此。
使用一组通用资源但允许偶尔例外的最佳做法是什么?
如果您使用的是 Puppet 3 或更高版本,解决此问题的最佳方法是使用 hiera 执行自动参数查找。简而言之,它允许您使用包含语法而不是资源样式语法来声明类,这意味着您可以对类进行多个声明。请注意,您不能将类的包含和资源样式声明混合在一起。
通常,如果您要使用包含语法来声明一个类,如果它有任何必需的参数,它就会失败。当您使用自动参数查找时,puppet 将尝试通过 hiera 查找参数的值。
Hiera 之所以如此命名,是因为它会尝试通过数据源的层次结构查找值。您可以在 hiera.yaml 中指定此层次结构,它可以匹配各种事实(主机名、自定义事实等)或检查硬编码文件。
这是一个可能适用于您的情况的简短示例:
类定义:
mytime.yaml:
common.yaml:
hiera.yaml:
在这种情况下,hiera 将尝试使用键 ntp::servers 在 ntp 类中查找服务器参数的值。它会首先在与主机名匹配的任何 yaml 文件中查找该密钥,然后在 common.yaml 中查找。
在大多数情况下,它会使用 common.yaml 中的键,但在 mytime 节点的情况下,它会在层次结构中找到更高的值并停止查找。
这是一个完整示例的链接,其中顺便介绍了 ntp 模块。