Как я могу обновить состояние узла, а не перезаписывать его?

Да, я знаю, что у нас есть инструмент под названием "spiceweasel" для обработки всего этого, но мне очень любопытно, как и почему он работает таким образом в шеф-поваре.

Шеф-повар предлагает хорошую идею иметь целый репозиторий описанных вами сред, эта идея великолепна, но кажется, что узлы не работают так, как я ожидаю.

Итак, вот ситуация: у вас настроен шеф-сервер/рабочая станция, и в вашем кластере уже есть узлы bootstraped и provisioned. Как вы знаете, каждый узел работает chef-client с некоторым интервалом, который я определю. Таким образом, каждая нода повторно запускает рецепты со случайным интервалом, чтобы проверить, не произошло ли ничего случайно, если изменения - они меняются обратно.

Итак, у вас есть папка nodes/ в вашем репозитории. И когда вы делаете knife upload /nodes, конфигурация всех узлов должна быть обновлена, но теперь она заменяет состояние узла полностью. Так почему это плохо? Потому что, допустим, я отредактировал файл конфигурации ноды и загрузил его на шеф-сервер, тогда состояние ноды сбрасывается до следующей chef-client run операции. У меня есть поваренная книга/роль, которая находится на другом узле, и она проверяет IP с определенного узла (который владеет определенной ролью). Есть большая вероятность, что когда chef-client run будет выполняться на одном из узлов, он не найдет IP другого узла, и вся поваренная книга не запустится!

Может быть, неправильно использовать состояния узлов в кулинарной книге, но эй, это повсюду... так что теперь было бы неплохо иметь возможность просто ОБНОВИТЬ состояние узла, а не перезаписывать его.

Итак, вопрос: возможно ли обновить состояние узла вместо его уничтожения?


person holms    schedule 21.11.2013    source источник


Ответы (3)


Вы можете написать плагин для ножа, который извлекает существующий объект узла с сервера шеф-повара, обновляет его локальными значениями и снова сохраняет.

Я использую этот плагин в течение некоторого времени (первоначально Крис Гаффни):

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

person Holger Just    schedule 21.11.2013
comment
это на самом деле гениально!!! Я принимаю ваш ответ, если ничего не всплывает, меня действительно интересует причина, по которой шеф-сервер ведет себя так. Очень приятно, что это может быть в самом репозитории шеф-повара!!! - person holms; 21.11.2013

вы можете сохранять и обновлять все обычные/переопределяющие/автоматические атрибуты узла каждый раз, если вы не возражаете.

  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

что означает, что вы постоянно сохраняете и обновляете все атрибуты.

person shawnzhu    schedule 21.11.2013
comment
есть ли шанс, что состояние узла будет изменено, если ничего не изменилось в роли и поваренной книге? если это не так, то это идеальное решение :) и, вероятно, этот плагин выше делает то же самое - person holms; 21.11.2013
comment
@holms просто сбрасывает все атрибуты узла, включая обычные, переопределения и автоматические, так что да, это состояние узла. Однако обычно это занимает 30 КБ на один узел, поэтому с точки зрения эксплуатации это не очень эффективно. - person shawnzhu; 22.11.2013

Ответ Хольгера не подходил для моей среды, с помощью его плагина многие автоматически сгенерированные атрибуты были удалены в 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
person albs    schedule 24.06.2015