きんちゃんシステムをChefで実装。

欽ちゃんシステムとは、自分が開発した投票システムです。


これをChefを使ってデプロイ出来るようにしたいと思います。

今回行うべきこと
PHP,Nginx,Mysqlのインストール
githubからコードをClone
・Nginxの設定
・データベースの作成

以上です。

下準備

まずcookbookの作成からです。今回はBreksfileのコマンドを利用します。
berks cookbook cookbook_kinchan
以下のファイルが作成されます。
32

これでおkです。

必要なパッケージをインストール

必要なBerksfileと同じ階層にはmetadata.rbが存在します。
ここに必要なパッケージ化されているcookbookを登録します。

デフォルトでは以下のようになっています。
Berksfile
site :opscode

metadata

metadata.rb
name             'cookbook_kinchan'
maintainer       'YOUR_NAME'
maintainer_email 'YOUR_EMAIL'
license          'All rights reserved'
description      'Installs/Configures myface'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version          '0.1.0'
Berksfileの方でmetadata.rbを読み込むように設定されているのが分かります。
metadata.rbを書き直します
name             'cookbook_kinchan'
maintainer       'Tomohisa Omagari'
maintainer_email 'ooma0301@gmail.com'
license          'All rights reserved'
description      'Installs/Configures cookbook_kinchan'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version          '0.1.0'

depends "mysql", "~> 3.0.0"
depends "nginx", "~> 1.8.0"
depends "php", "~> 1.2.4"
Berksfileと同じ階層にあるmetadata.rbはGemfileみたいなもので依存関係のcookbookを取得します。
しかし、取得できるのパッケージ化されたcookbookのみになりますので注意してください。
これに関してブログを書こうと思っています。

recipes/default.rb
include_recipe 'mysql::server'
include_recipe 'nginx'
include_recipe 'php'

Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.hostname = "cookbook-kinchan-berkshelf"
  config.vm.box = "test"
  config.vm.box_url = "https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box"
  config.vm.network :private_network, ip: "33.33.33.10"
  config.ssh.max_tries = 40
  config.ssh.timeout   = 120

  config.berkshelf.enabled = true

  config.vm.provision :chef_solo do |chef|
    chef.json = {
      mysql: {
        server_root_password: 'rootpass',
        server_debian_password: 'debpass',
        server_repl_password: 'replpass',
        bind_address: "127.0.0.1"
      }
    }

    chef.run_list = [
      "recipe[cookbook_kinchan::default]"
    ]
  end
end
これでうまくいきました。
ここまでやったことはnginx,mysql,phpのインストールのみです。

githubからコードをCloneする

githubからのコードのダウンロードを行います。
Chefのリソースには「git」があるためこちらを利用します。

Opscode_Resource_git
gitのリソースを利用するためにgitのパッケージでgitをインストールします。

metadata.rb 追記
depends "git", "~> 2.6.0"

attributes/default.rb
default['kinchan']['path'] = "/var/www/kif"

recipes/default.rb 追記
include_recipe 'git' 
git "#{node['kinchan']['path']}" do
repository "https://github.com/oomatomo/kif.git" action :sync end
これでおkです。

Nginxの設定

nginxの設定では先ほどcloneしたソースをnginxでアクセス出来るようにします。
行うこと
 ・iptablesの停止
 ・/etc/nginx/site-enabledの直下にcloneしたコードの設定ファイル

attributes/default.rb 追記
default['kinchan']['path'] = "/var/www/kif"

recipes/default.rb 追記
# setting nginx
template "#{node['nginx']['dir']}/sites-enabled/default" do
  source "default-site.erb"
end
service "iptables" do action :stop end 

template/default/default-site.rb 追記
server {
  listen   80;
  access_log  <%= node['nginx']['log_dir'] %>/localhost.access.log;
  location / {
    root   <%= node['kinchan']['path'] %>;
    index  index.html index.htm;
  }
}
これは仮想環境側では以下の通りになります。

/etc/nginx/sites-enabled/default
 server {
  listen   80;
  server_name  cookbook-kinchan-berkshelf;
  access_log  /var/log/nginx/localhost.access.log;
  location / {
    root   /var/www/kif;
    index  index.html index.htm;
  }
}
ではアクセスしてみます。
http://33.33.33.10/
49
nginxのデフォルトしか表示されません。

いろいろと探していたらStackOverFlowにありました。
how-to-disable-default-nginx-site-when-using-chef-and-vagrant

recipes/default.rb 変更
# setting nginx
nginx_site 'default' do
  enable false
end

##変更点 file "/etc/nginx/conf.d/default.conf" do action :delete end template "#{node['nginx']['dir']}/sites-enabled/default" do source 'default-site.erb' notifies :restart, 'service[nginx]' end ##ここまで
service "iptables" do action :stop end
 
12
表示されました。よかった。よかった。

データベースの設定 

最後にデータベースの設定をします。これをやらないと投票が出来ないからです。
mysqlのインストールはすでに完了してますがデータベースの作成は別のパッケージがあります。

