タグ: Chef

cookbook-anyenvのCentOS7対応とグローバルインストール対応

koba04/cookbooks-anyenvはVagrant+Chefで利用した際、/home/vagrant以下にanyenvをインストールし、anyenvからrbenvなどの*envをインストール、さらにperl,ruby,nodejs,python,phpをインストールしてくれるものです。

レシピ内の依存パッケージがdebianのものになっていてCentOSではインストール時にエラーになり、またanyenvのインストール先を/opt/以下にしたかったため、いくつか変更しました。

変更点

  • CentOSにインストールできるように依存パッケージを追加
  • /home/vagrant以下にインストールするモードと/opt以下にインストールするモードを切り替えられるように
  • プログラミング言語処理系のインストールをせず、明示的に指定するようにした。(デフォルトでは*envはインストールするが、それらを使ってperlなどはインストールしない)

変更したもの: mistymagich/cookbooks-anyenv
デモ: mistymagich/cookbooks-anyenv-demo

nginx cookbookのpassengerレシピのCentOS7対応

nginxのcookbookである miketheman/nginx にはpassengerをモジュールとして追加できるレシピがあります。

そこで、CentOS7上で利用するために、attributeの node[nginx][repo_source]passengernode[‘nginx’][‘install_method’]package に設定してインストールしようとしたところ、

recipes/package.rbには

if platform_family?('rhel')
  if node['nginx']['repo_source'] == 'epel'
    include_recipe 'yum-epel'
  elsif node['nginx']['repo_source'] == 'nginx'
    include_recipe 'nginx::repo'
    package_install_opts = '--disablerepo=* --enablerepo=nginx'
  elsif node['nginx']['repo_source'].to_s.empty?
    log "node['nginx']['repo_source'] was not set, no additional yum repositories will be installed." do
      level :debug
    end
  else
    fail ArgumentError, "Unknown value '#{node['nginx']['repo_source']}' was passed to the nginx cookbook."
  end

としてrepo_source==passengerの選択肢はなく、

recipes/repo_passenger.rb には

case node['platform_family']
when 'rhel', 'fedora'

  log 'There is not official phusion passenger repo for redhat based systems.' do
    level :info
  end

とあり、パッケージリポジトリがない。

また、readme.mdには

Basic configuration to use the official Phusion Passenger repositories:
node['nginx']['repo_source'] – ‘passenger’
node['nginx']['package_name'] – ‘nginx-extras’
node['nginx']['passenger']['install_method'] – ‘package’

とあるが、nginx-extras はCentOSのパッケージにはないため、インストールができない。

一方、PHUSION Passengerの公式ドキュメントには

We provide an official Phusion Passenger YUM repository with packages for Red Hat Enterprise Linux and CentOS.

とあり、パッケージリポジトリが用意されている。そこで、これをrepo_passenger.rbに組み込み、passengerモジュールをインストールする

変更ファイル

  • recipes/package.rb
    プラットフォームファミリーがrhelの場合にrepo_source==’passenger’の選択肢を増やす
  • recipes/repo_passenger.rb
    RHEL,CentOS用のリポジトリファイルを/etc/yum.repos.dにおいて、キャッシュを更新する
  • attributes/passenger.rb
    /etc/nginx/conf.d/passenger.confにあるpassenger_rootの値が違っていたため、プラットフォームファミリーがrhelの場合の時だけ変更する

オリジナルからの変更点一覧: https://github.com/mistymagich/nginx/commit/6327617a066cb09e60703b8dac17fe4c746dc15b?diff=unified

miketheman/nginxをforkして、上記変更を適用したものをmistymagic/nginxに置きました。

またそれを使ってインストールしたpassengerに対して、PHUSION Passengerの公式ドキュメントにあるデモをVagrant+Chefの組み合わせで動かしたデモをmistymagich/nginx-passenger-on-CentOS7-demo
に置きました。

DBが存在しないときにDBを作成するChefレシピを作ったときの試行錯誤メモ

開発サーバ用のcookbookを作る際に、MySQLのDBが存在しないときにDBを作成したかったときの試行錯誤メモ

opscode-cookbooks/wordpressのDB作成部分を参考にというかほぼそのまま流用

使用したboxは

http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-i386-v20130731.box

やりたいこと

  1. MySQLのインストールと起動
  2. DBユーザの作成
  3. DBの作成
  4. テーブルの作成

1.MySQLのインストールと起動

package "mysql-server" do
    action :install
end

service "mysqld" do
    action [ :enable, :start ]
    supports :status => true, :restart => true, :reload => true
end

