如何在 Chef 中使用角色和环境来控制服务器配置

介绍


当您构建基础设施时,管理您的许多服务器、服务、用户和应用程序可能会很快变得困难,可使用配置管理系统来帮助您管理这种混乱。

Chef是一个很好的配置管理系统,可以让您很容易地配置整个系统的不同组件。在以前的指南中,我们讨论了 Chef 术语,如何安装 Chef 服务器,工作站和节点(使用 Chef 12Chef 11),以及 如何创建简单的烹饪书来管理配置

在本指南中,我们将继续探索如何管理您的环境,这次,我们将讨论如何使用角色和环境来根据服务器和服务的功能来区分它们。

我们将假设您已经安装了服务器,工作站和客户端,并且您可以使用我们在我们最后的指南中创建的烹饪书籍。

角色与环境


什么是角色?


在您的组织中,如果您的基础设施增长以满足更高的流量需求,可能会有多个多余的服务器,这些服务器都执行相同的基本任务,例如,这些服务器可能是负载平衡器传递请求的网页服务器,它们都具有相同的基本配置,可以说每个服务器都满足相同的角色

厨师对 角色的看法几乎完全与常规定义相同. 厨师中的角色是描述特定机器应该做什么的分类。

例如,如果您正在测试您的软件,一个服务器可能会包含数据库和Web服务器组件,而在生产中,您计划将这些组件放在单独的服务器上。

通过 Chef,这可以像将第一个服务器分配给两个角色一样简单,然后将每个角色分配给您的生产机器的单独计算机。每个角色将包含将机器带到完全运行状态所需的配置细节,以满足其特定的角色。

什么是环境?


与角色的概念有关的是 Chef environments的概念,一个环境只是一个旨在帮助管理员知道服务器是生产过程的哪个阶段的一部分的命名。

默认情况下,会创建一个名为_default的环境,每个节点将被放置在这个环境中,除非另一个环境被指定。

例如,一個環境可能被稱為測試,另一個環境可能被稱為生產。由於您不希望在您的生產機器上仍在測試的任何代碼,所以每台機器只能在一個環境中。

在上面的角色示例中,您可以指定在测试环境中,Web 和数据库服务器的角色将在单一机器上。

环境还可以帮助测试过程本身,您可以指定在生产中,厨师本应该是一个稳定版本,但是,您可以指定如果机器是测试环境的一部分,它可以收到厨师本的更新的版本。

如何使用角色


使用 Ruby DSL 创建角色


我们可以使用我们工作站上的chef-repo目录中的角色目录创建角色。

登录您的工作站,现在进入此目录:

1cd ~/chef-repo/roles

在此目录中,我们可以创建不同的文件,定义我们在组织中想要的角色. 每个角色文件可以用 Chef’s Ruby DSL 或 JSON 编写。

让我们为我们的Web服务器创建一个角色:

1nano web_server.rb

在此文件中,我们可以从指定有关角色的一些基本数据开始:

1name "web_server"
2description "A role to configure our front-line web servers"

这些应该是相当直前的。我们给出的名称不能包含间隙,通常应该匹配我们为这个角色选择的文件名,减去扩展。

接下来,我们可以指定我们想要用于这个特定角色的 run_list. 角色的 run_list 可以包含烹饪书(将运行默认配方),烹饪书的食谱(使用烹饪书::食谱语法规定的),以及其他角色。

如果我们想指定 run_list 应该是我们在最后一个指南中配置的,我们将有这样的东西:

1name "web_server"
2description "A role to configure our front-line web servers"
3run_list "recipe[apt]", "recipe[nginx]"

我们还可以使用环境特定的 run_lists 来指定可变的配置变化,取决于服务器所属的环境。

例如,如果节点处于生产环境中,您可能希望在nginx厨房中运行一个特殊的食谱,以使该服务器达到生产策略的要求。

假设这两个食谱分别被称为config_prodconfig_test,我们可以创建一些环境特定的运行列表,如下:

1name "web_server"
2description "A role to configure our front-line web servers"
3run_list "recipe[apt]", "recipe[nginx]"
4env_run_lists "production" => ["recipe[nginx::config_prod]"], "testing" => ["recipe[nginx::config_test]"]

