Chef 简明教程
Chef - Overview
Chef 是一项由 Opscode 开发的开源技术。Opscode 联合创始人 Adam Jacob 被称为 Chef 的创始人。这项技术使用 Ruby 编码来开发基础构建模块,如配方和菜谱。Chef 用于基础设施自动化,并协助减少基础设施管理的手动且重复的任务。
Chef is an open source technology developed by Opscode. Adam Jacob, co-founder of Opscode is known as the founder of Chef. This technology uses Ruby encoding to develop basic building blocks like recipe and cookbooks. Chef is used in infrastructure automation and helps in reducing manual and repetitive tasks for infrastructure management.
Chef 对不同的构建模块有它自己的惯例,而这些模块是管理和自动化基础设施所必须的。
Chef have got its own convention for different building blocks, which are required to manage and automate infrastructure.
Why Chef?
Chef 是一种用于自动化基础设施配置的配置管理技术。它是基于 Ruby DSL 语言开发的。它用于简化配置任务和管理公司的服务器。它有能力与任何云技术集成。
Chef is a configuration management technology used to automate the infrastructure provisioning. It is developed on the basis of Ruby DSL language. It is used to streamline the task of configuration and managing the company’s server. It has the capability to get integrated with any of the cloud technology.
在 DevOps 中,我们使用 Chef 来部署和管理内部和云端的服务器及应用程序。
In DevOps, we use Chef to deploy and manage servers and applications in-house and on the cloud.
Features of Chef
以下是 Chef 最突出的功能:
Following are the most prominent features of Chef −
-
Chef uses popular Ruby language to create a domain-specific language.
-
Chef does not make assumptions on the current status of a node. It uses its mechanisms to get the current status of machine.
-
Chef is ideal for deploying and managing the cloud server, storage, and software.
Advantages of Chef
Chef 提供了以下优点:
Chef offers the following advantages −
-
Lower barrier for entry − As Chef uses native Ruby language for configuration, a standard configuration language it can be easily picked up by anyone having some development experience.
-
Excellent integration with cloud − Using the knife utility, it can be easily integrated with any of the cloud technologies. It is the best tool for an organization that wishes to distribute its infrastructure on multi-cloud environment.
Disadvantages of Chef
Chef 的一些主要缺点如下:
Some of the major drawbacks of Chef are as follows −
-
One of the huge disadvantages of Chef is the way cookbooks are controlled. It needs constant babying so that people who are working should not mess up with others cookbooks.
-
Only Chef solo is available.
-
In the current situation, it is only a good fit for AWS cloud.
-
It is not very easy to learn if the person is not familiar with Ruby.
-
Documentation is still lacking.
Key Building Blocks of Chef
Recipe
可以将其定义为用于管理基础设施的一系列属性的集合。配方中存在的这些属性用于更改现有状态或设置特定基础设施节点。它们在 Chef 客户端运行期间加载,并与节点(机器)的现有属性进行比较。然后它进入配方中的节点资源中定义的状态。它是菜谱的主力。
It can be defined as a collection of attributes which are used to manage the infrastructure. These attributes which are present in the recipe are used to change the existing state or setting a particular infrastructure node. They are loaded during Chef client run and comparted with the existing attribute of the node (machine). It then gets to the status which is defined in the node resource of the recipe. It is the main workhorse of the cookbook.
Cookbook
菜谱是一系列配方。它们是上传到 Chef 服务器的基本构建模块。当 Chef 运行发生时,它确保其内部的配方能将给定的基础设施达到配方中列出的所需状态。
A cookbook is a collection of recipes. They are the basic building blocks which get uploaded to Chef server. When Chef run takes place, it ensures that the recipes present inside it gets a given infrastructure to the desired state as listed in the recipe.
Resource
它是用来管理具有不同状态的基础设施的配方的一个基本组件。一个配方中可以有多个资源,这有助于配置和管理基础设施。例如:
It is the basic component of a recipe used to manage the infrastructure with different kind of states. There can be multiple resources in a recipe, which will help in configuring and managing the infrastructure. For example −
-
package − Manages the packages on a node
-
service − Manages the services on a node
-
user − Manages the users on the node
-
group − Manages groups
-
template − Manages the files with embedded Ruby template
-
cookbook_file − Transfers the files from the files subdirectory in the cookbook to a location on the node
-
file − Manages the contents of a file on the node
-
directory − Manages the directories on the node
-
execute − Executes a command on the node
-
cron − Edits an existing cron file on the node
Attribute
它们主要是设置。可以将其视为一个键值对,它可以是任何想要在 cookbooks 中使用的东西。有几种不同的属性可以应用,对节点操作的最终设置有着不同的优先级。
They are basically settings. They can be thought of as a key value pair of anything which one wants to use in the cookbook. There are several different kinds of attributes that can be applied, with a different level of precedence over the final settings that the node operates under.
File
它是 cookbook 中的一个子目录,包含任何将放置在使用 cookbooks 的节点上的静态文件。那么可以将配方声明为一个将文件从该目录移到最终节点的资源。
It’s a subdirectory within the cookbook that contains any static file which will be placed on the nodes that uses the cookbooks. A recipe then can be declared as a resource that moves the files from that directory to the final node.
Templates
它们与文件相似,但不是静态的。模板文件的扩展名为 .ebr,这意味着它们包含嵌入式 Ruby。它们主要用于在文件中替换属性值,以创建最终的文件版本,该版本将被放置在节点上。
They are similar to files, but they are not static. Template files end with the .ebr extension, which means they contain embedded Ruby. They are mainly used to substitute an attribute value into the files to create the final file version that will be placed on the node.
Metadata.rb
它用于管理有关软件包的元数据。这包括名称和软件包的详细信息等详细信息。它还包括依赖信息,这些信息会说明此 cookbooks 需要哪些 cookbooks 才能运行。这允许 Chef 服务器正确构建节点的运行列表,并确保所有部分都能正确传输。
It is used to manage the metadata about the package. This includes details like the name and details of the package. It also includes things such as dependency information that tells which cookbooks this cookbook needs to operate. This allows the Chef server to build the run-list of the node correctly and ensures that all of the pieces are transferred correctly.
Chef − Related Technologies
以下是 Chef 相关技术的列表。
Following is the list of Chef related technologies.
Puppet
Puppet 提供了一种在任何地方运行的软件传递和操作的标准化方法。它是 Linux、Unix 和 Windows 系统的一个自动化管理引擎,它可以根据集中化规范执行管理任务。
Puppet provides a standard way of delivering and operating software, no matter where it runs. It is an automated administrative engine for Linux, Unix, and Windows system that performs administrative tasks based on centralized specification.
主要的 features of Puppet 有如下内容:
The primary features of Puppet are as follows −
-
Implementing new systems with a uniform configuration.
-
Updating the systems and upgrading the security and software packages.
-
Incorporating new features and adding dexterous capabilities.
-
Customizing configurations for ensuring the availability of data sources.
-
Optimizing the available resources and minimizing the cost.
-
Simplifying the roles and enabling the team to focus on core and productive issues.
-
Getting a bird’s eye view of the available infrastructure.
Ansible
Ansible 是一个极为简单的 IT 自动化平台,它让您的应用程序和系统更易于部署。无需编写脚本或自定义代码来部署和更新您的应用程序——使用接近英语的语言以 SSH 形式自动化,无需在远程系统上安装任何代理。
Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications — automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.
主要 features of Ansible 如下 −
The primary features of Ansible are as follows −
-
Simple and easy to learn
-
Written in Python
-
Agentless
-
YAML-based Playbooks
-
Ansible galaxy
SaltStack
SaltStack 用于数据驱动配置。它是一种基于动态通信总线的新型基础设施管理方法。它用于数据驱动的编排、任何基础设施的远程执行以及任何应用程序堆栈的配置管理。
SaltStack is used for data-driven configuration. It is a new approach of infrastructure management built on dynamic communication bus. It is used for data-driven orchestration, remote execution for any infrastructure, and configuration management for any app stack.
Chef - Architecture
Chef 采用三层客户机服务器模式,其中工作单元(如食谱)均在 Chef 工作站上开发。从命令行实用程序(如刀)中,它们上传到 Chef 服务器,并且架构中呈现的所有节点均在 Chef 服务器中注册。
Chef works on a three-tier client server model wherein the working units such as cookbooks are developed on the Chef workstation. From the command line utilities such as knife, they are uploaded to the Chef server and all the nodes which are present in the architecture are registered with the Chef server.

为了获得到位的工作 Chef 基础设施,我们需要依次设置多个内容。
In order to get the working Chef infrastructure in place, we need to set up multiple things in sequence.
在以上设置中,我们有以下组件。
In the above setup, we have the following components.
Chef Workstation
这是所有配置开发所在的位置。Chef 工作站安装在本地计算机上。本教程的后续章节将讨论详细的配置结构。
This is the location where all the configurations are developed. Chef workstation is installed on the local machine. Detailed configuration structure is discussed in the later chapters of this tutorial.
Chef Server
这作为 Chef 设置的集中工作单元,所有配置文件在开发后都上传到此处。有不同类型的 Chef 服务器,有些是托管的 Chef 服务器,有些则是在场内构建的。
This works as a centralized working unit of Chef setup, where all the configuration files are uploaded post development. There are different kinds of Chef server, some are hosted Chef server whereas some are built-in premise.
Chef Nodes
它们是将由 Chef 服务器管理的实际计算机。所有节点可以根据要求具有不同类型的设置。Chef 客户端是所有节点的关键组件,有助于在 Chef 服务器和 Chef 节点之间建立通信。Chef 节点的其他组件是 Ohai,该组件有助于获取特定节点的当前状态。
They are the actual machines which are going to be managed by the Chef server. All the nodes can have different kinds of setup as per requirement. Chef client is the key component of all the nodes, which helps in setting up the communication between the Chef server and Chef node. The other components of Chef node is Ohai, which helps in getting the current state of any node at a given point of time.
Chef - Version Control System Setup
使用版本控制系统是基础设施自动化的基本部分。有多种版本的控制系统,例如 SVN、CVS 和 GIT。由于 GIT 在 Chef 社区中的流行,我们将使用 GIT 设置。
Using Version Control system is a fundamental part of infrastructure automation. There are multiple kinds of version control system such as SVN, CVS, and GIT. Due to the popularity of GIT among the Chef community, we will use the GIT setup.
Note − 不要不使用版本控制系统构建基础设施即代码。
Note − Don’t think of building an infrastructure as a code without a version control system.
On Windows
Step 1 − 从 www.git-scm.org 下载 Windows 安装程序,然后按照安装步骤进行操作。
Step 1 − Download the Windows installer from www.git-scm.org and follow the installation steps.
Step 2 − 在 GitHub 上注册一个中心仓库。
Step 2 − Sign up for a central repository on GitHub.
Step 3 − 将 SSH 密钥上传到 GitHub 账户,以便可以轻松地与其交互。有关 SSH 密钥的详细信息,请访问以下链接 https://help.github.com/articles/generatingssh-keys 。
Step 3 − Upload the ssh key to the GitHub account, so that one can interact with it easily. For details on ssh key visit the following link https://help.github.com/articles/generatingssh-keys.
Step 4 − 最后,使用 chef-repo 的名称访问 https://github.com/new ,在 github 账户上创建一个 repo。
Step 4 − Finally create a repo on the github account by visiting https://github.com/new with the name of chef-repo.
在实际开始编写食谱之前,可以在开发机上设置一个初始的 GIT 仓库,并克隆 Opscode 提供的空仓库。
Before actually starting to write a cookbook, one can set up an initial GIT repository on the development box and clone the empty repository provided by Opscode.
Step 1 − 下载 Opscode Chef 仓库的空结构。
Step 1 − Download Opscode Chef repository empty structure.
$ wget https://github.com/opscode/chef-repo/tarball/master
Step 2 − 提取 tar 包。
Step 2 − Extract the tar ball.
$ tar –xvf master
Step 3 − 重命名目录。
Step 3 − Rename the directory.
$ mv opscode-chef-repo-2c42c6a/ chef-repo
Step 4 − 将当前工作目录更改为 chef repo。
Step 4 − Change the current working directory to chef repo.
$ cd chef-repo
Step 5 − 初始化一个新的 get repo。
Step 5 − Initialize a fresh get repo.
$ git init.
Step 6 − 连接到 git hub 上的 repo。
Step 6 − Connect to your repo on the git hub.
$ git remote add origin git@github.com:vipin022/chef-
Step 7 − 将本地 repo 推送到 github。
Step 7 − Push the local repo to github.
$ git add.
$ git commit –m “empty repo structure added”
$ git push –u origin maste
通过使用上述过程,您将获得一个空的 chef repo。然后,您可以开始开发配方和食谱。完成后,可以将更改推送到 GitHub。
By using the above procedure, you will get an empty chef repo in place. You can then start working on developing the recipes and cookbooks. Once done, you can push the changes to the GitHub.
Chef - Workstation Setup
Chef 遵循客户端-服务器架构的理念,因此为了开始使用 Chef,需要在工作站上设置 Chef 并在本地开发配置。稍后可以将其上传到 Chef 服务器,使其在 Chef 节点上运行,需要对其进行配置。
Chef follows the concept of client-server architecture, hence in order to start working with Chef one needs to set up Chef on the workstation and develop the configuration locally. Later it can be uploaded to Chef server to make them working on the Chef nodes, which needs to be configured.
Opscode 提供了一个完整的打包版本,其中没有任何外部先决条件。这个完全打包的 Chef 被称为 omnibus installer 。
Opscode provides a fully packaged version, which does not have any external prerequisites. This fully packaged Chef is called the omnibus installer.
On Windows Machine
Step 1 − 在计算机上下载 chefDK 的安装 .msi 文件。
Step 1 − Download the setup .msi file of chefDK on the machine.
Step 2 − 按照安装步骤进行操作,并将其安装在目标位置。
Step 2 − Follow the installation steps and install it on the target location.
安装程序将如下面的屏幕截图所示。
The setup will look as shown in the following screenshot.

