Chef是,由Ruby开发的服务器的构成管理工具
想像一下我们现在需要搭建一台mysql database slave服务器,安装过程我们手动操作了 没过多久,我们需要第二台,这时候我们会想,如果之后安装第一台的时候把操作过程执行的命令写成脚本 现在安装第二台,运行一下脚本就行了,节约时间而且不容易出错
chef就相当于这样的一个脚本管理工具,但功能要强大得多,可定制性强 chef将脚本命令代码化,定制时只需要修改代码,安装的过程就是执行代码的过程
打个比方,Chef就像一个制作玩具的工厂,它可以把一些原材料做成漂亮的玩具, 它有一些模板,你把原材料放进去,选择一个模板(比如怪物史莱克),它就会制造出这个玩具 服务器的配置也是这样,一台还没有配置的服务器,你给它指定一个模板(role或recipe), Chef就会把它配置成你想要的线上服务器
这个只是Chef的一方面,因为可以安装好系统后执行一个脚本也达到同样的目的,Chef还有另一方面 是脚本达不到的,那就是Chef对经过的配置的服务器有远程控制的能力,它可以随时对系统进行进一步的配置或修改 就像前面的玩具工厂可以随时改变它的玩具的颜色,大小(好像现实中不太可能) 你也可以通过手动的方式达到目的, 但是当服务器比较多的时候,可能手动的方法就不是那么欢乐了
Chef提供了更方便统一的方法
在系统的世界中,基本上不会说解决课题的工具只有1个, 各自工具都有自己的长处和短处,所以可能的话要选择最合适的那个
服务器的构成管理工具而言,知名度与Chef平分天下的是叫“Puppet”的工具, 这两个都作为OSS是知名度排名最前的2个。让我们来比较下它们的不同处:
注: 下面的表格来自用Chef来简化服务器管理
|------------------+------------------------------------+-----------------------------------------------------------------------| | 比较 | Puppet | Chef | |------------------+------------------------------------+-----------------------------------------------------------------------| | 历史 | 有一些 | 还年轻 | | 用户 | 多,有名的公司也在用 | 还比较少,但我认为有37signals在使用 | | 开发的活跃度 | 中等 | 活跃(感觉正在旺季) | | 文档 | 多 | 也足够了 | | 设定文件 | 用专用的文法书写(外部DSL) | 用Ruby书写(内部DSL) | | 设定的构成 | 有点难懂 | 相对容易理解,命名等很合适 | | 依存关系的处理 | 运行次序是根据状况由系统端决定的。 | 好像Makefile 基本上是书写顺序。相比Puppet更具脚本风格 | | 必要的中间软件 | 没有 | 服务端需要有CouchDB、RabbitMQ | | 安装 | 简单,用gem的安装就可以 | 服务端容易死。没有加入包中的话比较困难。客户端的话简单,只要gem就可以 | | 和其他系统的协作 | 感觉基本上没有 | 因为使用RESTful的服务API,用JSON可以取值,所以好像能做许多事 | |------------------+------------------------------------+-----------------------------------------------------------------------|
这是Chef的结构图,对图做一点解释:
由一台普通电脑控制所有的服务器,不需要专设一台chef-server
所有的服务器作为chef-client,统一由chef-server进行管理,管理包括安装、配置等工作 chef-server可以自建,但安装的东西较多,由于使用solr作为全文搜索引擎,还需要安装java
Chef能做什么,答案的Anything,这个实际上很好理解,只要你可以对一台服务执行命令 你就可以对这台服务做任何配置(不是有那句话嘛:Where there is a SHELL, there is a way)
这里大家可能对Chef有一些误解,由于Chef使用类似模板的方法对服务进行配置, 大家可能认识它只适合于一些配置比较类似的服务, 这里完全小看Chef了,我从他们的网站上下载过mysql的cookbook,它可以同时支持:
debian ubuntu centos suse fedora redhat scientific amazon freebsd windows
当你对Chef怎么做有一定的了解后你就不会感到惊讶了
如果忽略所有的细节,Chef是这样工作的:
Chef为了描述Client如何配置自己定义了一些名词,对这些新东西了解有利用理解Chef工作原理
Resource是Chef提供给你的用来描述系统的某一部分希望怎么配置(处于什么状态),请看例子
package "vim" do
action :install
end
这就是一条Resource,它想要表达的是希望vim安装(处于安装的状态)
这里package是一个Resource类型,这里列出几个比较常用的Resource:
Provider的概念可能比较抽象,像上面的Resource的例子,我们之所以不关关心vim怎么被安装(apt,yum…),就是因为有Provider 也就是说Provider负责把抽象的Resource对应到实际的命令(如上面的例子可能是:yum -y install vim)
下面我会列一些Resource的例子,如果你对Resource已经有理解了,可以跳到下一节Recipe
service "ntpd" do
action[:enable,:start]
end
这是一条类型为service的Resource,这描述的是:启动ntpd服务并设置成开机启动 注:虽然使用action这个词,但实际上它描述的是一种状态(它不会每次都试图去start)
user "random" do comment "Random User" uid 1000 gid "users" home "/home/random" shell "/bin/zsh" end
上面的Resource的类型为user,名字为random,然后一些参数(uid,gid,home,shell) 它描述的是:在系统上以这些参数创建random这个用户
上面的例子并没有action,这是因为'user'这个Resource的默认动作为create,可以省略
file "/tmp/something" do owner "root" group "root" mode "0755" action :create content "just test" end
这个Resource的类型为file, 名字为'/tmp/something',动作为'create',还有一些参数 它描述的是:
template "/tmp/config.conf" do source "config.conf.erb" variables( :config_var => node[:configs][:config_var] ) end
这是一个类型的template的Resource,它把服务器上的config.conf.erb文件传到客户机上,重命名为config.conf并做变量替换(template后面会详细的讲一下)
简单的说把多个Resource写到一起就是Recipe,客户端会把Recipe里面的Resouce按照顺序(重要)一条一条的应用到自身
看一个配置ntp服务的Recipe
vim /var/chef/cookbooks/ntp/recipes/default.rb
package "ntp" do action [:install] end template "/etc/ntp.conf" do source "ntp.conf.erb" variables( :ntp_server => "time.nist.gov" ) end service "ntpd" do action[:enable,:start] end
将把这个Recipe加到客户的run list(后面会说到)时,它会按顺序(重要)应用这些Resouce到自身:
这里顺序很重要,如果整个反过来,可能就不能正确配置ntp服务了
Recipe可以包含其它的Recipe,如这个Recipe
vim /var/chef/cookbooks/mysql/recipes/default.rb
include_recipe "ntp::default" package "mysql-server" do action :install end service "mysql-server" do action :start end
当这条Recipe被加到客户服务器的run list里时,它会首先把ntp::default这条Recipe展开成一条一条的Resource应用到自身,然后再应用后面的Resource
总结一下Recipe:
把它们写在一起是因为他们都有一个run_list,而且他们的run_list都可以包含Recipe和Role
knife node show client1.chefdemo.com
Node Name: client1.chefdemo.com Environment: _default FQDN: client1.chefdemo.com IP: 192.168.122.10 Run List: recipe[ntp::default], recipe[mysql::default] Roles: Recipes: ntp::default, mysql::default Platform: centos 6.2
knife role show mysql
chef_type: role default_attributes: description: env_run_lists: json_class: Chef::Role name: mysql override_attributes: run_list: recipe[ntp::default] recipe[mysql::default]
Role可以用来描述一台服务器希望被配置成什么样子(配置成web服务器,mysql服务器,甚至是一个论坛)
它有一个run_list, 里面包含了要把一台服务器配置成这个样子所需要的Recipe和Role(Role可以包含Role)
Node很好理解,每一个被Chef管理的服务器(运行chef-client)就是一个Node
当一个Node上的chef-client启动的时候,它会去chef-server查到自己的run_list里包含那些Role和Recipe,然后把它们按顺序依次展开并应用到自身
Role和Node的关系是:可以把Role应用到Node,实际上这个过程只是简单的把这个Role的run_list里包含的东西(Role和Recipe)加到这个Node的run_list里(一个Node可以包含任意多个Role或Recipe)
这里举一个例子帮助理解,有两个Recipe: ntp::default和mysql::default
package "ntp" do action [:install] end# 后面把这一条Resource简称为:安装ntp的Resource service "ntpd" do action[:enable,:start] end# 后面把这一条Resource简称为:启动ntp的Resource
package "mysql-server" do action :install end# 后面把这一条Resource简称为:安装mysql-server的Resource service "mysql-server" do action :start end# 后面把这一条Resource简称为:启动mysql-server的Resource
我们创建一个名叫ntp_and_mysql的Role并把这两个Recipe加到里面,相应的命令为
EDITOR=vim knife role create ntp_and_mysql
这条命令会用vim打开一个文件让你编辑这个role,修改成这样然后保存退出
{ "override_attributes": { }, "chef_type": "role", "env_run_lists": { }, "json_class": "Chef::Role", "name": "ntp_and_mysql", "run_list": [ "recipe[ntp::default]", "recipe[mysql::default]" ], "default_attributes": { }, "description": "" }
然后把这个Role应用到一个Node上(实际上就是把这个Role的runlist里的Recipe加到Node的runlist里)
knife node run list add client1.chefdemo.com 'role[ntp_and_mysql]'
最后client1.chefdemo.com这个Node会把它展开为4条Resource(按顺序)
安装ntp的Resource 启动ntp的Resource 安装mysql-server的Resource 启动mysql-server的Resource
再由Provider将其转为对应的命令,最后这个Node所要做的就是:安装ntp,启动ntp,安装mysql-server,启动mysql-server
Cookbook实际上就是Recipe等一些东西的打包,像前面的ntp::default,ntp就是一个Cookbook
Cookbook的目录结构类似这样
tree /var/chef/cookbooks/ntp/
/var/chef/cookbooks/ntp/ ├── attributes ├── definitions ├── files │ └── default ├── libraries ├── metadata.rb ├── providers ├── README.md ├── recipes │ ├── default.rb │ └── ntp.rb ├── resources └── templates └── default └── ntp.conf.erb 10 directories, 5 files
更多Cookbook的内容请查看官方Wiki
由于创建用户的那个Recipe就用到了Data Bag, 所以这里简单说一下
Data Bag提供了定义全局信息的方法,直接看例子
首先我们创建一个Data Bag
knife data bag create admin
这条命令在chef-server上创建一个Data Bag, 可以在里面存储信息
mkdir -p /var/chef/data_bags/admin vim /var/chef/data-bags/admin/william.json
{ "id": "william", "shell": "/bin/bash", "comment": "william", "action": "create", }
然后上传到服务端
cd /var/chef
knife data bag from file admin william.json
现在就可以在Recipe里访问这些信息,可以有两个方法:data_bag和data_bag_item
data_bag("admin")# => ["william"]
'# =>' 这里指返回的意思,也就是说如果这样写:
username=data_bag("admin")
那么username就等["william"]
data_bag_item('admins', 'charlie')# => {"id"=>"william", "shell"=>"/bin/bash", "comment"=>"william", "action"=>"create"}
现在你已经知道这些新的概念了,我们再来看下Chef如何工作
这里简单的说一个template这个Resource,因为可以正好从侧面消除大家对Chef的误解 它非常适合用来管理配置文件,先看一个例子
template "/etc/ntp.conf" do source "ntp.conf.erb" variables( :ntp_server => node[:ntp_server] ) end
这个Resource用来从服务端复制配置文件到客户端,复制的过程中还进行了变量替换(ntpserver),也就是不同的服务器可以有各自的ntpserver
这个模板文件(ntp.conf.erb)内容为:
# generated by Chef. restrict default kod nomodify notrap nopeer noquery restrict -6 default kod nomodify notrap nopeer noquery restrict 127.0.0.1 restrict -6 ::1 server <%= @ntp_server %> server 127.127.1.0 # local clock driftfile /var/lib/ntp/drift keys /etc/ntp/keys
这个文件保存在什么地方呢,如果对前面的Cookbook的目录结构有印象,应该还记得有template这个目录 这个目录下有default这个目录,一般就保存在这里
假设有一个Node(主机名为client1.chefdemo.com, 安装了centos6.2的系统)的runlist里有这一条Resource, 那么它从服务端传这个文件的时候,它会按这个顺序在服务端查找
.../template/host-client1.chefdemo.com/ntp.conf.erb .../template/centos-6.2/ntp.conf.erb .../template/centos/ntp.conf.erb .../template/default/ntp.conf.erb
也就是说不同的客户端可以有各自的配置文件
总结一下:
从这两点我们可以看到Chef不只适用于配置比较相似的情况,同样可以胜任个性化的配置
Date: 2012-06-24 13:56:19 CST
Author: William
Org version 7.8.02 with Emacs version 23
Validate XHTML 1.0