Chef:以代码定义基础设施

FreeGuideOnline 5阅读 2026-07-03

Chef 基础设施:以代码定义基础设施

Chef 是一款强大的基础设施自动化平台,它将服务器配置和管理转化为可版本控制、可测试、可复用的代码。通过 Chef,你能用声明性的方式描述系统期望的状态,实现从裸机到云端的全生命周期管理。

本教程面向初学者,将带你从零开始掌握 Chef 核心概念、环境搭建以及编写第一个配置脚本,逐步解锁“基础设施即代码”的实战能力。


理解 Chef 的核心架构

Chef 采用客户端-服务器(Client-Server)模式,但也能以独立模式(Chef Solo)运行。整个体系由以下几个关键组件构成:

  • Chef Workstation(工作站):你本地开发、测试代码的机器。上面安装 Chef Development Kit (ChefDK),包含编写和调试配置所需的所有工具。
  • Chef Server(服务器):中心存储库。所有配置脚本(Cookbook)、节点信息、数据包都保存在这里。节点通过它拉取最新的配置。
  • Chef Node(节点):被管理的目标机器。节点上运行 Chef Client,定期向 Chef Server 注册并执行分配的配置。
  • Chef Supermarket(超市):社区共享的 Cookbook 仓库,你可以直接复用成千上万现成的配置来加速开发。

在概念上,Chef 将基础设施的每一个可配置单元抽象成资源(Resource),比如软件包、服务、文件、用户等。你只需声明资源的目标状态,Chef 负责让它达到该状态,无需关心底层命令的差异。


必备术语:从食谱到运行清单

想要顺畅使用 Chef,必须熟悉三个核心抽象:Cookbook、Recipe 与 Run-list

  • Recipe(菜谱)
    最基本的配置单位,一个 Ruby 文件,其中包含一系列描述资源状态的代码。例如安装 Nginx 并确保它正在运行。

  • Cookbook(食谱书)
    Recipe 的容器,也是 Chef 的分享和复用单元。一个 Cookbook 包含多个 Recipe,以及对应的模板、属性、文件、测试等。例如一个 Web 服务器 Cookbook 可能包含 default.rb(基本安装)、ssl.rb(配置 HTTPS)等多个 Recipe。

  • Run-list(运行清单)
    节点上要执行的有序 Recipe 列表。你可以精确控制哪些配置、以什么顺序应用到某个节点。

三者关系可以理解为:Cookbook 装载 Recipe,Run-list 指定次序应用 Recipe。


安装与准备 Chef Workstation

在工作站上安装 Chef Workstation(原 ChefDK)是开始的第一步。这里以 Ubuntu 为例,说明基础环境搭建。

  1. 下载并安装 Chef Workstation

    wget https://packages.chef.io/files/stable/chef-workstation/23.4.1032/ubuntu/20.04/chef-workstation_23.4.1032-1_amd64.deb
    sudo dpkg -i chef-workstation_*.deb
    
  2. 验证安装

    chef --version
    

    看到 Chef Workstation version: ... 即表示安装成功。这会包括 chef-clientknifeberkskitchen 等一系列工具。

  3. 配置 Git Chef Workstation 依赖 Git 来管理版本和依赖,请确保已安装并配置:

    git config --global user.name "Your Name"
    git config --global user.email "[email protected]"
    

创建第一个 Cookbook

现在动手创建管理 SSH 服务的基础 Cookbook,体验从生成到应用的完整流程。

第一步:生成 Cookbook 骨架

chef generate cookbook ssh_basics
cd ssh_basics

此命令会在当前目录生成符合厨师规范的目录结构,包含 recipesattributestemplates 等文件夹。

第二步:编写默认 Recipe 编辑 recipes/default.rb,添加以下内容:

# 确保 openssh-server 包已安装
package 'openssh-server' do
  action :install
end

# 管理 sshd 服务:开启、自启动
service 'sshd' do
  action [:enable, :start]
  supports restart: true, reload: true
end

# 写一个基础的 sshd_config 模板
template '/etc/ssh/sshd_config' do
  source 'sshd_config.erb'
  owner 'root'
  group 'root'
  mode '0644'
  notifies :restart, 'service[sshd]'
end

第三步:创建配置模板 创建 templates/sshd_config.erb 文件,写入可配置的关键参数,例如:

Port <%= node['ssh_basics']['port'] %>
PermitRootLogin <%= node['ssh_basics']['permit_root_login'] %>
PasswordAuthentication <%= node['ssh_basics']['password_auth'] %>

此处利用了 Chef 的**属性(Attribute)**机制,允许从外部动态设置值。

第四步:定义默认属性attributes/default.rb 中设置默认值:

default['ssh_basics']['port'] = 22
default['ssh_basics']['permit_root_login'] = 'yes'
default['ssh_basics']['password_auth'] = 'yes'

第五步:语法检查与本地测试 使用 chef exec 运行 Cookstyle 进行代码风格与静态检查:

cookstyle .

确保没有报错。然后利用 kitchen 在虚拟机中测试(需要提前安装 VirtualBox/Vagrant):

