介绍
Chef 是一个配置管理系统,旨在让您以自动化、可靠和可扩展的方式自动化和控制大量计算机。
在之前的教程中,我们查看了一些 常见的 Chef 术语 并讨论了如何安装 Chef 服务器、工作站和节点(使用 Chef 12 或 Chef 11 )。 在本指南中,我们将使用这些指南作为起点,开始讨论如何自动化您的环境。
在本文中,我们将讨论创建 Chef 食谱的基础知识。 Cookbooks 是配置单元,允许我们在远程节点上的 Chef 中配置和执行特定任务。 我们构建说明书,然后告诉厨师我们要运行说明书中概述的步骤的节点。
在本指南中,我们将假设您从我们结束 上一课 的三台机器开始。 您应该有一台服务器、一台工作站和至少一个节点来将配置更改推送到。
基本食谱概念
Cookbook 是 Chef 用来将节点带入特定状态的配置和策略详细信息的基本单元。 这只是意味着 Chef 使用说明书来执行工作并确保节点上的内容与它们应有的一样。
Cookbooks 通常用于处理一项特定的服务、应用程序或功能。 例如,可以创建食谱以使用 NTP 设置节点时间并将其与特定服务器同步。 它可以安装和配置数据库应用程序。 Cookbooks 基本上是用于基础设施选择的软件包。
食谱在工作站上创建,然后上传到 Chef 服务器。 从那里,食谱中描述的食谱和策略可以作为节点“运行列表”的一部分分配给节点。 运行列表是厨师客户端在节点上运行的配方和角色的顺序列表,以使节点符合您为其设置的策略。
通过这种方式,您在说明书中编写的配置详细信息将应用于您希望遵守说明书中描述的场景的节点。
食谱以完全独立的目录结构组织。 有许多不同的目录和文件用于不同的目的。 现在让我们回顾一些更重要的。
食谱
食谱是食谱的主要内容。 一本食谱可以包含多个食谱,或者依赖于外部食谱。 配方用于声明不同资源的状态。
Chef 资源描述了系统的一部分及其所需的状态。 例如,资源可以说“应该安装包 x”。 另一个资源可能会说“x 服务应该正在运行”。
菜谱是一个与资源列表相关的资源,它告诉 Chef 如果系统实现了菜谱,系统应该是什么样子。 当 Chef 运行配方时,它会检查每个资源是否符合声明的状态。 如果系统匹配,它会移动到下一个资源,否则,它会尝试将资源移动到给定状态。
资源可以有许多不同的类型。 您可以在这里了解不同的资源类型。 一些常见的有:
- package:用于管理节点上的包
- service:用于管理节点上的服务
- user:管理节点上的用户
- group:管理群组
- template:使用嵌入的 ruby 模板管理文件
- cookbook_file:将文件从食谱中的文件子目录传输到节点上的某个位置
- file:管理节点上文件的内容
- directory:管理节点上的目录
- execute:在节点上执行命令
- cron:编辑节点上已有的cron文件
属性
Chef 中的属性基本上是设置。 将它们视为您可能想在食谱中使用的任何内容的简单键值对。
有几种不同类型的属性可以应用,每种属性对节点操作的最终设置具有不同的优先级。 在说明书级别,我们通常定义我们正在配置的服务或系统的默认属性。 这些可以稍后被特定节点的更具体的值覆盖。
创建说明书时,我们可以在说明书的属性子目录中为我们的服务设置属性。 然后,我们可以在食谱的其他部分引用这些值。
文件
食谱中的文件子目录包含我们将放置在使用食谱的节点上的任何静态文件。
例如,任何我们不太可能修改的简单配置文件都可以完整地放在 files 子目录中。 然后,配方可以声明一个资源,将文件从该目录移动到它们在节点上的最终位置。
模板
模板类似于文件,但它们不是静态的。 模板文件以 .erb
扩展名结尾,这意味着它们包含嵌入的 Ruby。
这些主要用于将属性值替换到文件中,以创建将放置在节点上的最终文件版本。
例如,如果我们有一个属性定义了服务的默认端口,则模板文件可以调用以在文件中声明端口的位置插入该属性。 使用这种技术,您可以轻松地创建配置文件,同时保留您希望在其他地方更改的实际变量。
元数据.rb
毫不奇怪,metadata.rb 文件用于管理有关包的元数据。 这包括包的名称、描述等内容。
它还包括依赖信息等内容,您可以在其中指定此说明书需要操作哪些说明书。 这将允许 Chef 服务器正确地为节点构建运行列表,并确保所有部分都正确传输。
创建一个简单的食谱
为了演示使用食谱所涉及的一些工作流程,我们将创建自己的食谱。 这将是一本非常简单的食谱,它在我们的节点上安装和配置 Nginx Web 服务器。
首先,我们需要进入我们工作站上的 ~/chef-repo
目录:
cd ~/chef-repo
在那里,我们可以使用刀创建食谱。 正如我们在之前的指南中提到的,knife 是一种用于配置与 Chef 系统的大多数交互的工具。 我们可以使用它在我们的工作站上执行工作,也可以连接到 Chef 服务器或单个节点。
创建食谱的一般语法是:
刀食谱创建食谱名称
由于我们的说明书将处理安装和配置 Nginx,我们将适当地命名我们的说明书:
knife cookbook create nginx
** Creating cookbook nginx ** Creating README for cookbook: nginx ** Creating CHANGELOG for cookbook: nginx ** Creating metadata for cookbook: nginx
Knife 在这里所做的是在我们的食谱目录中为我们的新食谱构建一个简单的结构。 我们可以通过导航到cookbooks 目录并进入带有cookbook 名称的目录来查看我们的cookbook 结构。
cd cookbooks/nginx ls
attributes CHANGELOG.md definitions files libraries metadata.rb providers README.md recipes resources templates
如您所见,这已经创建了一个文件夹和文件结构,我们可以使用它来构建我们的食谱。 让我们从配置的最大部分开始,即配方。
创建一个简单的食谱
如果我们进入 recipes
子目录,我们可以看到里面已经有一个名为 default.rb
的文件:
cd recipes ls
default.rb
如果您引用“nginx”配方,这是将运行的配方。 这是我们将添加代码的地方。
使用文本编辑器打开文件:
nano default.rb
# # Cookbook Name:: nginx # Recipe:: default # # Copyright 2014, YOUR_COMPANY_NAME # # All rights reserved - Do Not Redistribute #
当前,该文件中唯一的内容是注释标题。
我们可以从计划我们的 Nginx Web 服务器启动并按照我们希望的方式运行所需发生的事情开始。 我们通过配置“资源”来做到这一点。 资源没有描述如何做某事; 它们只是描述了系统的一部分在完成后应该是什么样子。
首先,我们显然需要确保安装了软件。 我们可以通过首先创建一个“包”资源来做到这一点。
package 'nginx' do action :install end
这段小代码为 Nginx 定义了一个包资源。 第一行以资源类型(包)和资源名称('nginx')开头。 其余的是一组动作和参数,它们声明我们希望对资源发生什么。
在此资源中,我们看到 action :install
。 这一行告诉 Chef 应该安装我们所描述的资源。 运行此配方的节点将检查 Nginx 是否已安装。 如果是,它会从待办事项列表中检查出来。 如果没有,它将使用客户端系统上可用的方法安装程序,然后将其选中。
安装服务后,我们可能想要调整它在节点上的当前状态。 默认情况下,Ubuntu 在安装后不会启动 Nginx,因此我们需要更改它:
service 'nginx' do action [ :enable, :start ] end
在这里,我们看到了“服务”类型的资源。 这表明对于 Nginx 服务组件(允许我们使用 init 或 upstart 管理服务器的部分),我们希望立即启动该服务,并使其在机器重新启动时自动启动。
我们将要声明的最终资源是我们将要提供的实际文件。 由于这只是一个我们不会修改的简单文件,我们可以简单地声明我们想要文件的位置,并告诉它在食谱中的哪个位置获取文件:
cookbook_file "/usr/share/nginx/www/index.html" do source "index.html" mode "0644" end
我们使用“cookbook_file”资源类型告诉 Chef 该文件在食谱本身中可用,并且可以按原样传输到该位置。 在我们的示例中,我们将文件传输到 Nginx 的文档根目录中。
在我们的例子中,我们在第一行指定我们试图创建的文件名。 在“源”行中,我们告诉它要在说明书中查找的文件的名称。 Chef 在说明书的“files/default”子目录中查找此文件。
“mode”行设置我们正在创建的文件的权限。 在这种情况下,我们允许 root 用户读取和写入权限以及其他所有人读取权限。
完成后保存并关闭此文件。
创建索引文件
正如你在上面看到的,我们定义了一个“cookbook_file”资源,它应该将一个名为“index.html”的文件移动到节点上的文档根目录中。 我们需要创建这个文件。
我们应该把这个文件放在我们食谱的“files/default”子目录中。 现在输入:
cd ~/chef-repo/cookbooks/nginx/files/default
在这个目录中,我们将创建我们引用的文件:
nano index.html
该文件将只是一个非常简单的 HTML 文档,旨在证明我们的资源已按照我们希望的方式运行。
将其粘贴到文件中:
<html> <head> <title>Hello there</title> </head> <body> <h1>This is a test</h1> <p>Please work!</p> </body> </html>
完成后保存并关闭文件。
创建助手食谱
在我们继续之前,让我们先发制人地解决一个小问题。 当我们的节点尝试运行我们现在创建的食谱时,它很可能会失败。
这是因为它会尝试从 Ubuntu 存储库安装 Nginx,并且我们节点上的包数据库很可能已过期。 通常,我们在运行包命令之前运行“sudo apt-get update”。
为了解决这个问题,我们可以创建一个简单的说明书,其唯一目的是确保更新包数据库。
我们可以使用之前使用的刀语法来做到这一点。 让我们称这本食谱为“apt”:
knife cookbook create apt
这将创建与我们第一次开始使用 Nginx 食谱时相同的目录结构。
让我们直奔主题,为我们的新食谱编辑默认食谱。
nano ~/chef-repo/cookbooks/apt/recipes/default.rb
在这个文件中,我们将声明一个“执行”资源。 这只是定义我们要在节点上运行的命令的一种方式。
我们的资源如下所示:
execute "apt-get update" do command "apt-get update" end
第一行为我们的资源命名。 在我们的例子中,为了简单起见,我们将资源称为 this。 如果定义了“command”属性(正如我们所做的那样),那么这就是实际执行的命令。
由于这些完全相同,因此没有任何关系。
保存并关闭文件。
现在我们有了新的说明书,有很多方法可以确保我们在 Nginx 说明书之前执行它。 我们可以将它添加到 Nginx 说明书之前的节点运行列表中,但我们也可以将它绑定到 Nginx 说明书本身。
这可能是更好的选择,因为我们不必记住在要为 Nginx 配置的每个节点上的“nginx”说明书之前添加“apt”说明书。
我们需要调整 Nginx 食谱中的一些内容来实现这一点。 首先,让我们再次打开 Nginx 配方文件:
nano ~/chef-repo/cookbooks/nginx/recipes/default.rb
在这本食谱的顶部,在我们定义的其他资源之前,我们可以通过键入以下内容来阅读“apt”默认配方:
include_recipe “恰当” 包'nginx'做动作:安装结束 服务'nginx'做动作[:启用,:开始]结束 cookbook_file “/usr/share/nginx/www/index.html” do source “index.html” mode “0644” end
保存并关闭文件。
我们需要编辑的另一个文件是 metadata.rb
文件。 当 Chef 服务器将运行列表发送到节点时会检查此文件,以查看应将哪些其他配方添加到运行列表中。
现在打开文件:
nano ~/chef-repo/cookbooks/nginx/metadata.rb
在文件的底部,您可以添加以下行:
名称“nginx”维护者“YOUR_COMPANY_NAME”维护者电子邮件“YOUR_EMAIL”许可证“保留所有权利”描述“安装/配置 nginx”long_description IO.read(File.join(File.dirname( 文件 ), ' 自述文件.md ')) 版本'0.1.0' 取决于“合适”
完成后,我们的 Nginx 食谱现在依赖我们的 apt 食谱来处理包数据库更新。
将 Cookbook 添加到您的节点
现在我们的基本食谱已经完成,我们可以将它们上传到我们的厨师服务器。
我们可以通过键入以下内容单独执行此操作:
knife cookbook upload apt knife cookbook upload nginx
或者,我们可以通过键入以下内容上传所有内容:
knife cookbook upload -a
无论哪种方式,我们的食谱都会上传到 Chef 服务器。
现在,我们可以修改节点的运行列表。 我们可以通过键入以下内容轻松完成此操作:
刀节点编辑name_of_node
如果您需要查找可用节点的名称,可以键入:
knife node list
client1
出于我们的目的,当我们输入这个时,我们会得到一个如下所示的文件:
knife node edit client1
{ "name": "client1", "chef_environment": "_default", "normal": { "tags": [ ] }, "run_list": [ ] }
您可能需要在此工作之前设置您的 EDITOR 环境变量。 您可以通过键入以下内容来执行此操作:
导出 EDITOR= name_of_editor
如您所见,这是一个简单的 JSON 文档,描述了我们节点的某些方面。 我们可以看到一个“run_list”数组,它目前是空的。
我们可以使用以下格式将我们的 Nginx 食谱添加到该数组中:
“食谱[ name_of_recipe ]”
完成后,我们的文件应如下所示:
{ "name": "client1", "chef_environment": "_default", "normal": { "tags": [ ] }, "run_list": [ "recipe[nginx]" ] }
保存并关闭文件以实施新设置。
现在,我们可以通过 SSH 连接到我们的节点并运行 Chef 客户端软件。 这将导致客户端签入 Chef 服务器。 完成此操作后,它将看到已分配给它的新运行列表。
SSH 进入您的节点,然后运行:
sudo chef-client
Starting Chef Client, version 11.8.2 resolving cookbooks for run list: ["nginx"] Synchronizing Cookbooks: - apt - nginx Compiling Cookbooks... Converging 4 resources Recipe: apt::default * execute[apt-get update] action run - execute apt-get update Recipe: nginx::default * package[nginx] action install (up to date) * service[nginx] action enable - enable service service[nginx] * service[nginx] action start (up to date) * cookbook_file[/usr/share/nginx/www/index.html] action create (up to date) Chef Client finished, 2 resources updated
如您所见,我们的 apt 食谱也被发送并运行,即使它不在我们创建的运行列表中。 这是因为 Chef 在节点上执行之前智能地解决了依赖关系并修改了实际的运行列表。
注意:有多种方法可以确保一本食谱或食谱在另一本之前运行。 添加依赖项只是一种选择,其他方法可能是首选。
我们可以通过转到我们节点的 IP 地址或域名来验证这是否有效:
http:// node_domain_or_IP
您应该会看到如下所示的内容:
恭喜,您已经使用 Chef 说明书配置了您的第一个节点!
结论
尽管这是一个非常简单的示例,可能并没有为您节省太多手动配置服务器的时间,但希望您可以开始看到这种构建基础架构的方法的可能性。
它不仅允许快速部署和配置不同类型的服务器,还可以确保您了解所有机器的确切配置。 这使您可以验证和测试您的基础架构,并为您提供快速重新部署基础架构所需的框架。