2013-11-21 42 views
0

是的,我知道,我们有一个名为“spiceweasel”的工具来处理所有这些,但我非常好奇,它是如何以及为什么它在主厨中以这种方式工作。如何更新节点的状态而不是覆盖它?

厨师带来了一个很好的想法,有一个你描述的环境的整个存储库,这个想法是伟大的,但节点似乎并不像我期望的那样工作。

所以出现这种情况: 您有厨师服务器/工作站设置,并且您的群集中已有bootstrapedprovisioned节点。如您所知,每个节点在某个时间间隔运行chef-client,我将定义。因此,每个节点都会按照随机间隔重新运行食谱,检查是否没有机会,如果发生变化 - 它会变回原处。

因此,您的资料库中有文件夹nodes/。而当你做knife upload /nodes时,所有节点的配置必须是更新了,但现在它完全覆盖了节点的状态。那么为什么这是不好的?因为,假设我编辑了节点配置文件并将其上载到主服务器,则节点状态将重置,直到下一次chef-client run操作。我有一个驻留在另一个节点上的cookbook /角色,它检查特定节点(它拥有特定角色)的IP。有一个很大的机会,当chef-client run将在其中一个节点上执行时,它不会找到另一个节点的IP,整个食谱将无法运行!

也许是错误的食谱使用节点状态,但嘿,这是所有的地方..所以现在会是不错的选择,只是为了UPDATE节点状态,而不是将其覆盖。

所以问题是:是否有可能更新节点的状态,而不是销毁它?

回答

2

您可以编写一个knife插件,从厨师服务器获取现有节点对象,使用本地值更新并再次保存。

我现在用this plugin一段时间(最初由Chris Gaffney):

class NodeUpdateFromFile < ::Chef::Knife 
    deps do 
    require "chef/node" 
    require "chef/json_compat" 
    require "chef/knife/core/object_loader" 
    end 

    banner "knife node update from file FILE (options)" 

    def loader 
    @loader ||= ::Chef::Knife::Core::ObjectLoader.new(Chef::Node, ui) 
    end 

    def run 
    update = loader.load_from("nodes", @name_args[0]) 
    begin 
     node = ::Chef::Node.load(update.name) 
    rescue Net::HTTPServerException 
     ui.info("Could not load existing node #{update.name}, assuming new node.") 
     node = ::Chef::Node.new 
     node.name(update.name) 
    end 

    # Replace attributes, run_list, and chef_environment from the new node 
    # definition. 
    node.normal_attrs = update.normal_attrs 
    node.override_attrs = update.override_attrs 
    node.default_attrs = update.default_attrs 

    node.run_list.reset!(update.run_list) 
    node.chef_environment(update.chef_environment) 

    # Expand the run_list in case it has changed 
    node.expand! 
    node.save 

    output(format_for_display(node)) if config[:print_after] 

    ui.info("Updated Node #{update.name}!") 
    end 
end 

只要把它放到你的厨师库中.chef/plugins/knife/node_update_from_file.rb并使用新的命令

knife node update from file my.node.json 

而不是旧knife node from file my.node.json

+0

这实际上是辉煌!如果没有任何东西会弹出,我已经接受了你的回答,但我确实对主厨服务器的行为感兴趣。这真的很好,这可以在厨师回购本身! – holms

1

您可以保存和更新节点每个t的所有正常/超驰/自动属性如果你不介意的话。

  1. 执行knife node show your-node-name --format json -l > nodes/your-node-name.json转储所有节点属性。注意参数-l表示长输出,包括正常,覆盖和自动属性。
  2. 更新它
  3. 执行knife node from file nodes/your-node-name.json

这就意味着你保存和更新所有属性,所有的时间。

+0

如果角色和食谱没有任何变化,是否有可能改变节点状态?如果它不会,那么这是完美的解决方案:)并且上面的插件可能也是一样的 – holms

+0

@holms它只是转储所有节点属性,包括正常,覆盖和自动,所以是的,那就是节点状态。但是,每个节点通常需要30KB,所以从操作角度来看效率不高。 – shawnzhu

0

霍尔格的答案是不适合我的环境下,用自己的插件许多自动生成的属性在node.default_attrs = update.default_attrs

被删除,因此,我的解决问题的方法是叠代的更新节点属性,并将它们添加到节点厨师服务员。由此产生的代码是:

class NodeUpdateFromFile < ::Chef::Knife 
    deps do 
    require "chef/node" 
    require "chef/json_compat" 
    require "chef/knife/core/object_loader" 
    end 

    banner "knife node update from file FILE (options)" 

    def loader 
    @loader ||= ::Chef::Knife::Core::ObjectLoader.new(Chef::Node, ui) 
    end 

    def run 
    update = loader.load_from("nodes", @name_args[0]) 
    begin 
     node = ::Chef::Node.load(update.name) 
    rescue Net::HTTPServerException 
     ui.info("Could not load existing node #{update.name}, assuming new node.") 
     node = ::Chef::Node.new 
     node.name(update.name) 
    end 

    # Replace attributes, run_list, and chef_environment from the new node 
    # Note: With this appproach attributes will never be removed from the chefserver 
    update.normal_attrs.each { |key, value| node.normal_attrs[key] = value } 
    update.override_attrs.each { |key, value| node.override_attrs[key] = value } 
    update.default_attrs.each { |key, value| node.default_attrs[key] = value } 

    node.run_list.reset!(update.run_list) 
    node.chef_environment(update.chef_environment) 

    # Expand the run_list in case it has changed 
    node.expand! 
    node.save 

    output(format_for_display(node)) if config[:print_after] 

    ui.info("Updated Node #{update.name}!") 
    end 
end 
相关问题