配置管理 101:编写 Chef 食谱

简而言之,服务器配置管理(通常也称为IT自动化)是一种将基础设施管理转化为代码库的解决方案,它描述了在一组可以进行版本控制并易于重用的配置脚本中部署服务器所需的所有流程。随着时间的推移,它可以大大提高任何服务器基础设施的完整性。

在以前的guide](https://andsky.com/tech/tutorials/an-introduction-to-configuration-management),中,我们谈到了为您的服务器基础设施实施配置管理策略的主要好处、配置管理工具如何工作,以及这些工具通常有哪些共同之处。

本系列的这一部分将带您完成使用Chef自动化服务器配置的过程,Chef是一个强大的配置管理工具,它利用Ruby编程语言来自动化基础设施管理和配置。我们将重点介绍创建简化示例所需的语言术语、语法和特性,以使用Apache完全自动化Ubuntu 18.04Web服务器的部署。

为了实现我们的目标,以下是我们需要自动执行的步骤:

1.更新apt缓存 2.安装Apache 3.创建自定义文档根目录 4.在自定义文档根目录中放置一个index.html文件 5.应用模板来设置我们的自定义虚拟主机 6.重新启动Apache

我们将首先看一看Chef使用的术语,然后概述可用于编写食谱的主要语言功能。在本指南的最后,我们将分享完整的示例,以便您可以亲自尝试。

<$>[备注] 注意: 本指南旨在向您介绍Chef语言,以及如何编写配方来自动执行服务器配置。有关厨师的更具介绍性的视图,包括安装和开始使用该工具所需的步骤,请参阅厨师官方documentation. <$>

入门

在我们开始更实际地了解Chef之前,重要的是我们要熟悉这个工具引入的重要术语和概念。

厨师术语

  • Chef Server :存储信息和管理节点供应的中央服务器
  • Chef Node :由Chef服务器管理的单个服务器
  • 厨师工作站 :创建供应并上传到厨师服务器的控制器机器
  • 配方 :包含一组要执行的指令(资源)的文件。食谱必须包含在_Cookbook_内
  • 资源 :声明系统元素和应该执行的操作的代码部分。例如,要安装一个包,我们使用操作** Install** 声明a_Package_resource
  • Cookbook :以预定义的方式组织的食谱和其他相关文件的集合,以促进部分供应的共享和重用
  • 属性 :具体节点的详细信息。属性可以是自动的(参见下一个定义),也可以在食谱中定义
  • 自动属性 :包含系统信息的全局变量,如网络接口、操作系统(在其他工具中称为_FACTS_)。这些自动属性由名为_OHAI_的工具收集
  • 服务 :用于触发服务状态的改变,如重启或停止服务

菜谱格式

厨师食谱是使用Ruby编写的。配方基本上是资源定义的集合,这些资源定义将创建由节点执行的逐步指令集。这些资源定义可以与Ruby代码混合使用,以获得更大的灵活性和模块化。

下面是一个简单的食谱示例,它将运行apt-get update,然后安装vim

1execute "apt-get update" do
2 command "apt-get update"
3end
4
5apt_package "vim" do
6 action :install
7end

写作秘诀

使用变量

局部变量可以在配方中定义为常规Ruby局部变量。下面的示例显示如何创建稍后在资源定义中使用的局部变量:

1package  = "vim"
2
3apt_package package do
4 action :install
5end

但是,这些变量的作用域有限,仅在定义它们的文件内有效。如果您希望创建一个变量并使其全局可用,以便可以在任何食谱或食谱中使用它,则需要定义一个自定义属性

使用属性

属性表示有关节点的详细信息。Chef有自动属性,这些属性是由一个名为OHAI的工具收集的属性,包含有关系统的信息(如平台、主机名和默认IP地址),但它也允许您定义自己的自定义属性。

属性具有不同的优先级别,由您创建的属性类型定义。default属性是最常见的选择,因为如果需要,它们仍然可以被其他属性类型覆盖。

下面的示例显示了使用default节点属性而不是局部变量的上一个示例:

1node.default['main']['package'] = "vim"
2
3apt_package node['main']['package'] do
4 action :install
5end

在本例中有两个要注意的细节:

定义节点变量时,推荐的做法是使用当前使用的食谱作为键将它们组织为散列。在本例中,我们使用了main,因为我们有一本同名的食谱。如果您使用的多本食谱可能具有相似的命名属性,则可以避免混淆。 注意,我们在定义属性时使用了node.default,但在稍后访问它的值时,我们直接使用了nodenode.default用法定义我们正在创建一个默认 类型的属性。此属性的值可能会被优先级更高的其他类型覆盖,例如** 正常** 或** 覆盖** 属性。

这些属性的优先顺序一开始可能会有些混乱,但经过一些练习后您会习惯的。为了说明该行为,请考虑以下示例:

1node.normal['main']['package']  = "vim"
2
3node.override['main']['package'] = "git"
4
5node.default['main']['package'] = "curl"
6
7apt_package node['main']['package'] do
8 action :install
9end

您知道在这种情况下将安装哪个程序包吗?如果你猜对了‘git’,那么你猜对了。无论定义属性的顺序如何,类型override的较高优先级将使node[‘main’][‘Package’]的计算结果为git`。

使用循环

循环通常用于使用不同的输入值重复任务。例如,不需要创建10个任务来安装10个不同的包,您可以创建单个任务,并使用循环对要安装的所有不同包重复该任务。

Chef支持在食谱内创建循环的所有Ruby循环结构。为了简单起见,each是一种常见的选择:

1['vim', 'git', 'curl'].each do |package|
2 apt_package package do
3   action :install
4 end
5end

您还可以创建一个变量或属性来定义要在循环内使用的参数,而不是使用内联数组。这将使文章更有条理,更容易阅读。下面是使用局部变量定义应该安装的程序包的相同示例:

1packages = ['vim', 'git', 'curl']
2
3packages.each do |package|
4 apt_package package do
5   action :install
6 end
7end

使用条件

例如,条件语句可以用于基于变量或命令的输出来动态地决定是否应该执行代码块。

Chef支持所有Ruby条件,用于在菜谱中创建条件语句。此外,所有资源类型都支持两个特殊属性,它们将在决定是否执行任务之前对表达式进行评估:if_onlynot_if

下面的示例将在尝试安装扩展名php-pear之前检查是否存在php。它将使用命令Which来验证该系统上当前是否安装了php可执行文件。如果哪个php命令返回FALSE,则不会执行该任务:

1apt_package "php-pear" do
2 action :install
3 only_if "which php"
4end

如果我们想要做相反的事情,在除了 当一个条件被评估为真时,一直执行一条命令,我们使用not_if。此示例将安装php5,除非系统为CentOS:

1apt_package "php5" do
2 action :install
3 not_if { node['platform'] == 'centos' }
4end

对于执行更复杂的评估,如果您想要在特定条件下执行多个任务,您可以使用任何标准的Ruby条件。以下示例仅在系统为Debian Ubuntu时才执行apt-get update

1if node['platform'] == 'debian' || node['platform'] == 'ubuntu'
2 execute "apt-get update" do
3   command "apt-get update"
4 end
5end

<$>[备注] 属性node[‘Platform’]是来自Chef的自动属性。最后一个例子只是演示了一个更复杂的条件构造,但是可以用一个使用自动属性node[‘PLATFORM_FAMILY’]的简单测试来代替它,该属性对于Debian和Ubuntu系统都将返回debian

使用模板

模板通常用于设置配置文件,允许使用变量和其他旨在使这些文件更具通用性和可重用性的功能。

Chef使用嵌入式Ruby(ERB)模板,这与Puptet使用的格式相同。它们支持条件、循环和其他Ruby特性。

下面是一个用于设置Apache虚拟主机的ERB模板的示例,它使用一个变量来定义该主机的文档根目录:

1<VirtualHost *:80>
2    ServerAdmin webmaster@localhost
3    DocumentRoot <%= @doc_root %>
4
5    <Directory <%= @doc_root %>>
6        AllowOverride All
7        Require all granted
8    </Directory>
9</VirtualHost>

为了应用模板,我们需要创建一个template资源。您可以通过以下方式应用此模板来替换默认的Apache虚拟主机:

1template "/etc/apache2/sites-available/000-default.conf" do
2 source "vhost.erb"
3 variables({ :doc_root => node['main']['doc_root'] })
4 action :create
5end

Chef在处理本地文件时做了一些假设,以加强组织和模块化。在这种情况下,Chef将在应该位于该食谱所在的同一食谱中的_Templates_文件夹中查找一个vhost.erb模板文件。

与我们迄今为止看到的其他配置管理工具不同,Chef对变量有更严格的范围。这意味着在定义template资源时,您必须显式地提供您计划在模板中使用的任何变量。在这个例子中,我们使用了variables方法来传递我们在虚拟主机模板中需要的doc_root属性。

定义和触发服务

服务资源用于确保服务已初始化和启用。它们还用于触发服务重新启动。

在Chef中,在尝试通知服务资源之前需要声明服务资源,否则会出现错误。

让我们考虑一下前面的模板使用示例,在该示例中,我们设置了一个Apache虚拟主机。如果您希望确保在虚拟主机更改后重新启动Apache,您首先需要为Apache服务创建一个_SERVICE_RESOURCE。以下是Chef中对此类资源的定义:

1service "apache2" do
2  action [ :enable, :start ]
3end

现在,在定义模板 资源时,需要加上notfy选项才能触发重启:

1template "/etc/apache2/sites-available/000-default.conf" do
2 source "vhost.erb"
3 variables({ :doc_root => node['main']['doc_root'] })
4 action :create
5 notifies :restart, resources(:service => "apache2")
6end

食谱示例

现在,让我们看一看在Ubuntu 14.04系统中自动安装ApacheWeb服务器的方法,如本指南的介绍中所讨论的。

完整的示例,包括用于设置Apache的模板文件和Web服务器提供的HTML文件,可以在Github上找到。该文件夹还包含一个Vagrant文件,您可以使用Vagrant管理的虚拟机在简化的设置中测试配方。vagrantup.com

你可以在下面找到完整的食谱:

 1node.default['main']['doc_root'] = "/vagrant/web"
 2
 3execute "apt-get update" do
 4 command "apt-get update"
 5end
 6
 7apt_package "apache2" do
 8 action :install
 9end
10
11service "apache2" do
12 action [ :enable, :start ]
13end
14
15directory node['main']['doc_root'] do
16 owner 'www-data'
17 group 'www-data'
18 mode '0644'
19 action :create
20end
21
22cookbook_file "#{node['main']['doc_root']}/index.html" do
23 source 'index.html'
24 owner 'www-data'
25 group 'www-data'
26 action :create
27end
28
29template "/etc/apache2/sites-available/000-default.conf" do
30 source "vhost.erb"
31 variables({ :doc_root => node['main']['doc_root'] })
32 action :create
33 notifies :restart, resources(:service => "apache2")
34end

食谱解说

第一行

菜谱以属性 定义node[‘main’][‘docroot’]开始。我们在这里可以使用一个简单的局部变量,但是在大多数用例场景中,食谱需要定义将从包含的食谱或其他文件中使用的全局变量。对于这些情况,有必要创建属性而不是局部变量,因为后者的作用域有限。

3-5行

EXECUTE 资源运行apt-get update

第7-10行

apt_Package 资源安装apache2包。

第12-15行

服务 资源启动和启动服务apache2。稍后,我们将需要通知此资源重新启动服务。重要的是,服务定义要放在试图通知服务的任何资源之前,否则会出现错误。

第17-22行

目录 资源使用自定义属性node[‘main’][‘docroot’]定义的值来创建一个目录,作为我们的** 文档根目录** 。

第24-29行

cookbook_file 资源用于将本地文件复制到远程服务器。这个资源将复制我们的index.html文件,并将其放置在我们在上一个任务中创建的文档根目录中。

第31-36行

最后,这个模板 资源应用我们的apache虚拟主机模板,并通知服务apache2重启。

总结

Chef是一个强大的配置管理工具,它利用Ruby语言自动化服务器配置和部署。它让您可以自由地使用标准语言功能以获得最大的灵活性,同时还为某些资源提供自定义DSL。

Published At
Categories with 技术
comments powered by Disqus