On Linux Machine
为了在 Linux 计算机上进行设置,我们首先需要在计算机上使用 curl。
In order to set up on the Linux machine, we need to first get curl on the machine.
Step 1 − 一旦在计算机上安装了 curl,我们需要使用 Opscode 的 omnibus chef 安装程序在工作站上安装 Chef。
Step 1 − Once curl is installed on the machine, we need to install Chef on the workstation using Opscode’s omnibus Chef installer.
$ curl –L https://www.opscode.com/chef/install.sh | sudo bash
Step 2 − 在机器上安装 Ruby。
Step 2 − Install Ruby on the machine.
Step 3 − 将 Ruby 添加到路径变量。
Step 3 − Add Ruby to path variable.
$ echo ‘export PATH = ”/opt/chef/embedded/bin:$PATH”’ ≫ ~/.bash_profile &&
source ~/.bash_profile
Chef 总线将把 Ruby 和所有必需的 Ruby gem 安装到 /opt/chef/embedded 中,方法是在 .bash_profile 文件中添加 /opt/chef/embedded/bin 目录。
The Omnibus Chef will install Ruby and all the required Ruby gems into /opt/chef/embedded by adding /opt/chef/embedded/bin directory to the .bash_profile file.
如果已安装 Ruby,则通过运行以下命令在机器上安装 Chef Ruby gem。
If Ruby is already installed, then install the Chef Ruby gem on the machine by running the following command.
$ gem install chef
Chef - Client Setup
为了使 Chef 节点与 Chef 服务器通信,您需要在节点上设置 Chef 客户端。
In order to make Chef node communicate with Chef server, you need to set up Chef client on the node.
Chef Client
这是 Chef 节点的关键组件之一,它从 Chef 服务器检索食谱并在节点上执行它们。它也被称为 Chef provisioner。
This is one of the key components of Chef node, which retrieves the cookbooks from the Chef server and executes them on the node. It is also known as the Chef provisioner.
在这里,我们将使用 Vagrant 来管理 VM。Vagrant 还可以使用 provisioner 配置,例如 Shell 脚本、Chef 和 Puppet,以使 VM 进入所需状态。在我们的例子中,我们将使用 Vagrant 使用 VirtualBox 和 Chef 客户端管理 VM。
Here, we will use Vagrant to manage VM. Vagrant can also be configured with the provisioner such as Shell script, Chef and Puppet to get VM into a desired state. In our case, we will use Vagrant to manage VMs using VirtualBox and Chef client as a provisioner.
Step 1 − 从 https://www.virtualbox.org/wiki/downlod 下载并安装 VirtualBox
Step 1 − Download and install VirtualBox from https://www.virtualbox.org/wiki/downlod
Step 2 − 从 http://downloads.vagrantup.com 下载并安装 Vagrant
Step 2 − Download and install Vagrant at http://downloads.vagrantup.com
Step 3 − 安装 Vagrant 总线插件,以便 Vagrant 能够在 VM 上安装 Chef 客户端。
Step 3 − Install Vagrant Omnibus plugin to enable Vagrant to install Chef client on the VM.
$ vagrant plugin install vagrant-omnibus
Creating and Booting Virtual
Step 1 − 我们可以从 Opscode vagrant repo 下载所需的 Vagrant box。从以下 URL 下载 opscode-ubuntu-12.04 box https://opscode-vmbento.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_provisionerless.box
Step 1 − We can download the required Vagrant box from the Opscode vagrant repo. Download the opscode-ubuntu-12.04 box from the following URL https://opscode-vmbento.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_provisionerless.box
Step 2 − 拥有 Vagrant 文件后,下载需要编辑 Vagrant 文件的路径。
Step 2 − Once you have the Vagrant file, download the path you need to edit the Vagrant file.
vipin@laptop:~/chef-repo $ subl Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "opscode-ubuntu-12.04"
config.vm.box_url = https://opscode-vm-bento.s3.amazonaws.com/
vagrant/opscode_ubuntu-12.04_provisionerless.box
config.omnibus.chef_version = :latest
config.vm.provision :chef_client do |chef|
chef.provisioning_path = "/etc/chef"
chef.chef_server_url = "https://api.opscode.com/
organizations/<YOUR_ORG>"
chef.validation_key_path = "/.chef/<YOUR_ORG>-validator.pem"
chef.validation_client_name = "<YOUR_ORG>-validator"
chef.node_name = "server"
end
end
在上面的程序中,您需要将 <YOUR_ORG> 名称更新为正确的或必需的组织名称。
In the above program, you need to update the <YOUR_ORG> name with the correct or required organization name.
Step 3 − 配置后的下一步是从启动 vagrant box。为此,您需移动到 vagrant box 所在位置并运行以下命令。
Step 3 − Next step after the configuration is, to get the vagrant box up. For this, you need to move to the location where Vagrant box is located and run the following command.
$ vagrant up
Step 4 − 机器启动后,您可以使用以下命令登录到机器。
Step 4 − Once the machine is up, you can login to the machine using the following command.
$ vagrant ssh
在上面的命令中,vagrantfile 在 Ruby 领域特定语言 (DSL) 中编写,用于配置 vagrant 虚拟机。
In the above command, vagrantfile is written in a Ruby Domain Specific Language (DSL) for configuring the vagrant virtual machine.
在 vagrant 文件中,我们有 config 对象。Vagrant 将使用此 config 对象来配置 VM。
In the vagrant file, we have the config object. Vagrant will use this config object to configure the VM.
Vagrant.configure("2") do |config|
…….
End
在 config 块内,您将告诉 vagrant 使用哪个 VM 映像,以便启动节点。
Inside the config block, you will tell vagrant which VM image to use, in order to boot the node.
config.vm.box = "opscode-ubuntu-12.04"
config.vm.box_url = https://opscode-vm-bento.s3.amazonaws.com/
vagrant/opscode_ubuntu-12.04_provisionerless.box
在下一步中,您将告诉 Vagrant 下载总线插件。
In the next step, you will tell Vagrant to download the omnibus plugin.
config.omnibus.chef_version = :latest
在选择要启动的 VM 框后配置如何使用 Chef 进行框配置。
After selecting the VM box to boot, configure how to provision the box using Chef.
config.vm.provision :chef_client do |chef|
…..
End
在此处内,您需要设置有关如何将虚拟节点连接至 Chef 服务器的说明。您需要告知 Vagrant 您需要在节点上存储所有 Chef 相关内容的位置。
Inside this, you need to set up instruction on how to hook up the virtual node to the Chef server. You need to tell Vagrant where you need to store all the Chef stuff on the node.
chef.provisioning_path = "/etc/chef"
Chef - Test Kitchen Setup
Test Kitchen 是 Chef 集成的测试框架。它启用书写测试配方,这些配方在实例化并通过配方汇总后将在 VM 上运行。测试配方在该 VM 上运行,并且可以验证所有内容是否按预期运行。
Test Kitchen is Chef’s integrated testing framework. It enables writing test recipes, which will run on the VMs once they are instantiated and converged using the cookbook. The test recipes run on that VM and can verify if everything works as expected.
ChefSpec 仅仅是模拟 Chef 运行。Test Kitchen 引导实际节点并在此节点上运行 Chef。
ChefSpec is something which only simulates a Chef run. Test kitchen boots up real node and runs Chef on it.
Step 1 - 安装 test kitchen Ruby gem 和 test kitchen vagrant gem,以使 test kitchen 能够使用 vagrant 启动测试。
Step 1 − Install test kitchen Ruby gem and test kitchen vagrant gem to enable test kitchen to use vagrant for spinning up test.
$ gem install kitchen
$ gem install kitchen-vagrant
Step 2 - 设置 test kitchen。这可通过在 cookboo 目录内创建 .kitchen.yml 完成。
Step 2 − Set up test kitchen. This can be done by creating .kitchen.yml in the cookbook directory.
driver_plugin: vagrant
driver_config:
require_chef_omnibus: true
platforms:
- name: ubuntu-12.04
driver_config:
box: opscode-ubuntu-12.04
box_url: https://opscode-vm.s3.amazonaws.com/vagrant/opscode_
ubuntu-12.04_provisionerless.box
suites:
- name: default
run_list:
- recipe[minitest-handler]
- recipe[my_cookbook_test]
attributes: { my_cookbook: { greeting: 'Ohai, Minitest!'} }
在上述代码中,一部分定义 vagrant 需要启动 VM,并定义您希望 Omnibus 将 Chef 安装到目标节点。
In the above code, one part defines that vagrant needs to spin up the VMs and it defines that you want Omnibus to install Chef on the target node.
第二部分定义您要测试 cookboo 的平台。Vagrant 将总是创建并摧毁新实例。您不必担心使用 Vagrant 文件启动的 vagrant VM 所带来的副作用。
The second part defines which platform you want to test the cookbooks. Vagrant will always create and destroy new instances. You do not have to fear about the side effects with vagrant VMs you spin up using Vagrant file.
Test Kitchen 可被认为是帮助在类似于生产环境的临时环境中运行和测试 cookboo 的临时环境。启用 test kitchen 后,在真正将指定代码部分部署到测试环境、预生产环境和生产环境之前,可以确定该部分是否运行。许多组织采用 test kitchen 的此项功能,作为在实际工作环境中放置 cookboo 的步骤。
Test kitchen can be considered as a temporary environment that helps to run and test cookbooks in a temporary environment that is similar to production. With test kitchen on, one can make sure that the given piece of code is working, before it is actually getting deployed on to testing, preproduction, and production environment. This feature of test kitchen is followed by many organizations as a set before putting the cookbooks in an actual working environment.
Test Kitchen Workflow
以下是 Test Kitchen Workflow 所涉及的步骤。
Following are the steps involved in Test Kitchen Workflow.

Creating a Cookbook Using Chef
使用以下代码创建 cookbook。
Use the following code to create a cookbook.
$ chef generate cookbook motd_rhel
Installing Cookbook Gems:
Compiling Cookbooks...
Recipe: code_generator::cookbook
* directory[C:/chef/cookbooks/motd_rhel] action create
- create new directory C:/chef/cookbooks/motd_rhel
* template[C:/chef/cookbooks/motd_rhel/metadata.rb] action create_if_missing
- create new file C:/chef/cookbooks/motd_rhel/metadata.rb
- update content in file C:/chef/cookbooks/motd_rhel/metadata.rb from none to
d6fcc2 (diff output suppressed by config)
* template[C:/chef/cookbooks/motd_rhel/README.md] action create_if_missing
- create new file C:/chef/cookbooks/motd_rhel/README.md
- update content in file C:/chef/cookbooks/motd_rhel/README.md from none to 50deab
(diff output suppressed by config)
* cookbook_file[C:/chef/cookbooks/motd_rhel/chefignore] action create
- create new file C:/chef/cookbooks/motd_rhel/chefignore
- update content in file C:/chef/cookbooks/motd_rhel/chefignore from none to 15fac5
(diff output suppressed by config)
* cookbook_file[C:/chef/cookbooks/motd_rhel/Berksfile] action create_if_missing
- create new file C:/chef/cookbooks/motd_rhel/Berksfile
- update content in file C:/chef/cookbooks/motd_rhel/Berksfile from none to 9f08dc
(diff output suppressed by config)
* template[C:/chef/cookbooks/motd_rhel/.kitchen.yml] action create_if_missing
- create new file C:/chef/cookbooks/motd_rhel/.kitchen.yml
- update content in file C:/chef/cookbooks/motd_rhel/.kitchen.yml
from none to 49b92b (diff output suppressed by config)
* directory[C:/chef/cookbooks/motd_rhel/test/integration/default/serverspec]
action create
- create new directory
C:/chef/cookbooks/motd_rhel/test/integration/default/serverspec
* directory[C:/chef/cookbooks/motd_rhel/test/integration/helpers/serverspec]
action create
- create new directory
C:/chef/cookbooks/motd_rhel/test/integration/helpers/serverspec
* cookbook_file
[C:/chef/cookbooks/motd_rhel/test/integration/helpers/serverspec/spec_helper.rb]
action create_if_missing
- create new file
C:/chef/cookbooks/motd_rhel/test/integration/helpers/serverspec/spec_helper.rb
- update content in file
C:/chef/cookbooks/motd_rhel/test/integration/helpers/serverspec/spec_helper.rb
from none to d85df4 (diff output suppressed by config)
* template
[C:/chef/cookbooks/motd_rhel/test/integration/default/serverspec/defaul t_spec.rb]
action create_if_missing
- create new file
C:/chef/cookbooks/motd_rhel/test/integration/default/serverspec/default_spec.rb
- update content in file
C:/chef/cookbooks/motd_rhel/test/integration/default/serverspec/default_spec.rb
from none to 3fbdbd (diff output suppressed by config)
* directory[C:/chef/cookbooks/motd_rhel/spec/unit/recipes] action create
- create new directory C:/chef/cookbooks/motd_rhel/spec/unit/recipes
* cookbook_file
[C:/chef/cookbooks/motd_rhel/spec/spec_helper.rb] action create_if_missing
- create new file C:/chef/cookbooks/motd_rhel/spec/spec_helper.rb
- update content in file
C:/chef/cookbooks/motd_rhel/spec/spec_helper.rb from none to 587075
(diff output suppressed by config)
* template
[C:/chef/cookbooks/motd_rhel/spec/unit/recipes/default_spec.rb]
action create_if_missing
- create new file C:/chef/cookbooks/motd_rhel/spec/unit/recipes/default_spec.rb
- update content in file
C:/chef/cookbooks/motd_rhel/spec/unit/recipes/default_spec.rb
from none to ff3b17 (diff output suppressed by config)
* directory[C:/chef/cookbooks/motd_rhel/recipes] action create
- create new directory C:/chef/cookbooks/motd_rhel/recipes
* template[C:/chef/cookbooks/motd_rhel/recipes/default.rb] action create_if_missing
- create new file C:/chef/cookbooks/motd_rhel/recipes/default.rb
- update content in file
C:/chef/cookbooks/motd_rhel/recipes/default.rb from none to c4b029
(diff output suppressed by config)
* execute[initialize-git] action run
- execute git init .
* cookbook_file[C:/chef/cookbooks/motd_rhel/.gitignore] action create
- create new file C:/chef/cookbooks/motd_rhel/.gitignore
- update content in file C:/chef/cookbooks/motd_rhel/.gitignore from none to 33d469
(diff output suppressed by config)
* execute[git-add-new-files] action run
- execute git add .
* execute[git-commit-new-files] action run
- execute git commit -m "Add generated cookbook content"
以下是上述代码的输出作为创建的 Cookbook 结构。
Following is the Created Cookbook Structure as an output of the above code.