2.DBユーザの作成

GRANT文をまとめたgrants.sql.erbをtemplatesに格納しておき、/tmpにUPの後、mysqlコマンドで流し込む。

grants.sql.erbの中身

GRANT ALL ON <%= @database %>.* TO '<%= @user %>'@'localhost' IDENTIFIED BY '<%= @password %>';
GRANT ALL ON <%= @database %>.* TO '<%= @user %>'@'%' IDENTIFIED BY '<%= @password %>';
FLUSH PRIVILEGES;

レシピに追加

execute "mysql-create-user" do
    command "/usr/bin/mysql -u root --password=\"#{node['example']['db']['rootpass']}\"  < /tmp/grants.sql"
    action :nothing
end

template "/tmp/grants.sql" do
    owner "root"
    group "root"
    mode "0600"
    variables(
        :user     => node['example']['db']['user'],
        :password => node['example']['db']['pass'],
        :database => node['example']['db']['database']
    )
    notifies :run, "execute[mysql-create-user]", :immediately
end

executeリソースではaction :nothingで実行せず、templateリソースでnotifiesを使ってexecuteリソースを実行させる

3.DBの作成

Mysql::list_dbsを利用して、DBの存在チェックを行い、なければmysqladminコマンドでDBを作成する。

package "mysql-devel" do
    action :install
end.

chef_gem "mysql" do
    action :nothing
    subscribes :install, "package[mysql-devel]", :immediately
end

execute "mysql-create-database" do
    command "/usr/bin/mysqladmin -u root create #{node['example']['db']['database']}"
    not_if do
        require 'rubygems'
        Gem.clear_paths
        require 'mysql'
        m = Mysql.new(node['example']['db']['host'], "root", node['example']['db']['rootpass'])
        m.list_dbs.include?(node['example']['db']['database'])
    end
end

executeリソースのnot_ifにあるrubyプログラム部で、Mysqlライブラリを使うためには、chefを動かしているrubyに対して、インストールする必要がある。
そこで、chef_gemリソースを使う。

またgem install msyqlの際にmysqlのヘッダファイルが必要になるので、mysql-develもインストールする。

しかしそれだけだと、最初のpackage “mysql-devel”よりも先に、chef_gemリソースが実行されてしまうので、

================================================================================
Error executing action `install` on resource 'chef_gem[mysql]'
================================================================================

Gem::Installer::ExtensionBuildError
-----------------------------------
ERROR: Failed to build gem native extension.

というエラーになってしまう。
そこで、subscribesを使って、package mysql-develを実行した後に、即時実行するように指定する。

4.テーブルの作成

2.と同様にCREATE TABLES文をまとめたtables.sqlをfilesに格納しておき、/tmpにUPの後、mysqlコマンドで流し込む。
3.と同様にテーブルがなければ実行するようにしたが、tables.sqlがアップ済みなら実行されないので冗長かもしれない。

execute "mysql-create-tables" do
    command "/usr/bin/mysql -u root #{node['example']['db']['database']} < /tmp/tables.sql"
    action :nothing
    only_if do
        require 'rubygems'
        Gem.clear_paths
        require 'mysql'
        m = Mysql.new(node['example']['db']['host'], "root", node['example']['db']['rootpass'])
        begin
            m.select_db(node['example']['db']['database'])
            m.list_tables.empty?
        rescue Mysql::Error
            return false
        end
    end
end

cookbook_file "/tmp/tables.sql" do
    owner "root"
    group "root"
    mode "0600"
    notifies :run, "execute[mysql-create-tables]", :immediately
end

注釈

  • node[‘example’]~はattributesのdefault.rbで定義した値
    default['example']['db']['user'] = 'username'
    default['example']['db']['pass'] = 'password'
    default['example']['db']['database'] = 'database-name'
    default['example']['db']['host'] = 'localhost'
    default['example']['db']['rootpass'] = ''
    

    exampleのところはクックブック名に置き換える。
    rootpassが何もないのは、インストール後のデフォルトではrootのパスワードはないため

  • grants.sqlやtables.sqlは/tmpではなくてきちんとしたところにUPしたほうがいい
  • 同様のことは、opscode-cookbooks/databaseを使えばできる。

参考になったページ

自己認証局のルート証明書をCentOSのca-bundle.crtにインストールするレシピ

開発環境(CentOS)から、自己認証局で認証した証明書を使ったHTTPS領域のリポジトリにアクセスする必要があったので、chefのレシピを作りました。

自己認証局のルート証明書をCentOSのca-bundle.crtにインストールするレシピ

