オープンソースこねこね

Webプログラミングなどについてあれこれ。

chef-soloとgitでCentOSの環境構築をらくらく自動化

世の中テクノロジーはどんどん進化していてもうびっくりです。

CentOSでWebアプリのサーバ環境を作る場合、yumコマンドを実行して、適宜設定ファイルを修正して、デーモンなどを再起動するってなことを毎回やっていたのですが、今はchefによるサーバ構築自動化ができるわけです。

そのchefを利用するにはRubyをインストールしてgemからchefのパッケージをインストールする必要があったのですが、これも最近Omunibusというコマンド一発でできる仕組みができて更にらくちんになりました。

というわけで、gitリポジトリにchefのcookbookを置いて管理し、これをセットアップするサーバーにpull、chef-soloを実行して、環境構築を自動化してしまう手順のサンプルを以下にまとめてみました。

https://github.com/kohkimakimoto/chef-for-centos

chefサーバも不要で、なんとOSインストール後たった6ステップでセットアップがすんでしまいます。

構成について

さて上記のchefリポジトリですが、構成を単純にするため、設定するサーバ(ノード)一台ごとにchefのroleを個別に定義するようにしています。roleは本来いくつかのwebサーバとかdbサーバとか、複数あって同じ役割をもつサーバの共通定義を記述するのに使うようですが、あえてそうしていません。

加えて、chef-soloをラップしたシェルスクリプトを書いて、「ホスト名と同じ名前のroleでchef-soloを実行する」ようにしています。こんな感じのスクリプトです。

#!/bin/bash

#
#   Execute chef-solo with auto generated run_list that is relied on hostname.
#

CMD_NAME=${0##*/}
CMD_DIR=$(cd $(dirname $0);pwd)
REPO_DIR=$(cd ${CMD_DIR}/..;pwd)

HN=${HOSTNAME%%.*}
LANG=en
FILE_DATE=`date +%y%m%d%H%M%S%N`
RUN_LIST_FILE="/tmp/chef_solo_run_list.${FILE_DATE}.json"

#
# Update chef reopository directory using git pull.
#
cd ${REPO_DIR}
git pull

#
# Generate run_list json file using hostname. and then execute chef-solo command.
#
echo "{\"run_list\":[\"role[${HN}]\"]}" > ${RUN_LIST_FILE}
echo "Generated run list file. [${RUN_LIST_FILE}]"

chef-solo -c ${REPO_DIR}/config/solo.rb -j ${RUN_LIST_FILE}

/bin/rm -f ${RUN_LIST_FILE}
echo "Deleted run list file. [${RUN_LIST_FILE}]"

この構成のメリットは、サーバごとに異なる設定があるとき、それをroleに柔軟に記述できるところです。新たにサーバーの追加があったときも、roleファイルを一個追加するだけで、すぐに対応できます。もちろんサーバ台数が100台とかあるとその数だけroleファイルが増えてしまって煩雑になるとはおもうけれど、現実としてそんな台数のサーバを管理する立場に私はない(あっても10数台かな)ので、これで十分なのです。

また、ホスト名と同じ名前のroleでchef-soloを実行するという縛りがあるので、上記のラッパースクリプトを利用する限り、間違ってほかのホスト用の設定でchef-soloを実行してしまうのも避けられます。

本来のroleの使い方である複数のサーバ間の共通的な定義は別途下記のようなbese.rbという共通部分だけ切り出したroleをつくって、サーバ個別のroleの中から読み込むように設定することで対応できます。

base.rb - 複数サーバ共通定義用role

name "base"
description ""
run_list(
  "recipe[common]",
  "recipe[selinux]",
  "recipe[yum]",
  "recipe[iptables]",
  "recipe[httpd]",
  "recipe[php]",
  "recipe[mysql]"
)

default_attributes({
  :role                => "base",
})

web.rb - サーバ個別のrole

name "web"
description ""
run_list(
  "role[base]"
)

default_attributes({
  :role                => "web",
})

サーバごとに異なる設定(たとえばホストのIPアドレスとかを指定するときなど)はサーバ個別のrole内のdefault_attributesで設定しておけば、recipeやtemplateでnodeという変数から参照、利用できます。

サンプルの実行手順

https://github.com/kohkimakimoto/chef-for-centos

  1. サーバのホスト名を修正する。

     # vi /etc/sysconfig/network
    

    以下のようにする。今回のサンプルではwebというホスト名固定。

     NETWORKING=yes
     HOSTNAME=web
    
  2. サーバを再起動して、ホスト名を反映させる。

     # reboot
    
  3. Omnibusを使ってchefをインストール。以下のコマンドを実行するだけでOK。

     # curl -L https://www.opscode.com/chef/install.sh | bash
    

    なおOmunibuseについてはこちらの記事を参考にしてください。http://www.opscode.com/blog/2012/06/29/omnibus-chef-packaging/.

  4. gitをインストールする

     # yum install -y git
    
  5. サンプルのchefリポジトリをgithubからcloneする

     # git clone https://github.com/kohkimakimoto/chef-for-centos.git /var/chef
    
  6. chef-soloを以下のラッパースクリプトから実行する。

     # sh /var/chef/bin/chef-host
    

以上で終わりです。このサンプルではApache、MySQL、PHPとよく使う野良リポジトリ(remi,epel)のセットアップが完了します。