Test Kitchen Configuration File
.kitchen.yaml file
driver:
name: vagrant
provisioner:
name: chef_zero
# verifier:
# name: inspec
# format: doc
platforms:
- name: ubuntu-14.04
suites:
- name: default
run_list:
- recipe[motd_rhel::default]
attributes:
Drivers - 指定管理计算机软件。
Drivers − It specifies the software which manages the machine.
Provisioner - 提供有关 Chef 运行方式的规范。我们使用 chef_zero,因为它能够在 local 计算机上模仿 Chef 服务器环境。这允许使用节点属性和 Chef 服务器规范。
Provisioner − It provides specification on how Chef runs. We are using chef_zero because it enables to mimic a Chef server environment on the local machine. This allows to work with node attributes and Chef server specifications.
Platform - 指定目标操作系统。
Platform − This specifies the target operating system.
Suites - 定义希望应用到虚拟环境的内容。在此处,定义多个定义。它是在定义运行列表的位置,该列表指定要运行的配方和需要运行这些配方的顺序。
Suites − It defines what one wants to apply on the virtual environment. Here, you define multiple definition. It is the location where you define the run list, which specifies which recipe to run and in which sequence we need to run.
Running the Commands in Sequence
Kitchen List
$ kitchen list
Instance Driver Provisioner Verifier Transport Last Action
ubuntu-1404 Vagrant ChefZero Busser Ssh <Not Created>
Kitchen Create
$ kitchen create
-----> Starting Kitchen (v1.4.2)
-----> Creating <default-centos-72>...
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'opscode-centos-7.2' could not be found.
Attempting to find and install...
default: Box Provider: virtualbox
default: Box Version: >= 0
==> default: Box file was not detected as metadata. Adding it directly...
==> default: Adding box 'opscode-centos-7.2' (v0) for provider: virtualbox
default: Downloading:
https://opscode-vmbento.s3.amazonaws.com/vagrant/virtualbox/
opscode_centos-7.1_chefprovisionerless.box[...]
Vagrant instance <default-centos-72> created.
Finished creating <default-centos-72> (3m12.01s).
-----> Kitchen is finished. (3m12.60s)
Kitchen Converge
$ kitchen converge
-----> Converging <default-centos-72>...
Preparing files for transfer
Preparing dna.json
Resolving cookbook dependencies with Berkshelf 4.0.1...
Removing non-cookbook files before transfer
Preparing validation.pem
Preparing client.rb
-----> Chef Omnibus installation detected (install only if missing)
Transferring files to <default-centos-72>
Starting Chef Client, version 12.6.0
resolving cookbooks for run list: ["motd_rhel::default"]
Synchronizing Cookbooks: - motd_rhel (0.1.0)
Compiling Cookbooks... Converging 1 resources
Recipe: motd_rhel::default (up to date)
Running handlers: Running handlers complete
Chef Client finished, 0/1 resources updated in 01 seconds
Finished converging <default-centos-72> (0m3.57s).
-----> Kitchen is finished. (0m4.55s)
Testing Setup
Kitchen login 用于测试测试 VM 是否得到正确配置。
Kitchen login is used to test if the testing VM is provisioned correctly.
$ kitchen login
Last login: Thu Jan 30 19:02:14 2017 from 10.0.2.2
hostname: default-centos-72
fqdn: default-centos-72
memory: 244180kBcpu count: 1
Destroying Setup
$ Kitchen destroy
-----> Starting Kitchen (v1.4.2)
-----> Destroying <default-centos-72>...
==> default: Forcing shutdown of VM...
==> default: Destroying VM and associated drives...
Vagrant instance <default-centos-72> destroyed.
Finished destroying <default-centos-72> (0m4.94s).
-----> Kitchen is finished. (0m5.93s)
Chef - Knife Setup
Knife 是 Chef 的命令行工具,用于与 Chef 服务器进行交互。人们使用它来上传 cookbook 并管理 Chef 的其他方面。它在本地计算机上的 chefDK(Repo)与 Chef 服务器之间提供一个界面。它有助于管理:
Knife is Chef’s command-line tool to interact with the Chef server. One uses it for uploading cookbooks and managing other aspects of Chef. It provides an interface between the chefDK (Repo) on the local machine and the Chef server. It helps in managing −
-
Chef nodes
-
Cookbook
-
Recipe
-
Environments
-
Cloud Resources
-
Cloud Provisioning
-
Installation on Chef client on Chef nodes
Knife 提供了一组用于管理 Chef 基础设施的命令。
Knife provides a set of commands to manage Chef infrastructure.
Client Commands
-
knife client bulk delete REGEX (options)
-
knife client create CLIENTNAME (options)
-
knife client delete CLIENT (options)
-
knife client edit CLIENT (options)
-
Usage: C:/opscode/chef/bin/knife (options)
-
knife client key delete CLIENT KEYNAME (options)
-
knife client key edit CLIENT KEYNAME (options)
-
knife client key list CLIENT (options)
-
knife client key show CLIENT KEYNAME (options)
-
knife client list (options)
-
knife client reregister CLIENT (options)
-
knife client show CLIENT (options)
Cookbook Commands
-
knife cookbook bulk delete REGEX (options)
-
knife cookbook create COOKBOOK (options)
-
knife cookbook delete COOKBOOK VERSION (options)
-
knife cookbook download COOKBOOK [VERSION] (options)
-
knife cookbook list (options)
-
knife cookbook metadata COOKBOOK (options)
-
knife cookbook metadata from FILE (options)
-
knife cookbook show COOKBOOK [VERSION] [PART] [FILENAME] (options)
-
knife cookbook test [COOKBOOKS…] (options)
-
knife cookbook upload [COOKBOOKS…] (options)
Cookbook Site Commands
-
knife cookbook site download COOKBOOK [VERSION] (options)
-
knife cookbook site install COOKBOOK [VERSION] (options)
-
knife cookbook site list (options)
-
knife cookbook site search QUERY (options)
-
knife cookbook site share COOKBOOK [CATEGORY] (options)
-
knife cookbook site show COOKBOOK [VERSION] (options)
-
knife cookbook site unshare COOKBOOK
Data Bag Commands
-
knife data bag create BAG [ITEM] (options)
-
knife data bag delete BAG [ITEM] (options)
-
knife data bag edit BAG ITEM (options)
-
knife data bag from file BAG FILE|FOLDER [FILE|FOLDER..] (options)
-
knife data bag list (options)
-
knife data bag show BAG [ITEM] (options)
Environment Commands
-
knife environment compare [ENVIRONMENT..] (options)
-
knife environment create ENVIRONMENT (options)
-
knife environment delete ENVIRONMENT (options)
-
knife environment edit ENVIRONMENT (options)
-
knife environment from file FILE [FILE..] (options)
-
knife environment list (options)
-
knife environment show ENVIRONMENT (options)
Node Commands
-
knife node bulk delete REGEX (options)
-
knife node create NODE (options)
-
knife node delete NODE (options)
-
knife node edit NODE (options)
-
knife node environment set NODE ENVIRONMENT
-
knife node from file FILE (options)
-
knife node list (options)
-
knife node run_list add [NODE] [ENTRY[,ENTRY]] (options)
-
knife node run_list remove [NODE] [ENTRY[,ENTRY]] (options)
-
knife node run_list set NODE ENTRIES (options)
-
knife node show NODE (options)
OSC Commands
-
knife osc_user create USER (options)
-
knife osc_user delete USER (options)
-
knife osc_user edit USER (options)
-
knife osc_user list (options)
-
knife osc_user reregister USER (options)
-
knife osc_user show USER (options)
Path-Based Commands
-
knife delete [PATTERN1 … PATTERNn]
-
knife deps PATTERN1 [PATTERNn]
-
knife diff PATTERNS
-
knife download PATTERNS
-
knife edit [PATTERN1 … PATTERNn]
-
knife list [-dfR1p] [PATTERN1 … PATTERNn]
-
knife show [PATTERN1 … PATTERNn]
-
knife upload PATTERNS
-
knife xargs [COMMAND]
Role Commands
-
knife role bulk delete REGEX (options)
-
knife role create ROLE (options)
-
knife role delete ROLE (options)
-
knife role edit ROLE (options)
-
knife role env_run_list add [ROLE] [ENVIRONMENT] [ENTRY[,ENTRY]] (options)
-
knife role env_run_list clear [ROLE] [ENVIRONMENT]
-
knife role env_run_list remove [ROLE] [ENVIRONMENT] [ENTRIES]
-
knife role env_run_list replace [ROLE] [ENVIRONMENT] [OLD_ENTRY] [NEW_ENTRY]
-
knife role env_run_list set [ROLE] [ENVIRONMENT] [ENTRIES]
-
knife role from file FILE [FILE..] (options)
-
knife role list (options)
-
knife role run_list add [ROLE] [ENTRY[,ENTRY]] (options)
-
knife role run_list clear [ROLE]
-
knife role run_list remove [ROLE] [ENTRY]
-
knife role run_list replace [ROLE] [OLD_ENTRY] [NEW_ENTRY]
-
knife role run_list set [ROLE] [ENTRIES]
-
knife role show ROLE (options)
User Commands
-
knife user create USERNAME DISPLAY_NAME FIRST_NAME LAST_NAME EMAIL PASSWORD (options)
-
knife user delete USER (options)
-
knife user edit USER (options)
-
knife user key create USER (options)
-
knife user key delete USER KEYNAME (options)
-
knife user key edit USER KEYNAME (options)
-
knife user key list USER (options)
-
knife user key show USER KEYNAME (options)
-
knife user list (options)
-
knife user reregister USER (options)
-
knife user show USER (options)
Knife Setup
为了设置 Knife,需要移动到 .chef 目录并在 Chef 仓库中创建 knife.rb ,它会告知 Knife 有关配置详情。这里会有几个详细信息。
In order to set up knife, one needs to move to .chef directory and create a knife.rb inside the chef repo, which tells knife about the configuration details. This will have a couple up details.
current_dir = File.dirname(__FILE__)
log_level :info
log_location STDOUT
node_name 'node_name'
client_key "#{current_dir}/USER.pem"
validation_client_name 'ORG_NAME-validator'
validation_key "#{current_dir}/ORGANIZATION-validator.pem"
chef_server_url 'https://api.chef.io/organizations/ORG_NAME'
cache_type 'BasicFile'
cache_options( :path => "#{ENV['HOME']}/.chef/checksums" )
cookbook_path ["#{current_dir}/../cookbooks"]
在上面的代码中,我们使用的是托管 Chef 服务器,它采用以下两个密钥。
In the above code, we are using the hosted Chef server which uses the following two keys.
validation_client_name 'ORG_NAME-validator'
validation_key "#{current_dir}/ORGANIZATION-validator.pem"
此处,knife.rb 告知 Knife 要使用哪个组织以及在哪儿查找私钥。它告知 Knife 在哪儿查找用户的私钥。
Here, knife.rb tells knife which organization to use and where to find the private key. It tells knife where to find the users’ private key.
client_key "#{current_dir}/USER.pem"
以下代码行告知 Knife 我们使用的是托管服务器。
The following line of code tells knife we are using the hosted server.
chef_server_url 'https://api.chef.io/organizations/ORG_NAME'
使用 knife.rb 文件,validator knife 现在可以连接到您组织的托管 Opscode。
Using the knife.rb file, the validator knife can now connect to your organization’s hosted Opscode.
Chef - Solo Setup
Chef-Solo 是一款开放源代码工具,可在本地运行,且能够使用 Chef 食谱预配置客户机,避免任何 Chef 客户端和服务器配置的复杂性。它有助于在自创建的服务器上执行食谱。
Chef-Solo is an open source tool that runs locally and allows to provision guest machines using Chef cookbooks without the complication of any Chef client and server configuration. It helps to execute cookbooks on a self-created server.
在本地计算机上运行 Chef-Solo 前,需要在本地计算机上安装以下两个文件。
Before running Chef-Solo on the local machine, one needs to install the following two files on the local machine.
-
Solo.rb − This file tells Chef about where to find cookbooks, roles, and data bags.
-
Node.json − This file sets the run list and any node-specific attribute, if required.
solo.rb Configuration
以下是配置 solo.rb 的步骤。
Following are the steps to configure solo.rb.
Step 1 − 在厨师存储库中创建一个 solo.rb 文件。
Step 1 − Create a solo.rb file inside the chef repo.
current_dir = File.expand_path(File.dirname(__FILE__))
file_cache_path "#{current_dir}"
cookbook_path "#{current_dir}/cookbooks"
role_path "#{current_dir}/roles"
data_bag_path "#{current_dir}/data_bags"
Step 2 − 将该文件添加到 git 存储库。
Step 2 − Add the file to git repo.
$ git add solo.rb
Step 3 − 在厨师存储库中创建一个 node.json 文件,其内容如下。
Step 3 − Create a node.json file inside the chef repo with the following content.
{
"run_list": [ "recipe[ntp]" ]
}
Step 4 − 使用 knife 在厨师存储库中获取 ntp 食谱。
Step 4 − Get the ntp cookbook inside the chef repo using knife.
vipin@laptop:~/chef-repo $ knife cookbook site install ntp
Installing ntp to /Users/mma/work/chef-repo/cookbooks
…TRUNCATED OUTPUT…
Cookbook ntp version 1.3.0 successfully installed
Step 5 − 将 node.json 文件添加到 Git。
Step 5 − Add the node.json file to Git.
$ git add node.json
Step 6 − 提交并推送文件到 git 存储库。
Step 6 − Commit and push the files to git repo.
vipin@laptop:~/chef-repo $ git commit -m "initial setup for Chef Solo"
vipin@laptop:~/chef-repo $ git push
Counting objects: 4, done.
Delta compression using up to 4 threads.
...TRUNCATED OUTPUT...
To git@github.com:mmarschall/chef-repo.git
b930647..5bcfab6 master -> master
Running the Cookbook on the Node
Step 1 − 登录到想要设置 Chef-Solo 的节点。
Step 1 − Login to the node where one wants to provision the Chef-Solo.
Step 2 − 在计算机上克隆厨师存储库。
Step 2 − Clone the Chef repo on the machine.
$ git clone $URL_PATH
Step 3 − cd 到厨师存储库。
Step 3 − cd to the chef repo.
$ cd chef-repo
最后,运行 Chef-Solo 以合并节点 −
Finally, run the Chef-Solo to converge the node −
$ sudo chef-solo -c solo.rb -j node.json
[2017-20-08T22:54:13+01:00] INFO: *** Chef 11.0.0 ***
[2017-20-08T22:54:13+01:00] INFO: Setting the run_list to
["recipe[ntp]"] from JSON
...TRUNCATED OUTPUT...
[2012-12-08T22:54:16+01:00] INFO: Chef Run complete in 2.388374
seconds
[2012-12-08T22:54:16+01:00] INFO: Running report handlers
solo.rb 将 Chef-Solo 配置为在其当前目录(厨师存储库)中查找其食谱、角色和数据包。
solo.rb configures Chef-Solo to look for its cookbooks, roles, and data bags inside the current directory: the Chef repository.
Chef-Solo 从一个 JSON 文件中获取其节点配置。在我们的示例中,我们称之为 node.json。如果您要管理多台服务器,则需要为每个节点提供一个单独的文件。然后,Chef-Solo 仅根据 solo.rb 和 node.json 中找到的配置数据执行一个 Chef 运行。
Chef-Solo takes its node configuration from a JSON file. In our example, we called it node.json. If you’re going to manage multiple servers, you’ll need a separate file for each node. Then, Chef-Solo just executes a Chef run based on the configuration data found in solo.rb and node.json.
Chef - Cookbooks
食谱是 Chef 的基本工作单元,其中包含所有与工作单元相关的信息,它能够修改配置以及配置为 Chef 基础设施节点的任何系统的状态。食谱可以执行多项任务。食谱包含有关节点所需状态的一些值。这是通过使用所需的外部库在 Chef 中实现的。
Cookbooks are fundamental working units of Chef, which consists of all the details related to working units, having the capability to modify configuration and the state of any system configured as a node on Chef infrastructure. Cookbooks can perform multiple tasks. Cookbooks contain values about the desired state of node. This is achieved in Chef by using the desired external libraries.
Key Components of a Cookbook
-
Recipes
-
Metadata
-
Attributes
-
Resources
-
Templates
-
Libraries
-
Anything else that helps to create a system
Creating a Cookbook
可以通过两种方式动态创建食谱。
There are two ways to dynamically create a cookbook.
-
Using chef command
-
Using knife utility
Using Chef Command
要创建空的 Cookbook,请使用 Chef 命令运行以下命令。
To create an empty cookbook using Chef command, run the following command.
C:\Users\vipinkumarm>chef generate cookbook <Cookbook Name>
C:\Users\vipinkumarm>chef generate cookbook VTest
Installing Cookbook Gems:
Compiling Cookbooks...
Recipe: code_generator::cookbook
* directory[C:/Users/vipinkumarm/VTest] action create
- create new directory C:/Users/vipinkumarm/VTest
* template[C:/Users/vipinkumarm/VTest/metadata.rb] action create_if_missing
- create new file C:/Users/vipinkumarm/VTest/metadata.rb
- update content in file C:/Users/vipinkumarm/VTest/metadata.rb
from none to 4b9435 (diff output suppressed by config)
* template[C:/Users/vipinkumarm/VTest/README.md] action create_if_missing
- create new file C:/Users/vipinkumarm/VTest/README.md
- update content in file C:/Users/vipinkumarm/VTest/README.md
from none to 482077 (diff output suppressed by config)
* cookbook_file[C:/Users/vipinkumarm/VTest/chefignore] action create
- create new file C:/Users/vipinkumarm/VTest/chefignore
- update content in file C:/Users/vipinkumarm/VTest/chefignore
from none to 15fac5 (diff output suppressed by config)
* cookbook_file[C:/Users/vipinkumarm/VTest/Berksfile] action create_if_missing
- create new file C:/Users/vipinkumarm/VTest/Berksfile
- update content in file C:/Users/vipinkumarm/VTest/Berksfile
from none to 9f08dc (diff output suppressed by config)
* template[C:/Users/vipinkumarm/VTest/.kitchen.yml] action create_if_missing
- create new file C:/Users/vipinkumarm/VTest/.kitchen.yml
- update content in file C:/Users/vipinkumarm/VTest/.kitchen.yml
from none to 93c5bd (diff output suppressed by config)
* directory[C:/Users/vipinkumarm/VTest/test/integration/default/serverspec]
action create
- create new directory
C:/Users/vipinkumarm/VTest/test/integration/default/serverspec
* directory[C:/Users/vipinkumarm/VTest/test/integration/helpers/serverspec]
action create
- create new directory
C:/Users/vipinkumarm/VTest/test/integration/helpers/serverspec
* cookbook_file
[C:/Users/vipinkumarm/VTest/test/integration/helpers/serverspec/sp ec_helper.rb]
action create_if_missing
- create new file
C:/Users/vipinkumarm/VTest/test/integration/helpers/serverspec/spec_helper.rb
- update content in file
C:/Users/vipinkumarm/VTest/test/integration/helpers/serverspec/spec_helper.rb
from none to d85df4 (diff output suppressed by config)
* template
[C:/Users/vipinkumarm/VTest/test/integration/default/serverspec/default _spec.rb]
action create_if_missing
- create new file
C:/Users/vipinkumarm/VTest/test/integration/default/serverspec/default_spec.rb
- update content in file
C:/Users/vipinkumarm/VTest/test/integration/default/serverspec/default_spec.rb
from none to 758b94 (diff output suppressed by config)
* directory[C:/Users/vipinkumarm/VTest/spec/unit/recipes] action create
- create new directory C:/Users/vipinkumarm/VTest/spec/unit/recipes
* cookbook_file[C:/Users/vipinkumarm/VTest/spec/spec_helper.rb]
action create_if_missing
- create new file C:/Users/vipinkumarm/VTest/spec/spec_helper.rb
- update content in file C:/Users/vipinkumarm/VTest/spec/spec_helper.rb
from none to 587075 (diff output suppressed by config)
* template[C:/Users/vipinkumarm/VTest/spec/unit/recipes/default_spec.rb]
action create_if_missing
- create new file C:/Users/vipinkumarm/VTest/spec/unit/recipes/default_spec.rb
- update content in file
C:/Users/vipinkumarm/VTest/spec/unit/recipes/default_spec.rb
from none to 779503 (diff output suppressed by config)
- create new file C:/Users/vipinkumarm/VTest/recipes/default.rb
- update content in file C:/Users/vipinkumarm/VTest/recipes/default.rb
from none to 8cc381 (diff output suppressed by config)
* cookbook_file[C:/Users/vipinkumarm/VTest/.gitignore] action create
- create new file C:/Users/vipinkumarm/VTest/.gitignore
- update content in file C:/Users/vipinkumarm/VTest/.gitignore from none to 33d469
(diff output suppressed by config)
带 VTest 名称的 Cookbook 结构将创建在目录中,并且 Cookbook 结构也将遵循以下结构。
The cookbook structure with the name VTest will be created in the directory and following will be the structure for the same.

Using Knife Utility
使用以下命令使用刀具程序创建 Cookbook。
Use the following command to create a cookbook using knife utility.
C:\Users\vipinkumarm\VTest>knife cookbook create VTest2
WARNING: No knife configuration file found
** Creating cookbook VTest2 in C:/chef/cookbooks
** Creating README for cookbook: VTest2
** Creating CHANGELOG for cookbook: VTest2
** Creating metadata for cookbook: VTest2
以下是 Cookbook 结构。
Following will be the structure of the cookbook.

