サーバー設定ツール「Chef」の概要と基礎的な使い方 3ページ

chef-soloコマンド用の設定ファイルを作成する

 作成したCookbookは、chef-soloコマンドで実行できる。chef-soloコマンドの挙動はコマンドラインオプションのほか、設定ファイルで指定でき、そのパスはデフォルトでは/etc/chef/solo.rbファイルとなっている。このファイルは自動的には作成されないので、手動で作成しておく必要がある。

# mkdir /etc/chef
# vi /etc/chef/solo.rb

 このファイルの内容についてはsolo.rbに関するドキュメントを参照してほしいが、今回はCookbookを格納しているディレクトリの指定のみを行うこととする。たとえば「/home/hylom/chef-repo/cookbooks」というディレクトリ内にCookbookを格納している場合、以下のように記述すれば良い。

cookbook_path ["/home/hylom/chef-repo/cookbooks"]

 solo.rbファイルを作成したら、chef-soloコマンドでCookbookを実行してみよう。なお、実行にはroot権限が必要だ。実行するRecipe名は「-o」オプションで指定できる。Recipe名は「<Cookbook名>::<Recipe名>」という形で指定する。Recipe名を省略してCookbook名のみを指定することも可能だ。その場合、recipesディレクトリ内の「default.rb」というRecipeが実行される。

 以下の例は、先ほど作成したsetup-userのdefault.rbというRecipeを実行したものだ。

# chef-solo -o setup-user
Starting Chef Client, version 11.6.0
Compiling Cookbooks...
Converging 2 resources
Recipe: setup-user::default
  * group[taro] action create
    - create group[taro]

  * user[taro] action create
    - create user user[taro]

Chef Client finished, 2 resources updated

 出力結果からは、Recipeファイルに記述したとおりにグループとユーザーが作成されていることが分かる。ちなみに、同じCookbookを再度実行すると、次のようにメッセージが表示される。

# chef-solo -o setup-user
Starting Chef Client, version 11.6.0
Compiling Cookbooks...
Converging 3 resources
Recipe: setup-user::default
  * group[taro] action create (up to date)
  * user[taro] action create
    * You must have ruby-shadow installed for password support!

 ここでは「ruby-shadow」が必要と表示されているが、gemコマンドでこのパッケージをインストールすればこのメッセージは表示されなくなる。

# gem install ruby-shadow

実行するRecipeを指定する

 先の例では-oオプションで実行するRecipeを指定したが、通常は実行するRecipeをファイルに記述し、そのファイルをコマンドラインオプションで指定するのが一般的だ。実行するRecipe一覧はJSON形式で記述し、chef-soloコマンドの-jオプションでそのファイルを指定する。

 たとえば、先の「setup-user」Recipeを実行する場合、JSONファイルは以下のようになる。

{
  "run_list": [
    "recipe[setup-user]"
  ]
}

 /etc/chef/solo.jsonというファイルにこれを記述した場合、次のようにしてchef-soloを実行する。

# chef-solo -j /etc/chef/solo.json

 なお、ここで指定したJSONファイルではRecipeやCookbookに与えるパラメータ(Attribute)を記述することも可能だ。こちらについては後述する。

パッケージをインストールさせる

 続いては、Chefのデフォルトで用意されているリソースタイプを使ったRecipeをいくつか紹介しておこう。まず、yum経由でパッケージをインストールするには「yum_package」リソースタイプを利用する。

yum_package <パッケージ名> do
  action :install
end

 たとえば「sudo」パッケージをyumでインストールするRecipeは以下のようになる。

yum_package "sudo" do
  action :install
end

 また、RPMファイルからパッケージをインストールするには、「rpm_package」リソースタイプを利用する。

rpm_package <パッケージ名> do
  source <RPMファイルのパス名>
  action :install
end

 ただし、rpm_packageリソースタイプではローカルにあるファイルしかインストールできない。リモートにあるRPMファイルをインストールしたい場合、リモートからファイルをダウンロードする「remote_file」リソースタイプと組み合わせて利用する必要がある。

remote_file <ダウンロードしたファイルの保存先パス名> do
  source <ダウンロードするURL>
end

 以下のRecipeは、「http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm」というURLで公開されているRPMファイルをダウンロードしてインストールするものだ。

remote_file "#{Chef::Config[:file_cache_path]}/epel-release-6-8.noarch.rpm" do
  source "http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm"
  not_if "rpm -qa | grep -q '^epel-release'""
  action :create
  notifies :install, "rpm_package[epel-release]", :immediately
end

