我正在为我的团队寻找自动化部署解决方案,并且过去几天一直在与 Chef 一起玩。我已经能够使用 Chef-solo 从基础 Red Hat VM 运行一个简单的 Web 应用程序。
我们的最终目标是使用 Chef(或其他系统)在我们运行构建时自动将应用程序拓扑部署到云中。我们的流程基本上是这样运行的:
让 Chef 服务器运行有什么好处和/或用例?
与使用 Chef-solo 并拥有从 SCM 提取食谱的脚本相比,使用 Chef 服务器持有并从 SCM 获取食谱有什么主要好处吗?
我的团队创作了大量厨师食谱。我想知道我应该研究哪些方法和框架,以便我们可以开始创建测试以确保我们的节点配置正确?
automated-testing testing configuration-management chef chef-solo
如果我有一个正在创建的模板,我如何确保该目录存在?例如:
template "#{node[:app][:deploy_to]}/#{node[:app][:name]}/shared/config/database.yml" do
source 'database.yml.erb'
owner node[:user][:username]
group node[:user][:username]
mode 0644
variables({
:environment => node[:app][:environment],
:adapter => node[:database][:adapter],
:database => node[:database][:name],
:username => node[:database][:username],
:password => node[:database][:password],
:host => node[:database][:host]
})
end
Run Code Online (Sandbox Code Playgroud)
这失败了,因为/var/www/example/shared/config不存在database.yml要复制到。我在考虑 puppet 如何让您“确保”目录存在。
我了解在多服务器环境中使用 Chef 和 puppet 的优势。它非常适合在许多服务器上执行和描述配置。
但是假设您只有一台服务器,chef-solo与简单地手动配置服务器相比,您有什么优势?我喜欢厨师,但我想不出为什么花时间设置厨师独奏值得在单个甚至两个服务器架构上麻烦,但显然人们这样做了。
当该属性没有合理的默认值时,在资源(如模板)中使用属性的推荐方法是什么。期望在运行时提供属性值。如果不是,厨师食谱执行应该出错。
我现在拥有的方式是将属性值应用于模板时为空字符串。
/食谱/default.rb
template "/var/tmp/my_script.sh" do
source "my_script.erb"
mode "0755"
variables({
:url => node['environment']['url']
})
end
Run Code Online (Sandbox Code Playgroud)
/templates/default/my_script.erb
#!/bin/bash
echo "The url is: <%= @url %>"
Run Code Online (Sandbox Code Playgroud)
生成的 /var/tmp/my_script.sh 文件如下所示:
#!/bin/bash
echo "The url is: "
Run Code Online (Sandbox Code Playgroud)
但我希望它会出错。有什么建议吗?
有人可以向我解释厨师是如何工作的吗?这是一个相当广泛的问题,所以为了缩小范围,我有一个非常简单的方法,它循环遍历用户列表并创建每个用户(如果它们尚不存在)。这是行不通的。
据我所知,循环似乎正如我所期望的那样发生。一旦循环完成了我创建每个用户的 bash 命令,循环中的每次迭代都会执行一次。然而,当 bash 命令被执行时,它们似乎只有来自第一次循环迭代的用户值。
编写类似于此示例的循环变量数据的配方的正确方法是什么?
这是食谱:
node[:users].each do |user|
puts "in loop for #{user['username']}"
bash "create_user" do
user "root"
code do
puts "running 'useradd' for #{user['username']}"
"useradd #{user['username']}"
end
not_if do
puts "checking /etc/passwd for #{user['username']}"
"cat /etc/passwd | grep #{user['username']}"
end
end
end
Run Code Online (Sandbox Code Playgroud)
我正在使用具有以下设置的 Vagrant 对此进行测试:
Vagrant::Config.run do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
config.vm.provision :chef_solo do |chef|
chef.add_recipe "sample"
chef.json = {
:users => [
{:username => 'testA'},
{:username => 'testB'},
{:username => 'testC'},
{:username …Run Code Online (Sandbox Code Playgroud) 我正在构建一个结构来运行 Rails 应用程序。应用程序本身在 Heroku 上运行。但是,它向集群发出请求,集群通过 C 中的程序执行调用。
为了能够更快地从崩溃中恢复,我想使用 Chef 创建一个例程。我设法编写了一个“食谱”来安装您需要的一切,当我使用 Vagrant 虚拟机时,它可以完美运行。
但是,当我申请真正的服务器时,它失败了。另外我用的是Chef Solo,运行脚本之前需要手动在机器上安装一些东西,不太实用。
我不知道在这种情况下我是否应该使用 Chef Server。恐怕这是满足“小”需求的“伟大”工具。
这个集群只有三台机器组成,这个应该不会增加太多。但是,该应用程序还会向另一个稍大的集群(6 台机器)发出请求,尽管安装速度非常快,但也可以使用 Chef 服务器。
应该使用 Chef 还是 Chef Solo Server?有没有关于它的教学指南?开发人员文档非常混乱。
我的食谱中有以下几行
service "apache" do
action :stop
end
# Do something..
service "apache" do
action :start
end
Run Code Online (Sandbox Code Playgroud)
我发现第二个块没有执行。任何原因?
我有一个厨师食谱,我想获取 node['cfn']['environment'] 下的所有属性并将它们写入 yml 文件。我可以做这样的事情(它工作正常):
content = {
"environment_class" => node['cfn']['environment']['environment_class'],
"node_id" => node['cfn']['environment']['node_id'],
"reporting_prefix" => node['cfn']['environment']['reporting_prefix'],
"cfn_signal_url" => node['cfn']['environment']['signal_url']
}
yml_string = YAML::dump(content)
file "/etc/configuration/environment/platform.yml" do
mode 0644
action :create
content "#{yml_string}"
end
Run Code Online (Sandbox Code Playgroud)
但我不喜欢我必须明确列出属性的名称。如果稍后我添加一个新属性,如果它自动包含在写出的 yml 文件中,那就太好了。所以我尝试了这样的事情:
yml_string = node['cfn']['environment'].to_yaml
Run Code Online (Sandbox Code Playgroud)
但是因为节点实际上是一个 Mash,所以我得到了一个像这样的 platform.yml 文件(它包含很多我不想要的意外嵌套):
--- !ruby/object:Chef::Node::Attribute
normal:
tags: []
cfn:
environment: &25793640
reporting_prefix: Platform2
signal_url: https://cloudformation-waitcondition-us-east-1.s3.amazonaws.com/...
environment_class: Dev
node_id: i-908adf9
...
Run Code Online (Sandbox Code Playgroud)
但我想要的是这个:
----
reporting_prefix: Platform2
signal_url: https://cloudformation-waitcondition-us-east-1.s3.amazonaws.com/...
environment_class: Dev
node_id: i-908adf9
Run Code Online (Sandbox Code Playgroud)
如何在不按名称显式列出属性的情况下实现所需的 yml 输出?
Chef-solo 缺乏环境支持似乎很有争议。一方面,环境的特征之一是能够将食谱固定到特定环境,而这对于 Chef-solo 来说完全没有意义。另一方面,我们很多人都希望在使用 Vagrant 进行测试时能够合并环境级别的属性并使用特定于环境的运行列表。我想我可能已经找到了一个简单的方法来解决这个问题。假设我在所有环境和角色中使用 JSON 语法,并且我坚持以下约定来设置属性(从最低到最高优先级):
看起来我可以自己解析这些文件并使用 -j 选项将属性注入到chef-solo中。例如,我可以在我的 Vagrantfile 中做这样的事情:
chef_env_conf = parse_json("./environments/#{ENV['CHEF_ENVIRONMENT']}.json")
chef.json = chef_env_conf["override_attributes"]
Run Code Online (Sandbox Code Playgroud)
由于通过 -j 选项设置的属性在正常优先级级别应用,因此这可以是覆盖角色默认值的另一种方法,并且这可能是您在未自动拉入环境的上下文中所需的全部内容。
您可以执行类似的操作来获取每个环境的运行列表(通过解析角色文件):
chef_role_conf = parse_json("./roles/#{role}.json")
chef.run_list = chef_role_conf["env_run_lists"][ENV['CHEF_ENVIRONMENT']]
Run Code Online (Sandbox Code Playgroud)
我意识到这不是最优雅的 hack,但对于某些人来说,这似乎是一个可行的解决方案。有没有人认为这是一个非常糟糕的主意?