それがdatabaseです。
こちらのREADMEを見ると。必要なのは以下の3つかなと思います
# Use mysql :socket key in connection info
mysql_connection_info = {
  :host => "localhost",
  :username => 'root',
  :password => node['mysql']['server_root_password'],
  :socket => '/db/mysql.sock'
}

mysql_database_user 'newrelic' do
  connection mysql_connection_info
  password newrelic_pass
  action :create
end

# same create commands, connection info as an external hash
mysql_database 'foo' do
  connection mysql_connection_info
  action :create
end
以下の通りでデータベースとユーザーが作成されます。
ついでにVagrantfileに直接書いていたchef.jsonをattributeに移して以下のようになりました。


attribute/default.rb
default['kinchan']['path'] = "/var/www/kif"
default['kinchan']['database']['host'] = '127.0.0.1'
default['kinchan']['database']['name'] = 'kif'
default['kinchan']['database']['user'] = 'kin'
default['kinchan']['database']['pass'] = 'kin'

default['mysql']['server_root_password'] = 'rootpass'
default['mysql']['server_debian_password'] = 'debpass'
default['mysql']['server_repl_password'] = 'replpass'
default['mysql']['bind_address'] = default['kinchan']['database']['host']
recipes/default.rb
include_recipe 'mysql::ruby'
include_recipe 'mysql::server'
include_recipe 'database::mysql'
# connect mysql
mysql_connection_info = {
  :host => node['kinchan']['database']['host'],
  :username => 'root',
  :password => node['mysql']['server_root_password']
}

# create database mysql_database node['kinchan']['database']['name'] do connection mysql_connection_info action :create end
# create mysql user mysql_database_user node['kinchan']['database']['user'] do connection mysql_connection_info password node['kinchan']['database']['pass'] database_name node['kinchan']['database']['name'] action [ :create, :grant ] end
次は実際のテーブルの作成を行います。
方法は以下の通りです。
 ①SQLのファイルをfiles/default/以下に作成する。
 ②chefでサーバにファイルを作成するコードを書く。
 ③mysqlで実行を行うchefを実装する。

①はすぐに終わると思います。
②cookbook_fileを利用します。
cookbook_fileはcookbookのfilesをサーバへおくことが出来ます。

cookbook_file [ 設置したいサーバのパス ] do
source [ cookbookのファイルパス ]
end

attribute/default.rb
default['kinchan']['database']['sql_file'] = '/tmp/kif.sql'
recipes/default.rb
cookbook_file node['kinchan']['database']['sql_file'] do
  source "kif.sql"
  owner "root"
  group "root"
  mode "0600"
end

③excuteを利用します
recipes/default.rb
execute "create mysql table" do
  command "mysql -h #{node['kinchan']['database']['host']} -u #{node['kinchan']['database']['user']} -p#{node['kinchan']['database']['pass']} -D #{node['kinchan']['database']['name']} < #{node['kinchan']['database']['sql_file']}"
  not_if  "mysql -h #{node['kinchan']['database']['host']} -u #{node['kinchan']['database']['user']} -p#{node['kinchan']['database']['pass']} -D #{node['kinchan']['database']['name']}  -e 'describe users;'"
end

よしこれで完了だ。動かしてみよう!!

動かない。
忘れてたphp-fpmが入ってない!!!

PHP-FPMの設定でNginxでPHPを動かす

NginxでPHPを動かすためにはPHP-FPMが必要になります。

attributes/default.rb 追加
default['php-fpm']['host'] = '127.0.0.1:9000'
default['php-fpm']['user'] = 'nginx'
default['php-fpm']['group'] = 'nginx'

templates/default/default-site.erb 変更
server {
  listen   80;
  access_log  <%= node['nginx']['log_dir'] %>/localhost.access.log;
  root   <%= node['kinchan']['path'] %>;

  location ~* \.php$ {
    fastcgi_pass  <%= node['php-fpm']['host'] %>;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    include     fastcgi_params;
  }
}

templates/default/php-fpm-www.conf.erb
[www]
listen  = <%= node['php-fpm']['host'] %>
user    = <%= node['php-fpm']['user'] %>
group   = <%= node['php-fpm']['group'] %>
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
recipes/default.rb

# setting php-fpm package 'php-fpm' do action [:install, :upgrade] end file "/etc/php-fpm.d/www.conf" do action :delete end template "/etc/php-fpm.d/www.conf" do mode 0644 source "php-fpm-www.conf.erb" end service 'php-fpm' do action :start end

これでうまく動きました。よかったです。

コードをきれいにする

ちょっと長いので別の記事で。


感想
Chefは面白いですね。またパッケージが豊富なため楽であることとパッケージ化されたコードを見ることでかなりの勉強になると感じました。あとはdatabase←のコードを見ていて思ったことが実際にデータベースを作成しているのはRubyで書いているような気がします。こんな書き方もあるんですね。

さて、新人研修や配属後の仕事で半年ほど自分の勉強を怠ったため知識が
半年分遅れている気がするので今後は自主的な勉強の時間の確保を頑張ります。

参考にしたページ

berkshelf-application-cookbooks

getting-started-writing-chef-cookbooks-the-berkshelf-way

include_recipeで他のレシピを呼び出せることに便利さを感じました。
今後も活用したいと思います。