我尝试说明的用例是何时使用默认配置声明某些项目(例如 mysqld 服务),这些项目可以包含在每个节点上(示例中的类剥离,对于 basenode),并且仍然能够在某些特定类(例如 mysql::server)中覆盖同一项,并包含在特定节点中(例如 myserver.local)
我通过下面的示例说明了此用例,其中我想在所有节点上禁用 mysql 服务,但在特定节点上激活它。但当然,Puppet 解析失败,因为 Service[mysql] 被包含两次。当然,类 mysql::server 与类 stripdown 的子类没有任何关系
有没有办法覆盖 Service["mysql"],或者将其标记为主要服务,或者其他什么?我正在考虑虚拟项目和实现函数,但它只允许多次应用一个项目,而不允许重新定义或覆盖。
# In stripdown.pp :
class stripdown {
service {"mysql": enable => "false", ensure => "stopped" }
}
# In mysql.pp :
class mysql::server {
service { mysqld:
enable => true,
ensure => running,
hasrestart => true,
hasstatus => true,
path => "/etc/init.d/mysql",
require => Package["mysql-server"],
}
}
# Then nodes in nodes.pp :
node basenode {
include stripdown
}
node myserver.local inherits basenode {
include mysql::server` # BOOM, fails here because of Service["mysql"] redefinition
}
答案1
每当您发现自己说“我希望这个组件在一个节点上以一种方式运行,但在另一个节点上以不同的方式运行”时,您可能需要查看由变量驱动的定义,可以通过类定义中的条件或模板中的替换。
不幸的是,您的示例显示您试图使用继承,这在 Puppet 中被严重破坏并且会给您带来很多麻烦,因为它破坏的事情之一是节点中的变量重新定义。
更新:旧答案的详细信息已过时
从 2.7 开始,我所做的就是确保类使用的所有变量都不是全局变量,而是具有合理默认值的参数。你仍然不想使用 Puppet 内置的继承,但现在您可以直接从节点定义覆盖特定变量,甚至可以通过让一个类获取变量然后将它们传递给另一个类的调用来手动获得原始形式的继承。例如,您可以在节点定义中使用:
node experimental_server {
# This will still call class 'databases', but will install Postgresql and not Mysql
# as a default. You can still override it the same way as with 'databases'
class { 'mydept::nextgeneration': },
}
node server_with_mysql {
class { 'databases':
mysql_enabled => true,
}
}
node server_with_no_db {
class { 'databases': # this installs only the clients }
}
class databases (
# By default, install no servers, just clients
$pgsql_enabled => false,
$mysql_enabled => false
)
{
...
}
class mydept::nextgeneration (
# If not explicitly overridden, an undef value passed as a parameter to a class
# assumes the default value in that class
$mysql_enabled => undef,
$pgsql_enabled => true
)
{
class { 'databases':
mysql_enabled => $mysql_enabled,
pgsql_enabled => $pgsql_enabled,
}
}
正如一位评论者所说,现在还有一项名为 Hiera 的新功能,它允许您将默认值卸载到单独的数据结构中,如果您有 Puppet 3.2,您应该研究一下它。不幸的是,许多 Linux 发行版仍然附带 2.6 或 2.7,因此这可能还不适合您。
先前的答案详细信息保留在下面
我通常处理此类问题的方法是创建一个“default_parameters.pp”文件,该文件中除了一长串变量的默认赋值外什么都没有,因此在这种情况下,它将包含一行类似的内容$mysql_enabled = false
。然后,此文件被模块的 init.pp 文件包含。然后,节点定义文件将如下所示:
import "mymodule"
node myserver.local { # NOTE: no inheritance!
$mysql_enabled = true
include mysql::server
}
node otherserver.local {
include mysql::server
}
然后在 mysql::server 的类定义中检查是否$mysql_enabled
为真,如果是,则使用选择器上enable
和ensure
。
如果节点 myserver.local 继承了任何东西,这会立即中断,因为这会在继承时锁定变量的值,并且节点定义内部的进一步更改将不会产生任何影响,但除此之外,我在各处使用这种技术让各个组件表现不同,而无需生成多个类。
如果您绝对必须具有继承,但是启用了 mysql 的机器列表很小,则可以采用备用路线:不要在节点定义中设置变量,而是根据 构建选择器$fqdn
,默认为禁用,并启用选定的 fqdns。
答案2
尝试一下这个:
# In stripdown.pp :
class stripdown {
service { "mysql":
enable => "false",
ensure => "stopped"
}
}
# In mysql.pp :
class mysql::server {
if defined(Service["mysql"]) {
Service["mysql"] {
enable => true,
ensure => running,
hasrestart => true,
hasstatus => true,
path => "/etc/init.d/mysql",
require => Package["mysql-server"],
}
} else {
service { "mysql":
enable => true,
ensure => running,
hasrestart => true,
hasstatus => true,
path => "/etc/init.d/mysql",
require => Package["mysql-server"],
}
}
}
# Then nodes in nodes.pp :
node basenode {
include stripdown
}
node myserver.local inherits basenode {
include mysql::server
}
当然,这有一个警告,即您已经在其他地方定义了 Package["mysql-server"],如果没有您的require
语句,它将会失败。
我发现的另一个错误是选项后面的空格太多。节中的选项必须对齐,且不能比最长选项名称多 1 个空格。
答案3
尝试一下
# In stripdown.pp :
class stripdown {
service { "mysql":
enable => "false",
ensure => "stopped"
}
}
# In mysql.pp :
class mysql::server inherits stripdown {
Service["mysqld"] {
enable => true,
ensure => running,
hasrestart => true,
hasstatus => true,
path => "/etc/init.d/mysql",
require => Package["mysql-server"],
}
}
# Then nodes in nodes.pp :
node basenode {
include stripdown
}
node myserver.local inherits basenode {
include mysql::server
}
答案4
您可能需要查看虚拟资源,以解决资源的多重定义问题。有关该主题的文档可在此处找到:http://reductivelabs.com/trac/puppet/wiki/VirtualResources
当然,另一种方法是简单地为每个不运行 mysql 的主机创建节点对象,然后在那里加载剥离的类。