是的我知道,我们有一个名为“spiceweasel”的工具来处理所有这些,但我真的很好奇,它是如何以及为什么它在厨师那样工作。
Chef带来了一个很好的想法,拥有一个描述环境的完整存储库,这个想法很棒,但节点似乎不像我期望的那样工作。
所以这是一个情况:
您有主厨服务器/工作站设置,并且您的群集中已有bootstraped
和provisioned
个节点。如您所知,每个节点在某个时间间隔内运行chef-client
,我将定义。因此,每个节点在随机间隔重新运行配方,以检查是否有任何机会,如果更改 - 它会更改。
因此您的存储库中有文件夹nodes/
。当您执行knife upload /nodes
时,所有节点配置必须更新,但现在完全覆盖节点状态。那为什么这很糟糕?因为,假设我编辑了节点配置文件并将其上传到chef-server,然后节点状态重置,直到下一个chef-client run
操作。我有一个驻留在另一个节点上的cookbook / role,它从特定节点(拥有特定角色)检查ip。有一个很大的机会,当chef-client run
将在其中一个节点上执行时,它将找不到另一个节点的IP,整个食谱将无法运行!
也许在cookbook中使用节点状态是错误的,但是嘿,它已经遍布整个地方..所以现在很高兴有一个选项,只是 UPDATE 节点状态,而不是覆盖它
所以问题是:是否有可能更新节点的状态,而不是销毁它?
答案 0 :(得分:2)
您可以编写一个刀插件,从Chef服务器获取现有节点对象,使用本地值更新它并再次保存。
我现在使用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
答案 1 :(得分:1)
如果你不介意的话,你可以每次保存和更新节点的所有正常/覆盖/自动属性。
knife node show your-node-name --format json -l > nodes/your-node-name.json
以转储所有节点属性。注意参数-l
表示长输出,包括普通,覆盖和自动属性。knife node from file nodes/your-node-name.json
表示您始终保存并更新所有属性。
答案 2 :(得分:0)
Holger的答案不适合我的环境,使用他的插件在node.default_attrs = update.default_attrs
中删除了许多自动生成的属性
因此,我对该问题的解决方案是迭代更新节点中的属性,并将它们添加到chefserver中的节点。结果代码是:
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