在上面的示例中,我们指定了如果节点是生产环境的一部分,它应该在nginx厨房中运行config_prod配方,但是,如果节点是在测试环境中,它会运行config_test配方。

同样,我们可以指定默认属性和超级属性. 您应该熟悉此时的默认属性. 在我们的角色中,我们可以设置默认属性,这些属性可以超级其他任何位置的默认属性。

我们还可以设置超级属性,这些属性具有比许多其他属性声明更高的优先级,我们可以使用此方法来试图强迫分配给这个角色的节点以某种方式行为。

在我们的档案中,它们可以像这样添加:

1name "web_server"
2description "A role to configure our front-line web servers"
3run_list "recipe[apt]", "recipe[nginx]"
4env_run_lists "production" => ["recipe[nginx::config_prod]"], "testing" => ["recipe[nginx::config_test]"]
5default_attributes "nginx" => { "log_location" => "/var/log/nginx.log" }
6override_attributes "nginx" => { "gzip" => "on" }

在这里,我们已经为节点中的任何服务器设置了默认日志位置,我们还指定了,尽管其他属性声明在其他位置声明了什么,在这个角色中的节点应该有 gzip 属性设置为启用

使用 JSON 创建角色


您可以使用的角色配置的另一个格式是 JSON. 事实上,我们可以使用刀子来探索这个格式,自动创建这个格式中的角色。

1knife role create test

你的文本编辑器将打开一个模板角色文件预加载. 它应该看起来像这样的东西:

 1{
 2  "name": "test",
 3  "description": "",
 4  "json_class": "Chef::Role",
 5  "default_attributes": {
 6  },
 7  "override_attributes": {
 8  },
 9  "chef_type": "role",
10  "run_list": [
11
12  ],
13  "env_run_lists": {
14  }
15}

这基本上是我们输入了Ruby DSL格式文件的相同信息,唯一的差异是格式化和添加两个名为json_classchef_type的新键。

除此之外,我们可以很容易地在JSON中重建我们的其他文件,例如:

 1{
 2  "name": "web_server",
 3  "description": "A role to configure our front-line web servers",
 4  "json_class": "Chef::Role",
 5  "default_attributes": {
 6    "nginx": {
 7      "log_location": "/var/log/nginx.log"
 8    }
 9  },
10  "override_attributes": {
11    "nginx": {
12      "gzip": "on"
13    }
14  },
15  "chef_type": "role",
16  "run_list": [
17    "recipe[apt]",
18    "recipe[nginx]"
19  ],
20  "env_run_lists": {
21    "production": [
22      "recipe[nginx::config_prod]"
23    ],
24    "testing": [
25      "recipe[nginx::config_test]"
26    ]
27  }
28}

这应该与上面Ruby版本几乎相同的功能。

工作站和服务器之间的角色转移


当我们使用刀指令创建的 JSON 文件时,角色会被创建在 Chef 服务器上,而我们本地创建的 Ruby 文件不会被上传到服务器上。

我們可以將 Ruby 檔案上傳到伺服器,執行這樣的命令:

knife role from file path/to/role/file

这将将我们文件中指定的角色信息上传到服务器,这将与Ruby DSL格式文件或JSON文件一起工作。

在类似的情况下,如果我们想从服务器上获取我们的 JSON 文件,我们可以告诉刀子命令在 JSON 中显示该角色文件,然后将其输入到这样的文件中:

knife role show web_server -Fjson > path/to/save/to

将角色分配给节点


所以现在,无论我们使用的格式如何,我们在厨师服务器上都有自己的角色,我们如何分配一个节点的特定角色?

我们将角色分配给一个节点,就像我们在节点的 run_list 中分配给一个食谱一样。

因此,要将我们的角色添加到一个节点,我们会通过发出来找到节点:

1knife node list

然后,我们会发出这样的命令:

knife node edit node_name

这将带来节点的定义文件,这将允许我们将角色添加到其 run_list:

 1{
 2  "name": "client1",
 3  "chef_environment": "_default",
 4  "normal": {
 5    "tags": [
 6
 7    ]
 8  },
 9  "run_list": [
10    "recipe[nginx]"
11  ]
12}

例如,我们可以用我们在这个文件中的角色来替代我们的食谱:

{
  "name": "client1",
  "chef_environment": "_default",
  "normal": {
    "tags": [

    ]
  },
  "run_list": [
    "role[web_server]"
  ]
}

