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