Cookbook是Chef框架的关键组成部分之一,其描述了相关节点的所需状态,并允许Chef推送需达到该状态的更改数据。由于需要进行配置的选项和区域数量众多,第一眼看上去,创建一本Cookbook是一项艰巨的任务,因此在本指南中我们将介绍通常人们在学习其配置的第一件事:设置LAMP(Linux Apache MySQL/MariaDB/Percona PHP)软件环境。
在使用本指南之前,请先参照“ 设置Chef服务器,workstation工作站和相关节点”这一指南来设置Chef。在遵循该指南时,请选择Ubuntu 16.04作为Chef节点的Linux映像。必须选择该版本的Ubuntu是因为将使用的MySQL Chef cookbook与Ubuntu 18.04尚不兼容。
如果觉得有必要的话,您也可以先查看Chef新手指南。
本教程中的示例需要root用户账户权限。选择使用普通用户帐户的读者在使用Chef客户端节点时,很可能会需要使用sudo前缀命令。如果您尚未创建普通用户帐户,请按照“ 保护服务器” 指南中的步骤进行操作。
创建Cookbook
- 在workstation工作站中,定位到
chef-repo
分支下的cookbooks
目录:cd chef-repo/cookbooks
- 创建cookbook。在这个例子中,cookbook的标题是
lamp_stack
:chef generate cookbook lamp_stack
- 定位到cookbook新创建的目录下:
cd lamp_stack
- 对位于新创建的cookbook中的文件列表,以查看是否已创建了相关目录和文件:
ls
Berksfile CHANGELOG.md chefignore LICENSE metadata.rb README.md recipes spec test
有关这些目录的更多配置方案,请参阅Chef框架初学者指南。
default.rb
recipes
中的default.rb
文件包含“默认”的recipe资源配置方案。
因为LAMP环境的每个部分(Apache、MySQL和PHP)都有属于自己的recipe配置方案,所以该default.rb
文件也就是为服务器所准备的。
- 1.在您的
lamp_stack
目录中,定位到recipes
文件夹:cd recipes
- 2.打开
default.rb
文件并添加下面可以实现系统更新的Ruby命令:
#
# Cookbook Name:: lamp_stack
# Recipe:: default
#
#
execute "update-upgrade" do
command "sudo apt-get update && sudo apt-get upgrade -y"
action :run
end
recipe配置方案是由一系列的资源组成。在该例中,使用的是执行资源,其会调用一个执行一次的命令。command
部分定义了apt-get update && apt-get upgrade -y
指令,action
操作设置为:run
执行命令。
这是一个比较容易编写的Chef recipe配置方案,也是一个好的初步实践文件。其他你认为比较重要的启动步骤也可以通过模仿上述代码模板来添加到文件中。
- 3.假如需要测试recipe配置方案,请将LAMP环境中的cookbook添加到Chef服务器:
knife cookbook upload lamp_stack
- 4.测试recipe配置方案是否已添加到Chef服务器:
knife cookbook list
- 5.将recipe添加到所选节点的运行列表中,并将
nodename
替换为相应节点名称:knife node run_list add nodename "recipe[lamp_stack]"
因为这是默认recipe配置方案,所以不需要在上面的代码中的lamp_stack
cookbook之后来定义recipe名称。 - 6.访问您选择的节点并运行chef-client:
chef-client
它应该输出Chef的成功运行配置方案。如果没有,请查看代码以查找错误,通常它们会在chef-client
运行输出中定义。
Apache
安装并启用
- 1.在Chef workstation工作站中,在
~/chef-repo/cookbooks/lamp_stack/recipes
目录下创建一个新文件apache.rb
,该文件将包含所有Apache配置方案。 - 2.打开文件,并定义用于安装Apache的包资源:
package "apache2" do
action :install
end
同样,这是一个非常基础的recipe配置方案。包资源会调用相应包(apache2
)。包名称值必须是一个合法的包名称。操作设置为install是因为在此步骤中执行了Apache安装操作,这里无需附加操作就可与运行安装操作。
- 3.允许Apache服务并设置重启时运行。在同一个文件中,添加附加代码:
service "apache2" do
action [:enable, :start]
end
这使用服务资源,该服务资源将调用Apache服务。enable使能操作使得它在开机时可以使用,并在_启动_Apache时启动。
保存并关闭该apache.rb
文件。
- 4.如果需要测试Apache recipe配置方案,请更新服务器上的LAMP软件环境上的recipe配置方案:
knife cookbook upload lamp_stack
- 5.将recipe添加到所选节点的运行列表中,并将
nodename
替换为相应节点名称:knife node run_list add nodename "recipelamp_stack::apache"
因为这不是default.rb
默认recipe配置方案,其名称apache必须附加到recipe值。 - 6.从该节点运行
chef-client
:chef-client
如果由于语法错误导致配方失败,Chef将在输出期间标注它。 - 7.
chef-client
运行成功后,请检查Apache是否正在运行:systemctl status apache2
它的配置方案输出应该表明apache2
正在运行。
注意 重复5-7步来上传cookbook并根据本文剩余部分指引按需运行chef客户端来确保您的recipe配方能正常无错运行。在添加一个新的recipe时,请记得替换运行列表中的recipe名。
配置虚拟主机
此配置基于如何在Ubuntu 16.04上安装LAMP软件环境一文。
- 1.因为可能会需要配置多个网站,因此请使用Chef的属性功能来定义虚拟主机文件的特定内容。ChefDK(chef软件工具包)中有一个内置命令,可以在cookbook中生成属性目录和
default.rb
文件。请将~/chef-repo/cookbooks/lamp_stack
替换为你的cookbook路径:chef generate attribute ~/chef-repo/cookbooks/lamp_stack default
- 2.在新的
default.rb
文件中,创建cookbook的默认值:
default["lamp_stack"]["sites"]["example.com"] = { "port" => 80, "servername" => "example.com", "serveradmin" => "webmaster@example.com" }
前缀default
中内容定义了example.com
网站将会在lamp_stack
中进行调用的值。这也可以看作是一种层次结构:在cookbook下层的是基于URL地址定义的网站。
紧随之后的数组中的值(在大括号({}
)中定义的)就是用来设置虚拟主机文件的值。Apahce被设置为在80端口监听并使用列表中的值作为服务名和管理员权限邮箱。
假如有需要添加超过一个网站或URL地址(例如,example.org
),第二个URL地址也应该模仿上例:
default["lamp_stack"]["sites"]["example.com"] = { "port" => 80, "servername" => "example.com", "serveradmin" => "webmaster@example.com" }
default["lamp_stack"]["sites"]["example.org"] = { "port" => 80, "servername" => "example.org", "serveradmin" => "webmaster@example.org" }
- 3.返回
recipes
目录下的apach.rb
文件调用之前定义的属性。使用node
资源执行此操作:
# 安装并使能Apache
package "apache2" do
action :install
end
service "apache2" do
action [:enable, :start]
end
# 虚拟主机文件
node["lamp_stack"]["sites"].each do |sitename, data|
end
该文件会调用["lamp_stack"]["sites"]
下的对应值。sitename
定义的对应值将会生成对应的添加代码块。data
值会调用每个sitename
属性数组中列出的值。
- 4.请在
node
资源中定义文档根路径。将会使用该根路径来定义公共HTML文件和一些自动生成的日志文件:
node["lamp_stack"]["sites"].each do |sitename, data|
document_root = "/var/www/html/#{sitename}"
end
- 5.这种操作并不会创建目录本身。为了创建目录,我们可以使用
directory
资源并结合true
递归值来创建所有定向到sitename
的目录。权限值0755
表明允许文件所有者具有对目录的完全访问权限,而组和常规用户将仅具有读取和执行权限:
node["lamp_stack"]["sites"].each do |sitename, data|
document_root = "/var/www/html/#{sitename}"
directory document_root do
mode "0755"
recursive true
end
end
- 6.这里将会使用模板功能来自动生成所需的虚拟主机文件。在
chef-repo
目录下携带cookbook路径和定义的模板文件名来运行chef generate template
命令:chef generate template ~/chef-repo/cookbooks/lamp_stack virtualhosts
- 7.打开并编辑
virtualhosts.erb
文件。请以Ruby变量来写入虚拟主机参数而不是以直接写入实际值的方式,Ruby变量由<%= @variable_name %>
语法标识,所使用的变量名称需要在recipe文件中定义过:
<VirtualHost *:<%= @port %>>
ServerAdmin <%= @serveradmin %>
ServerName <%= @servername %>
ServerAlias www.<%= @servername %>
DocumentRoot <%= @document_root %>/public_html
ErrorLog <%= @document_root %>/logs/error.log
<Directory <%= @document_root %>/public_html>
Require all granted
</Directory>
</VirtualHost>
你可能会觉得有些变量似曾相识,其实它们是在第二步中创建的默认变量。
- 8.回到
apache.rb
recipe文件。在directory
资源之后,使用template
资源调用刚刚创建的模板文件:
# 虚拟主机文件
node["lamp_stack"]["sites"].each do |sitename, data|
document_root = "/var/www/html/#{sitename}"
directory document_root do
mode "0755"
recursive true
end
template "/etc/apache2/sites-available/#{sitename}.conf" do
source "virtualhosts.erb"
mode "0644"
variables(
:document_root => document_root,
:port => data["port"],
:serveradmin => data["serveradmin"],
:servername => data["servername"]
)
end
end
模板资源的名称应该是虚拟主机文件放置在节点上的位置。source
就是模板文件的名称。Mode 0644
赋予文件所有者读写权限,其他人都仅有读取权限。variables
部分中定义的值取自属性文件,它们与模板中调用的值相同。
- 9.现在需要在Apache中启用站点,并重新启动服务器。只有在虚拟主机发生更改时,才可以将
notifies
值应将该值添加到template
资源中。当事务发生变化时,notifies
会告诉Chef,并在此情况下才会运行以下命令:
template "/etc/apache2/sites-available/#{sitename}.conf" do
source "virtualhosts.erb"
mode "0644"
variables(
:document_root => document_root,
:port => data["port"],
:serveradmin => data["serveradmin"],
:servername => data["servername"]
)
notifies :restart, "service[apache2]"
end
notifies
命令命名了要提交:action
的操作,之后在对资源和方括号中的资源名进行操作。
- 10.
notifies
也可以调用execute
命令,execute
命令可以运行a2ensite
并启用我们为其创建的虚拟主机文件的站点。添加下面的execute
命令到template
资源代码中并创建a2ensite
脚本
# [...]
directory document_root do
mode "0755"
recursive true
end
execute "enable-sites" do
command "a2ensite #{sitename}"
action :nothing
end
template "/etc/apache2/sites-available/#{sitename}.conf" do
# [...]
action :nothing
指令表明相关资源将会等待已被调用。在之前template
资源中的notifies
代码段前添加新的notifies
代码:
# [...]
template "/etc/apache2/sites-available/#{sitename}.conf" do
# [...]
notifies :run, "execute[enable-sites]"
notifies :restart, "service[apache2]"
end
# [...]
- 11.这里需要创建虚拟主机文件中所指向的路径。再强调一次,这里必须在
directory
资源下操作,并且必须在最后的end
标签前添加完成。
# [...]
node["lamp_stack"]["sites"].each do |sitename, data|
# [...]
directory "/var/www/html/#{sitename}/public_html" do
action :create
end
directory "/var/www/html/#{sitename}/logs" do
action :create
end
end
Apache配置
配置虚拟主机文件并启用网站后,请配置Apache以让其在服务器上高效运行,启用和配置多处理模块(MPM)并编辑apache2.conf
。
MPM都位于Apache的mods_available
目录中。在此示例中,将使用位于/etc/apache2/mods-available/mpm_event.conf
下的event
MPM。如果我们计划部署到不同大小的节点,我们将创建一个模板文件来替换原始节点,这将允许更多自定义特定变量。在此例中,将使用cookbook文件来编辑模板文件。
Cookbook文件是对服务器上相同语言环境中的文档进行操作的静态文档。如果进行了任何更改,则cookbook文件会备份原始文件并将其替换为新文件。
- 1.在您的cookbook主目录下定位到
files/default
来创建一个cookbook文件。如果目录尚不存在,请创建它们:
mkdir -p ~/chef-repo/cookbooks/lamp_stack/files/default/
cd ~/chef-repo/cookbooks/lamp_stack/files/default/
- 2.创建一个名为
mpm_event.conf
的文件并将MPM事件配置复制到其中,更改所需的值:
<IfModule mpm_event_module>
StartServers 2
MinSpareThreads 6
MaxSpareThreads 12
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 25
MaxConnectionsPerChild 3000
</IfModule>
- 3.返回到
apache.rb
文件,并使用该cookbook_file
资源调用我们刚刚创建的文件。因为需要启用MPM,所以我们将再次使用notifies
命令,这次执行a2enmod mpm_event
。在end
标记之前将execute
和cookbook_file
资源添加到apache.rb
文件中:
# [...]
node["lamp_stack"]["sites"].each do |sitename, data|
# [...]
execute "enable-event" do
command "a2enmod mpm_event"
action :nothing
end
cookbook_file "/etc/apache2/mods-available/mpm_event.conf" do
source "mpm_event.conf"
mode "0644"
notifies :run, "execute[enable-event]"
end
end
- 4.请将
apache2.conf
文件中的KeepAlive
值设置为off
,这也是文件中做出的唯一更改地方。这可以通过模板或cookbook文件进行更改,但在此例中可以使用一个简单的sed
命令来与execute
资源配对。使用新execute
资源来对apache.rb
更新:
# [...]
directory "/var/www/html/#{sitename}/logs" do
action :create
end
execute "keepalive" do
command "sed -i 's/KeepAlive On/KeepAlive Off/g' /etc/apache2/apache2.conf"
action :run
end
execute "enable-event" do
# [...]
您的apache.rb
文件现在完成了。最终的示例文件在此处。
MySQL
下载MySQL库
- 1.Chef 市场有一个OpsCode维护的MySQL cookbook,其可以用于设置要使用的MySQL 轻量级资源/供应商(LWRP)。请从工作站下载并安装该cookbook:
knife cookbook site install mysql
此处还将安装使用cookbook所需的相关依赖项。这些依赖包括smf
和yum-mysql-community
cookbook,而它们又依赖于rbac
和yum
cookbook。 - 2.从LAMP环境中cookbook的主目录,打开
metadata.rb
文件并为MySQL cookbook添加依赖项:
depends 'mysql', '~> 8.5.1'
注意 请查看MySQL Cookbook的市场页面,确保这是该手册的最新版本。同时MySQL Cookbook还不支持Ubuntu 18.04。
- 3.将这些cookbook上传到服务器:
knife cookbook upload mysql --include-dependencies
创建并加密您的MySQL密码
Chef包含一个称为数据包的功能。数据包存储配置方案,并且可以加密相关配置方案以存储密码和其他敏感数据。
- 1.在工作站上,生成一个密钥:
openssl rand -base64 512 > ~/chef-repo/.chef/encrypted_data_bag_secret
- 2.将此密钥上传到节点的
/etc/chef
目录,可以手动通过scp
(可以在“ 设置Chef”指南中找到示例)来执行,也可以通过使用recipe和cookbook文件来更新。 - 3.在工作站上,创建一个包含root密码的
rtpass.json
文件的mysql
数据包:
knife data bag create mysql rtpass.json --secret-file ~/chef-repo/.chef/encrypted_data_bag_secret
注意 某些knife命令要求使用文本编辑器将配置方案编辑为JSON数据格式。您的
knife.rb
文件应包含用于此类命令的文本编辑器的配置。如果您的knife.rb
文件尚未包含此配置,请添加knife[:editor] = "/usr/bin/vim"
到文件底部以将vim设置为默认文本编辑器。
系统将要求您编辑rtpass.json
文件:
{
"id": "rtpass.json",
"password": "password123"
}
请将password123
替换为安全密码。
- 4.确认
rtpass.json
文件已创建:knife data bag show mysql
它应该输出rtpass.json
。如果需要确保它是加密的,请运行:knife data bag show mysql rtpass.json
由于加密,输出将无法读取有效配置方案,并且应类似于:
WARNING: Encrypted data bag detected, but no secret provided for decoding. Displaying encrypted data.
id: rtpass.json
password:
cipher: aes-256-cbc
encrypted_data: wpEAb7TGUqBmdB1TJA/5vyiAo2qaRSIF1dRAc vkBhQ=
iv: E5TbF 9thH9amU3QmGxWmw==
version: 1
user:
cipher: aes-256-cbc
encrypted_data: VLA00Wrnh9DrZqDcytvo0HQUG0oqI6 6BkQjHXp6c0c=
iv: 6V 3ROpW9RG /honbf/RUw==
version: 1
设置MySQL
下载MySQL库并准备好加密的root密码后,您现在可以设置下载和配置MySQL的recipe。
- 1.在
recipes
中打开一个mysql.rb
新文件并定义将要使用的数据包:
mysqlpass = data_bag_item("mysql", "rtpass.json")
- 2.因为MySQL cookbook提供了LWRP,所以MySQL的初始安装和数据库创建可以在一个资源中完成:
mysqlpass = data_bag_item("mysql", "rtpass.json")
mysql_service "mysqldefault" do
version '5.7'
initial_root_password mysqlpass["password"]
action [:create, :start]
end
mysqldefault
是此容器的MySQL服务的名称。在创建数据库并启动MySQL服务的同时,inital_root_password
会调用上文中定义的相关值。
注意 从节点运行MySQL时,您需要定义套接字:
mysql -S /var/run/mysql-mysqldefault/mysqld.sock -p
PHP
- 1.在recipes目录下,创建一个新文件
php.rb
。使用以下命令安装PHP以及Apache和MySQL所需的所有软件包:
package "php" do
action :install
end
package "php-pear" do
action :install
end
package "php-mysql" do
action :install
end
- 2.为了便于配置,创建
php.ini
文件并将其用作cookbook文件,就像上面的MPM模块一样。你可以:- 添加PHP recipe,从节点(位于
/etc/php/7.0/cli/php.ini
)中运行chef-client
和复制文件,或者: - 从chef-php.ini示例中复制文件,该文件应移动到
chef-repo/cookbooks/lamp_stack/files/default/
目录下。如果需要更好适配您的配置,也可以将其转换为模板。
- 添加PHP recipe,从节点(位于
- 3.
php.ini
是一个大型文件,搜索并编辑以下值来适配您的Linode主机。下面建议的值适用于2GB Linode主机:
max_execution_time = 30
memory_limit = 128M
error_reporting = E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log
max_input_time = 30
- 4.返回
php.rb
文件并将cookbook_file
资源附加到recipe的末尾:
cookbook_file "/etc/php/7.0/cli/php.ini" do
source "php.ini"
mode "0644"
notifies :restart, "service[apache2]"
end
- 5.因为对
php.ini
文件进行了修改,所以需要创建/var/log/php
目录并将其所有权设置为Apache用户。这是通过notifies
命令和execute
资源完成的,如前所述。将这些资源附加到以下php.rb
末尾:
execute "chownlog" do
command "chown www-data /var/log/php"
action :nothing
end
directory "/var/log/php" do
action :create
notifies :run, "execute[chownlog]"
end
PHP recipe配置方案现已完成!在此处查看php.rb文件的示例。
- 6.确保您的Chef服务器包含更新的cookbook,并且您的节点的运行列表是最新的。请将
nodename
替换为Chef节点的名称:
knife cookbook upload lamp_stack
knife node run_list add nodename "recipe[lamp_stack],recipe[lamp_stack::apache],recipe[lamp_stack::mysql],recipe[lamp_stack::php]"
您刚刚创建了LAMP 环境 cookbook。通过本指南,您应该已经学会使用recipe配方中的执行、
包、服务、节点、目录、模板、cookbook_file和mysql_service资源,以及下载和使用LWRP,创建加密数据包,上传/更新您的cookbook到服务器,还有使用属性、模板、cookbook文件。这些将为您在未来项目中创建Chef和cookbook奠定坚实的基础。
更多配置方案
有关此主题的其他配置方案,您可能需要参考以下资源。虽然我们希望提供的是有效资源,但请注意,我们无法保证外部托管材料的准确性或及时性。
- Chef