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