Vagrant + Chef Solo で Movable Type が動く LAMP 環境を作ってみた 準備編で Vagrant の VM を Chef で管理できる状態になりましたので、レシピを調合するにあたって工夫した点をまとめてみます。
なお、完成した Cookbook を GitHub で公開しました。
chef cookbooks for CentOS:
https://github.com/dreamseeker/chef-cookbooks-centos
はじめて作ったこともあり「こんな感じでいいのか?」という疑問は残りつつ、BUN でも理解できるくらいのシンプルな構成になっていますので、ご参考程度ということで。
Cookbook の構成
おそらく一般的な手法だと思うのですが、タスクごとに Cookbook を分けてみました。
あとで Cookbook を追加し run_list を調整すれば、apache を nginx に切り替えたりも容易。
Grunt や gulp.js などのタスクランナーツールと同じようなイメージですね。
chef-cookbooks-centos/
├── apache/
│ ├── attributes/
│ │ └── default.rb # apache 関連の初期値
│ ├── recipes/
│ │ ├── default.rb # レシビ : apache のインストール・設定
│ │ └── vhosts.rb # レシビ : バーチャルホスト用
│ └── templates/
│ └── default/
│ ├── hosts.erb # /etc/hosts
│ ├── httpd-vhosts.conf.erb # /etc/httpd/conf.d/httpd-vhosts.conf
│ ├── httpd.conf.erb # /etc/httpd/conf/httpd.conf
│ └── phpinfo.php.erb # /var/www/html/test.domain/phpinfo.php
├── iptables/
│ ├── recipes/
│ │ └── default.rb # レシビ : iptables の設定
│ └── templates/
│ └── default/
│ └── iptables.erb # /etc/sysconfig/iptables
├── mysqld/
│ ├── attributes/
│ │ └── default.rb # MySQL 関連の初期値
│ ├── recipes/
│ │ └── default.rb # レシビ : mysql のインストール・設定
│ └── templates/
│ └── default/
│ └── my.cnf.erb # /etc/my.cnf
├── perl_modules/
│ ├── attributes/
│ │ └── default.rb # Perl モジュール関連の初期値
│ └── recipes/
│ └── default.rb # レシビ : Perl モジュールのインストール
├── php/
│ ├── attributes/
│ │ └── default.rb # php 関連の初期値
│ ├── recipes/
│ │ └── default.rb # レシビ : php のインストール・設定
│ └── templates/
│ └── default/
│ └── php.ini.erb # /etc/php.ini
└── yum/
├── attributes/
│ └── default.rb # yum 関連の初期値
└── recipes/
├── add_repo.rb # レシビ : epel,rpmforge,remi リポジトリの追加
├── default.rb # レシビ : 空
└── update.rb # レシビ : yum のアップデート
なお、iptables の設定は下記を参考にさせていただきました。
iptables (ファイアーウォール)の設定 〜 CentOS6 | EasyRamble:
http://easyramble.com/iptables-setting.html
Vagrant の VM に適用する前提なので、公開サーバの場合は改めて調べてみようと思います。
Attributes で パッケージを指定
タスクごとにインストールするパッケージは、attributes/default.rb に定義。
# apache/attributes/default.rb
default['apache'][:packages] = %w[
httpd
httpd-devel
mod_ssl
]
この配列を使って recipes/default.rb 内でループ処理します。
# apache/recipes/default.rb
node['apache']['packages'].each do |pkg|
package "#{pkg}" do
action :install
notifies :restart, 'service[httpd]', :delayed
end
end
後述する JSON ファイルで override_attributes を明示すれば上書きできるので、サーバごとにインストールするパッケージを調整するのも簡単ですね。
初回のみ処理するタスク
yum リポジトリの追加は、/etc/yum.repos.d/remi.repo が存在しない場合のみ実行する形に。
# yum/recipes/add_repo.rb
if !File.exists?('/etc/yum.repos.d/remi.repo')
bash 'add_epel' do
user 'root'
code <<-EOC
rpm -ivh "#{node['yum']['repo']['epel']}"
sed -i -e "s/enabled *= *1/enabled=0/g" /etc/yum.repos.d/epel.repo
EOC
end
end
MySQL インストール直後に実行していた mysql_secure_install コマンドと同等の処理では、only_if で root ユーザのパスワードがセットされていない場合のみに制限しています。
# mysql/recipes/default.rb
script 'mysql_secure_install' do
interpreter 'bash'
user 'root'
only_if "mysql -u root -e 'show databases'"
code <<-EOC
mysqladmin -u root password "#{node['mysqld']['root_pwd']}"
mysql -u root -p#{node['mysqld']['root_pwd']} -e "SET PASSWORD FOR root@localhost=PASSWORD('#{node['mysqld']['root_pwd']}');"
mysql -u root -p#{node['mysqld']['root_pwd']} -e "SET PASSWORD FOR root@'127.0.0.1'=PASSWORD('#{node['mysqld']['root_pwd']}');"
mysql -u root -p#{node['mysqld']['root_pwd']} -e "DELETE FROM mysql.user WHERE User='';"
mysql -u root -p#{node['mysqld']['root_pwd']} -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1');"
mysql -u root -p#{node['mysqld']['root_pwd']} -e "DROP DATABASE test;"
mysql -u root -p#{node['mysqld']['root_pwd']} -e "FLUSH PRIVILEGES;"
EOC
end
なお、このコードは下記を参考にさせていただきました。
chefでmysql-5.6インストールしようとしたら苦労した話 - blog.youyo.info:
http://blog.youyo.info/blog/2013/07/11/chef-mysql56/
#{node['mysqld']['root_pwd']} には mysql/attributes/default.rb へ定義した値が代入されますが、本来は data_bag で暗号化した方がよさそうですね。
Cookbook を実行してみる
前回の準備編で作成した chef_repo/site-cookbooks へ GitHub で公開している apache と同階層の Cookbook を一式セットしたら、chef_repo/roles へ lamp.json を作成します。
あえてロールにセットするのは、個人的な好みです(。-_-。)
{
"name": "lamp",
"chef_type": "role",
"json_class": "Chef::Role",
"run_list": [
"recipe[yum::add_repo]",
"recipe[apache]",
"recipe[apache::vhosts]",
"recipe[iptables]",
"recipe[php]",
"recipe[mysqld]",
"recipe[perl_modules]",
"recipe[yum::update]"
],
"override_attributes": {
"mysqld": {
"root_pwd": "vagrant"
},
"perl_modules": {
"packages": [
"perl-core",
"perl-Archive-Tar"
]
}
}
}
override_attributes には、それぞれの Cookbook の attributes/default.rb で定義された値のうち、変更したいものだけを記述したら、続けて chef_repo/nodes/localhost.json を作成します。
{
"run_list": [
"role[lamp]"
],
"automatic": {
"ipaddress": "localhost"
}
}
ここまでできれば、あとはナイフを投げるだけ(。-_-。)
$ knife solo cook localhost
自動処理が終われば Vagrant の VM 上で Movable Type を動かすことができます。
php-gd や php-mysqlnd なども含めているので、WordPress も問題ないハズ。。。
Vagrantfile のサンプル
vagrant up または vagrant provision の際に実行する場合は、Vagrantfile を調整します。
config.vm.provision :chef_solo do |chef|
# ssl_verify_mode の設定
chef.custom_config_path = "Vagrantfile.chef"
# cookbook と role のパスを設定
chef.cookbooks_path = ["./chef_repo/cookbooks", "./chef_repo/site-cookbooks"]
chef.roles_path = "./chef_repo/roles"
# ロールの追加
chef.add_role("lamp")
end
やってみて
準備編の設定が終わっている状態から vagrant up したところ、5分も待たずにセットアップが終わりました。
確かに、これは鼻血が出ますね w
なお、今回作成した Cookbook では Perl モジュールを yum でインストールしているのですが、remi などのリポジトリを指定してもエラーになってしまう Cache::File のみ除いてあります。
PSGI 化についても手順は判っているので、perlbrew や cpanminus への対応とあわせて、おいおいアップデートできるといいのですが・・・先は長そうですね(。-_-。)