Chef中的动态角色属性

时间:2013-01-11 15:37:49

标签: ruby chef

我希望Chef cookbook network_interfaces为每个节点提供ip地址,netmasks等的动态值。对我有用的是:

db_role.rb(block1):

override_attributes(
  "network_interfaces" => {
      :device => 'eth0',
      :address => '123.123.123.123',
  }
)

但这不是很有活力。我的想法是将IP地址(,网络掩码等)提交给knife bootstrap上的每个节点。

然后节点看起来像这样(block2):

{
    "normal": {
      "network_interfaces" => {
          "device" : "eth0",
          "address" : "123.123.123.123"
      }
    },
    "name": "foobar",
    "run_list": [
       "recipe[zsh]",
       "role[networking_interfaces]"
    ]
}

不幸的是,network_interfaces食谱默认不会获取这些值。我的想法是在角色定义中引用block2中显示的节点特定属性,如下所示:

override_attributes(
  "network_interfaces" => {
      :device => node['network_interfaces']['device'],
      :address => node['network_interfaces']['address'],
  }
)

这不起作用,因为它显然不是json,而且Chef无法处理角色文件中动态分配的值。

如何运行network_interfaces配方并将特定于节点的值传递给它?

2 个答案:

答案 0 :(得分:6)

Maciej,我听从了你的建议。 我在bootstrap上使用-j选项上传自定义参数,如IP,广播等。

knife bootstrap IP_OF_THE_NODE -r 'role[main_application]' -j '{ "network_interfaces" : {"device" : "eth1.0000", "type" : "static", "address" : "192.168.1.1", "netmask" : "255.255.255.0", "broadcast" : "192.168.0.255","gateway": "192.168.0.1"}}'     

另外,我写了一个自定义配方来实现动态匹配。这是代码:

#setup a custom network config per vm
network_interfaces node["network_interfaces"]["device"] do
  Chef::Log.info("Compiling network_interfaces")
  target node["network_interfaces"]["address"]
  mask node["network_interfaces"]["netmask"]
  broadcast node["network_interfaces"]["broadcast"]
  gateway node["network_interfaces"]["gateway"]
  custom node["network_interfaces"]["custom"]
  action :save
end

答案 1 :(得分:2)

如果您通过knife bootstrap -j …添加普通属性,并在角色中保留覆盖属性,则覆盖将接管(请参阅http://docs.opscode.com/essentials_node_object_attributes_precedence.html以获取完整的属性优先级列表。如果您在运行override_attributes之前已从db_role.rb删除knife bootstrap,或将其更改为default_attributes,那么在节点属性中设置IP应该有效。

最后一个片段不起作用:角色是Chef服务器上的静态JSON文档,并且在将角色上传到服务器时,knife只解释一次Ruby(http://docs.opscode.com/ essentials_roles_formats.html)。你不能从角色的Ruby代码中引用节点的属性,因为它甚至在触及任何节点之前都被编译为JSON。如果您想尝试类似的方法,您需要使用自定义食谱(例如,my_network_interfaces),食谱看起来像这样:

node.set['network_interface']['device'] = …
node.set['network_interface']['address'] = …
include_recipe 'network_interfaces'

这样,您就可以使用network_interfaces作为“库”食谱,由您的“应用程序”食谱my_network_interfaces调用,它可以实现您需要的任何逻辑。从你的问题,我不能建议你如何计算设备和地址,因为你的例子只是试图复制相同的属性,这是一个无操作。据我所知,您希望在角色中使用default_attributes,并将具有普通属性的特定JSON传递给knife bootstrap以覆盖默认值。< / p>