rpm_package "epel-release" do
  source "#{Chef::Config[:file_cache_path]}/epel-release-6-8.noarch.rpm"
  action :nothing
end

 「#{Chef::Config[:file_cache_path]}」はChefの設定データベース内で「file_cache_path」というキーに格納されている値を参照するという意味だ。ここにはファイルキャッシュとして使用するディレクトリのパス名が格納されている。また、「not_if」は指定した文字列を実行し、その結果が真でなければ処理を実行するよう指定するものだ。ここでは「epel-release」パッケージがインストールされていなければ処理を実行するよう指定している。さらに、「notifies」属性はそのリソースに対する処理が実行された際に、続けて実行するリソースを指定するものだ。ここでは「rpm_package」型の「epel-release」というリソースについて、即座に(immediately)インストールを実行するよう指定している。

 「epel-release」リソースのactionに「:nothing」が指定されていることも注目したい。これが指定されたリソースは通常何の処理も実行されない。つまり、このRecipeはepel-releaseパッケージがインストールされていない場合にのみパッケージをダウンロードしてインストールする、という内容になる。

テンプレートを使う

 次は、設定ファイルを指定したディレクトリに作成するRecipeを紹介しよう。内容としては、httpdパッケージをインストールしてhttpdサービスを起動し、/var/www/testというディレクトリと/etc/httpd/conf.d/mysite.confという設定ファイルを作成する、というものだ。

 設定ファイルを作成する場合、そのひな形はtemplates/defaultディレクトリ内に格納する。また、テンプレートファイルはeRuby形式(拡張子は.erb)で記述する。今回の例では、templates/default/mysite.conf.erbとして設定ファイルを作成する。

NameVirtualHost *:8000
<VirtualHost *:8000>
        ServerName <%= @hostname %>
        DocumentRoot /var/www/test
        ErrorLog logs/test-error_log
        CustomLog logs/test-access_log common
</VirtualHost>

 eRuby形式についての詳細は割愛するが、「<%」と「%>」 で囲まれた部分がRubyコードとして実行され、また「<%=」と「%>」で囲まれた部分はその実行結果に置き換えられる(「<% print」と「%>」で囲んだものと等価)。つまり、このテンプレートファイルでは「<%= @hostname %>」の部分がhostname変数の値に置き換えられる、ということになる。

 この設定ファイルを利用するRecipeは次のようになる。

# httpdパッケージをインストールする
yum_package "httpd" do
  action :install
end

# httpdサービスを起動する
service "httpd" do
  action :start
end

# /var/www/testディレクトリを作成する
directory "/var/www/test" do
  owner "root"
  group "root"
  mode 0755
  action :create
end

# mysite.conf.erbというテンプレートから
# /etc/httpd/conf.d/mysite.confという設定ファイルを作成する
template "/etc/httpd/conf.d/mysite.conf" do
  source "mysite.conf.erb"
  owner "root"
  group "root"
  mode 0644
  action :create
  variables({ # テンプレートに与える変数の値を指定する
    :hostname => `/bin/hostname`.chomp
  })
end

 設定内容はコメントに記載したとおりだが、注目したいのが「/etc/httpd/conf.d/mysite.conf」リソースでの「variables」属性だ。ここではテンプレートに与えるhostname変数の値を指定しているのだが、Rubyの「`」(バッククォート)構文を使って/bin/hostnameコマンドを実行し、その結果の行末の改行を取り除いたものを変数に格納している。このように、Rubyの機能を利用してRecipeを記述できるのがChefの特徴の1つだ。

コマンドを実行する

 「execute」リソースタイプでは、特定のコマンドを実行するリソースを作成できる。実行するコマンドは「command」属性で指定する。また、actionには「:run」もしくは「:nothing」が指定できる。

execute <リソース名> do
  command <実行するコマンド>
  action <実行するアクション>
end

 たとえば、sedコマンドを使って「/etc/yum.repos.d/epel.repo」という設定ファイルを編集するようなRecipeは、以下のように記述できる。

execute 'epel.repo' do
  command "/bin/sed -i -e 's/^enabled\s*=\s*1/enabled=0/g' /etc/yum.repos.d/epel.repo"
  action :nothing
  subscribes :run, "rpm_package[epel-release]", :immediately
end

 ここで指定されている「subscribes」属性は、指定したリソースが実行された後に特定のactionを実行する、ということを指定するものだ。この例の場合、「rpm_package[epel-release]」というリソースが実行された場合、即座にこのリソースに対し「:run」というアクションを実行する、ということを意味している。