在 Chef 中设置 "utility" 资源的最佳方式是什么

What's the best way to set up "utility" resources in Chef

一些背景

  1. 我正在使用 Vagrant 和 chef-zero;厨师服务器不是我的一部分 等式
  2. 我有两个角色:baseinfrastructure,还有两个 食谱:aptphpbase 角色的目的是进行一些基本的供应和包管理,并从 github 克隆存储库等。apt 食谱有一个食谱,update_upgrade.rb 运行 是一个 execute 资源,可以有效地调用 apt updateapt upgradeapt-get autoremove 等等
  3. infrastructure 角色通过 php 说明书设置 PHP。稍后会包含更多内容,但它是我的需求的一个很好的例子。
  4. php 食谱有两个食谱:add_repository.rbinstall.rbadd_repository 配方 运行 是一个 execute 资源,用于将 ondrej/php 存储库添加到 aptinstall 配方遍历软件包列表,以便从添加的存储库安装 php。这就是实用程序发挥作用的地方。

关键是,我需要 运行 apt update 在添加 PHP 存储库之后和安装它的软件包之前。实现此目标的最佳方法是什么?

我试过的

最初,我将我的 add_repositoryinstall 资源组合成一个 install 食谱,并计划使用 include_recipe apt::update_upgrade 插入我的 apt食谱的 execute 资源到该食谱中。然而,在搜索了 chef 文档和这篇方便的文章:Should I use include_recipe or add the recipe to run_list? 之后,似乎 include_recipe 并没有立即 运行 它所在的位置。上述文章中的建议是使用 运行 列表来指示食谱的精确执行,厨师文档确实建议食谱按照列出的顺序执行。

这导致我将 php 资源分解为 add_repositoryinstall,并为 infrastructure 使用以下角色 运行 列表:

"run_list": [
    "recipe[php::add_repository]",
    "recipe[apt::update_upgrade]",
    "recipe[php::install]"
    ]

我的 php 食谱 metadata.rbdepends apt,Chef 没有出错。但是,它也不会在 add_repository 之后触发 update_upgrade 配方。相反,install 配方在 add_repository 之后的 运行 秒会导致错误。

这一切让我假设角色 运行 列表也以类似于 include_recipe 的阶段执行。这准确吗?

我的结论

如果这些假设是准确的,那么用新存储库更新 apt 的唯一可靠方法似乎是将我的 execute 资源从我的 apt 食谱复制到我的 `[=156= 】 食谱。我内心的 DRY-ist 对此尖叫;因此,实用程序的问题 recipe/resource.

编辑

使用 apt 资源

正如原回答者所指出的,对于这个具体描述的用例是使用 apt_packageapt_updateapt_repository 的组合。以下是我如何设置它以获得我想要的:

在上述apt食谱中,我现在有两个食谱,install.rbupdate.rb。关键配方是 update:

apt_update 'update_packages' do
    action :update
  end

根据文档 (https://docs.chef.io/resource_apt_update.html),:update 操作将在 Chef Infra 客户端 运行 启动时更新 Apt 存储库。这对我很有用,因为我想在我的 VM 首次启动时更新我的​​ OS 包。

这是我的 base 角色的 运行 列表,它使用了 apt::update 配方:

"run_list": [
    "recipe[apt::install]",
    "recipe[apt::update]",
    ...
]

接下来,PHP。首先,我想添加 ondrej/php 存储库,然后遍历软件包列表并安装它们。最后,我想在安装新软件包后 运行 apt update

我做的第一件事是再次确保我的 php 食谱的 metadata.rb 有:

depends 'apt'

这将允许我重用我在 apt 食谱中定义的 apt_update['update_packages'] 资源。

我的 php 食谱中的 install.rb 食谱现在包含以下内容:

# Add PHP repository
apt_repository 'php7' do
    uri "ppa:#{node[:infrastructure][:php][:repository][:name]}"
    action :add # I know this is unnecessary, but I like to be explicit
end

# Install PHP
node[:infrastructure][:php][:extensions][:list].each do |package|
    apt_package package do
        action :install
        notifies :update, 'apt_update[update_packages]', :delayed
    end
end

由于我遍历了存储在属性中的包列表,所以在使用 :delayed 计时器安装所有 php 包后,我通知 apt_update[update_packages] 资源。

最后,这里是处理 PHP 说明书执行的 infrastructure 角色:

"run_list": [
    "recipe[php::install]"
]

这个解释很好地处理了上面的用例,现在希望使用适当的 Chef 资源。但是,还有一些其他 Apt 操作未包含在资源中,并且可能仍需要一些特定的 execute 资源。考虑 this apt_cleanup cookbook 中的食谱,其中包括:

查看这些食谱,我看到了 execute 资源的集合,这意味着对于这些操作,execute 方法可能仍然是必要的。 (尽管在食谱中)。

最佳做法是将适当的厨师资源与 notification 结合使用。

因为您正在使用 apt,请使用适当的 apt 资源,例如 apt_update (to make sure apt repositories are up to date), apt_package (to manipulate packages using apt, apt_repository (to add apt respository) and try to avoid using execute resource to do all of that - this will take advantage of chef idompotance (you might like reading Thinking Like a Chef)

每个厨师资源,可以通知and\or订阅通知。但如果你按顺序编写资源,你可能不需要使用它。

如果您的这些建议无法为您提供正确的方法,请post一个您遇到问题的相关片段,我会尽力帮助您。

更新

由于 apt 在更新过程中遇到很多失败,我会重试几次并定期更新。

apt_update 'update_packages' do
  retries 3
  action [:update, :periodic]
end

根据您使用的 chef-client 版本,apt 资源已捆绑到 chef 标准资源集合中,而不是使用 apt cookbook

因此您可能不需要在 metadata.rb 文件中指定对 apt cookbook 的依赖。另外,请确保内置 aptapt 食谱功能之间没有冲突。

如果您希望所有节点在启动时都有 apt_update 步骤,那么将使用 apt_update 的配方放在您的基本厨师角色中,并确保每个节点 运行 这个食谱(通过 运行 宁 base 角色)首先在节点 运行-列表中。

在使用 apt_repository 时,您没有为资源指定任何选项,例如 arch 和其他选项。确保这是你想要的。

当使用 apt_package 安装 php 软件包时,无需再次更新 a​​pt 存储库。因此,无需在每次调用 apt_package 时通知 apt_update