这将执行与我们以前的食谱相同的步骤,但相反,它只是对服务器应该扮演的角色进行交谈。

例如,您可以通过搜索特定角色中的所有服务器进行搜索,通过搜索角色和环境来搜索生产环境中的所有数据库服务器:

1knife search "role:database_server AND chef_environment:prod" -a name

这将为您提供配置为数据库服务器的节点列表,您可以在烹饪书中内部使用此列表来配置 Web 服务器,以便自动将所有生产数据库服务器添加到其池中,以便从中进行阅读请求。

如何使用环境


创造一个环境


在某些方面,环境与角色相当相似,它们也被用来区分不同的服务器,但而不是通过服务器的功能来区分,环境则通过机器所属的开发阶段来区分。

我们早些时候在谈论角色时讨论了一些这些问题。与您的实际产品生命周期相匹配的环境最有意义。

与角色一样,我们可以在Ruby DSL或JSON中设置定义文件。

在我们的工作站上的chef-repo目录中,我们应该有一个环境目录,这就是我们应该把我们的环境文件放在那里。

1cd ~/chef-repo/environments

在此目录中,如果我们要定义一个开发环境,我们可以创建这样的文件:

1nano development.rb

 1name "development"
 2description "The master development branch"
 3cookbook_versions({
 4    "nginx" => "<= 1.1.0",
 5    "apt" => "= 0.0.1"
 6})
 7override_attributes ({
 8    "nginx" => {
 9        "listen" => [ "80", "443" ]
10    },
11    "mysql" => {
12        "root_pass" => "root"
13    }
14})

正如您所看到的,将环境纳入您的系统的主要优点之一是,您可以为烹饪书和部署的食谱指定版本限制。

我们也可以使用 JSON 格式,刀具工具可以通过键入来生成环境文件的模板:

1knife environment create development

这将打开我们的编辑器(再次,您可以将您的编辑器设置为导出编辑器=nano)与一个预加载的环境文件,名称填写。

我们可以通过键入创建相同的文件:

 1{
 2  "name": "development",
 3  "description": "The master development branch",
 4  "cookbook_versions": {
 5    "nginx": "<= 1.1.0",
 6    "apt": "= 0.0.1"
 7  },
 8  "json_class": "Cheff:Environment",
 9  "chef_type": "environment",
10  "default_attributes": {
11  },
12  "override_attributes": {
13    "nginx": {
14      "listen": [
15        "80",
16        "443"
17      ]
18    },
19    "mysql": {
20      "root_pass": "root"
21    }
22  }
23}

与上面的JSON角色文件一样,环境JSON文件有两个额外的信息(‘json_class’和‘chef_type’),应该单独留下来。

移动环境文件到和从服务器


在此时,如果你使用了Ruby DSL,你的文件在工作站,如果你使用了JSON,你的文件只有在服务器上。

我們可以將 Ruby 檔案上傳到 Chef 伺服器,輸入以下文字:

1knife environment from file ~/chef-repo/environments/development.rb

对于我们的 JSON 文件,我们可以通过键入类似的东西来将环境文件从服务器上移除:

1knife environment show development -Fjson > ~/chef-repo/environments/development.json

这将显示来自服务器的 JSON 文件,并将结果导入环境子目录中的本地文件中。

在节点中设置环境


我们可以通过编辑其节点信息来指定节点所属的环境。

例如,要编辑一个名为client1的节点,我们可以输入以下内容:

1knife node edit client1

这将打开与当前节点参数的 JSON 格式文件:

 1{
 2  "name": "client1",
 3  "chef_environment": "_default",
 4  "normal": {
 5    "tags": [
 6
 7    ]
 8  },
 9  "run_list": [
10    "role[web_server]"
11  ]
12}

正如您所看到的,chef_environment最初设置为_default。我们可以简单地修改这个值,将节点放入一个新的环境。

完成后,保存并关闭文件. 下一个厨师客户端在节点上运行时,它将收集新的属性和版本限制,并修改自己以符合新策略。

结论


到目前为止,您应该对不同方法有很好的了解,您可以与角色和环境一起工作,以巩固您的机器应该处于的状态。

By Justin Ellingwood
Published At
Categories with 技术
comments powered by Disqus