用vagrant和Chef Solo在实机上实施。构建centos6.5 + nginx,PHP,Ruby,MySQL环境
在实际设备上验证了《Chef实践入门》第6章自动构建应用程序执行环境的备忘录。
0.环境前提
0. 环境的先决条件
已经安装了MacOSX的Vagrant和VirtualBox。
1. 安装Bundler,并安装Chef、Knife-solo和Berkshelf。
(Bundler是用于管理Gem的Ruby工具)
#環境用ディレクトリの作成
mkdir lnmpr
cd lnmpr
#Bundlerのインストール
sudo gem install bundler
#Gemfile作成
cat <<'EOF' > Gemfile
source 'https://rubygems.org'
gem 'chef'
gem 'knife-solo'
gem 'berkshelf'
EOF
#bundleコマンドの実行
bundle install
#Vagrantfile作成
vagrant init
2. 安装nginx
(1) 由knife-solo创建的烹饪书单。
bundle exec knife cookbook create nginx -o ./site-cookbooks
(2) 创建nginx配方
include_recipe "yum-epel"
package "nginx" do
action :install
end
service "nginx" do
action [ :enable, :start ]
supports :status =>true, :restart =>true, :reload =>true
end
创建Berksfile文件,并定义运行簿的依赖关系。
*嗯,嗯 – yum-epel无法正常运行,直到从https://supermarket.getchef.com下载并安装至本地的site-cookbooks。在这里遇到了一些问题。
source "https://supermarket.getchef.com"
cookbook 'yum', path: "./site-cookbooks/yum"
cookbook 'yum-epel', path: "./site-cookbooks/yum-epel"
cookbook 'nginx', path: "./site-cookbooks/nginx"
执行berks vendor命令以下载社区烹饪书。
bundle exec berks vendor ./cookbooks
#yum-epel,nginx、依存関係のあるその他のcookbooksが配置されている事を確認
ls -Rla ./cookbooks
(5)安装vagrant-omnibus插件
vagrant plugin install vagrant-omnibus
vagrant plugin list
(6)Vagrantfile的配置
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.hostname = "guest"
config.vm.box = "centos6.5"
config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5-i386_chef-provisionerless.box"
config.vm.network "private_network", ip: "192.168.33.10"
# vagrant-omnibusの有効化
config.omnibus.chef_version = :latest
# Chef solo の設定
config.vm.provision :chef_solo do |chef|
# クックブックの配置場所
chef.cookbooks_path = ["./cookbooks","./site-cookbooks"]
#適用するクックブックの定義
chef.run_list = %w[
recipe[yum]
recipe[yum-epel]
recipe[nginx]
]
end
end
(7) 虛擬伺服器的啟動與配置
vagrant up --provision
确认
从浏览器访问192.168.33.10,确认nginx界面。
3. 安装PHP5.5(php、php-fpm、php-opcache)
(1) 通过knife-solo创建cookbook
bundle exec knife cookbook create php-env -o ./site-cookbooks
(2) 制作食谱
yum_repository 'remi' do
description 'Les RPM de Remi -Repository'
baseurl 'http://rpms.famillecollet.com/enterprise/6/remi/x86_64/'
gpgkey 'http://rpms.famillecollet.com/RPM-GPG-KEY-remi'
fastestmirror_enabled true
action :create
end
yum_repository 'remi-php55' do
description 'Les RPM de remi de PHP5.5 pour Enterprise Linux6'
baseurl 'http://rpms.famillecollet.com/enterprise/6/php55/$basearch/'
gpgkey 'http://rpms.famillecollet.com/RPM-GPG-KEY-remi'
fastestmirror_enabled true
action :create
end
%w{php php-fpm php-opcache}.each do |pkg|
package pkg do
action :install
notifies :restart, "service[php-fpm]"
end
end
service "php-fpm" do
action [:enable, :start]
end
(3) 修改Vagrantfile
chef.run_list = %w[
recipe[yum-epel]
recipe[nginx]
#以下行を追加
recipe[php-env]
]
(4)编辑Berksfile
请增加以下内容
cookbook "php-env", path:"./site-cookbooks/php-env"
(5) 执行berks vendor命令
bundle exec berks vendor ./cookbooks
执行供应计划
vagrant provision
(7) 确认在客户操作系统上已安装了PHP。
vagrant ssh
yum list installed | grep php
exit
3. 更改nginx的配置文件 (nginx与PHP-FPM协作)
创建模板
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events{
worker_connections 1024;
}
http{
include /etc/nginx/mime.types;
default_type application/octes-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "$http_referer"'
'"$http_user_agent" "http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server{
listen 80 default_server;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm index.php;
}
_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root /usr/share/nginx/html;
}
<% if node['nginx']['env'].include?("php") %>
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
<% end %>
}
}
将nginx的配置文件nginx.conf.erb添加到nginx的recipe中以使其生效。
请增加以下内容
template 'nginx.conf' do
path '/etc/nginx/nginx.conf'
source "nginx.conf.erb"
owner 'root'
group 'root'
mode '0644'
notifies :reload, "service[nginx]"
end
(3) 设定Attribute的初始值
default['nginx']['env'] = []
(4) 在Vagrant文件中添加 provisioning 配置。
在config.vm.provision下添加以下内容。
#Attributeの定義
chef.json = {
nginx: {
env: ["php"]
}
}
(5)执行berks vendor命令
bundle exec berks vendor ./cookbooks
(6) 执行配置(输出日志)
VAGRANT_LOG=info vagrant provision >&vagrant.log
(7)通过浏览器进行访问确认。
请在客户端创建以下文件
<?php
phpinfo();
?>
(8) 通过浏览器连接到192.168.33.10/index.php,并进行显示确认。
4. Ruby环境的建立
(1) 使用Knife Solo 创建 Cookbook。
bundle exec knife cookbook create ruby-env -o ./site-cookbooks
(2)编辑 Berksfile
请补充以下内容。
cookbook "ruby-env", path:"./site-cookbooks/ruby-env"
(3) 修改Vagrantfile
chef.run_list = %w[
recipe[yum]
recipe[yum-epel]
recipe[nginx]
recipe[php-env]
#以下行を追加
recipe[ruby-env]
]
(4) 制作食谱
创建配方(进行的步骤:安装rbenv,并使用rbenv的插件ruby-build安装ruby)
%w{gcc git openssl-devel sqlite-devel}.each do |pkg|
package pkg do
action :install
end
end
git "/home/#{node['ruby-env']['user']}/.rbenv" do
repository node["ruby-env"]["rbenv_url"]
action :sync
user node['ruby-env']['user']
group node['ruby-env']['group']
end
template ".bash_profile" do
source ".bash_profile.erb"
path "/home/#{node['ruby-env']['user']}/.bash_profile"
mode 0644
owner node['ruby-env']['user']
group node['ruby-env']['group']
not_if "grep rbenv ~/.bash_profile", :environment => {:'HOME' => "/home/#{node['ruby-env']['user']}"}
end
directory "/home/#{node['ruby-env']['user']}/.rbenv/plugins" do
owner node['ruby-env']['user']
group node['ruby-env']['group']
mode 0755
action :create
end
git "/home/#{node['ruby-env']['user']}/.rbenv/plugins/ruby-build" do
repository node["ruby-env"]["ruby-build_url"]
action :sync
user node['ruby-env']['user']
group node['ruby-env']['group']
end
execute "rbenv install #{node['ruby-env']['version']}" do
command "/home/#{node['ruby-env']['user']}/.rbenv/bin/rbenv install #{node['ruby-env']['version']}"
user node['ruby-env']['user']
group node['ruby-env']['group']
environment 'HOME' => "/home/#{node['ruby-env']['user']}"
not_if { File.exists?("/home/#{node['ruby-env']['user']}/.rbenv/versions/#{node['ruby-env']['version']}")}
end
(5) 设定 Attribute 的初始值
default['ruby-env']['user'] = "vagrant"
default['ruby-env']['group'] = "vagrant"
default['ruby-env']['version'] = "2.1.1"
default["ruby-env"]["rbenv_url"] = "https://github.com/sstephenson/rbenv"
default["ruby-env"]["ruby-build_url"] = "https://github.com/sstephenson/ruby-build"
使用模板来更改环境变量。
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashsrc ]; then
. ~/.bashsrc
fi
# User specific enviroment and startup programs
PATH=$PATH:$HOME/bin
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
(7)执行berks vendor命令。
bundle exec berks vendor ./cookbooks
(8) 执行供给
VAGRANT_LOG=info vagrant provision >&vagrant.log
确认在客户操作系统中安装了 Ruby 2.1.1。
vagrant ssh
rbenv versions
#2.1.1 と表示されればOK
exit
5. Unicorn的安装
使用Rails框架时,在AP服务器上安装Uicorn。
(1)修复ruby-env菜谱
请在以下内容中添加(Unicorn的安装)。
execute "rbenv global #{node['ruby-env']['version']}" do
command "/home/#{node['ruby-env']['user']}/.rbenv/bin/rbenv global #{node['ruby-env']['version']}"
user node['ruby-env']['user']
group node['ruby-env']['group']
environment 'HOME' => "/home/#{node['ruby-env']['user']}"
end
%w{rbenv-rehash bundler}.each do |gem|
execute "gem install #{gem}" do command "/home/#{node['ruby-env']['user']}/.rbenv/shims/gem install #{gem}"
user node['ruby-env']['user']
group node['ruby-env']['group']
environment 'HOME' => "/home/#{node['ruby-env'] ['user']}"
not_if "/home/#{node['ruby-env']['user']}/.rbenv/ shims/gem list | grep #{gem}"
end
end
(2) 更改nginx的默认配置(与Unicorn进行配合)
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events{
worker_connections 1024;
}
http{
include /etc/nginx/mime.types;
default_type application/octes-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "$http_referer"'
'"$http_user_agent" "http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
#以下Unicorn連携用の記述1/2
<% if node['nginx']['env'].include?("ruby") %>
upstream unicorn{
server unix:/tmp/unicorn.sock;
}
<% end %>
#ここまで
server{
listen 80 default_server;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm index.php;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root /usr/share/nginx/html;
}
<% if node['nginx']['env'].include?("php") %>
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
<% end %>
#以下Unicorn連携用の記述2/2
<% if node['nginx']['env'].include?("ruby") %>
location /unicorn{
rewrite ^/unicorn/(.+) /$1 break;
proxy_pass http://unicorn/$1;
}
<% end %>
#ここまで
}
}
(3)使用Attribute来设置初始值。
#変更前
chef.json = {
nginx: {
env: ["php"]
}
}
#変更後
chef.json = {
nginx: {
env: ["php","ruby"]
}
}
执行berks vendor命令
bundle exec berks vendor ./cookbooks
(5) 执行供应
VAGRANT_LOG=info vagrant provision >&vagrant.log
(6) 为了确认动作,创建一个RubyOnRails的项目
创建一个用于简单操作验证的Rails项目。
vagrant ssh
yum -y install libxml2 libxslt libxml2-devel libxslt-devel
gem install nokogiri -- --use-system-libraries
gem install rails -V
rails new test_unicorn --skip-bundle
cd test_unicorn
mkdir -p shared/{pids,log}
在客户端修改Gemfile,然后执行bundle install。
source 'https://rubygems.org'
gem 'rails', '4.0.4'
gem 'sqlite3'
gem 'sass-rails','~>4.0.2'
gem 'uglifier', '>=1.3.0'
gem 'coffee-rails','~>4.0.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder','~>1.2'
group :doc do
gem 'sdoc',require: false
end
gem 'unicorn'
安装依赖包
(7) 创建Unicorn的配置文件。
在客户端创建Unicorn配置文件。
listen "/tmp/unicorn.sock"
worker_processes 2 # this should be >= nr_cpus
pid "/home/vagrant/test_unicorn/shared/pids/unicorn.pid"
stderr_path "/home/vagrant/test_unicorn/shared/log/unicorn.log"
stdout_path "/home/vagrant/test_unicorn/shared/log/unicorn.log"
(8) 安装Node.js
创作一本食谱手册。
bundle exec knife cookbook create nodejs -o ./site-cookbooks
②修改Berksfile文件
请添加以下内容。
cookbook "nodejs",path:"./site-cookbooks/nodejs"
创建一个用于安装Node.js的烹饪书。
%w{gcc-c++}.each do |pkg|
package pkg do
action :install
end
end
remote_file "tmp/#{node['nodejs']['filename']}" do
source "#{node['nodejs']['remote_uri']}"
end
bash "install nodejs" do
user "root"
cwd "/tmp"
code <<-EOC
tar xvzf #{node['nodejs']['filename']}
cd #{node['nodejs']['dirname']}
make
make install
EOC
end
设定属性的初始值。
default['nodejs']['version'] = "v0.10.26"
default['nodejs']['dirname'] = "node-#{default['nodejs']['version']}"
default['nodejs']['filename'] = "#{default['nodejs']['dirname']}.tar.gz"
default['nodejs']['remote_uri'] = "http://nodejs.org/dist/#{default['nodejs']['version']}/#{default['nodejs']['filename']}"
将Vagrantfile的运行列表中添加
以下增加
recipe[nodejs]
执行berks vendor命令
bundle exec berks vendor ./cookbooks
进行供应
VAGRANT_LOG=info vagrant provision >&vagrant.log
(9) 确认独角兽的动作
一只独角兽开始运行。
vagrant ssh
cd test_unicorn
bundle exec unicorn -c config/unicorn.rb -D
使用浏览器访问 http://192.168.33.10/unicorn → 错误!!已发现nginx的上游出现错误,但无法解决。放弃故障排除,暂时搁置…
将问题留给作业,继续前进。
[error] 22931#0: *28 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.33.1, server: _, request: "GET /unicorn HTTP/1.1", upstream: "http://unix:/tmp/unicorn.sock:/", host: "192.168.33.10"
6. MySQL的安装
(1) 由knife-solo创建的烹饪书籍制作
bundle exec knife cookbook create mysql -o ./site-cookbooks
(2)将其添加到Berksfile中
cookbook "mysql" , path:"./site-cookbooks/mysql"
使用属性进行初始值设定。
default['mysql']['user'] = "vagrant"
default['mysql']['group'] = "vagrant"
default['mysql']['server_root_password'] = ""
(4)创建MySQL安装配方
あとで
(5) 编辑Vagrantfile
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.hostname = "guest"
config.vm.box = "centos6.5"
config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5-i386_chef-provisionerless.box"
config.vm.network "private_network", ip: "192.168.33.10"
# vagrant-omnibusの有効化
config.omnibus.chef_version = :latest
# Chef solo の設定
config.vm.provision :chef_solo do |chef|
# クックブックの配置場所
chef.cookbooks_path = ["./cookbooks","./site-cookbooks"]
# Attributeの定義
chef.json = {
#適当なパスワードに変えること
mysql: {
server_root_password: 'rootpass'
},
nginx: {
env: ["php","ruby"]
}
}
#適用するクックブックの定義
chef.run_list = %w[
recipe[yum]
recipe[yum-epel]
recipe[nginx]
recipe[php-env]
recipe[ruby-env]
recipe[nodejs]
recipe[mysql]
]
end
end
(6)创建MySQL配置文件
[mysqld]
log-bin
datadir=/var/lib/mysql/mysql.sock
user=mysql
#Disebling symbolic-links is recommended to prevent assorted security risks
sybolic-links=0
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
(7) 执行berks vendor命令
bundle exec berks vendor ./cookbooks
(8) 进行设置
VAGRANT_LOG=info vagrant provision >&vagrant.log
确认:使用mysql进行连接。
vagrant ssh
mysql -u root -p
show databases;
7. 将代码提交至 GitHub。
为了将来作为开发环境使用,我们将本次创建的cookbook等提交到GitHub。
GitHub->
GitHub->