同様のことができそうなレシピ

Fulcrumのcookbookを作成

FulcrumPivotal Trackerのクローンを目標にしているプロジェクトです。

Pivotal Trackerに似ているツールFulcrum: プログラマの思索

malclocke/fulcrumのインストール方法を参考にcookbookを作りました。
さらにそれを使って、Vagrantとchef-soloでCentOS6.4(x86_64)上で動かしてみました。

1. 条件

  • Fulcrumの依存パッケージ(Qt 4.8)をインストールするためにゲストOSはCentOS 6.4の64bitのみ
  • FulcrumはRuby on Rails製で、今回使用するRubyはbox内にすでにある/opt/chef/embedded/binにあるruby(1.9.3p286)です。
  • 検証用として作成したので、実行時の環境(RAILS_ENV)はdevelopmentでDBはSQLiteを使い、実体はdb/development.sqlite3となります。

2. 必要なもの

  • VirtualBoxとVagrantとchef-solo,knife-solo一式
    入門Chef Solo – Infrastructure as Codeなどを参考に
  • Berkshell
    RubyGemsのbundlerのようなもの
    cookbookを作成するに当り、yum cookbookが必要だったので、依存管理のため

3. ファイルの構成

chef-repo/ - cookbook置き場(A)
    Berksfile
    cookbooks/
    data_bags/
    nodes/
    roles/
    site-cookbooks/
fulcrum/ - ゲストOS(B)
    Vagrantfile

chef-repo(A)はknife soloを使用して

knife solo init chef-repo

としたときのもの

fulcrum(B)は
ディレクトリを作成(mkdir fulcrum)して、

vagrant init

とした状態

4. cookbookの作成

  1. (A)に移動
    cd chef-repo
    
  2. Berksfileを編集して
    cookbook 'yum'
    

    を追記。新規作成する場合は

    site :opscode
    cookbook 'yum'
    
  3. Berkshellを使って依存cookbookをダウンロード
    berks install --path cookbooks
    
  4. Fulcrum用cookbookを新規作成
    knife cookbook create chef-fulcrum -o site-cookbooks
    
  5. metadata.rbを編集して依存cookbookを列挙する
    cd site-cookbooks/chef-fulcrum
    
    depends 'yum'
    
  6. recipes/default.rbを編集
    長いのでこちら

5. Vagrantを使ってゲストOSを起動する

  1. (B)に移動
    cd ../../../fulcrum
    
  2. Vagrantfileを編集
    # Centos 6.4 64bit版のbox
    config.vm.box = "CentOS-6.4-x86_64-ja"
    config.vm.box_url = "https://dl.dropboxusercontent.com/u/428597/vagrant_boxes/CentOS-6.4-x86_64-ja.box"
    
    # ホストOSからアクセスするためにIPをセット(IPは各々の環境に応じて変更する)
    config.vm.network :private_network, ip: "192.168.33.105"
    
    # chef soloのprovitionを有効にして、cookbookのパスを設定、run_listにfulcrum cookbookを設定
    config.vm.provision :chef_solo do |chef|
    chef.cookbooks_path = ["../chef-repo/cookbooks", "../chef-repo/site-cookbooks"]
    chef.roles_path = "../chef-repo/roles"
    chef.data_bags_path = "../chef-repo/data_bags"
    
    chef.run_list = [
        "recipe[chef-fulcrum]"
    ]
    end
    
  3. ゲストOS起動
    vagrant up
    
  4. upし終わったら、http://192.168.33.105:3000でアクセス
    ユーザID:test@example.com、パスワード:testpassでログイン
ユーザID:test@example.com、パスワード:testpassでログイン

ユーザID:test@example.com、パスワード:testpassでログイン

Fulcrumログイン後の画面

Fulcrumログイン後の画面

サンプルプロジェクトの中身

サンプルプロジェクトの中身

6. 作成したcookbookをgithubにUPしました。

mistymagich/chef-fulcrum

6.1 使用方法

  1. 3.の状態で(A)に移動し、Berksfileを編集
    site :opscode
    
    cookbook 'chef-fulcrum', git: 'https://github.com/mistymagich/chef-fulcrum.git'
    
  2. Berkshellを使ってcookbookをダウンロード
    berks install --path cookbooks
    
  3. あとは4. は不要で、5. の手順でvagrant up

boxのダウンロード後、ゲストOS起動からURLでアクセスできるようになるまで、Vagrant起動時の表示では794sec(約13分)、実際には19分程度かかりました。(ホストOS WindowsXP / CPU Core2 Quad Q9550 / Memory 3.5GB)