saberma

分享技术实践,创业历程

应用chef构建服务器集群自动化部署与管理

2011-01-27

为了将rails程序部署到服务器上,需要做的工作有

  1. 安装服务器各组件,如libcurl等
  2. 配置服务器,如用户管理、iptable等
  3. 安装数据库
  4. 安装缓存服务
  5. 安装配置前端应用服务器
  6. 安装rvm
  7. 安装项目所需gems

以上工作属于新服务器到位后的一次性工作,而项目更新升级的工作属于不定期重复性工作,大致如下:

  1. 下载最新源代码
  2. 运行数据库脚本
  3. 重新启动应用服务器

此外,日常工作还包括服务器的监控、维护等

当项目规模不大,服务器只有一两台时,可以手动或者应用 Capistranodeprec 自动处理

capistrano的缺点

在应用capify安装某些组件的过程中,如果出现问题,只能进入源代码检查相应的recipe,因为capistrano的recipe相对来说是隐性的
比如,安装之前,我们不知道mysql的安装会是通过package直接安装还是通过下载source本地编译后安装,也无法获知其版本
而当recipe不符合你的要求时,需要对其进行改造的成本比较大

随着项目规模的不断扩大,比如,有了专门的数据库服务器,甚至是数据库服务器集群,这时候capistrano就会显示力不从心了
我们需要有专业的服务器管理配置工具来统一管理所有的服务器,这类工具不少,这里只介绍chef

Chef

Chef是一个什么样的工具

想像一下我们现在需要搭建一台mysql database slave服务器,安装过程我们手动操作了
没过多久,我们需要第二台,这时候我们会想,如果之后安装第一台的时候把操作过程执行的命令写成脚本
现在安装第二台,运行一下脚本就行了,节约时间而且不容易出错

chef就相当于这样的一个脚本管理工具,但功能要强大得多,可定制性强
chef将脚本命令代码化,定制时只需要修改代码,安装的过程就是执行代码的过程

架构图

Chef的三种管理模式

1. Chef-Solo

由一台普通电脑控制所有的服务器,不需要专设一台chef-server

2. Client-Server

所有的服务器作为chef-client,统一由chef-server进行管理,管理包括安装、配置等工作
chef-server可以自建,但安装的东西较多,由于使用solr作为全文搜索引擎,还需要安装java

3. Opscode Platform

类似于Client-Server,只是Server端不需要自建,而是采用 http://www.opscode.com 提供的chef-server服务,本文描述以此方式为主,免费帐号可以管理5个服务器

Library程序库

程序库是定义的module方法,可以在chef中任何地方被调用,在方法体内可以执行与数据库等资源的交互动作
详见 Libraries

操作对象

chef可以通过recipe指定新建目录、生成配置文件、安装gems等操作,可控性非常强

新建目录

新建目录/data,owner为node[:user]指定的内容,权限代码为0755

directory “/data” do
 owner node[:user]
 mode 0755
end

生成配置文件

以someservice.conf.erb为模板,生成/data/someservice.conf配置文件,生成时会传递参数applications给模板

template “/data/someservice.conf” do
 owner node[:user]
 mode 0644
 source “someservice.conf.erb”
 variables({
  :applications => node[:apps]
 })
end

把一台新的vps纳入chef管理

假设vps ip为188.188.188.188
ssh密码为123456

注册

https://cookbooks.opscode.com/users/new 注册帐号
通过邮件认证后,进入控制台 https://manage.opscode.com 创建organization
按提示下载两个链接文件至~/Downloads: Download validation key | Generate knife config
点击右上角的用户名,下载链接文件至~/Download: Get a new private key

下载后的knife.txt要改名为knife.rb
以上三个文件请妥善保管,下载之后opscode平台不再保存这些文件

本地安装

gem install chef net-ssh-multi --no-ri --no-rdoc
cd ~/Documents
git clone git://github.com/opscode/chef-repo.git
cd chef-repo
mkdir -p .chef
# USERNAME和ORGANIZATION改为实际的文件名称
cd ~/Downloads
cp USERNAME.pem ~/Documents/chef-repo/.chef
cp ORGANIZATION-validator.pem ~/Documents/chef-repo/.chef
cp knife.rb ~/Documents/chef-repo/.chef
#测试连接opscode platform
knife client list
#成功连接则显示validator的数组,如
#[ "shopqi-validator" ]

为vps安装ruby及chef客户端环境

knife bootstrap 188.188.188.188 -u root -P 123456
#ssh登录服务器不再需要输入密码
ssh root@188.188.188.188 'sh -c "mkdir ~/.ssh"'
scp ~/.ssh/id_rsa.pub root@188.188.188.188:/root/.ssh/authorized_keys