kitchen list   # 查看测试套件
kitchen create # 创建测试实例
kitchen converge # 执行配置
kitchen verify  # 运行集成测试
kitchen destroy # 清理环境

将 Cookbook 上传到 Chef Server

经过本地测试后,通常会把 Cookbook 上传至 Chef Server,以便节点拉取。如果你没有自建 Server,可以注册Chef Automate(免费试用)来快速体验。

  1. 下载并解压 Starter Kit
    Chef Server 管理员会提供 Starter Kit,内含密钥及 knife.rb 配置文件。将解压后的目录放在 ~/chef-repo 附近,或直接复制到你的 Chef 仓库中。

  2. 下载并配置 Knife
    确保 knife.rbchef_server_urlclient_keynode_name 正确指向你的 Server。

  3. 上传 Cookbook

    knife upload cookbooks/ssh_basics
    

    或通过 Policyfile 方式管理更复杂的依赖与版本约束,但基础学习时直接用 knife upload 即可。

  4. 引导(Bootstrap)节点
    在 Server 上新增节点通常用 knife bootstrap 命令完成,它会将 Chef Client 安装到目标机器并注册到 Server:

    knife bootstrap 192.168.1.100 --ssh-user ubuntu --sudo --identity-file ~/keys/mykey.pem --node-name web-node --run-list 'recipe[ssh_basics]'
    

    执行后,节点会拉取 ssh_basics Cookbook,应用配置,并每隔 30 分钟自动与 Server 同步。


常用 Chef 资源一览

除了已经使用的 packageservicetemplate,Chef 提供了数十种内置资源,覆盖绝大多数运维场景。下面列举几个高频使用的资源及典型用法。

管理与创建文件

file '/etc/motd' do
  content "Welcome to Chef-managed system\n"
  owner 'root'
  group 'root'
  mode '0644'
end

目录创建

directory '/srv/app/shared' do
  owner 'deploy'
  group 'deploy'
  mode '0755'
  recursive true
end

执行命令(谨慎使用)

execute 'update apt cache' do
  command 'apt-get update'
  action :run
  not_if { ::File.exist?('/var/lib/apt/periodic/update-success-stamp') }
end

使用 not_if/only_if 守卫条件来保证幂等性。

管理用户和组

user 'appuser' do
  comment 'Application User'
  shell '/bin/bash'
  manage_home true
end

group 'devops' do
  members ['appuser']
  action :create
end

Cron 任务编排

cron 'log cleanup' do
  minute '0'
  hour '3'
  command '/usr/local/bin/clean_logs.sh'
  user 'root'
end

属性、数据与可复用性的核心实践

真正的“以代码定义基础设施”要求配置具备动态性和环境适应性。Chef 通过以下机制实现这一点:

  • 属性优先级:从低到高依次为默认属性、Ohai 自动收集的属性、Cookbook 属性、Role 属性、环境属性、覆盖属性。理解优先级可避免配置冲突。
  • 数据包(Data Bags):存放全局共享信息的 JSON 数据,比如用户密码、服务密钥等,可加密存储。例如创建 users 数据包,在 Recipe 中通过 data_bag_item('users', 'alice') 调用。
  • 角色(Role):将公共配置的 Run-list 和属性打包成角色,赋予节点角色后自动应用一组 Recipe,例如 web_server 角色包含 apache2firewall 等 Cookbook。
  • 环境(Environment):隔离不同阶段的配置,如开发、测试、生产环境,可以为同一 Cookbook 指定不同的属性值。

基础设施测试与代码质量

你不仅要写配置,还要保证它正确、稳定。Chef 内建了强大的测试驱动基础设施:

  • Cookstyle – 持续检查 Ruby 代码风格和最佳实践。
  • Test Kitchen – 自动化集成测试环境,可在 Docker 容器、Vagrant 虚拟机甚至云实例中验证脚本。
  • ChefSpec – 模拟 Chef Client 运行,编写单元测试,验证资源是否按照预期收敛。
  • InSpec – 基础设施合规性扫描框架,用自然语言编写断言,如“检查 SSH 是否运行在 22 端口”。

将测试纳入日常工作流,才能放心地持续交付基础设施变更。


进阶话题与学习路径

掌握基础之后,可以考虑以下方向深入 Chef 之旅:

  • Policyfile 与 Workflow:取代旧的 Berkshelf + Environment 流程,实现更精确的依赖锁定和部署流水线。
  • Chef Automate 与 Compliance:集中可视化节点状态、审计历史和自动合规补救。
  • 自定义资源(Custom Resource):封装复杂操作为可复用、统一接口的资源,提升 Cookbook 的可读性。
  • 集成云平台:利用 kitchen-ec2kitchen-azurerm 等驱动在云端测试,并使用 Chef Provisioning(现已独立为 chef-solo)动态创建基础设施。

Chef 的核心理念始终不变:用代码描述你希望系统成为的样子,而不是执行步骤。 随着对资源和抽象理解的加深,你将能管理从单机到大规模集群的任意基础设施。


本教程为“免费在线教程”网站原创,仅供学习参考。实际环境部署时请结合官方文档核对版本差异。