- DevOps
- 运维
- IaC
【免费下载链接】chef
Chef Infra, a powerful automation platform that transforms infrastructure into code automating how infrastructure is configured, deployed and managed across any environment, at any scale
本文面向 Chef 开发者和高级用户,系统讲解 Chef Infra 代码仓库中位于docs/dev/devtools/下的开发者工具文档,并以其中唯一的工具条目chef-apply(可执行程序)为主线展开。你将掌握 chef-apply 的全部命令行选项、三种 recipe 输入方式、why-run 模式的用途,以及它在 Chef Infra 源码(lib/chef/application/apply.rb)中从参数解析到资源收敛的完整执行链路,从而在日常调试、资源探索和快速验证中获得可直接落地的实战方案。
认识 devtools 文档区:官方不背书、后果自负的“龙区”
仓库中的 docs/dev/devtools/README.md 用一句经典的 “Here there be dragons”(此处有龙)作为开场,明确界定了这一文档区的定位:
Here is where we document tools that may be useful to Chef developers or power users. These tools have no guarantees and are not supported. You're welcome to use them, but you are on your own.
翻译过来就是:这里收录的工具对 Chef 开发者或高级用户可能很有用,但官方不做任何保证、不提供支持;你可以放心使用,但出了问题要自己负责。因此,阅读本文后你应当把 chef-apply 定位为“探索与调试利器”,而不是生产环境的正式运行方式。
该目录下目前仅有一份工具文档:chef-apply.md,对应 Chef Infra 中的chef-apply可执行程序。在仓库源码层面,它的实现位于 lib/chef/application/apply.rb,产品常量定义在 chef-utils/lib/chef-utils/dist.rb(ChefUtils::Dist::Apply,其中PRODUCT = "Chef Infra Apply"、EXEC = "chef-apply")。
chef-apply 是什么:探索资源的单机利器
根据 chef-apply.md,chef-apply 是一个从命令行直接运行单个 recipe 的可执行程序,它有三个关键特征:
- 属于 Chef Workstation工具链的一部分(源码中通过
ChefUtils::Dist::Apply::EXEC引用其二进制名chef-apply); - 是探索 Chef 资源(resource)的绝佳方式——无需 cookbook、无需 Chef Server,一行命令即可验证某个资源的写法与行为;
- 不是 Chef 在生产环境中的运行方式——生产环境应当使用 chef-client / chef-solo 的完整运行体系。
它在仓库中的实现类是Chef::Application::Apply,继承自 lib/chef/application.rb 中的Chef::Application,其启动横幅写明了完整的用法形态:
Usage: chef-apply [RECIPE_FILE | -e RECIPE_TEXT | -s] [OPTIONS]也就是说,chef-apply 接受三种输入来源:recipe 文件路径、-e传入的 recipe 文本、-s从标准输入读取,后面可跟任意选项。
命令语法与全部选项
基本语法
chef-apply name_of_recipe.rb选项总览
原文档 chef-apply.md 给出的核心选项如下:
| 选项 | 完整形式 | 说明 |
|---|---|---|
-e RECIPE_TEXT | --execute RECIPE_TEXT | 用一个字符串执行资源(recipe 内容直接写在命令行里) |
-l LEVEL | --log_level LEVEL | 写入日志文件的日志级别 |
-s | --stdin | 使用标准输入(STDIN)执行资源 |
-v | --version | 显示 Chef Infra Client 版本 |
-W | --why-run | 以 why-run 模式运行,该模式会执行除“真正修改系统”之外的一切动作,用于理解 Chef Infra Client 的决策依据以及系统当前状态与目标状态 |
-h | --help | 显示命令帮助信息 |
源码中的扩展选项
对照 apply.rb 的实现,Chef::Application::Apply实际注册的选项比文档更多,值得一并掌握:
| 选项 | 说明 |
|---|---|
-j JSON_ATTRIBS/--json-attributes JSON_ATTRIBS | 从一个 JSON 文件或 URL 加载节点属性(源码中由Chef::ConfigFetcher获取并解析) |
-F FORMATTER/--format FORMATTER | 指定输出格式(如 doc/minimal 等),通过Chef::Config.add_formatter(format)生效 |
-L LOGLOCATION/--logfile LOGLOCATION | 设置日志文件位置,默认输出到 STDOUT,daemon 化场景推荐使用 |
--force-logger/--force-formatter | 强制使用 logger 或 formatter 输出 |
--always-dump-stacktrace | 无论日志级别如何,总是输出完整堆栈 |
--yaml | 将 recipe 按 YAML 格式解析(详见下文) |
--minimal-ohai | 只运行 Chef Infra 运行所需的最少量 Ohai 插件,加快启动 |
--[no-]color | 彩色输出开关,默认开启 |
--[no-]profile-ruby | 输出整次运行的完整 Ruby 调用图(仅限专家使用) |
--license-add/--license-list | 向许可证池添加 / 列出许可证密钥(仅当二进制名为chef-apply时注册) |
日志级别-l的可选值在源码中定义为trace, debug, info, warn, error, fatal(见 apply.rb),比文档描述更明确。
实战示例:从运行 recipe 到安装软件包
以下示例均来自原文档 chef-apply.md,保留了完整命令与输出。
运行一个 recipe 文件
假设当前目录下有一个名为machinations.rb的 recipe:
chef-apply machinations.rb执行后,chef-apply 会读取该文件并在本机完成资源收敛。
安装 Emacs
sudo chef-apply -e "package 'emacs'"返回:
Recipe: (chef-apply cookbook)::(chef-apply recipe) * package[emacs] action install - install version 23.1-25.el6 of package emacs安装 nano
sudo chef-apply -e "package 'nano'"返回:
Recipe: (chef-apply cookbook)::(chef-apply recipe) * package[nano] action install - install version 2.0.9-7.el6 of package nano安装 vim
sudo chef-apply -e "package 'vim'"返回:
Recipe: (chef-apply cookbook)::(chef-apply recipe) * package[vim] action install - install version 7.2.411-1.8.el6 of package vim-enhanced重复执行同一个 recipe(幂等性验证)
再次执行:
sudo chef-apply -e "package 'vim'"返回:
Recipe: (chef-apply cookbook)::(chef-apply recipe) * package[vim] action install (up to date)注意第二次输出变成了(up to date)——这正是 Chef 资源模型的**幂等(idempotent)**特性:目标状态已满足时不再重复操作。这一点在 kitchen-tests 的 end_to_end cookbook 等集成场景中同样被反复验证。
需要说明的是,上述示例输出中的版本号(如23.1-25.el6、2.0.9-7.el6)来自文档编写时的 RHEL 6 系环境,属示意性质;在你的系统上会显示该发行版仓库中实际解析到的版本。
使用标准输入
除了-e传字符串,还可以用-s从标准输入喂入 recipe:
echo "package 'htop'" | sudo chef-apply -s该能力对应源码中config[:stdin]分支:@recipe_text = STDIN.read,随后与-e一样写入临时文件再执行(apply.rb)。
源码视角:chef-apply 的一次运行经历了什么
要让“一行命令跑一个 recipe”成立,Chef::Application::Apply在 apply.rb 中完成了以下关键步骤:
- 参数与配置初始化:
reconfigure调用parse_options解析命令行,将结果合并进Chef::Config,随后完成日志、代理(export_proxies)、OpenSSL(init_openssl)初始化,并调用parse_json处理-j传入的属性文件。 - 读取 recipe 内容:
run_chef_recipe按优先级处理三种来源——-e的字符串、-s的 STDIN 均写入一个临时文件(Tempfile.open("recipe-temporary-file"),这样出错时用户能拿到带上下文的报错),否则读取命令行第一个参数指定的 recipe 文件;若既无-e也无-s且没有文件参数,则直接报错退出(No recipe file provided,抛Chef::Exceptions::RecipeNotFound)。 - 构造 run context:
get_recipe_and_run_context强制设置Chef::Config[:solo_legacy_mode] = true,创建Chef::Client实例并依次执行run_ohai、load_node、build_node,再基于节点构造Chef::RunContext,最后创建一个名为"(chef-apply cookbook)"::"(chef-apply recipe)"的Chef::Recipe——这正是示例输出中Recipe: (chef-apply cookbook)::(chef-apply recipe)一行的来源。 - 解析 recipe:默认通过
recipe.instance_eval(@recipe_text, @recipe_filename, 1)执行 Ruby 代码;若传入--yaml或文件扩展名为.yml,则走recipe.from_yaml(@recipe_text)分支,按 YAML 解析 recipe。 - 收敛与收尾:创建
Chef::Runner并调用runner.converge执行资源,结束后关闭临时文件句柄,并调用Chef::Platform::Rebooter.reboot_if_needed!处理需要重启的情况(apply.rb)。
整个流程与单元测试 spec/unit/application/apply_spec.rb 相互印证:该测试用例断言reconfigure后Chef::Config[:solo_legacy_mode]为真、read_recipe_file对空参数/不存在文件会触发Chef::Application.fatal!、临时文件会以recipe-temporary-file前缀创建并回写 recipe 文本,以及-j属性会通过Chef::ConfigFetcher正确加载。
why-run 模式:先看后做
-W/--why-run是文档中特别强调的调试选项。它对应源码中 apply.rb 的option :why_run,开启后 Chef Infra 会完整走一遍运行流程,但不真正修改系统——每个资源都会展示它“将要做什么”,输出中会标明 which actions would have been taken。
典型用法:
sudo chef-apply -W -e "package 'nginx'"适用于以下场景:
- 理解 Chef Infra 为什么做出某个决策(决策依据);
- 查看系统当前状态与chef-apply 期望的目标状态之间的差异;
- 在正式执行前对 recipe 进行安全的“彩排”。
适用边界:何时该用、何时不该用
结合 devtools README 与 chef-apply.md 的定位,可以给出清晰的使用建议:
适合使用 chef-apply 的场景:
- 快速验证某个资源写法的正确性(如
package、file、user等资源),属于“探索资源”的第一现场; - 在本机临时安装/配置软件,不想为一次性任务搭建完整 cookbook 工程;
- 调试单条 recipe 逻辑、验证 why-run 输出、测试属性加载(
-j)与 YAML recipe(--yaml)。
不应使用 chef-apply 的场景:
- 生产环境的基础设施配置与持续管理——文档明确强调它NOT是 Chef 的生产运行方式;
- 需要 cookbook 版本管理、Chef Server/Policyfile、依赖解析、多节点管理、报告与审计等能力的正式流水线,这些应交给 chef-client / chef-solo;
- 依赖官方支持与 SLA 的任务——devtools 区工具“没有保证、不被支持”。
小结
chef-apply 是 Chef Infra 开发者与高级用户工具箱里一件小而锋利的工具:语法简单(chef-apply [RECIPE_FILE | -e RECIPE_TEXT | -s] [OPTIONS])、反馈直观(收敛输出直接展示每个资源的动作与幂等状态)、模式丰富(why-run、YAML、JSON 属性均可)。通过阅读 lib/chef/application/apply.rb 与 spec/unit/application/apply_spec.rb 的源码,你能进一步理解它如何借助Chef::Client、Chef::RunContext与Chef::Runner完成从文本到收敛的完整闭环。记住它的边界——用于探索与验证,而非生产——你就能安全地在“龙区”里淘到宝。
- DevOps
- 运维
- IaC
【免费下载链接】chef
Chef Infra, a powerful automation platform that transforms infrastructure into code automating how infrastructure is configured, deployed and managed across any environment, at any scale
相关推荐
chef-apply 使用指南:用 Chef Infra Client 在命令行中运行单个 Recipe
chef apply 使用指南:用 Chef Infra Client 在命令行中运行单个 Recipe chef apply 是 Chef Workstati
DevOps运维IaCGetQzonehistory:用 Python 一键导出 QQ 空间全部历史说说(备份操作完整指南)
GetQzonehistory:用 Python 一键导出 QQ 空间全部历史说说(备份操作完整指南) GetQzonehistory 是一个开源的 Pytho
网页爬虫数据分析DB-GPT 如何导入自定义 Skill(zip 上传或 GitHub 链接)并在对话中使用
DB GPT 如何导入自定义 Skill(zip 上传或 GitHub 链接)并在对话中使用 当你的团队或社区已经有了打包好的 Skill( .zip / .s
DevOps运维IaC
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考