如何在Chef中使用角色和环境来控制服务器配置
介绍
随着您构建基础架构,管理您的许多服务器、服务、用户和应用程序可能会很快变得笨拙。 配置管理系统可用于帮助您管理这种混乱。
Chef 是一个出色的配置管理系统,可以让您非常轻松地配置整个系统的不同组件。 在之前的指南中,我们讨论了 Chef 术语、如何安装 Chef 服务器、工作站和节点(使用 Chef 12 或 Chef 11)和 [X161X ]如何创建简单的食谱来管理配置。
在本指南中,我们将继续探索如何使用 Chef 管理环境。 这一次,我们将讨论如何使用角色和环境来区分您的服务器和服务,基于它们应该展示什么样的功能。
我们将假设您已经安装了服务器、工作站和客户端,并且您拥有我们在上一个指南中创建的说明书。
角色和环境
什么是角色?
在您的组织中,如果您的基础架构不断增长以满足更高流量的需求,则可能会有多个冗余服务器都执行相同的基本任务。 例如,这些可能是负载均衡器将请求传递到的 Web 服务器。 它们都将具有相同的基本配置,并且可以说每个都满足相同的“角色”。
Chef 对 roles 的看法与常规定义几乎完全相同。 Chef 中的角色是一种分类,描述了特定机器应该 做什么。 它有什么职责,应该给它什么软件和设置。
在不同的情况下,您可能会让某些机器处理多个角色。 例如,如果您正在测试您的软件,一台服务器可能包含数据库和 Web 服务器组件,而在生产中,您计划将它们放在不同的服务器上。
使用 Chef,这就像将第一台服务器分配给两个角色然后将每个角色分配给生产机器的不同计算机一样简单。 每个角色都将包含使机器进入完全运行状态以履行其特定角色所需的配置详细信息。 这意味着您可以收集将处理软件包安装、服务配置、该角色的特殊属性等的说明书。
什么是环境?
与角色的概念相关的是 Chef environments 的概念。 环境只是一个名称,旨在帮助管理员了解服务器属于生产过程的哪个阶段。 每台服务器都可以是一个环境的一部分。
默认情况下,会创建一个名为“_default”的环境。 除非指定了另一个环境,否则每个节点都将放置在此环境中。 可以创建环境以将服务器标记为进程组的一部分。
例如,一种环境可能被称为“测试”,而另一种环境可能被称为“生产”。 由于您不希望任何仍在生产机器上测试的代码,因此每台机器只能在一个环境中。 然后,您可以为测试环境中的机器使用一种配置,而为生产中的计算机使用完全不同的配置。
在上面给出的角色示例中,您可以指定在您的测试环境中,Web 和数据库服务器角色将位于一台机器上。 在您的生产环境中,这些角色应该由各个服务器来处理。
环境也有助于测试过程本身。 您可以指定在生产中,cookbook 应该是稳定版本。 但是,您可以指定如果机器是测试环境的一部分,它可以接收更新版本的说明书。
如何使用角色
使用 Ruby DSL 创建角色
我们可以使用工作站上 chef-repo
目录中的 roles
目录来创建角色。
登录到您的工作站并立即进入此目录:
cd ~/chef-repo/roles
在这个目录中,我们可以创建不同的文件来定义我们在组织中想要的角色。 每个角色文件都可以用 Chef 的 Ruby DSL 或 JSON 编写。
让我们为我们的 Web 服务器创建一个角色:
nano web_server.rb
在这个文件中,我们可以从指定角色的一些基本数据开始:
name "web_server" description "A role to configure our front-line web servers"
这些应该是相当直截了当的。 我们提供的名称不能包含空格,并且通常应与我们为此角色选择的文件名相匹配,减去扩展名。 描述只是关于角色应该管理的内容的人类可读消息。
接下来,我们可以指定希望用于此特定角色的 run_list。 角色的 run_list 可以包含食谱(它将运行默认食谱)、食谱中的食谱(使用 cookbook::recipe 语法指定)和其他角色。 请记住,run_list 总是按顺序执行,因此将依赖项放在其他项之前。
如果我们想指定 run_list 应该与我们在上一个指南中配置的完全一样,我们会得到如下所示的内容:
name "web_server" description "A role to configure our front-line web servers" run_list "recipe[apt]", "recipe[nginx]"
我们还可以使用特定于环境的 run_lists 来指定变量配置更改,具体取决于服务器所属的环境。
例如,如果一个节点处于“生产”环境中,您可能希望在“nginx”说明书中运行一个特殊配方,以使该服务器达到生产策略要求。 您还可以在 nginx 食谱中有一个配方,用于配置测试服务器的特殊更改。
假设这两个配方分别称为“config_prod”和“config_test”,我们可以创建一些特定于环境的运行列表,如下所示:
name "web_server" description "A role to configure our front-line web servers" run_list "recipe[apt]", "recipe[nginx]" env_run_lists "production" => ["recipe[nginx::config_prod]"], "testing" => ["recipe[nginx::config_test]"]
在上面的例子中,我们已经指定如果节点是生产环境的一部分,它应该运行“nginx”说明书中的“config_prod”配方。 但是,如果节点在测试环境中,它将运行“config_test”配方。 如果节点位于不同的环境中,则将应用默认的 run_list。
同样,我们可以指定默认和覆盖属性。 此时您应该熟悉默认属性。 在我们的角色中,我们可以设置默认属性,这些属性可以覆盖其他任何地方设置的任何默认属性。
我们还可以设置覆盖属性,它比许多其他属性声明具有更高的优先级。 我们可以使用它来尝试强制分配了此角色的节点以某种方式运行。
在我们的文件中,可以这样添加:
name "web_server" description "A role to configure our front-line web servers" run_list "recipe[apt]", "recipe[nginx]" env_run_lists "production" => ["recipe[nginx::config_prod]"], "testing" => ["recipe[nginx::config_test]"] default_attributes "nginx" => { "log_location" => "/var/log/nginx.log" } override_attributes "nginx" => { "gzip" => "on" }
在这里,我们为节点中的任何服务器设置了默认日志位置。 我们还指定,尽管在其他位置有一些其他属性声明,但该角色中的节点应将 gzip 属性设置为“on”。 这可以在更多的地方被覆盖,但通常是一个高优先级声明。
使用 JSON 创建角色
可用于配置角色的另一种格式是 JSON。 实际上,我们可以通过使用knife自动创建这种格式的角色来探索这种格式。 让我们创建一个测试角色:
knife role create test
您的文本编辑器将使用预加载的模板角色文件打开。 它应该看起来像这样:
{ "name": "test", "description": "", "json_class": "Chef::Role", "default_attributes": { }, "override_attributes": { }, "chef_type": "role", "run_list": [ ], "env_run_lists": { } }
这与我们在 Ruby DSL 格式文件中输入的信息基本相同。 唯一的区别是格式和添加了两个名为 json_class
和 chef_type
的新键。 这些是内部使用的,不应修改。
除此之外,我们可以轻松地在 JSON 中重新创建我们的其他文件,例如:
{ "name": "web_server", "description": "A role to configure our front-line web servers", "json_class": "Chef::Role", "default_attributes": { "nginx": { "log_location": "/var/log/nginx.log" } }, "override_attributes": { "nginx": { "gzip": "on" } }, "chef_type": "role", "run_list": [ "recipe[apt]", "recipe[nginx]" ], "env_run_lists": { "production": [ "recipe[nginx::config_prod]" ], "testing": [ "recipe[nginx::config_test]" ] } }
这应该与上面的 Ruby 版本具有几乎相同的功能。
在工作站和服务器之间转移角色
当我们保存使用刀命令创建的 JSON 文件时,该角色会在 Chef 服务器上创建。 相比之下,我们在本地创建的 Ruby 文件并没有上传到服务器。
我们可以通过运行如下命令将 ruby 文件上传到服务器:
从文件路径/到/角色/文件的刀角色
这会将我们文件中指定的角色信息上传到服务器。 这适用于 Ruby DSL 格式文件或 JSON 文件。
类似地,如果我们想从服务器获取我们的 JSON 文件,我们可以告诉 knife 命令以 JSON 格式显示该角色文件,然后将其通过管道传输到如下文件中:
刀角色显示 web_server -Fjson >路径/到/保存/到
为节点分配角色
所以现在,不管我们使用什么格式,我们在 Chef 服务器上都有自己的角色。 我们如何为节点分配特定角色?
我们在节点的 run_list 中为节点分配角色,就像我们分配配方一样。
因此,要将我们的角色添加到节点,我们将通过发出以下命令找到该节点:
knife node list
然后我们会给出如下命令:
刀节点编辑node_name
这将打开节点的定义文件,这将允许我们将角色添加到它的 run_list:
{ "name": "client1", "chef_environment": "_default", "normal": { "tags": [ ] }, "run_list": [ "recipe[nginx]" ] }
例如,我们可以用我们在这个文件中的角色替换我们的食谱:
{“名称”:“client1”,“厨师环境”:“_default”,“正常”:{“标签”:[ ]
},“run_list”:[“角色[web_server] ”]}
这将执行与我们之前的食谱相同的步骤,但它只是说明服务器应该具有的角色。
这允许您通过搜索访问具有特定角色的所有服务器。 例如,您可以通过搜索角色和环境来搜索生产环境中的所有数据库服务器:
knife search "role:database_server AND chef_environment:prod" -a name
这将为您提供配置为数据库服务器的节点列表。 您可以在说明书内部使用它来配置 Web 服务器,以自动将所有生产数据库服务器添加到其池中以发出读取请求。
如何使用环境
创建环境
在某些方面,环境与角色非常相似。 它们也用于区分不同的服务器,但不是根据服务器的功能进行区分,而是根据机器所属的开发阶段来区分环境。
我们之前在谈论角色时讨论了其中的一些内容。 与您的实际产品生命周期一致的环境最有意义。 如果您通过测试、登台和生产运行代码,您应该有匹配的环境。
与角色一样,我们可以在 Ruby DSL 或 JSON 中设置定义文件。
在我们工作站上的“chef-repo”目录中,我们应该有一个环境目录。 这是我们应该放置环境文件的地方。
cd ~/chef-repo/environments
在这个目录中,如果我们要定义一个开发环境,我们可以创建一个像这样的文件:
nano development.rb
name "development" description "The master development branch" cookbook_versions({ "nginx" => "<= 1.1.0", "apt" => "= 0.0.1" }) override_attributes ({ "nginx" => { "listen" => [ "80", "443" ] }, "mysql" => { "root_pass" => "root" } })
如您所见,将环境合并到系统中的主要优点之一是您可以为说明书和部署的配方指定版本约束。
我们也可以使用 JSON 格式。 刀工具可以通过键入以下内容生成环境文件的模板:
knife environment create development
这将打开我们的编辑器(同样,您可以使用 export EDITOR=nano
设置您的编辑器),其中包含一个预加载的环境文件,其中填写了名称。
我们可以通过输入以下内容来创建相同的文件:
{ "name": "development", "description": "The master development branch", "cookbook_versions": { "nginx": "<= 1.1.0", "apt": "= 0.0.1" }, "json_class": "Cheff:Environment", "chef_type": "environment", "default_attributes": { }, "override_attributes": { "nginx": { "listen": [ "80", "443" ] }, "mysql": { "root_pass": "root" } } }
该文件在功能上应该与我们上面演示的 Ruby 文件相同。 与 JSON 角色文件一样,环境 JSON 文件有两条额外的信息(json_class
和 chef_type
),它们应该单独保留。
将环境文件移入和移出服务器
此时,如果您使用 Ruby DSL,您的文件在工作站上,如果您使用 JSON,您的文件仅在服务器上。 我们可以通过刀轻松地来回移动文件。
我们可以通过输入以下命令将 Ruby 文件上传到 Chef 服务器:
knife environment from file ~/chef-repo/environments/development.rb
对于我们的 JSON 文件,我们可以通过键入以下内容从服务器获取环境文件:
knife environment show development -Fjson > ~/chef-repo/environments/development.json
这将显示来自服务器的 JSON 文件,并将结果通过管道传输到环境子目录中的本地文件中。
在节点中设置环境
每个节点都可以在一个环境中。 我们可以通过编辑节点信息来指定节点所属的环境。
例如,要编辑一个名为 client1
的节点,我们可以输入:
knife node edit client1
这将使用当前节点参数打开一个 JSON 格式的文件:
{ "name": "client1", "chef_environment": "_default", "normal": { "tags": [ ] }, "run_list": [ "role[web_server]" ] }
如您所见,最初将 chef_environment
设置为 _default
。 我们可以简单地修改该值以将节点放入新环境。
完成后,保存并关闭文件。 在节点上的下一次 chef-client 运行中,它将获取新的属性和版本约束并修改自身以与新策略保持一致。
结论
到目前为止,您应该对使用角色和环境的不同方式有一个很好的理解,以巩固您的机器应该处于的状态。 使用这些分类策略,您可以开始管理 Chef 在不同上下文中处理服务器的方式。