Puppet Include 与 Class 和最佳实践

Puppet Include vs Class and Best Practices

我应该什么时候使用 include 与 class 声明?我现在正在探索创建一个配置文件模块,但我正在为方法论和我应该如何布局而苦苦挣扎。

一些背景知识,我正在使用可以找到的 puppet-labs java 模块 here

我的 ./modules/profile/manifests/init.pp 看起来像这样:

class profile {

  ## Hiera Lookups
  $java_version = hiera('profile::jdk::package')

  class {'java':
    package => $java_version,
  }
}

这很好用,但我知道我也可以删除代码的 class {'java': 块并改用 include java。我的问题涉及两件事。第一,如果出于某种原因我想使用 include 语句,我怎么还能将包版本从 hiera 传递给它呢?其次,是否有一个首选的方法来做到这一点? include 是我真的不应该使用的东西,还是每种方法都有优点和缺点?

我的长期目标是为我的环境构建配置文件之类的模块。可能我会有一个适用于我所有服务器的默认配置文件,然后是用于不同应用程序加载的配置文件。我可以将配置文件包含到一个角色中,并将内容应用到该级别的我的各个节点。这有意义吗?

谢谢!

When should I be using an include vs a class declaration?

如果 class 声明了属于同一模块的另一个仅供内部使用的 class,您可以考虑使用类似资源的 class 声明。这利用了您对模块实现细节的了解,因为您需要能够证明在类似资源的声明之前不会评估相关 class 的其他声明。如果违反该约束,目录构建将失败。

在所有其他情况下,您应该使用 include 或其兄弟之一,requirecontain

One, if I wanted to use an include statement for whatever reason, how could I still pass the package version from hiera to it?

与您通过 Hiera 指定任何其他 class 参数的方式完全相同。 .

Second, is there a preferred method of doing this?

是的,见上文。

Is the include something I really shouldn't be using, or are there advantages and disadvantages to each method?

include 是您应该 使用的。这是您的默认设置,requirecontain 作为某些情况下的替代项。当 Puppet 团队首次在 Puppet 2.6 中引入类似资源的声明语法以及参数化的 classes 本身时,它们似乎很好。但事实证明,这种语法在语言中引入了深层的设计问题,并且它一直是许多错误和令人头疼的问题的根源。 Puppet 3 中引入了自动数据绑定,部分是为了解决其中的许多问题,允许您在不使用类似资源的声明的情况下为 class 参数赋值。

类似资源的语法有一个优点——如果您想将其视为一个优点——参数值直接在清单中表示。然而,传统的 Puppet 智慧认为最好将数据与代码分开,以避免在配置要求发生变化时需要修改清单。因此,只有当您确信它们永远不会改变时,直接在清单中表达参数值才是一个好主意。这种情况中最重要的一类是 class 从外部源读取数据( 通过 Hiera 查找),并希望将这些值传递给另一个class.

类资源语法有一个很大的缺点,即如果给定 class 的类资源声明在为给定目标节点构建目录期间的任何地方进行评估,那么它必须是第一个被评估的 class 的声明。相反,可以评估相同 class 的任意数量的类似 include 的声明,无论是代替或补充类似资源的声明。

类 是单例,因此多个声明对目标节点的影响并不比单个声明大。允许它们非常方便。然而,Puppet 清单的评估顺序是出了名的难以预测,因此如果在清单集中某处存在给定 class 的类似资源的声明,在一般情况下很难确保它是评估的 class 的第一个声明。这个困难可以在我上面描述的特殊情况下得到解决。这属于更一般的评估顺序依赖性类别,您应该注意确保您的清单集没有这些。

类资源语法还有其他问题,但 none 与评估顺序依赖性一样重要。


关于自动数据绑定的说明

上面提到的自动数据绑定将标识 class 参数的键与这些参数的相应值相关联。如果后端支持复合值,则支持复合值,默认的 YAML 后端实际上支持复合值。您对这个答案的评论表明您还没有完全理解这些细节,尤其是您没有认识到识别(整个)class 参数的键的重要性。

我以你的 class 为例,它一方面可以通过类似资源的声明来声明:

class { 'elasticsearch':
  config => { 'cluster.name' => 'clustername', 'node.name' => 'nodename' }
}

要改为使用类似包含的声明,我们必须在 Hiera 数据中为 class 的 "config" 参数提供一个值。此值的键将为 elasticsearch::config(<完全限定 class名称> :: <参数名称>)。关联值需要 puppet-side 作为散列(a.k.a。"associative array",a.k.a。"map"),所以这就是它在 YAML 格式的 Hiera 数据中指定的方式:

elasticsearch::config:
    "cluster.name": "clustername"
    "node.name":    "nodename"

如果有多个条目,值的散列性质会更清楚。如果您不熟悉 YAML,那么可能值得花时间至少浏览一下引物,例如 the one at yaml.org.

有了这些数据,我们现在可以简单地通过

在我们的 Puppet 清单中声明 class
include 'elasticsearch'