Chef-solo + Capistranoで簡単サーバ構成管理
サーバに対して何台も同じような設定をしていると、そんな刺身にたんぽぽのせるような仕事やってられるかー!となりますよね?特に最近だとクラウドや仮想化技術が身近になってきたので、環境をイメージコピーで構築する手法も増えているのではないかと思いますが、一方で、ハードやOSレベルでも技術が進化していくので、OSより上のレイヤー(ミドルウェアやアプリケーション)とOS以下のレイヤー(ハードウェアやOS)を粗結合にしておくことが重要だと思います。
OSより上のレイヤーのシステムの構成管理を自動化ツールとしてPuppetが有名でしたが、最近だとChefがRubyでスクリプトが書けて便利です。
ChefはChef-server, Chef-client, Chef-solo という3つの構成に分かれています。しかしChef-serverとChef-clientを利用した構成は構成がやや複雑になるので、中央で各サーバに対して指示を出す部分をCapistranoで行い、各サーバにはChef-soloを導入して各サーバ内でChef-soloを実行するという極力シンプルな構成にすることにしました。Chefが実行するスクリプトをRecipeと呼びますが今回はそれらのコードもGit上で管理する前提としています。構築の手順は以下の通り。
中央サーバにCapistranoをインストール
$ gem install capistrano
構成管理の対象サーバの設定
環境構築の自動化を目指しているので、これらのサーバはOSがインストールばかりのまっさらな環境であることを想定しています
- ネットワーク / sshの設定
中央サーバからsshの公開鍵認証でアクセスできるようにします。/etc/sysconfig/network-scriptsや~/.ssh/authorized_keysなど適宜設定します。
- Rubyとgitのインストール
$ wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p125.tar.gz $ ./configure $ make $ make install $ yum install git
ここまでは、タンポポのせ作業ですが、我慢しましょう(^^;
Capistranoの設定
- deploy.rbの準備
deploy.rbの設定例です。
role :web, "web001-desk001" # Your HTTP server, Apache/etc role :app, "web001-desk001" # This may be the same as your `Web` server role :db, "db001-desk001", :primary => true # This is where Rails migrations will run role :db, "db001-desk001" # Install Application and Middleware using Chef. (This task has to be execute by root user.) set :chef_repo_path, '/usr/local/src/chef-repo' namespace :chef do task :init do sync_chef_repo install_chef_solo end task :sync_chef_repo do run "git clone [email protected]:twodollarz/chef-repo.git #{chef_repo_path}" end task :install_chef_solo do run "gem install chef" end task :default do chef_solo_base chef_solo_web chef_solo_db end task :chef_solo_base do run "chef-solo -j #{chef_repo_path}/config/base.json -c #{chef_repo_path}/solo.rb" end task :chef_solo_web, :roles => [ :web ] do run "chef-solo -j #{chef_repo_path}/config/web.json -c #{chef_repo_path}/solo.rb" end task :chef_solo_db, :roles => [ :db ] do run "chef-solo -j #{chef_repo_path}/config/db.json -c #{chef_repo_path}/solo.rb" end end
- ssh_configの活用
role :web, "web001-desk001"
のように簡単にsshの接続先を指定していますがsshの細かい設定(接続ユーザや利用する鍵など)はdeploy.rbの方に細かく指定するのではなくssh_configで設定すると管理が楽になります。
- role
webサーバやDBサーバなど、インストール内容が異なるサーバ群をroleとして管理します。このあたりは普通のデプロイと同じです。
- 初期化処理(chef:init)
サーバの初期設定時に1回だけ実行することを想定しています。
$ cap chef:init
初期化処理では、chefのrecipeをgit cloneしています(ここではrecipeの詳細について説明しません)。その後chef-soloをgemを使ってインストールします。このようにchefのインストール自体も自動化しています。
- 通常処理(chef)
アプリケーションやミドルウェアのインストールを行います。
$ cap chef
実行するのはこれだけ。
deploy.rbの中で、以下のように全サーバに共通のtask(chef_solo_base)とroleごとのtask(chef_solo_web, chef_solo_db)を実行しています。
task :default do chef_solo_base chef_solo_web chef_solo_db end
例えばchef_solo_baseを実行するときに利用されるbase.jsonは以下のような内容になっています。このように各roleごとにインストールパッケージを選ぶことが出来るようになっています。
{ "run_list": [ "recipe[build-essential]", "recipe[emacs]", "recipe[git]", "recipe[screen]", "recipe[tmux]", "recipe[vim]" ] }
ここまで枠組みを準備してしまえば、あとはRoleにサーバを追加していくだけで、Chefがタンポポをのせてくれるようになります。結果、サーバの追加と設定まで今まで半日かかっていた作業が実作業は3分ほどでできるようになりました。