远程测试是否安装正常

ssh root@188.188.188.188
chef-client
#如果出现错误,可使用调试模式
chef-client -l debug

让vps运行第一个cookbook

安装完服务器操作系统后,第一件事情就是更新软件
一般情况下,我们会在服务器上运行命令

sudo apt-get update

现在我们要通过chef来指定vps运行此命令

本地安装apt cookbook

#此命令最常用,会从opscode官网 "http://cookbooks.opscode.com/":http://cookbooks.opscode.com/ 下载cookbook
knife cookbook site vendor apt

为node加入recipe

knife node list
#以上查看node id,假如为201166,现在查看node的run_list
knife node show 201166 -r
#加入apt recipe到vps的run list中
knife node run_list add 201166 "recipe[apt]"
knife node show 201166 -r
knife cookbook upload -a

远程登录vps,开始按run_list运行指定recipe

ssh root@188.188.188.188
chef-client
#每次本地更新后都要在远程运行chef-client比较麻烦,可以使用以下命令,设置为后台程序运行
chef-client -i 3600 -s 600

安装ruby-on-rails3

下载cookbook

#参数-d要求下载依赖的cookbook
knife cookbook site vendor rvm -d
#此cookbook调用了chef内置的deploy resource,实现类似于capistrano的部署功能
#但此cookbook还依赖了java cookbook等,忽略它们即可
knife cookbook site vendor application -d

新增apps data bag

data bag相当于全局变量,application cookcook需要根据apps指定role,recipe等参数

export EDITOR=vim
#参考 "https://github.com/opscode/cookbooks/tree/master/application":https://github.com/opscode/cookbooks/tree/master/application 将json粘贴进来
#退出vim时,data bag会被自动上传至chef server,本地不保存
knife data bag create apps 55true
#保存至本地
mkdir data_bags/apps
knife data bag show apps 55true > data_bags/apps/55true.json
knife data bag from file apps 55true.json

新增role rails

export EDITOR=vim
knife role create rails

Tip

服务器集群中可能会区分出production, staging环境,也可能同一应用部署在多台服务器中,但只需由其中的一台服务器运行数据库迁徙脚本

  1. 新增production, staging等role,设置app_environment attribute,分配至相应的node,这样可以重复使用deploy cookbook
  2. 新增app_name_run_migrations role,设置run_migrations attribute

常用cookbook

以下列出在 https://github.com/opscode/cookbooks 中常用的cookbook

apt

此recipt会运行apt-get update,用于更新操作系统

runit

用于保证unicorn等服务时刻处于运行状态
runsvdir服务会不停地监测/etc/sv目录下的服务目录,每个目录对应一个runsv服务
如果某个runsv服务出现故障停止了,runsvdir会自动重新启动它

#sv服务不启动时查看日志
ps -ef | grep runsvdir
#查看服务的状态
sv stat unicorn_server
#查看服务的日志
tail -f /etc/sv/unicorn_server/log/main/current

bluepill

runit保证了服务的运行,bluepill保证进程的cpu、memory占用率处于正常水平

users

新增用户,用户定义在users data bag中

mongodb

安装1.6.5版本的mongo server
https://github.com/papercavalier/mongodb-cookbook

unicorn

经过对比,还是选择37signal的unicorn cookbook,因为支持多app部署,而unicornapp不支持(opscode官方已经删除此cookbook)。为了对unicorn子线程进行监控,两者都使用了bluepill取代God进行监控。
注意:在production环境下,rails3默认不会处理public目录下静态文件的请求,所以不能像dev环境下直接通过指定端口访问某个unicorn服务

application

这个包含太多的依赖cookbook了,经过以上的实践,还是觉得不用它了,因为里面对rails项目有用的就是deploy部分,自己重写一个也很容易

注意事项

在service或者definition中传递参数时,如果将父params需要级联传递下去,得手动为params赋值至其他变量,因为在service或者definition块中,params参数已经被当前块覆盖了
详情参考:"http://tickets.opscode.com/browse/CHEF-422"

参考资源

Infrastructure Automation with Chef
Getting started with Chef tutorial
Getting Started With The Opscode Chef Platform – Configuration Management In The Cloud
How to Deploy Ruby on Rails With The Opscode Chef Application Cookbook
Cooking with Chef 101
Why Startups Need Automated Infrastructures
Deploy Resource
application cookbook

runit

blog comments powered by Disqus
Fork me on GitHub