在 Chef 中使用属性

Using attributes in Chef

最近刚开始使用 chef。我收集到的属性存储在一个名为 node 的大型整体哈希中,可用于您的食谱和模板。

似乎有多种定义属性的方法

  1. 直接在食谱中
  2. 在属性文件下 - 例如attributes/default.rb
  3. 在传递给 chef-solo 调用的 JSON 对象中。例如chef-solo -j web.json

鉴于以上3点,我很好奇

  1. 这些都是可以定义属性的方法吗?
  2. 这里的优先顺序是什么?我假设其中一种方法会取代其他方法
  3. #3(JSON 方法)仅对 chef-solo 有效吗?
  4. 我看到 nodedefault 哈希都已定义。有什么不同?我最好的猜测是 attributes/default.rb 中定义的 default 散列被合并到 node 散列中?

谢谢!

  1. 你的最后一个问题可能是最容易回答的。在属性文件中,您不必键入 'node',这样 attributes/default.rb:

default['foo']['bar']['baz'] = 'qux'

与recipes/whatever.rb:

中的完全一样

node.default['foo']['bar']['baz'] = 'qux'

回想起来,食谱和属性的不同语法令人困惑,但这种设计选择可以追溯到非常古老的 Chef 版本。

  1. -j 选项可用于 chef-client 或 chef-solo 并且都将设置属性。请注意,这些将是 'normal' 属性,它们在节点对象中持久存在,通常不建议使用。然而,服务器上的'run_list'、'chef_environment'和'tags'就是这样实现的。通常不建议使用其他 'normal' 属性并避免在配方(或属性)文件中使用 node.normal['foo'] = 'bar'node.set['foo'] = 'bar'。不同之处在于,如果您从食谱中删除 node.normal 行,节点上的旧设置将保留,而如果您从食谱中删除 node.default 设置,那么当您的 运行 厨师- 设置将被删除的节点上的客户端。

在 chef-client 中发生的事情 运行 使这种情况发生的是,在 运行 开始时,客户端发出 GET 以从服务器获取其旧节点文档。然后擦除默认、覆盖和自动 (ohai) 属性,同时保留 'normal' 属性。默认、覆盖和自动属性的行为最有意义——您从 运行 的开头重新开始,然后构建所有状态,如果它不在配方中,那么您看不到任何值那里。但是,通常 run_list 设置在节点上并且节点不(经常)管理它们自己的 run_list。为了使 run_list 持久化,它是一个普通属性。

选择 'normal' 这个词是不幸的,选择 'node.set' 设置 'normal' 属性也是如此。虽然这些看起来是用于设置属性的显而易见的选择,但用户应该避免使用它们。同样,问题是它们先出现,并且是 run_list 所必需的。通常只坚持默认和覆盖属性。通常您可以使用默认属性完成大部分工作,这些应该是首选。

  1. 这里有一张大优先级图:

https://docs.chef.io/attributes.html#attribute-precedence

这是属性优先级的最终真相来源。

  1. 该图描述了可以定义属性的所有不同方式。

Chef Attributes 的问题在于它们有机地成长并萌生出许多选项,试图帮助那些把自己逼到墙角的用户。一般来说,您永远不需要接触自动、正常、force_default 或 force_override 级别的属性。您还应该避免在配方代码中设置属性。您应该将配方中的设置属性移动到属性文件。剩下的就是这些设置属性的地方:

  • 在初始的 -j 参数中(设置普通属性,你应该限制使用它来设置 run_state,超过使用它通常是气味)
  • 在角色文件中作为默认或覆盖优先级别(不过要小心这一点,因为角色没有版本控制,如果你经常接触这些属性,你会导致生产问题)
  • 在食谱属性文件中作为默认值或覆盖优先级(这是您应该设置大部分属性的地方)
  • 在环境文件中作为默认或覆盖优先级别(对于数据中心中的 DNS 服务器等设置很有用,尽管您也可以为此使用角色 and/or 说明书)

您也可以在食谱中设置属性,但是当您这样做时,您总是会在 运行 通过 Chef Recipes 的两阶段编译收敛解析器中学习下一课。如果您有需要相互通信的食谱,最好使用 node.run_state,它只是一个不会被写入节点属性的散列。您可以将 node.run_state[:foo] = 'bar' 放在一个食谱中,然后在另一个食谱中阅读。你可能会看到设置属性的食谱,所以你应该意识到这一点。

希望对您有所帮助。

写食谱时,我将属性的三个层次可视化:

  1. 成功收敛的默认值 -- attributes/default.rb
  2. 本地测试覆盖值 -- JSON 或 .kitchen.yml(您是否尝试过 chef_zero 使用 ChefDK and Kitchen?)
  3. Environment/role 覆盖值——link 列在 lamont 的回答中:https://docs.chef.io/attributes.html#attribute-precedence