如何创建简单的 Chef Cookbooks 来管理 Ubuntu 上的基础设施

发布于:2024-05-16 ⋅ 阅读:(50) ⋅ 点赞:(0)

简介


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 :install
end

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 环境变量。你可以通过输入以下命令来完成:

export EDITOR=<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 配置了你的第一个节点!

结论


虽然这只是一个非常简单的例子,可能并没有比手动配置服务器节省多少时间,但希望你能开始看到使用这种基础设施构建方法的可能性。

它不仅可以实现快速部署和配置不同类型的服务器,还确保您了解所有机器的确切配置。这使您能够验证和测试您的基础设施,并为您提供了在需要时快速重新部署基础设施的框架。


网站公告

今日签到

点亮在社区的每一天
去签到