Chef - Cookbook Dependencies
定义 Cookbook 依赖项的功能有助于管理 Cookbook。当我们在其他 Cookbook 中想要使用一个 Cookbook 的功能时,就会使用该功能。
The features of defining cookbook dependencies help in managing cookbook. This feature is used when we want to use the functionality of one cookbook in other cookbooks.
例如,如果想要编译 C 代码,则需要确保安装了编译所需的全部依赖项。要进行编译,可能会有能够执行这种功能的独立 Cookbook。
For example, if one wants to compile C code then one needs to make sure that all the dependencies required to compile are installed. In order to do so, there might be separate cookbook which can perform such a function.
当我们在使用 Chef 服务器时,需要了解 Cookbook 中的这些依赖项,应在 Cookbook 元数据文件中对此进行延迟处理。此文件位于 Cookbook 目录结构的顶部。它会提供提示给 Chef 服务器,该服务器有助于在正确的节点上部署 Cookbook。
When we are using chef-server, we need to know such dependencies in cookbooks which should be decelerated in the cookbooks metadata file. This file is located at the top on the cookbook directory structure. It provides hints to the Chef server which helps in deploying cookbooks on the correct node.
Chef - Roles
Chef 中的角色是按逻辑方式分组节点的一种方式。通常情况下,角色用于 Web 服务器、数据库服务器等。用户可以设置所有节点的自定义运行列表并覆盖角色中的属性值。
Roles in Chef are a logical way of grouping nodes. Typical cases are to have roles for web servers, database servers, and so on. One can set custom run list for all the nodes and override attribute value within roles.
Create a Role
vipin@laptop:~/chef-repo $ subl roles/web_servers.rb
name "web_servers"
description "This role contains nodes, which act as web servers"
run_list "recipe[ntp]"
default_attributes 'ntp' => {
'ntpdate' => {
'disable' => true
}
}
一旦创建了角色,我们需要将角色上传到 Chef 服务器。
Once we have the role created, we need to upload to the Chef server.
Upload Role to Chef Server
vipin@laptop:~/chef-repo $ knife role from file web_servers.rb
现在,我们需要为名为 server 的节点分配一个角色。
Now, we need to assign a role to a node called server.
Assign a Role to Node
vipin@laptop:~/chef-repo $ knife node edit server
"run_list": [
"role[web_servers]"
]
Saving updated run_list on node server
Run the Chef-Client
user@server:~$ sudo chef-client
...TRUNCATED OUTPUT...
[2013-07-25T13:28:24+00:00] INFO: Run List is [role[web_servers]]
[2013-07-25T13:28:24+00:00] INFO: Run List expands to [ntp]
...TRUNCATED OUTPUT...
How It Works
-
Define a role in a Ruby file inside the roles folder of Chef repository.
-
A role consists of a name and a description attribute.
-
A role consists of role-specific run list and role-specific attribute settings.
-
Every node that has a role in its run list will have the role’s run list exacted into its own.
-
All the recipes in the role’s run list will be executed on the node.
-
The role will be uploaded to Chef server using the knife role from file command.
-
The role will be added to the node run list.
-
Running Chef client on a node having the role in its run list will execute all the recipes listed in the role.
Chef - Environment
Chef 帮助执行特定于环境的配置。为开发、测试和生产准备单独的环境始终是一个好主意。
Chef helps in performing environment specific configuration. It is always a good idea to have a separate environment for development, testing, and production.
Chef 能够将节点分组到单独的环境中,以支持排序的开发流。
Chef enables grouping nodes into separate environments to support an ordered development flow.
Creating an Environment
可以使用刀具实用工具在执行期间创建环境。以下命令将打开 Shell 的默认编辑器,以便修改环境定义。
Creation of environment on the fly can be done using the knife utility. Following command will open a Shell’s default editor, so that one can modify the environment definition.
vipin@laptop:~/chef-repo $ knife environment create book {
"name": "book",
"description": "",
"cookbook_versions": {
},
"json_class": "Chef::Environment",
"chef_type": "environment",
"default_attributes": {
},
"override_attributes": {
}
}
Created book
_default Environment
各个组织始终会从至少一个名为默认环境的环境开始,Chef server 始终提供该环境。无法以任何方式修改默认环境。仅可调整我们创建的自定义环境中的任何类型更改。
Each organization will always start with at least a single environment called default environment, which is always available to the Chef server. A default environment cannot be modified in anyway. Any kind of changes can only be accommodated in the custom environment that we create.
Environment Attributes
可以在环境中定义属性,进而使用这些属性替代节点中的默认设置。当 Chef 客户端运行时,将把这些属性与已经存在于节点中的默认属性进行比较。当环境属性优先于默认属性时,Chef 客户端在每个节点上运行 Chef 客户端时会应用这些设置和值。
An attribute can be defined in an environment and then used to override the default settings in the node. When the Chef client run takes place, then these attributes are compared with the default attributes that are already present in the node. When the environment attributes take precedence over the default attributes, Chef client will apply these settings and values when the Chef client run takes place on each node.
环境属性只能是 default_attribute 或 override_attribute。它不能是普通属性。可以使用 default_attribute 或 override_attribute 方法。
An environment attribute can only be either default_attribute or override_attribute. It cannot be a normal attribute. One can use default_attribute or override_attribute methods.
Attribute Type
Default − 默认属性始终在每次 Chef 客户端运行开始时重置,并且具有最低的属性优先级。
Default − A default attribute is always reset at the start of every Chef client run and have the lowest attribute precedence.
Override − 替代属性始终在每次 Chef 客户端运行开始时重置,并且具有比 default、force_default 和 normal 更高的属性优先级。替代属性最常在食谱中定义,但也可在角色或环境的属性文件。
Override − An override attribute is always reset at the start of every Chef client run and has a higher attribute precedence than default, force_default and normal. An override attribute is most often defined in the recipe but can also be specified in an attribute file for a role or for an environment.
Chef - Chef-Client as Daemon
以守护程序的身份运行 Chef-Client 有助于随时了解所有节点的状态。这有助于随时运行 Chef-Client。
Running Chef-Client as daemon helps in knowing the state of all the nodes at any point of time. This help in running the Chef-Client at any point of time.
Pre-requisites
该节点应向 Chef server 注册,并且应该在不出现任何错误的情况下运行 Chef-Client。
The node should be registered with Chef server and it should be running Chef-Client without any error.
Chef-Client in Daemon Mode
以守护程序模式启动 Chef-Client,每 30 分钟运行一次。
Start Chef-Client in daemon mode, running every 30 minutes.
user@server:~$ sudo chef-client -i 1800
在上面的代码中,– i 使能够在所需节点上以守护程序模式运行 Chef-Client,而 1800 秒定义了 Chef-Client 守护程序应每 30 分钟运行一次。
In the above code, – i enables to run the Chef-Client in daemon mode on the required node and 1800 seconds define that the Chef-Client daemon should run in every 30 minutes.
Validating Daemon Run
对 Chef-Client 作为守护程序运行进行验证。
Validate that the Chef-Client is running as a daemon.
user@server:~$ ps auxw | grep chef-client
上述命令将 grep Chef-Client 守护程序进程。
The above command will grep the running daemon process of Chef-Client.
Other Ways
我们可以将 Chef-Client 作为 cron job 运行,而不作为守护程序运行它。
Instead of running Chef-Client as a daemon, we can run the same as a cron job.
user@server:~$ subl /etc/cron.d/chef_client
PATH=/usr/local/bin:/usr/bin:/bin
# m h dom mon dow user command
*/15 * * * * root chef-client -l warn | grep -v 'retrying [1234]/5 in'
上面的 cron 作业将在每 15 分钟后运行。
The above cron job will run after every 15 minutes.
Chef - Chef-Shell
编写 Chef 烹饪书总是困难的。它让事情变得更加困难,因为它上传到 Chef 服务器、配置流浪 VM、检查它们在那里如何失败、冲洗和重复的漫长反馈周期。如果我们可以在一次完成所有这些繁重的工作之前尝试测试一些碎片或配方,那会更容易。
Writing Chef cookbooks is always hard. It makes it even harder because of long feedback cycle of uploading them to the Chef server, provisioning a vagrant VM, checking how they failed there, rinsing and repeating. It would be easier if we could try to test some pieces or recipes before we do all this heavy lifting at once.
Chef 带有 Chef-Shell,它本质上是 Chef 的交互式 Ruby 会话。在 Chef-Shell 中,我们可以创建 −
Chef comes with Chef-Shell, which is essentially an interactive Ruby session with Chef. In the Chef-Shell, we can create −
-
Attributes
-
Write Recipes
-
Initializing Chef runs
它用于即时评估食谱的各个部分,然后再将其上传到 Chef 服务器并在节点上执行完成的烹饪书。
It is used to evaluate parts of recipes on the fly, before uploading them to Chef server and execute complete cookbooks on the node.
Running Shell
Step 1 − 在独立模式下运行 Chef-Shell。
Step 1 − Run Chef-Shell in a standalone mode.
mma@laptop:~/chef-repo $ chef-shell
loading configuration: none (standalone chef-shell session)
Session type: standalone
Loading...[2017-01-12T20:48:01+01:00] INFO: Run List is []
[2017-01-12T20:48:01+01:00] INFO: Run List expands to []
done.
This is chef-shell, the Chef Shell.
Chef Version: 11.0.0
http://www.opscode.com/chef
http://wiki.opscode.com/display/chef/Home
run `help' for help, `exit' or ^D to quit.
Ohai2u mma@laptop!
chef >
Step 2 − 在 Chef-Shell 中切换到属性模式
Step 2 − Switch to attribute mode in the Chef-Shell
-
chef > attributes_mode
Step 3 − 设置属性值。
Step 3 − Setting attribute value.
-
chef:attributes > set[:title] = "Chef Cookbook" "Chef Cookbook"
-
chef:attributes > quit :attributes
-
chef >
Step 4 − 切换到菜谱模式。
Step 4 − Switch to recipe mode.
-
chef > recipe_mode
Step 5 − 创建文件资源。
Step 5 − Create a file resource.
chef:recipe > file "/tmp/book.txt" do
chef:recipe > content node.title
chef:recipe ?> end
=> <file[/tmp/book.txt] @name: "/tmp/book.txt" @noop: nil @
before: nil @params: {} @provider: Chef::Provider::File @allowed_
actions: [:nothing, :create, :delete, :touch, :create_if_missing]
@action: "create" @updated: false @updated_by_last_action: false
@supports: {} @ignore_failure: false @retries: 0 @retry_delay:
2 @source_line: "(irb#1):1:in `irb_binding'" @elapsed_time: 0 @
resource_name: :file @path: "/tmp/book.txt" @backup: 5 @diff: nil
@cookbook_name: nil @recipe_name: nil @content: "Chef Cookbook">
chef:recipe >
Step 6 − 开始 Chef 运行,以使用给定的内容创建文件。
Step 6 − Commence Chef run to create the file with the given content.
-
chef:recipe > run_chef
[2017-01-12T21:07:49+01:00] INFO: Processing file[/tmp/book.txt]
action create ((irb#1) line 1)
--- /var/folders/1r/_35fx24d0y5g08qs131c33nw0000gn/T/cheftempfile20121212-
11348-dwp1zs 2012-12-12 21:07:49.000000000
+0100
+++ /var/folders/1r/_35fx24d0y5g08qs131c33nw0000gn/T/chefdiff20121212-
11348-hdzcp1 2012-12-12 21:07:49.000000000 +0100
@@ -0,0 +1 @@
+Chef Cookbook
\ No newline at end of file
[2017-01-12T21:07:49+01:00] INFO: entered create
[2017-01-12T21:07:49+01:00] INFO: file[/tmp/book.txt] created file
/tmp/book.txt
How it Works
-
Chef-Shell starts with an Interactive Ruby (IRB) session enhanced with some specific features.
-
It offers modes such as attributes_mode and interactive_mode.
-
It helps in writing commands, which are written inside a recipe or cookbook.
-
It runs everything in an interactive mode.
我们可以在三种不同模式下运行 Chef-Shell: Standalone mode, Client mode 和 Solo mode 。
We can run Chef-Shell in three different modes: Standalone mode, Client mode, and Solo mode.
-
Standalone mode − It is the default mode. No cookbooks are loaded, and the run-list is empty.
-
Client mode − Here, the chef-shell acts as a chef-client.
-
Solo mode − Here, the chef-shell acts as a chef-solo client.
Chef - Testing Cookbooks
如果菜谱直接部署并在生产服务器上运行,菜谱可能会在生产中出现故障。防止这种情况发生的最佳方法是在设置环境中测试菜谱。
In case the cookbook is directly deployed and run on the production server, there are high chances that the cookbook can break up in production. The best way to prevent this from happening is, testing the cookbook in the setup environment.
以下是测试步骤。
Following are the steps for testing.
Step 1 − 使用以下命令安装菜谱。
Step 1 − Install the cookbook using the following command.
vipin@laptop:~/chef-repo $ knife cookbook site install <cookbook name>
Step 2 − 对正在使用的菜谱运行 knife cookbook test 命令。
Step 2 − Run the knife cookbook test commands on the working cookbook.
vipin@laptop:~/chef-repo $ knife cookbook test VTest
checking ntp
Running syntax check on ntp
Validating ruby files
Validating templates
Step 3 − 在菜谱中破坏一些内容并重新进行测试。
Step 3 − Break something in the cookbook and test again.
vipin@laptop:~/chef-repo $ subl cookbooks/VTest/recipes/default.rb
...
[ node['ntp']['varlibdir']
node['ntp']['statsdir'] ].each do |ntpdir|
directory ntpdir do
owner node['ntp']['var_owner']
group node['ntp']['var_group']
mode 0755
end
end
Step 4 − 再次运行 knife test 命令。
Step 4 − Run the knife test command again.
vipin@laptop:~/chef-repo $ knife cookbook test ntp
checking ntp
Running syntax check on ntp
Validating ruby files
FATAL: Cookbook file recipes/default.rb has a ruby syntax error:
FATAL: cookbooks/ntp/recipes/default.rb:25: syntax error,
unexpected tIDENTIFIER, expecting ']'
FATAL: node['ntp']['statsdir'] ].each do |ntpdir|
FATAL: ^
FATAL: cookbooks/ntp/recipes/default.rb:25: syntax error,
unexpected ']', expecting $end
FATAL: node['ntp']['statsdir'] ].each do |ntpdir|
FATAL:
Working Method
Knife cookbook test 对菜谱中所有 Ruby 文件以及所有 ERB 模板执行 Ruby 语法检查。它循环处理 Ruby 文件,并对每个文件运行 Ruby –c 。Ruby –c 检查脚本的语法并在不运行它的情况下退出。
Knife cookbook test executes a Ruby syntax check on all the Ruby files within the cookbook as well as all ERB templates. It loops through Ruby files and runs Ruby –c against each of them. Ruby –c checks the syntax of the script and quits without running it.
在遍历完所有 Ruby 文件后,knife cookbook test 将遍历所有 ERB 模板和通过 Ruby –c 创建的冗余版本 –x 。
After going through all the Ruby files, knife cookbook test goes through all ERB templates and pipes, the redundant version created by –x through Ruby –c.
Chef - Foodcritic
编写没有任何问题的优秀菜谱是一项相当困难的任务。但是,有一些方法可以帮助识别陷阱。Chef 菜谱中可以进行标记。Foodcritic 是实现此目的的最佳方式之一,它尝试识别菜谱逻辑和样式中的可能问题。
Writing good cookbooks without any issue is quite a difficult task. But there are ways which can help in identifying the pitfalls. Flagging in Chef Cookbook is possible. Foodcritic is one of the best way of archiving it, which tries to identify possible issues with the logic and style of cookbooks.
Foodcritic Setup
Step 1 − 添加 Foodcritic gem。
Step 1 − Add Foodcritic gem.
vipin@laptop:~/chef-repo $ subl Gemfile
source 'https://rubygems.org'
gem 'foodcritic', '~>2.2.0'
Step 2 − 安装 gem。
Step 2 − Install the gem.
vipin@laptop:~/chef-repo $ bundle install
Fetching gem metadata from https://rubygems.org/
...TRUNCATED OUTPUT...
Installing foodcritic (2.2.0)
Foodcritic Gem
Step 1 − 对菜谱运行 Foodcritic。
Step 1 − Run Foodcritic on the cookbook.
vipin@laptop:~/chef-repo $ foodcritic ./cookbooks/<Cookbook Name>
FC002: Avoid string interpolation where not required: ./cookbooks/
mysql/attributes/server.rb:220
...TRUNCATED OUTPUT...
FC024: Consider adding platform equivalents: ./cookbooks/<Cookbook Name>/
recipes/server.rb:132
Step 2 − 生成一份详细的报告。
Step 2 − Generate a detailed report.
vipin@laptop:~/chef-repo $ foodcritic -C ./cookbooks/mysql
cookbooks/<cookbook Name>/attributes/server.rb
FC002: Avoid string interpolation where not required
[...]
85| default['<Cookbook Name>']['conf_dir'] = "#{mysql['basedir']}"
[...]
cookbooks/<Cookbook Name>/recipes/client.rb
FC007: Ensure recipe dependencies are reflected in cookbook
metadata
40| end
41|when "mac_os_x"
42| include_recipe 'homebrew'
43|end
44|
Working Method
Foodcritic 定义了一组规则,并检查每个食谱代理。它带有针对各个领域的多个规则:样式、关联性、属性、字符串、概率、搜索、服务、文件、元数据等。
Foodcritic defines a set of rules and checks recipe agents, each one of them. It comes with multiple rules concerning various areas: styles, connectedness, attributes, string, probability, search, services, files, metadata, and so on.
Chef - ChefSpec
Test Driven Development (TDD) 是一种在编写任何实际的食谱代码之前编写单元测试的方法。测试应该是真实的,并且应该验证食谱的作用。由于没有开发食谱,它实际上应该会失败。一旦食谱开发完成,测试就应该通过。
Test Driven Development (TDD) is a way to write unit test before writing any actual recipe code. The test should be real and should validate what a recipe does. It should actually fail as there was no recipe developed. Once the recipe is developed, the test should pass.
ChefSpec 是建立在流行的 RSpec 框架之上的,它提供针对 Chef 食谱进行测试的定制语法。
ChefSpec is built on the popular RSpec framework and offers a tailored syntax for testing Chef recipe.
Creating ChefSpec
Step 1 − 创建包含 chefSpec gem 的 gem 文件。
Step 1 − Create a gem file containing the chefSpec gem.
vipin@laptop:~/chef-repo $ subl Gemfile
source 'https://rubygems.org'
gem 'chefspec'
Step 2 − 安装 gem。
Step 2 − Install the gem.
vipin@laptop:~/chef-repo $ bundler install
Fetching gem metadata from https://rubygems.org/
...TRUNCATED OUTPUT...
Installing chefspec (1.3.1)
Using bundler (1.3.5)
Your bundle is complete!
Step 3 − 创建一个 spec 目录。
Step 3 − Create a spec directory.
vipin@laptop:~/chef-repo $ mkdir cookbooks/<Cookbook Name>/spec
Step 4 − 创建 Spec
Step 4 − Create a Spec
vipin@laptop:~/chef-repo $ subl
cookbooks/my_cookbook/spec/default_spec.rb
require 'chefspec'
describe 'my_cookbook::default' do
let(:chef_run) {
ChefSpec::ChefRunner.new(
platform:'ubuntu', version:'12.04'
).converge(described_recipe)
}
it 'creates a greetings file, containing the platform
name' do
expect(chef_run).to
create_file_with_content('/tmp/greeting.txt','Hello! ubuntu!')
end
end
Step 5 − 验证 ChefSpec。
Step 5 − Validate ChefSpec.
vipin@laptop:~/chef-repo $ rspec cookbooks/<Cookbook Name>/spec/default_spec.rb
F
Failures:
1) <CookBook Name> ::default creates a greetings file, containing the platform name
Failure/Error: expect(chef_run.converge(described_recipe)).to
create_file_with_content('/tmp/greeting.txt','Hello! ubuntu!')
File content:
does not match expected:
Hello! ubuntu!
# ./cookbooks/my_cookbook/spec/default_spec.rb:11:in `block
(2 levels) in <top (required)>'
Finished in 0.11152 seconds
1 example, 1 failure
Failed examples:
rspec ./cookbooks/my_cookbook/spec/default_spec.rb:10 # my_
cookbook::default creates a greetings file, containing the
platform name
Step 6 − 编辑 Cookbooks 默认配方。
Step 6 − Edit Cookbooks default recipe.
vipin@laptop:~/chef-repo $ subl cookbooks/<Cookbook Name>/recipes/default.rb
template '/tmp/greeting.txt' do
variables greeting: 'Hello!'
end
Step 7 − 创建模板文件。
Step 7 − Create a template file.
vipin@laptop:~/chef-repo $ subl cookbooks/< Cookbook Name>/recipes/default.rb
<%= @greeting %> <%= node['platform'] %>!
Step 8 − 再次运行 rspec。
Step 8 − Run the rspec again.
vipin@laptop:~/chef-repo $ rspec cookbooks/<Cookbook Name>/spec/default_spec.rb
.
Finished in 0.10142 seconds
1 example, 0 failures
How It Works
为了使其生效,我们需要首先为 RSpec 设置针对 Chef 使用的基础设施。然后我们需要使用 ChefSpec Ruby gem,并且 Cookbook 需要一个目录(名为 spec),所有测试都将保存其中。
In order to make it work, we need to first set up the base infrastructure for using RSpec with Chef. Then we need to ChefSpec Ruby gem and the cookbook needs a directory called spec where all the tests will be saved.
Chef - Testing Cookbook with Test Kitchen
Test Kitchen 是 Chef 的集成测试框架。它允许编写测试,在使用 Cookbook 对 VM 实例化并执行收敛之后运行。这些测试对 VM 运行,并且可以验证所有内容已按预期执行。
Test kitchen is Chef’s integration testing framework. It enables writing tests, which run after VM is instantiated and converged using the cookbook. The tests run on VM and can verify that everything works as expected.
这是 ChefSpec 的节点约定,它仅模拟 Chef 运行。Test Kitchen 会启动实际节点并在其上运行 Chef。
This is node contract to ChefSpec, which only simulates a Chef run. Test Kitchen boots up a real node and runs Chef on it.
Setting Up
为了执行此操作,我们需要在机器上安装 Vagrant,有助于管理虚拟机。然后,我们需要安装 Cookbook,并将其与 Vagrant 结合在一起,以管理 Cookbook 依赖项。
In order to do this, we need to have Vagrant installed on the machine which helps in managing a virtual machine. Then we need to have bookshelf installed and hooked with Vagrant in order to manage cookbook dependencies.
Step 1 − 编辑 Cookbook 中的默认配方。
Step 1 − Edit default recipe in the cookbook.
vipin@laptop:~/chef-repo $ subl cookbooks/<Cookbook Name>/recipes/default.rb
file "/tmp/greeting.txt" do
content node['my_cookbook']['greeting']
end
Step 2 − 编辑 Cookbook 属性。
Step 2 − Edit cookbook attributes.
vipin@laptop:~/chef-repo $ subl cookbooks/<Cookbook Name>/attributes/default.rb
default['my_cookbook']['greeting'] = "Ohai, Chefs!"
Step 3 − 编辑 gem 文件,以安装必需的 Ruby gem。
Step 3 − Edit gem file to install the necessary Ruby gems.
vipin@laptop:~/chef-repo $ subl Gemfile
gem 'test-kitchen', '~> 2.0.0.alpha.7'
gem 'kitchen-vagrant'
Step 4 − 安装必需的 Ruby gem。
Step 4 − Install the necessary Ruby gem.
vipin@laptop:~/chef-repo $ bundle install
...TRUNCATED OUTPUT...
Installing test-kitchen (1.0.0.alpha.7)
Installing kitchen-vagrant (0.10.0) ...TRUNCATED OUTPUT...
Step 5 − 在 Cookbook 中创建 .kitchen.yml 文件。
Step 5 − Create .kitchen.yml file in the cookbook.
vipin@laptop:~/chef-repo/cookbooks/my_cookbook $ subl .kitchen.yml
---
driver_plugin: vagrant
driver_config:
require_chef_omnibus: true
platforms:
- name: ubuntu-12.04
driver_config:
box: opscode-ubuntu-12.04
box_url:
https://opscode-vm.s3.amazonaws.com/vagrant/
opscode_ubuntu12.04_provisionerless.box
suites:
- name: default
run_list:
- recipe[minitest-handler]
- recipe[my_cookbook_test]
attributes: { my_cookbook: { greeting: 'Ohai, Minitest!'} }
Step 6 − 在 Cookbook 内创建一个 test 目录。
Step 6 − Create a test directory inside the cookbook.
vipin@laptop:~/chef-repo/cookbooks/<Cookbook Name>$ mkdir test
Step 7 − 创建一个用于集成测试的 Test Cookbook。
Step 7 − Create a test cookbook for integration testing.
vipin@laptop:~/chef-repo/cookbooks/<Cookbook Name>/test $ knife
cookbook create my_cookbook_test
** Creating cookbook my_cookbook_test
** Creating README for cookbook: my_cookbook_test
** Creating CHANGELOG for cookbook: my_cookbook_test
** Creating metadata for cookbook: my_cookbook_test
Step 8 − 编辑 Test Cookbook 的默认配方。
Step 8 − Edit test cookbooks default recipe.
vipin@laptop:~/chef-repo/cookbooks/my_cookbook $ subl
test/cookbooks/my_cookbook_test/recipes/default.rb
include_recipe 'my_cookbook::default'
Step 9 − 在 Cookbook 内创建 Minitest Spec。
Step 9 − Create Minitest Spec inside the cookbook.
vipin@laptop:~/chef-repo/cookbooks/my_cookbook $ mkdir -p
test/cookbooks/my_cookbook_test/files/default/tests/minitest
vipin@laptop:~/chef-repo/cookbooks/my_cookbook $ subl
test/cookbooks/my_cookbook_test/files/default/tests/minitest/default_test.rb
require 'minitest/spec'
describe_recipe 'my_cookbook::default' do
describe "greeting file" do
it "creates the greeting file" do
file("/tmp/greeting.txt").must_exist
end
it "contains what's stored in the 'greeting' node
attribute" do
file('/tmp/greeting.txt').must_include 'Ohai, Minitest!'
end
end
Step 10 − 编辑您的主要 Cookbook 的 Berksfile。
Step 10 − Edit your main cookbook’s Berksfile.
vipin@laptop:~/chef-repo/cookbooks/my_cookbook $ subl Berksfile
site :opscode
metadata
cookbook "apt"
cookbook "minitest-handler"
cookbook "my_cookbook_test", path:
"./test/cookbooks/my_cookbook_test"
Testing the Setup
vipin@laptop:~/chef-repo/cookbooks/my_cookbook $ kitchen test
-----> Starting Kitchen (v1.0.0.alpha.7)
...TRUNCATED OUTPUT...
-----> Converging <default-ubuntu-1204>
-----> Installing Chef Omnibus (true)
...TRUNCATED OUTPUT...
Starting Chef Client, version 11.4.4
[2013-06-29T18:33:57+00:00] INFO: *** Chef 11.4.4 ***
[2013-06-29T18:33:58+00:00] INFO: Setting the run_list to
["recipe[minitest-handler]", "recipe[my_cookbook_test]"]
from JSON
...TRUNCATED OUTPUT...
# Running tests:
recipe::my_cookbook::default::greeting
file#test_0001_creates the greeting file = 0.00 s = .
recipe::my_cookbook::default::greeting
file#test_0002_contains what's stored in the 'greeting'
node attribute = 0.00 s = .
Finished tests in 0.011190s, 178.7277 tests/s, 178.7277
assertions/s.
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
...TRUNCATED OUTPUT...
-----> Kitchen is finished. (2m5.69s)
Chef - Nodes
Knife preflight 展示了使用某个配方的手册的所有节点的详细信息,然后将其上传到 Chef 服务器。
Knife preflight shows details about all the nodes which uses a certain cookbook before uploading it to Chef server.
Getting Started
为了开始,我们需要安装 knife-preflight 宝石。
In order to get started, we need to have knife-preflight gem installed.
Step 1 - 定义宝石文件中的路径。
Step 1 − Define the path in the gem file.
vipin@laptop:~/chef-repo $ subl Gemfile
source 'https://rubygems.org'
gem 'knife-preflight'
Step 2 - 运行 bundler 来安装 knife-preflight 宝石。
Step 2 − Run bundler to install knife-preflight gem.
vipin@laptop:~/chef-repo $ bundle install
Fetching gem metadata from https://rubygems.org/
...TRUNCATED OUTPUT...
Installing knife-preflight (0.1.6)
Working Method
对给定的配方运行 knife-preflight。
Run knife-preflight on the given cookbook.
我们可以运行 preflight 命令来找出在它们扩展的运行列表中具有给定配方的那些节点和角色。
We can run the preflight command to find out which nodes and roles have the given cookbook in their expanded run lists.
vipin@laptop:~/chef-repo $ knife preflight ntp
Searching for nodes containing ntp OR ntp::default in their
expanded run_list...
2 Nodes found
www-staging.example.com
cms-staging.example.com
Searching for roles containing ntp OR ntp::default in their
expanded run_list...
3 Roles found
your_cms_role
your_www_role
your_app_role
Found 6 nodes and 3 roles using the specified search
criteria
有许多方法能让配方在节点上执行。
There are multiple ways for a cookbook to get executed on the node.
-
You can assign the cookbook directly to a node by adding it to the node’s run list.
-
You can add a cookbook to the role and add the role to the node’s run list.
-
You can add the role to the run list of another role and add that other role to the node’s run list.
-
A cookbook can be a dependency of another used cookbook.
无论配方如何最终进入节点的运行列表,knife preflight 命令将会捕获它,因为 Chef 将所有扩展的角色列表和食谱存储在节点属性中。knife preflight 命令会准确地搜索这些节点属性。
No matter how a cookbook ends up in a node’s run list, the knife preflight command will catch it as Chef stores all expanded lists of roles and recipes in node attributes. The knife preflight command issues a search for exactly those node attributes.
Chef - Chef-Client Run
为了测试 Chef-Client 运行,我们需要将 Chef-Client 配置为使用托管的 Chef 或自有托管服务器。
In order to test Chef-Client run, we need to have Chef-Client configured to use the hosted Chef or own hosted server.
Running Chef-Client in Debug Mode
vipin@server:~$ sudo chef-client -l debug
…TRUNCATED OUTPUT…
Hashed Path:A+WOcvvGu160cBO7IFKLYPhh9fI=
X-Ops-Content-Hash:2jmj7l5rSw0yVb/vlWAYkK/YBwk=
X-Ops-Timestamp:2012-12-27T11:14:07Z
X-Ops-UserId:vagrant'
Header hash: {"X-Ops-Sign"=>"algorithm=sha1;version=1.0;",
"X-Ops-Userid"=>"vagrant", "X-Ops-Timestamp"=>"2012-12-
27T11:14:07Z", "X-Ops-Content-
Hash"=>"2jmj7l5rSw0yVb/vlWAYkK/YBwk=", "X-Ops-
Authorization-
1"=>"HQmTt9U/
LJJVAJXWtyOu3GW8FbybxAIKp4rhiw9O9O3wtGYVHyVGuoilWDao",
"X-Ops-Authorization-
2"=>"2/uUBPWX+YAN0g1/
fD2854QAU2aUcnSaVM0cPNNrldoOocmA0U5HXkBJTKok",
"X-Ops-Authorization-
3"=>"6EXPrEJg5T+
ddWd5qHAN6zMqYc3untb41t+eBpigGHPhtn1LLInMkPeIYwBm",
"X-Ops-Authorization-
4"=>"B0Fwbwz2HVP3wEsYdBGu7yOatq7fZBXHfIpeOi0kn/
Vn0P7HrucnOpONmMgU", "X-Ops-Authorization-
5"=>"RBmmbetFSKCYsdg2v2mW/
ifLIVemhsHyOQjffPYPpNIB3U2n7vji37NxRnBY",
"X-Ops-Authorization-
6"=>"Pb3VM7FmY60xKvWfZyahM8y8WVV9xPWsD1vngihjFw=="}
[2012-12-27T11:14:07+00:00] DEBUG: Sending HTTP Request via
GET to api.opscode.com:443/organizations/agilewebops/
nodes/vagrant
[2012-12-27T11:14:09+00:00] DEBUG: ---- HTTP Status and
Header Data: ----
[2012-12-27T11:14:09+00:00] DEBUG: HTTP 1.1 200 OK
[2012-12-27T11:14:09+00:00] DEBUG: server: nginx/1.0.5
[2012-12-27T11:14:09+00:00] DEBUG: date: Thu, 27 Dec 2012
Inspecting the Result of the Last Chef-Client Run
为了检查在开发新配方时的 Chef-Client 的最后一次运行,尤其是故障问题,我们需要确切地知道哪里出错了。尽管 Chef 在 stdout 中打印了一切,但人们可能想要再次查看调试日志。
In order to check the last Chef-Client run especially failure issues when we are developing a new cookbook, we need to know what exactly went wrong. Even though Chef prints everything in stdout, one might want to see the debug log again.
如果我们要进行测试,我们需要一份在编译时失败的错误配方。
If we want to test, we need to have a broken cookbook which is failing on compilation.
user@server:~$ sudo chef-client
==================================================================
==============
Recipe Compile Error in /srv/chef/file_store/cookbooks/my_
cookbook/recipes/default.rb
==================================================================
==============
NoMethodError
-------------
undefined method `each' for nil:NilClass
Cookbook Trace:
---------------
/srv/chef/file_store/cookbooks/my_cookbook/recipes/default.
rb:9:in `from_file'
Relevant File Content:
----------------------
/srv/chef/file_store/cookbooks/my_cookbook/recipes/default.rb:
2: # Cookbook Name:: my_cookbook
3: # Recipe:: default
4: #
5: # Copyright 2013, YOUR_COMPANY_NAME
6: #
7: # All rights reserved - Do Not Redistribute
8: #
9≫ nil.each {}
10:
欲了解更多详情,我们可以查看堆栈轨迹。
For more details, we can look into the stacktrace.
user@server:~$ less /srv/chef/file_store/chef-stacktrace.out
Generated at 2013-07-21 18:34:05 +0000
NoMethodError: undefined method `each' for nil:NilClass
/srv/chef/file_store/cookbooks/my_cookbook/recipes/default.rb:9:in
`from_file'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/
mixin/from_file.rb:30:in `instance_eval'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/
mixin/from_file.rb:30:in `from_file'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.4.4/lib/chef/
cookbook_version.rb:346:in `load_recipe'
Chef - Dynamically Configuring Recipes
属性是动态配置配方的主要组件。属性使作者可以配置配方。通过覆盖配方中设置的默认值,用户可以注入他们自己的值。
Attributes are the key components for dynamically configuring cookbooks. Attributes enable the authors to make the cookbook configurable. By overriding default values set in cookbooks, the user can inject their own values.
Step 1 - 为配方属性创建一个默认文件并向其添加一个默认属性。
Step 1 − Create a default file for cookbook attributes and add a default attribute to it.
vipin@laptop:~/chef-repo $ subl cookbooks/my_cookbook/attributes/default.rb
default['my_cookbook']['message'] = 'hello world!'
Step 2 - 在食谱中定义属性。
Step 2 − Define the attribute inside the recipe.
vipin@laptop:~/chef-repo $ subl cookbooks/<Cookbook Name>/recipes/default.rb
message = node['my_cookbook']['message']
Chef::Log.info("** Saying what I was told to say: #{message}")
Step 3 − 上传已修改的 cookbook。
Step 3 − Uploading the modified cookbook.
vipin@laptop:~/chef-repo $ knife cookbook upload my_cookbook
Uploading my_cookbook [0.1.0]
Step 4 − 运行已定义节点的 Chef 客户端。
Step 4 − Running Chef-Client of the defined node.
user@server:~$ sudo chef-client
...TRUNCATED OUTPUT...
[2013-01-13T20:48:21+00:00] INFO: ** Saying what I was told to
say: hello world!
...TRUNCATED OUTPUT...
Working Method
Chef 在执行属性之前加载属性文件中的所有属性。这些属性保存在节点对象中。可以在配方中访问保存在节点对象中的所有属性,并检索其当前值。
Chef loads all attributes from the attribute file before it executes them. The attributes are stored with the node object. One can access all the attributes stored with the node object within recipes and retrieve their current values.
Chef 具有受限结构,从最底层的默认开始,然后是普通结构(别名为 set),最后是覆盖。配方中设置的属性级别优先于在属性文件中设置的相同级别。
Chef has a restricted structure starting from the default being the lowest, then comes normal (which is aliased with the set) and then overrides. The attribute level set in the recipe has precedence over the same level set in an attribute file.
Overriding Attribute at the Node and Environment Level
在角色或环境中定义的属性具有最高优先级。
Attribute defined in roles or environment have the highest precedence.
Step 1 − 创建角色。
Step 1 − Create a role.
vipin@laptop:~/chef-repo $ subl roles/german_hosts.rb
name "german_hosts"
description "This Role contains hosts, which should print out
their messages in German"
run_list "recipe[my_cookbook]"
default_attributes "my_cookbook" => { "message" => "Hallo Welt!" }
Step 2 − 将角色上传至 Chef 服务器。
Step 2 − Upload the role to Chef server.
vipin@laptop:~/chef-repo $ knife role from file german_hosts.rb
Updated Role german_hosts!
Step 3 − 将角色分配给节点。
Step 3 − Assign the role to a node.
vipin@laptop:~/chef-repo $ knife node edit server
"run_list": [
"role[german_hosts]"
]
Saving updated run_list on node server
Step 4 − 运行 Chef 客户端。
Step 4 − Run the Chef-Client.
user@server:~$ sudo chef-client
...TRUNCATED OUTPUT...
[2013-01-13T20:49:49+00:00] INFO: ** Saying what I was told to
say: Hallo Welt!
...TRUNCATED OUTPUT...
Chef - Templates
在基础设施中, configuration management 涉及配置主机。总体来说,所有配置都是使用配置文件完成的。Chef 使用模板将配置文件填充动态值。
In Infrastructure, configuration management is all about how well one configures the hosts. In general, all the configurations are done using the configuration files. Chef uses templates to be able to fill the configuration file with dynamic values.
Chef 将模板用作食谱中可用的资源。可以从数据包、属性中获取配置文件的动态值,甚至可以通过将它们传递到模板中进行计算。
Chef provides templates as a resource which can be used in the recipe. Configuration files’ dynamic values can be retrieved from data bags, attributes or even calculate them by passing them into the template.
How to Use It?
Step 1 - 添加模板到食谱。
Step 1 − Add the template to the recipe.
vipin@laptop:~/chef-repo $ subl cookbooks/<Cookbook Name>/recipes/default.rb
template '/tmp/message' do
source 'Test.erb'
variables(
hi: 'Tesing',
world: 'Welt',
from: node['fqdn']
)
end
Step 2 - 添加 ERB 模板文件。
Step 2 − Add ERB Template file.
vipin@laptop:~/chef-repo $ subl cookbooks/<Cookbook Name>/templates/default/test.erb
<%- 4.times do %>
<%= @hi %>, <%= @world %> from <%= @from %>!
<%- end %>
Step 3 - 上传修改后的食谱到 Chef 服务器。
Step 3 − Upload the modified cookbook to Chef server.
vipin@laptop:~/chef-repo $ knife cookbook upload <Cookbook Name>
Uploading my_cookbook [0.1.0]
Run Chef Client on your node:
user@server:~$ sudo chef-client
...TRUNCATED OUTPUT...
[2017-01-14T20:41:21+00:00] INFO: Processing template[/tmp/
message] action create (my_cookbook::default line 9)
[2017-01-14T20:41:22+00:00] INFO: template[/tmp/message] updated
content
Step 4 - 验证上传文件的内容。
Step 4 − Validate the content of the uploaded file.
user@server:~$ sudo cat /tmp/message
Hallo, Welt from vagrant.vm!
Hallo, Welt from vagrant.vm!
Hallo, Welt from vagrant.vm!
Hallo, Welt from vagrant.vm!
Workflow
Chef 将 Erubis 用作其模板语言。它允许在模板的特殊符号中嵌入纯粹的 Ruby 代码。
Chef uses Erubis as its template language. It allows embedding pure Ruby code inside special symbols in the templates.
-
<%= %> is used if you want to print the value of a variable or Ruby expression into the generated file.
-
<%- %> is used if you want to embed Ruby logic into your template file. We use it to loop our expression four times.
Chef - Plain Ruby with Chef DSL
在 Chef 中,如果需要创建简单配方,可以使用 Chef 中可用的资源,如模板、remote_file 和服务。然而,随着配方的复杂性增加,需要使用高级技术,如条件语句,根据条件执行配方的部分内容。这是将纯 Ruby 与 Chef 特定领域语言 (DSL) 混合的优势。
In Chef, if one needs to create simple recipes one can use resources available in Chef, such as templates, remote_file, and services. However as the recipes become elaborate, one needs advanced techniques, such as conditional statements to execute parts of the recipe on condition. This is the power of mixing plain Ruby with Chef Domain Specific Language (DSL).
How to Use It?
在客户端模式下在任何节点上启动 Chef Shell,以便能够访问 Chef 服务器。
Start Chef Shell on any of the node in the client mode to be able to access the Chef server.
user@server:~$ sudo chef-shell --client
loading configuration: /etc/chef/client.rb
Session type: client
...TRUNCATED OUTPUT...
run `help' for help, `exit' or ^D to quit.
Ohai2u user@server!
Chef>
Basic Conditions with Chef DSL
使用纯 Ruby 按名称对节点进行排序。
Sort nodes by name using plain Ruby.
chef > nodes.sort! {|a,b| a.name <=> b.name }
=> [node[alice],node[server]]
遍历节点,打印其操作系统。
Loop through the nodes, printing their operating system.
chef > nodes.each do |n|
chef > puts n['os']
chef ?>
end
linux
windows
=> [node[server], node[alice]]
使用数组、循环和字符串扩展安装多个 Ruby gem,以构建 gem 名称。
Install multiple Ruby gems using an array, a loop, and string expansion to construct the gem names.
chef > %w{ec2 essentials}.each do |gem|
chef > gem_package "knife-#{gem}"
chef ?> end => ["ec2", "essentials"]
Working Method
Chef 配方是 Ruby 文件,在 Chef 运行的环境中进行评估。它们可以包含纯 Ruby 代码(如 if 语句和循环)以及 Chef DSL 元素(如资源)。
Chef recipes are Ruby files, which gets evaluated in the context of Chef run. They can contain plain Ruby code such as if statement and loops as well as Chef DSL elements such as resources.
在配方中,可以简单地声明 Ruby 变量并将其赋予值。
Inside the recipe, one can simply declare Ruby variables and assign values to it.
Chef - Ruby Gems with Recipes
配方是 cookbook 的关键构建模块,它基本上是 Ruby 代码。可以在 Chef 配方中使用 Ruby 语言的所有功能。大多数情况下,Ruby 的内置功能已经足够,但在某些情况下,可能需要使用其他 Ruby gem。例如,如果需要从配方本身访问 MySQL 数据库。
Recipes are the key building blocks of cookbook which is basically Ruby code. It is possible to use all of the Ruby language features inside the Chef recipe. Most of the time Ruby build in functionality is enough but sometimes one might need to use additional Ruby gems. For example, if one needs to access MySQL database from the recipe itself.
Chef 配方有能力获取所需的 Ruby gem,以便在同一个配方中使用它们。
Chef recipe has the capability to get the required Ruby gems in order to use them inside the very same recipe.
Using iptable Gem in the Given Recipe
Step 1 − 编辑 cookbook 的默认配方,并安装将在配方中使用的 gem。
Step 1 − Edit the default recipe of the cookbook and install the gem to be used inside the recipe.
vipin@laptop:~/chef-repo $ subl
cookbooks/my_cookbook/recipes/default.rb
chef_gem 'ipaddress'
require 'ipaddress'
ip = IPAddress("192.168.0.1/24")
Chef::Log.info("Netmask of #{ip}: #{ip.netmask}")
Step 2 − 将修改后的代码提交到 Chef 服务器。
Step 2 − Upload the modified cookbook to the Chef server.
vipin@laptop:~/chef-repo $ knife cookbook upload my_cookbook
Uploading my_cookbook [0.1.0]
Step 3 − 运行 Chef 客户端查看输出。
Step 3 − Running Chef client to see the output.
user@server $ sudo chef-client
...TRUNCATED OUTPUT...
[2013-01-18T14:02:02+00:00] INFO: Netmask of 192.168.0.1:
255.255.255.0
...TRUNCATED OUTPUT...
Working Method
Chef 运行步骤包括编译阶段(编译所有资源)和执行阶段(Chef 运行资源提供程序使节点进入所需状态)。如果在代码中需要任何特定的 Ruby gem,则需要在复杂阶段安装该 gem。
Chef run steps consist of the compilation phase, where it compiles all the resources and an execution phase where Chef runs the resource providers to converge the node to the desired state. If one needs any particular Ruby gem inside the cookbook, one needs to install the gem during the complication phase.
chef_gem 资源将执行完全相同的功能,并且在 Chef 中,Omnibus 是唯一的工作方式。它的主要功能是对 Chef 本身提供 gem。
The chef_gem resource will exactly do the same, and in Chef, Omnibus is the only way to work. Its main function is to make gems available to Chef itself.
Chef - Libraries
Chef 中的库提供了一个可以封装已编译逻辑的位置,以便代码整洁美观。
Libraries in Chef provides a place to encapsulate compiled logic so that the cookbook recipes remain neat and clean.
Creating the Library
Step 1 − 在代码的库中创建帮助方法。
Step 1 − Create a helper method in cookbook’s library.
vipin@laptop:~/chef-repo $ subl cookbooks/my_cookbook/libraries/ipaddress.rb
class Chef::Recipe
def netmask(ipaddress)
IPAddress(ipaddress).netmask
end
end
Step 2 − 使用帮助方法。
Step 2 − Use the helper method.
vipin@laptop:~/chef-repo $ subl cookbooks/my_cookbook/recipes/default.rb
ip = '10.10.0.0/24'
mask = netmask(ip) # here we use the library method
Chef::Log.info("Netmask of #{ip}: #{mask}")
Step 3 − 将修改后的代码提交到 Chef 服务器。
Step 3 − Upload the modified cookbook to the Chef Server.
vipin@laptop:~/chef-repo $ knife cookbook upload my_cookbook
Uploading my_cookbook [0.1.0]
Testing the Library
user@server $ sudo chef-client
...TRUNCATED OUTPUT...
[2013-01-18T14:38:26+00:00] INFO: Netmask of 10.10.0.0/24:
255.255.255.0
...TRUNCATED OUTPUT...
Working Method
Chef 库代码可以打开 chef::Recipe 类,并添加新方法(如步骤 1 中所示)。这不是最干净的步骤,但这是最简单的方法。
Chef library code can open the chef::Recipe class and add new methods as done in Step 1. This step is not the cleanest but the simplest way of doing it.
class Chef::Recipe
def netmask(ipaddress)
...
end
end
Best Practices
一旦我们打开 chef::recipe 类,就有可能污染该类。最佳做法是,通常最好在库中引入一个新的子类,并定义一个类方法作为方法。这样可以避免拉取 chef::recipe 命名空间。
Once we open the chef::recipe class, there are changes that it gets polluted. As a best practice, it is always a better way to introduce a new sub class inside the library and define a method as class method. This avoids pulling the chef::recipe namespace.
vipin@laptop:~/chef-repo $ subl cookbooks/my_cookbook/libraries/ipaddress.rb
class Chef::Recipe::IPAddress
def self.netmask(ipaddress)
IPAddress(ipaddress).netmask
end
end
我们可以在代码中使用如下方法:
We can use the method inside the recipe like
IPAddress.netmask(ip)
Chef - Definition
定义可以定义为一种对资源进行分组的逻辑方法,该资源会被反复使用。在此流程中,我们将资源分组并为它们命名,以重新获取已定义代码的可读性。
Definition can be defined as a logical method of grouping resources, which are used again and again. In this flow, we group the resources and give them a name to regain readability of defined cookbooks.
为此,我们应该有一个代码。在本例中,我们使用 test_cookbook 和节点运行列表,其中包括该代码。
In order to do this, we should have a recipe. In this case, we are using test_cookbook and a run list of nodes, which includes the cookbook.
Creating a Definition
Step 1 − 在代码定义文件夹中创建新的定义文件。
Step 1 − Create a new definition file in the cookbooks definition folder.
vipin@laptop:~/chef-repo $ subl cookbooks/test_cookbook/definitions/
capistrano_deploy_dirs.rb
define :capistrano_deploy_dirs, :deploy_to => '' do
directory "#{params[:deploy_to]}/releases"
directory "#{params[:deploy_to]}/shared"
directory "#{params[:deploy_to]}/shared/system"
end
Step 2 − 在代码默认配方中使用定义。
Step 2 − Use a definition inside the cookbooks default recipe.
vipin@laptop:~/chef-repo $ subl cookbooks/test_cookbook/recipes/default.rb
capistrano_deploy_dirs do
deploy_to "/srv"
end
Step 3 − 将代码提交到 chef 服务器。
Step 3 − Upload the cookbook to the chef server.
vipin@laptop:~/chef-repo $ knife cookbook upload test_cookbook
Uploading test_cookbook [0.1.0]
Step 4 − 在目标节点上运行 Chef 客户端。
Step 4 − Run the Chef client on the desired node.
vipin@laptop:~/chef-repuser@server $ sudo chef-client
...TRUNCATED OUTPUT...
[2013-01-18T16:31:11+00:00] INFO: Processing directory[/srv/
releases] action create (my_cookbook::default line 2)
[2013-01-18T16:31:11+00:00] INFO: directory[/srv/releases] created
directory /srv/releases
[2013-01-18T16:31:11+00:00] INFO: Processing directory[/srv/
shared] action create (my_cookbook::default line 3)
[2013-01-18T16:31:11+00:00] INFO: directory[/srv/shared] created
directory /srv/shared
[2013-01-18T16:31:11+00:00] INFO: Processing directory[/srv/
shared/system] action create (my_cookbook::default line 4)
[2013-01-18T16:31:11+00:00] INFO: directory[/srv/shared/system]
代码中的定义就像微服务,可以对资源进行分组并为它们命名。某个定义有一个名称,可以使用该名称从代码中分辨出可以调用哪些资源,它还有一个参数列表。
Definition in cookbooks are like micros, which group the resources and give them a name. A definition has a name by which one can tell them from which can be called inside the recipe and it has a list of perimeters.
在定义中,我们有若干参数,在我们的代码中,这些参数如下所示。
In the definition, we have parameters which in our code looks like the following.
…..
directory "#{params[:deploy_to]}/releases"
directory "#{params[:deploy_to]}/shared"
directory "#{params[:deploy_to]}/shared/system”
……
以下是在默认配方中使用它的方法。
It can be used inside the default recipe as follows.
capistrano_deploy_dirs do
deploy_to "/srv"`
end
Chef - Environment Variable
环境变量是让 Chef 配方在任何特定节点上成功运行的关键方法。有许多办法可以做到这一点,可以手动设置它们,也可以使用 Shell 脚本。在此处,我们需要通过配方来设置它们。
Environment variable is a key way to make Chef recipe run on any particular node successfully. There are multiple ways of doing it, either manually setting them up or by using a Shell script. Setting them via recipe is what we need to perform here.
为此,我们需要有一个食谱手册,在这里我们将使用 test_cookbook 和包含 test_cookbook 的运行列表。
To do this, we need to have a cookbook here we would use test_cookbook and a run list which contains test_cookbook.
Setting Environment Variable Using Chef Recipe
Step 1 - 使用环境变量更新 cookbook 的默认配方。
Step 1 − Update the default recipe of cookbook with an environment variable.
vipin@laptop:~/chef-repo $ subl cookbooks/test_cookbook/recipes/default.rb
ENV['MESSAGE'] = 'Testing environment variable update with chef !'
execute 'print value of environment variable $MESSAGE' do
command 'echo $MESSAGE > /tmp/message'
end
Step 2 - 将更新的 cookbook 上传到服务器。
Step 2 − Upload the updated cookbook to the server.
vipin@laptop:~/chef-repo $ knife cookbook upload test_cookbook
Uploading my_cookbook [0.1.0]
Step 3 - 运行 Chef 客户端以创建临时文件。
Step 3 − Running the Chef client to create a temp file.
user@server:~$ sudo chef-client
...TRUNCATED OUTPUT...
[2013-01-25T15:01:57+00:00] INFO: Processing execute[print
value of environment variable $MESSAGE] action run
(my_cookbook::default line 11)
[2013-01-25T15:01:57+00:00] INFO: execute[print value of
environment variable $MESSAGE] ran successfully
...TRUNCATED OUTPUT...
Working Method
Ruby 通过 ENV –a 哈希公开当前的环境变量,以读取和修改环境变量。
Ruby exposes the current environment variable via ENV –a hash to read and modify the environment variable.
Execute Resource
我们可以在 cookbook 的 Chef 默认配方中使用 execute 资源来执行相同的操作。
We can use execute resource to do the same inside the Chef default recipe of cookbook.
mma@laptop:~/chef-repo $ subl cookbooks/test_cookbook/recipes/default.rb
execute 'print value of environment variable $MESSAGE' do
command 'echo $MESSAGE > /tmp/message'
environment 'MESSAGE' => 'Hello from the execute resource'
end
Note - 使用 ENV 设置环境变量将在整个 Chef 运行过程中使该变量可用。相反,将其传递给 execute 资源将仅使其可用于资源执行的命令。
Note − Setting an environment variable using ENV will make that variable available during the whole Chef run. In contrast, passing it to the execute resource will only make it available for that one command executed by the resource.
Chef - Data Bugs
Chef 数据包可以定义为数据的一个任意集合,可以用于食谱。当不想在食谱中硬编码属性,也不想将属性存储在食谱中时,使用数据包非常有帮助。
Chef data bags can be defined as an arbitrary collection of data which one can use with cookbooks. Using data bags is very helpful when one does not wish to hardcode attributes in recipes nor to store attributes in cookbooks.
Working Method
在下面的设置中,我们尝试与 http 端点 URL 通信。为此,我们需要创建一个数据包来保存端点 URL 详细信息,并在食谱中使用它。
In the following setup, we are trying to communicate to http endpoint URL. For this, we need to create a data bag, which will hold the endpoint URL detail and use it in our recipe.
Step 1 - 为我们的数据包创建一个目录。
Step 1 − Create a directory for our data bag.
mma@laptop:~/chef-repo $ mkdir data_bags/hooks
Step 2 - 为请求 bin 创建数据包项。需要确保您使用已定义的 requestBin URL。
Step 2 − Create a data bag item for request bin. One needs to make sure one is using a defined requestBin URL.
vipi@laptop:~/chef-repo $ subl data_bags/hooks/request_bin.json {
"id": "request_bin",
"url": "http://requestb.in/1abd0kf1"
}
Step 3 - 在 Chef 服务器上创建数据包
Step 3 − Create a data bag on the Chef server
vipin@laptop:~/chef-repo $ knife data bag create hooks
Created data_bag[hooks]
Step 4 - 将数据包上传到 Chef 服务器。
Step 4 − Upload the data bag to the Chef server.
vipin@laptop:~/chef-repo $ knife data bag from file hooks requestbin.json
Updated data_bag_item[hooks::RequestBin]
Step 5 - 更新食谱的默认食谱,以从数据包接收所需的食谱。
Step 5 − Update the default recipe of the cookbook to receive the required cookbook from a data bag.
vipin@laptop:~/chef-repo $ subl cookbooks/my_cookbook/recipes/default.rb
hook = data_bag_item('hooks', 'request_bin')
http_request 'callback' do
url hook['url']
end
Step 6 - 将修改后的食谱上传到 Chef 服务器。
Step 6 − Upload the modified cookbook to the Chef server.
vipin@laptop:~/chef-repo $ knife cookbook upload my_cookbook
Uploading my_cookbook [0.1.0]
Step 7 - 在节点上运行 Chef 客户端,以检查是否执行了 http 请求 bin。
Step 7 − Run the Chef client on the node to check if the http request bin gets executed.
user@server:~$ sudo chef-client
...TRUNCATED OUTPUT...
[2013-02-22T20:37:35+00:00] INFO: http_request[callback]
GET to http://requestb.in/1abd0kf1 successful
...TRUNCATED OUTPUT...
How it Works
数据包是一个命名的结构数据条目集合。需要定义数据条目并在 JSON 文件中调用数据包项。还可以在食谱中搜索数据包项,以使用存储在数据包中的数据。
Data bag is a named collection of structure data entries. One needs to define data entry and call the data bag item in JSON file. One can also search for data bag item from within the recipes to use the data stored in the data bags.
我们创建了一个名为 hooks 的数据包。数据包是 Chef 存储库中的一个目录。我们在服务器上使用 knife 创建它。
We created a data bag called hooks. A data bag is a directory within Chef repository. We used knife to create it on the server.
Chef - Scripts for Data Bugs
在某些条件下,无法将服务器置于 Chef 的完全控制之下。在这种情况下,可能需要从脚本中访问 Chef 数据包中的值。为了做到这一点,需要将数据包的值存储在 JSON 文件中,并让添加的脚本访问这些值。
In certain conditions, it is not possible to put the server under the full control of Chef. In such cases, one might need to access values in Chef data bags from scripts. In order to do this, one needs to store data bag values in a JSON file and let the added script access those values.
为此,需要有一个食谱手册。在我们的例子中,我们将像之前一样使用 test_cookbook,并且在其中包含 test_cookbook 定义的节点的运行列表。
For this, one needs to have a cookbook. In our case we would use test_cookbook as earlier and should have the run list of the node including test_cookbook definition in it.
Working Method
Step 1 - 创建一个数据包。
Step 1 − Create a data bag.
vipin@laptop:~/chef-repo $ mkdir data_bags/servers
vipin@laptop:~/chef-repo $ knife data bag create servers
Created data_bag[servers]
Step 2 - 创建一个数据包项。
Step 2 − Create a data bag item.
vipin@laptop:~/chef-repo $ subl data_bags/servers/Storage.json {
"id": "storage",
"host": "10.0.0.12"
}
Step 3 - 更新数据包项。
Step 3 − Update the data bag item.
vipin@laptop:~/chef-repo $ subl data_bags/servers/Storage.json {
"id": "storage",
"host": "10.0.0.12"
}
Using in Cookbook
Step 1 - 需要创建包含数据包值的 JSON 文件,以便使用上面的 cookbook,外部脚本可以访问这些值。
Step 1 − Need to create a JSON file containing data bag values using the above cookbook so that external scripts can access those values.
vipin@laptop:~/chef-repo $ subl cookbooks/test_cookbook/recipes/default.rb
file "/etc/backup_config.json" do
owner "root"
group "root"
mode 0644
content data_bag_item('servers', 'backup')['host'].to_json
end
Step 2 - 将 test_cookbook 上传到 Chef 服务器。
Step 2 − Upload test_cookbook to Chef server.
vipin@laptop:~/chef-repo $ knife cookbook upload test_cookbook
Uploading my_cookbook [0.1.0]
Step 3 − 在节点上运行 Chef 客户端。
Step 3 − Run the Chef client on the node.
user@server:~$ sudo chef-client
...TRUNCATED OUTPUT...
[2013-03-14T20:30:33+00:00] INFO: Processing
file[/etc/backup_config.json] action create
(my_cookbook::default line 9)
[2013-03-14T20:30:34+00:00] INFO: entered create
[2013-03-14T20:30:34+00:00] INFO:
file[/etc/backup_config.json] owner changed to 0
[2013-03-14T20:30:34+00:00] INFO:
file[/etc/backup_config.json] group changed to 0
[2013-03-14T20:30:34+00:00] INFO:
file[/etc/backup_config.json] mode changed to 644
[2013-03-14T20:30:34+00:00] INFO:
file[/etc/backup_config.json] created file
/etc/backup_config.json
...TRUNCATED OUTPUT...
Step 4 - 验证生成 JSON 文件的内容。
Step 4 − Validating the content of the generated JSON file.
user@server:~$ cat /etc/backup_config.json
"10.0.0.12"
Workflow of Scripts
在上面的命令中,我们用来在 /etc 目录内创建 JSON 文件的文件资源是在默认 cookbook 中定义的。它使用 data_bag_item 方法直接从数据包获取文件内容。我们从数据包项访问主机值,并将其转换为 JSON。文件资源使用 JSON 转换的值作为其内容,并将其写入磁盘。
In the above command, the file resource that we have used which creates JSON file inside the /etc directory is defined in the default cookbook. It gets the file content directly from the data bag using the data_bag_item method. We access the host values from the data bag item and convert it to JSON. The file resource uses the JSON-converted values as its content and writes it to the disk.
Chef - Cross-Platform for Cookbooks
跨平台食谱是指采用其运行基础环境的食谱。Chef 提供了许多功能,有助于编写能够在将要部署的任何操作系统上运行的跨平台食谱。这有助于开发人员编写完全可操作的食谱。
Cross-Platform cookbooks are those cookbooks which adopt an underlying environment on which it is going to run. Chef provides a host of features, which helps in writing crossplatform cookbooks capable of running on any OS, on which it is going to get deployed. This helps a developer to write a completely operational cookbook.
为了执行此操作,我们需要一份食谱。在我们的示例中,它将是 test_cookbook 和一个包含食谱定义的运行列表。
In order to do this, we need to have a cookbook. In our case it will be test_cookbook and a run list which will have the cookbook definition in it.
Working Method
检索节点平台详细信息并在我们的食谱中执行条件逻辑取决于平台。在我们的示例中,我们将在 Ubuntu 上对此进行测试。
Retrieving the nodes platform detail and executing the conditional logic in our cookbook depends on the platform. In our case, we will test it for Ubuntu.
Step 1 − 如果节点为 Ubuntu,则记录一条消息。
Step 1 − Log a message if the node is Ubuntu.
vipin@laptop:~/chef-repo $ subl cookbooks/test_cookbook/recipes/default.rb
Log.info("Running on ubuntu") if node.platform['ubuntu']
Step 2 − 将食谱上传到 Chef 服务器。
Step 2 − Upload the cookbook to Chef server.
vipin@laptop:~/chef-repo $ subl cookbooks/test_cookbook/recipes/default.rb
Uploading my_cookbook [0.1.0]
Uploaded 1 cookbook.
Step 3 − 在节点上运行 Chef 客户端。
Step 3 − Run the Chef client on the node.
user@server:~$ sudo chef-client
...TRUNCATED OUTPUT...
[2013-03-03T20:07:39+00:00] INFO: Running on Ubuntu
...TRUNCATED OUTPUT...
如果无需关注特定平台,而只需知道正在使用哪种声明式平台,则可以使用以下语句。
Alternatively, if one is not interested in a specific platform but only needs to know which declarative one is using, the following statement can be used.
Log.info("Running on a debian derivative") if
platform_family?('debian')
在经过修改的食谱上传到 Chef 服务器并在 Ubuntu 节点上运行 Chef 客户端后,将显示以下结果。
Uploading the modified cookbook and running Chef client on Ubuntu node will show the following result.
[2013-03-03T20:16:14+00:00] INFO: Running on a debian
derivative
Workflow of Scripts
在以上命令中,Ohai 将发现节点操作系统的当前状态并将其作为平台属性存储在节点对象中。
In the above command, Ohai will discover the current status of the node’s operating system and store it as a platform attribute with the node object.
node['platform']
或者,您可以使用 -method 样式语法−
Or, you can use method style syntax −
node.platform
Setting Platform Specific Values
为了设定平台特定值,Chef 提供了便捷方法 value_for_platform 和 value_for_platform_family。可以使用它们来避免复杂的 case 语句,而使用简单的散列。
In order to set platform specific values chef offers convenience methods value_for_platform and value_for_platform_family. They can be used to avoid complex case statement and use a simple hash instead.
Example cookbook
execute "start-runsvdir" do
command value_for_platform(
"debian" => { "default" => "runsvdir-start" },
"ubuntu" => { "default" => "start runsvdir" },
"gentoo" => { "default" => "/etc/init.d/runit-start start" }
)
action :nothing
end
在以上示例中,命令被定义为操作系统特定。
In the above example, the command is OS specific as defined.
-
For Debian, "runsvdir-start" will work
-
For Ubuntu, "start runsvdir" will work
-
For Gentoo, "/etc/init.d/runit-start" will work
Chef - Resources
Chef 资源表示操作系统处于其所需状态的一部分。这是一份配置策略声明,描述了想要将当前配置升级到的节点的所需状态。它有助于使用 Chef 的 Ohai 机制了解目标机器的当前状态。它还有助于定义将目标机器置于该状态所需的步骤。资源被分组到食谱中,这些食谱描述了工作配置。
Chef resource represents a piece of the operating system at its desired state. It is a statement of configuration policy that describes the desired state of a node to which one wants to take the current configuration to using resource providers. It helps in knowing the current status of the target machine using the Ohai mechanism of Chef. It also helps in defining the steps required to perform to get the target machine to that state. The resources are grouped in recipes which describes the working configuration.
对于 Chef,chef::Platform 会针对每个节点映射提供程序和平台版本。在每次 Chef 客户端运行开始时,Chef 服务器会收集当前计算机状态的详细信息。稍后,Chef 服务器会使用这些值来识别正确的提供程序。
In case of Chef, chef::Platform maps the providers and platform versions of each node. At the beginning of every Chef-client run, Chef server collects the details of any machines current state. Later, Chef server uses those values to identify the correct provider.
Resource Syntax
type 'name' do
attribute 'value'
action :type_of_action
end
在以上语法中,“type”是资源类型,“name”是我们将要使用的名称。在 “do”和 “end”块中,我们有该资源的属性以及我们需要针对该特定资源执行的操作。
In the above syntax, ‘type’ is the resource type and ‘name’ is the name that we are going to use. In the ‘do’ and ‘end’ block, we have the attribute of that resource and the action that we need to take for that particular resource.
我们在配方中使用的每个资源都具有一组特定操作,其在 “do”和 “end”块内定义。
Every resource that we use in the recipe has its own set of actions, which is defined inside the ‘do’ and ‘end’ block.
Example
type 'name' do
attribute 'value'
action :type_of_action
end
所有资源共享一组通用功能、操作、属性、条件执行、通知和相关操作路径。
All resources share a common set of functionality, actions, properties, conditional execution, notification, and relevant path of action.
Actions |
The :nothing action can be used with any resource or custom resource. |
Properties |
The ignore_failure, provider, retries, retry_delay, and supports properties can be used with any resource or custom resources. |
Guards |
The not_if and only_if conditional executions can be used to put additional guards around certain resources, so that they are only run when the condition is met. |
Guard Interpreters |
Evaluates a string command using a script-based resource: bash, csh, perl, powershell_script, python, or ruby. |
Notifications |
The notifies and subscribes notifications can be used with any resource. |
Relative Paths |
The #{ENV['HOME']} relative path can be used with any resource. |
Windows File Security |
The template, file, remote_file, cookbook_file, directory, and remote_directory resources support the use of inheritance and access control lists (ACLs) within recipes. |
Run in Compile Phase |
Sometimes a resource needs to be run before every other resource or after all resources have been added to the resource collection. |
Available Resources
apt_package
使用 apt_package 资源来管理 Debian 和 Ubuntu 平台的软件包。
Use the apt_package resource to manage packages for the Debian and Ubuntu platforms.
Bash
使用 bash 资源来使用 Bash 解释器执行脚本。该资源还可以使用 execute 资源可用的任何操作和属性。使用该资源执行的命令(根据其本质)不是幂等的,因为这些命令通常针对其运行所在的环境是唯一的。使用 not_if 和 only_if 来保护该资源以确保幂等性。
Use the bash resource to execute scripts using the Bash interpreter. This resource may also use any of the actions and properties that are available to the execute resource. Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
Batch
使用 batch 资源来使用 cmd.exe 解释器执行批处理脚本。 batch 资源创建并执行临时文件(类似于 script 资源的行为),而不是内联运行该命令。
Use the batch resource to execute a batch script using the cmd.exe interpreter. The batch resource creates and executes a temporary file (similar to how the script resource behaves), rather than running the command inline.
该资源继承了 execute 资源的操作(:run 和 :nothing)和属性(creates、cwd、environment、group、path、timeout 和 user)。使用该资源执行的命令(根据其本质)不是幂等的,因为这些命令通常针对其运行所在的环境是唯一的。使用 not_if 和 only_if 来保护该资源以确保幂等性。
This resource inherits actions (:run and :nothing) and properties (creates, cwd, environment, group, path, timeout, and user) from the execute resource. Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
bff_package
使用 bff_package 资源来使用 installp 实用程序管理 AIX 平台的软件包。当从本地文件安装软件包时,必须使用 remote_file 或 cookbook_file resources 将其添加到节点中。
Use the bff_package resource to manage packages for the AIX platform using the installp utility. When a package is installed from a local file, it must be added to the node using the remote_file or cookbook_file resources.
chef_gem
使用 chef_gem 资源仅针对 Chef 客户端专用 Ruby 实例来安装 gem。当从本地文件安装 gem 时,必须使用 remote_file 或 cookbook_file 资源将其添加到节点中。
Use the chef_gem resource to install a gem only for the instance of Ruby that is dedicated to the Chef-Client. When a gem is installed from a local file, it must be added to the node using the remote_file or cookbook_file resources.
chef_gem 资源处理所有与 gem_package 资源相同的属性和选项,但不接受 gem_binary 属性,因为它始终使用 Chef 客户端在其下方运行的 CurrentGemEnvironment。除了执行类似于 gem_package 资源的操作外, chef_gem 资源还执行上述操作。
The chef_gem resource works with all of the same properties and options as the gem_package resource, but does not accept the gem_binary property because it always uses the CurrentGemEnvironment under which the Chef-Client is running. In addition to performing actions similar to the gem_package resource, the chef_gem resource does the above.
cookbook_file
使用` cookbook_file `资源将文件从`COOKBOOK_NAME/files/`的子目录传输到在运行`ChefClient`的主机上的指定路径。
Use the cookbook_file resource to transfer files from a sub-directory of COOKBOOK_NAME/files/ to a specified path located on a host that is running the ChefClient.
根据文件特殊性来选择文件,它允许根据主机名,主机平台(操作系统,发行版或相应版本)或平台版本来使用不同的源文件。位于`COOKBOOK_NAME/files/default`子目录中的文件可以在任何平台上使用。
The file is selected according to file specificity, which allows different source files to be used based on the hostname, host platform (operating system, distro, or as appropriate), or platform version. Files that are located in the COOKBOOK_NAME/files/default subdirectory may be used on any platform.
Cron
使用`cron`资源来管理基于时间作业调度的`cron`条目。如果未提供,则计划的属性将默认为`*。`cron`资源需要访问`crontab`程序,通常为`cron
。
Use the cron resource to manage cron entries for time-based job scheduling. Properties for a schedule will default to * if not provided. The cron resource requires access to a crontab program, typically cron.
Csh
使用`csh`资源使用`csh`解释器执行脚本。此资源也可以使用`execute`资源可用的所有操作和属性。
Use the csh resource to execute scripts using the csh interpreter. This resource may also use any of the actions and properties that are available to the execute resource.
使用此资源执行的命令(本质上)不是幂等的,因为它们通常是其运行环境中唯一的命令。使用`not_if`和`only_if`来保护此资源的幂等性。
Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
Deploy
使用` deploy `资源来管理和控制部署。这是一个流行的资源,但也很复杂,具有最多的属性,多个提供程序,回调的复杂性,以及四个支持从配方中修改布局的属性。
Use the deploy resource to manage and control deployments. This is a popular resource, but is also complex, having the most properties, multiple providers, the added complexity of callbacks, plus four attributes that support layout modifications from within a recipe.
Directory
使用` directory `资源来管理目录,目录是由构成计算机上存储的所有信息的文件夹组成的层次结构。根目录是顶级目录,其余目录都在此目录下组织。
Use the directory resource to manage a directory, which is a hierarchy of folders that comprises all of the information stored on a computer. The root directory is the top-level, under which the rest of the directory is organized.
` directory `资源使用`name`属性来指定目录中位置的路径。通常,需要具有访问目录中该位置的权限。
The directory resource uses the name property to specify the path to a location in a directory. Typically, permission to access that location in the directory is required.
dpkg_package
使用` dpkg_package 资源来管理
dpkg 平台的软件包。当从本地文件安装软件包时,必须使用
remote_file 或
cookbook_file `资源将其添加到节点。
Use the dpkg_package resource to manage packages for the dpkg platform. When a package is installed from a local file, it must be added to the node using the remote_file or cookbook_file resources.
easy_install_package
使用` easy_install_package `资源来管理 Python 平台的软件包。
Use the easy_install_package resource to manage packages for the Python platform.
Env
使用` env `资源来管理 Microsoft Windows 中的环境键。在设置了环境键之后,必须重新启动 Microsoft Windows,然后任务计划程序才能使用环境键。
Use the env resource to manage environment keys in Microsoft Windows. After an environment key is set, Microsoft Windows must be restarted before the environment key is available to the Task Scheduler.
erl_call
使用` erl_call `资源来连接到分布式 Erlang 系统中位于的节点。使用此资源执行的命令(本质上)不是幂等的,因为它们通常是其运行环境中唯一的命令。使用`not_if`和`only_if`来保护此资源的幂等性。
Use the erl_call resource to connect to a node located within a distributed Erlang system. Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
Execute
使用` execute 资源来执行单个命令。使用此资源执行的命令(本质上)不是幂等的,因为它们通常是其运行环境中唯一的命令。使用
not_if 和
only_if `来保护此资源的幂等性。
Use the execute resource to execute a single command. Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
freebsd_package
使用` freebsd_package `资源来管理 FreeBSD 平台的软件包。
Use the freebsd_package resource to manage packages for the FreeBSD platform.
gem_package
使用` gem_package 资源来管理仅包含在配方中的 gem 软件包。当从本地文件安装软件包时,必须使用
remote_file 或
cookbook_file `资源将其添加到节点。
Use the gem_package resource to manage gem packages that are only included in recipes. When a package is installed from a local file, it must be added to the node using the remote_file or cookbook_file resources.
Git
使用` git 资源来管理存在于`git`存储库中的源控制资源。要使用`git`资源中的所有功能,需要使用`git
1.6.5(或更高版本)。
Use the git resource to manage source control resources that exist in a git repository. git version 1.6.5 (or higher) is required to use all of the functionality in the git resource.
homebrew_package
使用` homebrew_package `资源来管理 Mac OS X 平台的软件包。
Use the homebrew_package resource to manage packages for the Mac OS X platform.
http_request
利用 http_request 资源发送带有任意消息的 HTTP 请求(GET、PUT、POST、DELETE、HEAD 或 OPTIONS)。通常,当需要自定义回调时,该资源非常有用。
Use the http_request resource to send an HTTP request (GET, PUT, POST, DELETE, HEAD, or OPTIONS) with an arbitrary message. This resource is often useful when custom callbacks are necessary.
ips_package
在 Solaris 11 平台上,使用 ips_package 资源来管理软件包(使用映像打包系统 (IPS))。
Use the ips_package resource to manage packages (using Image Packaging System (IPS)) on the Solaris 11 platform.
Ksh
使用 ksh 资源来使用 Korn shell (ksh) 解释器执行脚本。该资源还可以使用 execute 资源中提供的任何操作和属性。
Use the ksh resource to execute scripts using the Korn shell (ksh) interpreter. This resource may also use any of the actions and properties that are available to the execute resource.
使用此资源执行的命令(本质上)不是幂等的,因为它们通常是其运行环境中唯一的命令。使用`not_if`和`only_if`来保护此资源的幂等性。
Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
Log
使用 log 资源来创建日志条目。日志资源的行为与任何其他资源一样:在编译阶段内置到资源集中,然后在执行阶段运行。(要创建未内置到资源集中的日志条目,请使用 Chef::Log 而不是日志资源)
Use the log resource to create log entries. The log resource behaves like any other resource: built into the resource collection during the compile phase, and then run during the execution phase. (To create a log entry that is not built into the resource collection, use Chef::Log instead of the log resource)
macports_package
使用 macports_package 资源来管理 Mac OS X 平台的软件包。
Use the macports_package resource to manage packages for the Mac OS X platform.
Mdadm
使用 mdadm 资源来使用 mdadm 实用程序在 Linux 环境中管理 RAID 设备。mdadm 提供程序将创建和汇编阵列,但不会创建用于在重启后保留阵列的配置文件。
Use the mdadm resource to manage RAID devices in a Linux environment using the mdadm utility. The mdadm provider will create and assemble an array, but it will not create the config file that is used to persist the array upon reboot.
如果需要配置文件,则必须通过指定带有正确阵列布局的模板,然后使用 mount 提供程序来创建文件系统表 (fstab) 条目。
If the config file is required, it must be done by specifying a template with the correct array layout, and then by using the mount provider to create a file systems table (fstab) entry.
Ohai
使用 ohai 资源来重新加载节点上的 Ohai 配置。这使得改变系统属性的配方(例如,添加用户的配方)能够在 chef-client 运行期间引用这些属性。
Use the ohai resource to reload the Ohai configuration on a node. This allows recipes that change system attributes (like a recipe that adds a user) to refer to those attributes later on during the chef-client run.
Package
使用 package 资源来管理软件包。当软件包是从本地文件(例如使用 RubyGems、dpkg 或 RPM Package Manager)安装时,必须使用 remote_file 或 cookbook_file 资源将文件添加到节点。
Use the package resource to manage packages. When the package is installed from a local file (such as with RubyGems, dpkg, or RPM Package Manager), the file must be added to the node using the remote_file or cookbook_file resources.
pacman_package
使用 pacman_package 资源来使用 pacman 在 Arch Linux 平台上管理软件包。
Use the pacman_package resource to manage packages (using pacman) on the Arch Linux platform.
powershell_script
使用 powershell_script 资源来使用 Windows PowerShell 解释器执行脚本,就像使用脚本和基于脚本来源(bash、csh、perl、python 和 ruby)一样。powershell_script 具体用于 Microsoft Windows 平台和 Windows PowerShell 解释器。
Use the powershell_script resource to execute a script using the Windows PowerShell interpreter, much like how the script and script-based resources—bash, csh, perl, python, and ruby—are used. The powershell_script is specific to the Microsoft Windows platform and the Windows PowerShell interpreter.
Python
使用 python 资源来使用 Python 解释器执行脚本。该资源还可以使用 execute 资源中提供的任何操作和属性。
Use the python resource to execute scripts using the Python interpreter. This resource may also use any of the actions and properties that are available to the execute resource.
使用此资源执行的命令(本质上)不是幂等的,因为它们通常是其运行环境中唯一的命令。使用`not_if`和`only_if`来保护此资源的幂等性。
Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
Reboot
使用 reboot 资源来重启节点,这是在某些平台上某些安装的必要步骤。该资源支持在 Microsoft Windows、Mac OS X 和 Linux 平台上使用。
Use the reboot resource to reboot a node, a necessary step with some installations on certain platforms. This resource is supported for use on the Microsoft Windows, Mac OS X, and Linux platforms.
registry_key
使用 registry_key 资源来在 Microsoft Windows 中创建和删除注册表项。
Use the registry_key resource to create and delete registry keys in Microsoft Windows.
remote_directory
使用 remote_directory 资源来增量地将目录从配方传输到节点。从配方中复制的目录应位于 COOKBOOK_NAME/files/default/REMOTE_DIRECTORY 下。
Use the remote_directory resource to incrementally transfer a directory from a cookbook to a node. The directory that is copied from the cookbook should be located under COOKBOOK_NAME/files/default/REMOTE_DIRECTORY.
remote_directory 资源将遵守文件规范性。
The remote_directory resource will obey file specificity.
remote_file
使用 remote_file 资源通过文件指定性从远程位置传输文件。此资源类似于 file 资源。
Use the remote_file resource to transfer a file from a remote location using file specificity. This resource is similar to the file resource.
Route
使用 route 资源管理 Linux 环境中的系统路由表。
Use the route resource to manage the system routing table in a Linux environment.
rpm_package
使用 rpm_package 资源管理 RPM 包管理器平台的包。
Use the rpm_package resource to manage packages for the RPM Package Manager platform.
Ruby
使用 ruby 资源使用 Ruby 解释器执行脚本。此资源还可使用 execute 资源中的任何操作和属性。
Use the ruby resource to execute scripts using the Ruby interpreter. This resource may also use any of the actions and properties that are available to the execute resource.
使用此资源执行的命令(本质上)不是幂等的,因为它们通常是其运行环境中唯一的命令。使用`not_if`和`only_if`来保护此资源的幂等性。
Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
ruby_block
使用 ruby_block 资源在 Chef-Client 运行期间执行 Ruby 代码。ruby_block 资源中的 Ruby 代码在收敛期间与其他资源一起进行评估,而 ruby_block 资源之外的 Ruby 代码在编译食谱时在其他资源之前进行评估。
Use the ruby_block resource to execute Ruby code during a Chef-Client run. Ruby code in the ruby_block resource is evaluated with other resources during convergence, whereas Ruby code outside of a ruby_block resource is evaluated before other resources, as the recipe is compiled.
Script
使用 script 资源使用指定的解释器(如 Bash、csh、Perl、Python 或 Ruby)执行脚本。此资源还可使用 execute 资源中的任何操作和属性。
Use the script resource to execute scripts using a specified interpreter, such as Bash, csh, Perl, Python, or Ruby. This resource may also use any of the actions and properties that are available to the execute resource.
使用此资源执行的命令(本质上)不是幂等的,因为它们通常是其运行环境中唯一的命令。使用`not_if`和`only_if`来保护此资源的幂等性。
Commands that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
smart_os_package
使用 smartos_package 资源管理 SmartOS 平台的包。
Use the smartos_package resource to manage packages for the SmartOS platform.
solaris_package
solaris_package 资源用于管理 Solaris 平台的包。
The solaris_package resource is used to manage packages for the Solaris platform.
Subversion
使用 subversion 资源管理存在于 Subversion 存储库中的源代码控制资源。
Use the subversion resource to manage source control resources that exist in a Subversion repository.
Template
使用 template 资源通过将文件从 COOKBOOK_NAME/templates/ 的子目录传输到正在运行 Chef-Client 的主机上的指定路径,使用嵌入式 Ruby (ERB) 模板管理文件的内容。此资源包含来自 file 资源的操作和属性。由 template 资源管理的模板文件遵循与 remote_file 和 file 资源相同的 file 规范性规则。
Use the template resource to manage the contents of a file using an Embedded Ruby (ERB) template by transferring files from a sub-directory of COOKBOOK_NAME/templates/ to a specified path located on a host that is running the Chef-Client. This resource includes actions and properties from the file resource. Template files managed by the template resource follow the same file specificity rules as the remote_file and file resources.
User
使用 user 资源来添加用户、更新现有用户、删除用户以及锁定/解锁用户密码。
Use the user resource to add users, update existing users, remove users, and to lock/unlock user passwords.
windows_package
使用 windows_package 资源管理 Microsoft Windows 平台的 Microsoft 安装程序包 (MSI) 包。
Use the windows_package resource to manage Microsoft Installer Package (MSI) packages for the Microsoft Windows platform.
windows_service
使用 windows_service 资源管理 Microsoft Windows 平台上的服务。
Use the windows_service resource to manage a service on the Microsoft Windows platform.
yum_package
使用 yum_package 资源使用 Yum 为 Red Hat 和 CentOS 平台安装、升级和删除包。yum_package 资源能够解析包提供的数据,就像从命令行运行 Yum 时一样。这允许多种选项来安装包,如最小版本、虚拟提供和库名称。
Use the yum_package resource to install, upgrade, and remove packages with Yum for the Red Hat and CentOS platforms. The yum_package resource is able to resolve provides data for packages much like Yum can do when it is run from the command line. This allows a variety of options for installing packages, like minimum versions, virtual provides, and library names.
Chef - Lightweight Resource Provider
Lightweight resource provider (LWRP) 提供了通过扩展其特性来扩展可用资源列表的选项,并允许 Chef用户创建自定义资源。
Lightweight resource provider (LWRP) provides an option of extending the list of available resources by extending it features and allows Chef user to create custom resources.
通过创建自定义资源,你可以简单地编写食谱,因为你可以使用 Chef DSL 拥有丰富的自定义资源,这有助于使食谱代码更具表现力。
By creating custom resources one can simply write cookbooks because one can own enriched custom resources using Chef DSL which helps in making the recipe code more expressive.
在 Chef 社区中,许多自定义资源是使用 LWRP 实现的。有很多 LWRP 的工作示例,例如 iptables_rules 和 apt_repository 。
In Chef community, many of the custom resources are implemented using LWRPs. There are many working examples of LWRP such as iptables_rules and apt_repository.
Working Method
确保你有食谱名称 Testing_resource 和包含 Testing_resource 食谱的节点运行列表。
Make sure one has cookbook name Testing_resource and a run_list of node which contains Testing_resource cookbook.
Building LWRP
Step 1 − 在 Testing_resource 食谱中创建一个自定义资源。
Step 1 − Create a custom resource in Testing_resource cookbook.
vipin@laptop:~/chef-repo $ subl cookbooks/Testing_resource/resources/default.rb
actions :create, :remove
attribute :title, kind_of: String, default: "World"
attribute :path, kind_of: String, default: "/tmp/greeting.txt"
Step 2 − 在 Tesing_resource 食谱中为资源创建提供者。
Step 2 − Create a provider for resources in Tesing_resource cookbook.
vipin@laptop:~/chef-repo $ subl cookbooks/Testing_resource/provider/default.rb
action :create do
log "Adding '#{new_resource.name}' greeting as #{new_resource.
path}"
file new_resource.path do
content "#{new_resource.name}, #{new_resource.title}!"
action :create
end
action :remove do
Chef::Log.info "Removing '#{new_resource.name}' greeting #{new_resource.path}"
file new_resource.path do
action :delete
end
end
Step 3 − 通过编辑 Testing_resource 默认食谱来使用新资源。
Step 3 − Use a new resource by editing Testing_resource default recipe.
vipin@laptop:~/chef-repo $ subl cookbooks/Tesing_resource/recipes/default.rb
greeting "Ohai" do
title "Chef"
action :create
end
Step 4 − 将修改后的食谱上传到 Chef 服务器。
Step 4 − Upload the modified cookbook to Chef server.
vipin@laptop:~/chef-repo $ knife cookbook upload greeting
Uploading greeting [0.1.0]
Step 5 − 在节点上运行 Chef-Client。
Step 5 − Run Chef-Client on the node.
vipin@server:~$ sudo chef-client
...TRUNCATED OUTPUT...
2013-06-28T21:32:54+00:00] INFO: Processing greeting[Ohai] action
create (greeting::default line 9)
[2013-06-28T21:32:54+00:00] INFO: Adding 'Ohai' greeting as /tmp/
greeting.txt
[2013-06-28T21:32:54+00:00] INFO: Processing file[/tmp/greeting.
txt] action create (/srv/chef/file_store/cookbooks/greeting/
providers/default.rb line 7)
[2013-06-28T21:32:54+00:00] INFO: entered create
[2013-06-28T21:32:54+00:00] INFO: file[/tmp/greeting.txt] created
file /tmp/greeting.txt
...TRUNCATED OUTPUT...
Step 6 − 验证生成的文件的内容。
Step 6 − Validate the content of the generated file.
user@server:~$ cat /tmp/greeting.txt
Ohai, Chef!
Workflow Scripts
LWRP 存在于食谱中。自定义资源存在于食谱内,并且将在食谱名称下可用。在工作流中,首先定义定义,然后将属性传递给将在食谱中使用的资源。最后,在食谱中使用这些动作与属性。
LWRPs live in cookbooks. A custom resource lives inside the cookbooks, and will be available under the cookbook name. In the workflow, first we define the definitions and then pass the attributes to the resources which is going to be used in the cookbook. Finally, we use those actions and attributes in our recipe.
Chef - Blueprints
在 Chef 中,蓝图是用来找出和记录服务器上确切存在哪些内容的工具。蓝图记录所需的所有内容,如目录、软件包、配置文件等。蓝图有能力将服务器信息分割成不同的格式。其中之一是 Chef 食谱。这有助于使用 Chef 来配置唯一服务器。
In Chef, blueprints are the tools to find out and record exactly what is present on the server. Blueprints record all the things required such as directors, packages, configuration files, and so on. Blueprints have the capability to split server information in various formats. One of them is Chef recipe. This helps to configure unique server using Chef.
Woring Method
我们需要在需要运行蓝图的节点上安装 Python 和 Git。
We need to have Python and Git installed on the node where we need to run the blueprint.
Step 1 − 安装蓝图。
Step 1 − Install the blueprint.
vipin@server:~$ pip install blueprint
Step 2 − 创建蓝图。
Step 2 − Create a blueprint.
user@server:~$ sudo blueprint create internal-cookbook
# [blueprint] using cached blueprintignore(5) rules
# [blueprint] searching for Python packages
# [blueprint] searching for PEAR/PECL packages
# [blueprint] searching for Yum packages
# [blueprint] searching for Ruby gems
# [blueprint] searching for npm packages
# [blueprint] searching for software built from source
# [blueprint] searching for configuration files
# [blueprint] /etc/ssl/certs/AC_Ra\xc3\xadz_Certic\xc3\
xa1mara_S.A..pem not UTF-8 - skipping it
# [blueprint] /etc/ssl/certs/NetLock_Arany_=Class_Gold=_F\xc5\
x91tan\xc3\xbas\xc3\xadtv\xc3\xa1ny.pem not UTF-8 - skipping it
# [blueprint] /etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_Sa\
xc4\x9flay\xc4\xb1c\xc4\xb1s\xc4\xb1.pem not UTF-8 - skipping it
# [blueprint] /etc/ssl/certs/Certinomis_-_Autorit\xc3\xa9_Racine.
pem not UTF-8 - skipping it
# [blueprint] /etc/ssl/certs/T\xc3\x9cB\xc4\xb0TAK_UEKAE_K\xc3\
xb6k_Sertifika_Hizmet_Sa\xc4\x9flay\xc4\xb1c\xc4\xb1s\xc4\xb1_-_S\
xc3\xbcr\xc3\xbcm_3.pem not UTF-8 - skipping it
# [blueprint] searching for APT packages
# [blueprint] searching for service dependencies
Step 3 − 从蓝图创建食谱。
Step 3 − Create a cookbook from the blueprint.
user@server:~$ blueprint show -C internal-cookbook my-server/recipes/default.rb
Step 4 − 验证生成的文件的内容。
Step 4 − Validate the content of the generated file.
user@server:~$ cat internal-cookbook /recipes/default.rb
#
# Automatically generated by blueprint(7). Edit at your own risk.
#
cookbook_file('/tmp/96468fd1cc36927a027045b223c61065de6bc575.tar')
do
backup false
group 'root'
mode '0644'
owner 'root'
source 'tmp/96468fd1cc36927a027045b223c61065de6bc575.tar'
end
execute('/tmp/96468fd1cc36927a027045b223c61065de6bc575.tar') do
command 'tar xf "/tmp/96468fd1cc36927a027045b223c61065de6bc575.tar"'
cwd '/usr/local'
end
directory('/etc/apt/apt.conf.d') do
...TRUNCATED OUTPUT...
service('ssh') do
action [:enable, :start]
subscribes :restart, resources('cookbook_file[/etc/default/
keyboard]', 'cookbook_file[/etc/default/console-setup]',
'cookbook_file[/etc/default/ntfs-3g]', 'package[openssh-server]',
'execute[96468fd1cc36927a027045b223c61065de6bc575.tar]')
end
Workflow Script
蓝图是一个 Python 软件包,它找出服务器所有相关配置数据,并将其存储在 Git 仓库中。每个蓝图都有自己的名称。
Blueprint is a Python package that finds out all the relevant configuration data of the server and stores it in a Git repo. Each blueprint has its own name.
人们可以要求蓝图以各种格式显示其 Git 仓库的内容。
One can ask the blueprint to show the content of its Git repo in various formants.
user@server:~$ ls -l internal-cookbook /
total 8
drwxrwxr-x 3 vagrant vagrant 4096 Jun 28 06:01 files
-rw-rw-r-- 1 vagrant vagrant 0 Jun 28 06:01 metadata.rb
drwxrwxr-x 2 vagrant vagrant 4096 Jun 28 06:01 recipes
Blueprints Show Commands
user@server:~$ blueprint show-packages my-server
...TRUNCATED OUTPUT...
apt wireless-regdb 2011.04.28-1ubuntu3
apt zlib1g-dev 1:1.2.3.4.dfsg-3ubuntu4
python2.7 distribute 0.6.45
python2.7 pip 1.3.1
pip blueprint 3.4.2
pip virtualenv 1.9.1
前述命令显示所有已安装软件包的类型。其他显示命令如下 −
The preceding command shows all kinds of installed packages. Other show commands are as follows −
-
show-files
-
show-services
-
show-sources
Chef - Files & Packages
在 Chef 中,创建配置文件和移动软件包是关键组件。Chef 有多种方式来管理相同的。Chef 有多种方式来支持处理文件和软件包。
In Chef, creating configuration files and moving packages are the key components. There are multiple ways how Chef manages the same. There are multiple ways how Chef supports in dealing with the files and software packages.
Installing Packages from Third-Party Repo
Step 1 − 编辑食谱的默认食谱。
Step 1 − Edit the default recipe of the cookbook.
vipin@laptop:~/chef-repo $ subl cookbooks/test_cookbook/recipes/default.rb
include_recipe "apt"
apt_repository "s3tools" do
uri "http://s3tools.org/repo/deb-all"
components ["stable/"]
key "http://s3tools.org/repo/deb-all/stable/s3tools.key"
action :add
end
package "s3cmd"
Step 2 − 编辑元数据以添加对 apt 食谱的依赖性。
Step 2 − Edit the metadata to add dependency on the apt cookbook.
vipin@laptop:~/chef-repo $ subl cookbooks/my_cookbook/metadata.rb
...
depends "apt"
Step 3 – 上传修改后的配方至 Chef 服务器。
Step 3 − Upload the modified cookbook to the Chef server.
Step 4 — 验证尝试安装的软件包尚未安装。
Step 4 − Validate that the package you are trying to install, is not yet installed.
Step 5 — 验证默认仓库。
Step 5 − Validate the default repo.
Step 6 — 在该节点运行 Chef-Client。
Step 6 − Run Chef-Client on the node.
Step 7 — 验证必需的软件包已安装。
Step 7 − Validate that the required package is installed.
Installing Software from Source
如果需要安装不是特定平台的软件包的软件,则需要编译它。在 Chef 中,可以使用脚本资源来执行此操作。
If one needs to install a piece of software that is not available as a package for a given platform, one needs to compile it oneself. In Chef, we can do this by using the script resource.
Step 1 — 编辑默认配方。
Step 1 − Edit the default recipe.
vipin@laptop:~/chef-repo $ subl cookbooks/my_cookbook/recipes/
default.rb
version = "1.3.9"
bash "install_nginx_from_source" do
cwd Chef::Config['file_cache_path']
code ≪-EOH
wget http://nginx.org/download/nginx-#{version}.tar.gz
tar zxf nginx-#{version}.tar.gz &&
cd nginx-#{version} &&
./configure && make && make install
EOH
Step 2 − 将修改后的代码提交到 Chef 服务器。
Step 2 − Upload the modified cookbook to the Chef server.
Step 3 — 在该节点运行 Chef-Client。
Step 3 − Run the Chef-Client on the node.
Step 4 — 验证是否安装了 nginx。
Step 4 − Validate that the nginx is installed.
Chef - Community Cookbooks
社区配方与其他配方类似。之所以称为社区配方是因为任何了解编写配方的人都可以加入此社区并将其配方上传至集中式集线器。这些配方可免费获得,任何人均可下载并使用。为了使用这些社区配方,需要下载这些配方、根据需要修改它们并将其上传到各自的 Chef 服务器。
Community cookbooks are similar to any other cookbook. The only reason it is called community cookbook is because anyone who knows to write cookbooks can join this community and upload their cookbooks to the centralized hub. These cookbooks are available for free and anyone can download and use it. In order to use these community cookbooks, one needs to download them, modify them as per the requirement, and upload them to their respective Chef server.
需要在自己的系统上配置 Knife 才能更新、上传和下载配方。使用 Knife 配方命令与配方互动。使用 Knife 配方,可以创建、删除、显示、列出、下载和上传配方。阅读 Knife 配方命令文档以获取第 7 章的更多信息。
One needs to have knife configured on their system in order to update, upload, and download the cookbooks. Interact with cookbooks using the knife cookbook commands. With knife cookbook, you can create, delete, show, list, download, and upload cookbooks. Read the knife cookbook commands documentation for more information in Chapter 7.
以下是社区配方的链接: https://supermarket.chef.io/cookbooksdirectory
Following is the link of community cookbooks: https://supermarket.chef.io/cookbooksdirectory
