Vagrant + Chef Solo で Movable Type が動く LAMP 環境を作ってみた レシピ編

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 への対応とあわせて、おいおいアップデートできるといいのですが・・・先は長そうですね(。-_-。)