【问题标题】:Make chef cookbook recipe only run once让厨师食谱只运行一次
【发布时间】:2017-01-25 00:08:53
【问题描述】:

所以我使用以下配方:

include_recipe "build-essential"

node_packages = value_for_platform(
  [ "debian", "ubuntu" ]                      => { "default" => [ "libssl-dev" ] },
  [ "amazon", "centos", "fedora", "centos" ]  => { "default" => [ "openssl-devel" ] },
  "default"   => [ "libssl-dev" ]
)

node_packages.each do |node_package|
  package node_package do
    action :install
  end
end

bash "install-node" do
  cwd Chef::Config[:file_cache_path]
  code <<-EOH
    tar -xzf node-v#{node["nodejs"]["version"]}.tar.gz
    (cd node-v#{node["nodejs"]["version"]} && ./configure --prefix=#{node["nodejs"]["dir"]} && make && make install)
  EOH
  action :nothing
  not_if "#{node["nodejs"]["dir"]}/bin/node --version 2>&1 | grep #{node["nodejs"]["version"]}"
end

remote_file "#{Chef::Config[:file_cache_path]}/node-v#{node["nodejs"]["version"]}.tar.gz" do
  source node["nodejs"]["url"]
  checksum node["nodejs"]["checksum"]
  notifies :run, resources(:bash => "install-node"), :immediately
end

它在我的 Vagrant VM 上成功安装了 nodejs,但在重新启动时它又被执行了。我该如何防止这种情况?我不擅长阅读 ruby​​ 代码。

【问题讨论】:

    标签: ruby chef-infra vagrant chef-recipe


    【解决方案1】:

    要使remote_file 资源具有幂等性(即不再下载已经存在的文件),您必须正确指定文件的校验和。您可以在代码中使用node["nodejs"]["checksum"] 属性执行此操作。但是,这仅适用,如果校验和被正确指定为下载文件的 SHA256 哈希,则不支持其他算法(尤其是不支持 MD5)。

    如果校验和不正确,您的配方仍然有效。但是,在下一次运行时,Chef 会注意到现有文件的校验和与您指定的不同,并会再次下载该文件,从而通知 install node 资源并执行整个编译工作。

    【讨论】:

    • 谢谢,校验和确实是MD5,我用SHA256的时候就不麻烦了。
    【解决方案2】:

    对于厨师来说,食谱是幂等的很重要。这意味着他们应该能够在不改变结果的情况下一遍又一遍地奔跑。 Chef 希望能够定期在节点上运行所有食谱,这应该没问题。

    您是否有办法知道该配方中的哪个资源导致您出现问题? remote_file 是唯一一个我怀疑是非幂等的,但我不确定。

    查看 Chef wiki,我发现:

    不推荐使用的行为 在 Chef 0.8.x 及更早版本中,远程文件也是 用于从食谱中的 files/ 目录中获取文件。这个 行为现在由#Cookbook 文件提供,并使用远程文件 在 Chef 0.9.0 和 稍后。

    无论如何,按照 chef 的工作方式,它会查看 "#{Chef::Config[:file_cache_path]}/node-v#{node["nodejs"]["version"]}.tar.gz" 解析为是否存在,如果存在,它应该跳过该资源。 install-node 是否有可能在完成安装后删除该文件?如果是这样,厨师每次都会重新获取它。

    【讨论】:

    • 基于log 看起来它正在重新运行remote_file 部分。
    【解决方案3】:

    您只能在使用 -o 修饰符覆盖运行列表时运行配方。

    sudo chef-client -o "recipe[cookbook::recipe]"
    

    -o RunlistItem,RunlistItem..., 用指定项替换当前运行列表

    --覆盖运行列表

    【讨论】:

      【解决方案4】:

      根据我的经验,remote_file 总是在执行chef-client 时运行,即使目标文件已经存在。不过,我不确定为什么(还没有深入研究 Chef 代码以找到错误的确切原因)。

      您始终可以编写not_ifonly_if 来控制remote_file 资源的执行,但通常让它每次都运行是无害的。

      您的其余代码看起来已经是幂等的,因此重复运行客户端并没有什么坏处。

      您可以为remote_file 指定一个操作,使其有条件地运行:

      remote_file 'target' do
        source 'wherever'
        action :create_if_missing
      end
      

      the docs

      【讨论】:

      • 除非有明确的条件阻止匹配,否则每次下载文件都不是错误。它将确保文件始终是正确的,即使远程文件在同一 URL 上发生更改。
      【解决方案5】:

      如果您想测试您的食谱是否是幂等的,您可能会对 ToASTER 感兴趣,这是一个用于系统测试 Chef 脚本的框架。

      http://cloud-toaster.github.io/

      Chef recipes 在隔离的容器环境 (Docker VM) 中使用不同的配置执行,ToASTER 报告各种指标,例如系统状态变化、收敛属性和幂等性问题。

      【讨论】:

        猜你喜欢
        • 2020-09-04
        • 1970-01-01
        • 1970-01-01
        • 2013-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多