使用Chef
最后更新于:2022-04-01 02:42:20
# 使用Chef
### 以Chef Server管理模式为例
我们刚才创建的cookbook的名字叫: apache-tutorial-1。它的目的就是要在指定的node上面安装apache,并且启动服务。
### 1 编写recipe
让我们编写第一个recipe。试想一下,如果手工来安装apache,需要下面三步动作。
- 安装Apache
- 启动Apache并且把它添加到开机启动
- 配置home page
现在我们用recipe实现,打开cookbooks/apache-tutorial-1/recipes/default.rb文件,输入以下Ruby代码:
~~~
package 'apache2' do
action :install
end
service 'apache2' do
action [ :enable, :start ]
end
cookbook_file '/var/www/index.html' do
source 'index.html'
mode '0644'
end
~~~
我来解释下上面的代码:
在Chef中,package是一种资源类型,它告诉chef-client运行时候的「包」的名字,以及执行的动作,这段代码里,是告诉chef-client,要安装papache2. package在执行的时候,会自动的调用底层的provider来匹配相应的服务器平台。
service会告诉chef-client启动哪个服务。会调用底层的ohai组件来收集相关平台信息,从而正确启动相应的服务。这段代码里,是告诉chef-client,想要启动apache2.
cookbook_file会告诉chef-client来拷贝index.html文件到/var/www/index.html中,并且设置文件权限为0644.
这只是个简单的recipe,让我们继续。
把下面html代码添加到cookbook/apache-tutorial-1/files/default/index.html中:
~~~
<html>
<body>
<h1>Hello, world!</h1>
</body>
</html>
~~~
### 2 上传Cookbook
我们写完了这个cookbook,就可以把它上传到我们之前搭建的Chef Server上面(非chef-solo模式)。在chef-repo目录中执行下面命令:
~~~
$ knife cookbook upload apache-tutorial-1
~~~
然后打开我们的Chef Server Webui: [https://192.168.33.11/cookbooks](https://192.168.33.11/cookbooks)
就可以看到我们上传的Cookbook了,如图:
![cookbook](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-23_55d9d7adb50b6.png)
### 3 设置Run list
还是在Chef Server Webui上面,点击:[https://192.168.33.11/nodes](https://192.168.33.11/nodes)
选择你要安装的node, 点击编辑(edit),如图:
![node-edit](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-23_55d9d7adc7d1f.png)
在编辑界面,如图把apache-tutorial-1移动到右边,点击保存。
![run_list](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-23_55d9d7addd061.png)
~~~
说明: Run list就是一个运行列表,包含了所有需要安装的role,以及按依赖顺序把recipe排列。
~~~
### 执行cookbook配置node
cookbook设置完毕,我们就执行下面命令来配置node:
~~~
$ knife ssh 192.168.33.12 'sudo chef-client' -m -x vagrant -P vagrant
~~~
这个命令会在ip为192.168.33.12的node上面执行sudo chef-client命令来配置节点。当然,你也可以登陆到那台虚拟机上面手工执行sudo chef-client命令。
命令执行成功之后,你登陆到192.168.33.12那台虚拟机上面,就会看到apatch2已经正常运行了。
![apache-run](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-23_55d9d7adf25d9.png)
### 以OpsCode Chef为例
过程和自建Chef Server类似,可以自行练习。
### 以Chef Solo管理模式为例
当你对上面Chef Server模式有了一定了解,那么Chef Solo理解起来也不吃力了。
Chef Solo因为没有Server,所以我们直接在node机器上来执行。
我们继续拿上面用过的node2为例子。
**注意: 以下操作都在node2虚拟机上面**
~~~
$ mkdir -p /etc/chef/coobooks/nginx/recipes
~~~
必须要在/etc/chef目录下面。
~~~
cd /etc/chef/coobooks/nginx/recipes
sudo touch default.rb
sudo vi default.rb
~~~
写入下面Ruby代码:
~~~
package 'nginx'
~~~
然后回到/etc/chef 目录,创建node.json文件,然后编辑run list:
~~~
{ "run_list": ["recipe[nginx]"] }
~~~
然后在/etc/chef目录下,建立solo.rb文件:
~~~
cookbook_path File.expand_path("../cookbooks", __FILE__)
json_attribs File.expand_path("../node.json", __FILE__)
~~~
用来指定cookbooks和node.json的位置。
然后我们执行命令:
~~~
$ sudo chef-solo solo.rb
~~~
安装成功。
![Chef Solo](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-23_55d9d7ae10a5c.png)
*chef solo*
### 启动服务
我们需要在nginx被安装完之后,可以自动启动。
再次打开 /etc/chef/cookbooks/nginx/recipes/default.rb修改代码为下面几行:
~~~
package 'nginx'
service 'nginx' do
supports [:status, :restart, :reload]
action :start
end
~~~
我们在chef server那节里介绍过service这个资源的含义。supports,用来告诉Chef,支持status、restart、reload这三个命令。最后用action来告诉Chef,当前动作是start。
然后在/etc/chef下执行:
~~~
$ sudo chef-solo solo.rb
~~~
就能看到nginx被正常启动了。 很酷。
### 增加用户
用户,是我们经常使用的,Chef也提供了User资源,来帮助你管理这些Chef使用者的用户。
比如,我们可以在/etc/chef/cookbooks下面再创建一个名为user的recipes,
~~~
$ sudo mkdir /etc/chef/cookbooks/user/recipes
$ cd /etc/chef/cookbooks/user/recipes
$ sudo touch default.rb
~~~
在default.rb中输入下面代码:
~~~
user 'blackanger' do
password "$1$3YbJDvy2$JD2o6dEFjGvayRgmZWU030"
gid "admin"
home "/home/blackanger"
supports manage_home: true
end
~~~
说明: password,告诉Chef,此为用户的密码,是经过openssl加密的,使用此命令来加密:[openssl passwd -1 "passwd"]。 gid,告诉Chef,要把这个用户加到admin组里面,home,是指定用户的home目录, supports,指定管理其home的权限。
然后再打开/etc/chef/node.json, 加入recipes['user']:
~~~
{ "run_list": ["recipe[nginx]", "recipe[user]"] }
~~~
执行命令:
~~~
$ sudo chef-solo solo.rb
~~~
我们就可以看到执行结果了:
![add_user](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-23_55d9d7ae2a433.png)
*add user*
### 设定node.json
我们虽然创建好了用户,但是仔细想想,这种方式不太好,假如我们配置多台机器呢? user recipes里写的太死,代码无法重用了。 好在,我们Chef还可以允许我们把这种用户信息写到node.json里。
打开/etc/chef/node.json:
~~~
{
"run_list": ["recipe[nginx]", "recipe[user]"],
"user": {
"name": "blackanger",
"password": "$1$3YbJDvy2$JD2o6dEFjGvayRgmZWU030"
}
}
~~~
然后回到user recipes的default.rb文件中修改为:
~~~
user node[:user][:name] do
password node[:user][:password]
gid "admin"
home "/home/#{node[:user][:name]}"
supports manage_home: true
end
~~~
然后执行:
~~~
$ sudo chef-solo solo.rb
~~~
成功!是不是很酷啊!
### 使用template
回到刚才nginx的例子, 我们还需要给nginx设置一个配置文件,这个时候,就要用到template资源了。
~~~
$ sudo mkdir /etc/chef/cookbooks/nginx/templates/default
$ sudo touch /etc/chef/cookbooks/nginx/templates/default/nginx.conf.erb
~~~
注意,我们创建了一个nginx.conf.erb文件, 如果对Rails有了解的朋友,应该指定,erb是一个模板引擎,它可以支持你在这种模板里面变量运算、替换等操作。
打开nginx.conf.erb,输入下面代码:
~~~
server {
server_name 192.168.33.12;
root /home/<%= node[:user][:name] %>/demo;
}
~~~
注意:上面形如 <% ... %> 这样格式的代码,就是erb的语法,可以把需要替换的变量放到里面。
然后我们在回到nginx的recipe中告诉Chef应该使用这个template:
打开:/etc/chef/cookbooks/nginx/recipes/default.rb, 添加下面代码:
~~~
template "/etc/nginx/sites-enabled/nginx.conf" do
source 'nginx.conf.erb'
notifies :restart, 'service[nginx]', :immediately
end
~~~
说明:"/etc/nginx/sites-enabled/nginx.conf" 是告诉Chef,template文件要保存的路径。 source告诉Chef去哪找这个template, notifies是一个callback,告诉Chef要马上重启nginx服务。
然后我们分别使用directory和file资源来添加一个html文件,写法同上,下面给出完成的nginx recipe:
~~~
package 'nginx'
service 'nginx' do
supports [:status, :restart, :reload]
action :start
end
directory "/home/#{node[:user][:name]}/demo" do
owner node[:user][:name]
end
file "/home/#{node[:user][:name]}/demo/index.html" do
owner node[:user][:name]
content "<h1>Hello blackanger!</h1>"
end
template "/etc/nginx/sites-enabled/nginx.conf" do
source 'nginx.conf.erb'
notifies :restart, 'service[nginx]', :immediately
end
~~~
然后执行我们的老命令: sudo chef-solo solo.rb, 愿望达成:
![nginx_recipe](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-23_55d9d7ae385f9.png)
*run nginx recipe*
验证:
~~~
$ curl http://127.0.0.1
<h1>Hello blackanger!</h1>
~~~
至此,我们就学会了使用chef-solo来安装「一台」机器。如果你想安装多台, 那么继续按照上面的步骤,安装chef-solo,然后复制cookbooks,一台一台的执行命令。
这样是不是还是很麻烦呢?
那当然了! 辛亏我们还有knife,这个超级助手。
### chef-solo with knife
Knife是一套强大的命令行Chef管理工具。我们可以使用knife来帮助我们简化麻烦的工作,让我们不需要通过Chef Server就可以直接和需要配置的服务器交互。
因为我们使用的chef-solo方式,所以我们先安装一个gem:
~~~
$ gem install knife-solo
~~~
安装好之后执行命令:
~~~
$ knife solo init knife-solo-demo
~~~
就会帮助我们生成一个solo目录:
![knife-solo-dir](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-23_55d9d7ae57fd6.png)
注意: 在使用这个命令之前,要确保你的Ruby环境是否唯一,否则可能会出现找不到knife子命令solo的错误。
这个目录中,.chef/文件夹下面包含一个knife.rb文件。这个文件在我们讲过的Chef Server模式下也是一样存在的,具体的配置文档可以去[官网](http://docs.getchef.com/config_rb_knife.html)查看。这里生成的knife.rb文件中包含下面代码:
~~~
cookbook_path ["cookbooks", "site-cookbooks"]
node_path "nodes"
role_path "roles"
environment_path "environments"
data_bag_path "data_bags"
#encrypted_data_bag_secret "data_bag_key"
knife[:berkshelf_path] = "cookbooks"
~~~
这里cookbook_path是相对于仓库根目录的路径,指定了角色中使用的Cookbook信息node_path和role_path分别定义了节点和角色的存储位置,都是相对于根目录的路径。这里有个berkshelf_path, berkshelf是一个第三方cookbook管理工具,我们的cookbooks目录,就是存放这些第三方cookbook,而site-cookbooks是用来存放我们自己编写的cookbook的地方。
然后我们使用命令:
~~~
$ knife solo bootstrap vagrant@192.168.33.11
~~~
就可以在另一台vagrant机器(192.168.33.11)上配置chef-solo。它会帮我们安装chef-client, 创建node,创建cookbooks。
knife solo bootstrap实际上执行了两个命令:
-
knife solo prepare
这个命令主要是初始化服务器,安装chef,配置node,上传cookbook
-
knife solo cook
这个命令主要是上传cookbook,并且执行指令 chef-solo.
有了这个工具,就方便很多了。