目次

STEP1

さて、今回のテーマは最近何かとAnsibleに話題をさらわれがちな、サーバーの構成管理ツールChefです。以前紹介させていただいたAnsibleと同じく、サーバーセットアップを自動化してくれます。

ChefとAnsibleは利用方法が異なりますが、基本的な概念は似たようなものです。構成管理ツールに関する説明やAnsibleの概念は「構成管理ツールAnsibleを使ってみよう」の記事にて紹介していますので、本記事を読んで頂く前に一読していただくことをオススメします。

まずはChefの利用方法を説明する前にAnsibleとChefの違いについて軽く触れておきます。個人的主観が含まれますが、ざっくり比較すると下記違いがあります。

■Ansible

 ・ Python製

 ・ 管理対象サーバーの構成をPlaybookという仕組みで管理し、YAMLフォーマットで記述

 ・ Playbookの記述が簡潔

 ・ 管理対象サーバーへのパッケージインストールが不要

 ・ サーバー管理規模によらず利用形態は1つだけ。操作方法は簡潔だが大規模運用を行う場合は一工夫必要。

■Chef

 ・ Ruby(+Erlang)製

 ・ 管理対象サーバーの構成をCookbookという仕組みで管理し、Rubyスクリプトで記述

 ・ Cookbookの記述がやや複雑

 ・ 管理対象サーバーへのパッケージインストールが必要

 ・ サーバー管理規模に応じて複数の構成が提供されており、それぞれで利用方法が異なる。

   構成によって操作方法が異なり学習コストが高いが、小規模~大規模運用までカバーできる。

ざっと比較してみましたが、個人的な意見としてはAnsibleの方が構成やサーバーを管理するための記述もシンプルなので、敷居が低く構成管理ツールの入門に適しているかと思います。

ですが、あえてchefを押すならばRubyの知識をCookbook作成に活かせる点です。Rubyでコードを書く感覚でCookbookを作成できるので、重複する設定値や処理を変数や関数にまとめたり、Cookbookの作成自体をRubyで自動化なんてことも可能です。

Rubyが得意な方やこれからRubyを覚えようと思っている方にオススメなツールになります。

Chef delivers fast, scalable, flexible IT automation.

Chefの利用形態

Chefの敷居が高い点は、サーバーの管理規模数に応じて利用形態が複数あり、形態毎に利用方法が異なるためです。

始めは混乱するかもしれませんが、主に下記3パターンがあることを押さえておきましょう。

Chef Soloを利用したパターン(廃止予定)

STEP2

Chef Zeroを利用したパターン

STEP3

Chef Serverを利用したパターン

STEP4

chef-solo/chef-zeroを利用したパターンは小~中規模なサーバー構成管理に適しています。サーバー管理用端末と管理対象サーバーさえあれば良いので、Chefの入門編として良いでしょう。

注意点として、chef-soloに関しては同等の機能がchef-zeroへ統合されたため、Chef公式サイトでいずれ廃止するとアナウンスされている点です。今後学習するならchef-solo後継のchef-zeroが良いでしょう。

一方で、chef-serverは大規模なサーバー構成管理するための利用形態となります。最低でもサーバー管理用端末、Cookbook管理サーバー、管理対象サーバーが必要になり、設定方法もchef-solo/chef-zeroに比べ敷居が高いです。

今回はchef入門編として掲載しますので、お手軽に始められるchef-zeroについて取り扱っていきます。

chef-zeroのインストール

まずはお手元のpcでchef-zeroが利用できるようにし、サーバー管理クライアントとして利用できるようにしましょう。

chef-dkというchefのオールインワンパッケージが用意されていますので、お手元のPC環境に合わせて下記サイトからパッケージを取得してインストールし、追加で knife-zero もインストールしておきましょう。

Chef Development Kit

◯Redhat系

$ wget https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chefdk-0.3.5-1.x86_64.rpm
$ sudo rpm -ivh chefdk-0.3.5-1.x86_64.rpm
$ sudo chef gem install knife-zero

◯Ubuntu

$ wget https://opscode-omnibus-packages.s3.amazonaws.com/ubuntu/12.04/x86_64/chefdk_0.3.5-1_amd64.deb
$ sudo dpkg -i chefdk_0.3.5-1_amd64.deb
$ sudo chef gem install knife-zero

◯Debian系

$ wget https://opscode-omnibus-packages.s3.amazonaws.com/debian/6/x86_64/chefdk_0.3.5-1_amd64.deb
$ sudo dpkg -i chefdk_0.3.5-1_amd64.deb
$ sudo chef gem install knife-zero

◯MacOS

下記URLからパッケージをダウンロード
https://opscode-omnibus-packages.s3.amazonaws.com/mac_os_x/10.8/x86_64/chefdk-0.3.5-1.dmg
ダウンロード後にインストーラの指示に従いインストールし、ターミナルを起動して下記コマンドを実行
$ sudo chef gem install knife-zero

◯Windows

下記URLからパッケージをダウンロード
https://opscode-omnibus-packages.s3.amazonaws.com/windows/2008r2/x86_64/chefdk-0.3.5-1.msi
ダウンロード後にインストーラの指示に従いインストールし、コマンドプロンプトを起動して下記コマンドを実行
C:> chef gem install knife-zero

使ってみよう

まずはNode構成を管理するためのchefリポジトリを作成しましょう。以下のコマンドを実行してみてください。

$ chef generate repo chef-repo
$ cd chef-repo
$ ls chef-repo
LICENSE  README.md  Rakefile  certificates  chefignore  config  cookbooks  data_bags  environments  roles 

chef-repoというディレクトリが作成され、その中にNode構成を管理するためのディレクトリが作られます。

ディレクトリ構造はそれぞれに意味がありますが、まずは手順通りに作業をすすめ、chef-zeroを動かす所から始めてみましょう。

続いてchef-repoディレクトリ内に conf.rb ファイルを作成しましょう。

current_dir = File.absolute_path( File.dirname(__FILE__) )
cookbook_path ["#{current_dir}/cookbooks"]
node_path     "#{current_dir}/nodes"
role_path     "#{current_dir}/roles"
ssl_verify_mode  :verify_peer

作成した conf.rb は chef-zero にchefリポジトリのディレクトリ位置を知らせるためのものです。

後々使用しますので、chef-repo ディレクトリに作成しておきましょう。

Cookbook/Recipeの作成

ChefにはCookbookと言う仕組みがあります。Cookbook内に Recipe と呼ばれるRubyスクリプトフォーマットで書かれたファイルにサーバーに対する操作を定義していき、それを knife zero コマンドで実行することで、サーバーを常に Recipe で定義した状態にしておくことができます。

構成管理ツールAnsibleを使ってみよう」を読まれた方は Playbook と混同してややこしく感じるかと思いますが、Cookbook は Recipe をまとめる入れ物で、「Playbook = Recipe」と覚えるのが良いでしょう。

CHEF DOCUMENTS

書式や機能について、オフィシャルサイトにドキュメントはありますが、非常に多機能なのですべて読むのはなかなか大変です。

サンプルを見て実行してもらう方が理解が早いと思います。以下の通り進めてみてください。

◯Cookbookの作成

まずは Recipe をまとめる入れ物「Cookbook」 を作成しましょう。chef-repo ディレクトリ内で以下のコマンドを実行してみてください。

$ knife cookbook -c conf.rb create nginx
$ ls cookbooks
README.md  nginx
$ ls cookbooks/nginx
CHANGELOG.md  README.md  attributes  definitions  files  libraries  metadata.rb  providers  recipes  resources  templates 

nginx という名前のディクレクトリが作成され、その中に Recipe を格納するためのディレクトリ構造が作成されます。

では実際にRecipeを作成してみましょう。以下のサンプルを「chef-repo/cookbooks/nginx/recipes/default.rb」に保存してください。

◯Recipe の作成

package 'nginx' do
    action [ :install ]
    options "--enablerepo=epel"
end

%w{
    nginx
    iptables
}.each do |svc|
    service svc do
        supports [ :restart, :reload ]
        action [ :enable, :start ]
    end
end

iptables_conf_path = '/etc/sysconfig/iptables'
allow_port = 80
execute "allow port #{allow_port}" do
    not_if "grep '-A INPUT -p tcp -m state --state NEW -m tcp --dport #{allow_port}' #{iptables_conf_path}"
    command "sed -i -e '/:OUTPUT ACCEPT/a-A INPUT -p tcp -m state --state NEW -m tcp --dport #{allow_port} -j ACCEPT' #{iptables_conf_path}"
    action :run
    notifies :restart, "service[iptables]"
end

この Recipe は Node に対して、

 ・ nginxのインストール

 ・ iptablesの設定ファイルを変更してHTTPのポートを開放

 ・ iptablesをリスタート

 ・ nginxを起動

という手順で実行します。

構成管理ツールAnsibleを使ってみよう」で取り上げた Playbook のサンプルと同じ動作となっていますので、Ansible/Chef の記述の違いの参考にしてください。

Node の登録と Chef-client パッケージのインストール

Recipe を作成したら、chef-repo に Node を登録し、Nodeに chef-client パッケージのインストールを行います。

まずは、新しくVPSを作成して Key Pair のダウンロードと、IPアドレスをメモしておきましょう。

(今回は、「CentOS 6.5 64bit」を用いています。)

VPSの準備ができたら、以下のコマンドを実行してみましょう。「xxx.xxx.xxx.xxx」の箇所はメモしたIPアドレスを入力してください。

$ knife zero bootstrap XXX.XXX.XXX.XXX -x root -i [VPS Key Pair].key
$ ls nodes
vXXX-XXX-XXX-XXX.abcde.static.cnode.jp.json 

knife zero bootstrap コマンドを実行すると Node に chef-client がインストールされ、chef-repoディレクトリ内に nodes ディレクトリと[VPSホスト名].jsonファイルが作成されます。

このJSONファイルに先ほど作成した Recipe の名前を記述することで、どの Recipe をどの Node に対して適用するか定義することができます。

Node に Recipe を定義する

先ほど作成した Recipe を Nodeに定義してみましょう。以下のコマンドを実行してみてください。

$ knife node -c conf.rb run_list add vXXX-XXX-XXX-XXX.abcde.static.cnode.jp.json 'recipe[nginx]' -z

$ cat nodes/vXXX-XXX-XXX-XXX.abcde.static.cnode.jp.json
   ・
   ・
   ・
  "run_list": [
    "recipe[nginx]"
  ]

[VPSホスト名].json内の「run_list」に先ほど作成した Recipe が定義されましたね。今回は1つだけ Recipe を定義しましたが、run_list に複数 Recipe を定義していくことで、Node に適用する Recipe を増やしていくことができます。

Node に Recipe を適用する

それでは、以下のコマンドを実行して Node に Recipe を適用してみましょう。

$ knife zero -c conf.rb chef_client 'name:vXXX-XXX-XXX-XXX.abcde.static.cnode.jp' -x root -i [VPS Key Pair].key

STEP5

緑色の文字が chef-zero の適用によってセットアップされた箇所となります。初期状態のVPSに Nginx がインストールされ、起動と iptables のセットアップが行われました。

確認のため、http://[VPSのアドレス]にアクセスしてみましょう。nginxのデフォルトページが表示されると思います。

もう一度同じコマンドを実行してみましょう。

STEP6

(up to date)と表示され、緑色の文字が出力されないようになりました。Chef では冪等性(再実行しても同じ実行結果となる)を確保してくれるため、再実行の際に不要な変更処理を自動的にスキップしてくれます。

では次に、Recipe を以下のように変更し、MySQLも導入してみましょう。

%w{
    nginx
    mysql-server
}.each do |pkg|
    package pkg do
        action [ :install ]
        options "--enablerepo=epel"
    end
end

%w{
    nginx
    iptables
    mysqld
}.each do |svc|
    service svc do
        supports [ :restart, :reload ]
        action [ :enable, :start ]
    end
end

iptables_conf_path = '/etc/sysconfig/iptables'
allow_port = 80
execute "allow port #{allow_port}" do
    not_if "grep '-A INPUT -p tcp -m state --state NEW -m tcp --dport #{allow_port}' #{iptables_conf_path}"
    command "sed -i -e '/:OUTPUT ACCEPT/a-A INPUT -p tcp -m state --state NEW -m tcp --dport #{allow_port} -j ACCEPT' #{iptables_conf_path}"
    action :run
    notifies :restart, "service[iptables]"
end

Recipeを変更したら再度同じコマンドを実行してみてください。

STEP7

MySQLのインストール、起動、サービスの有効化が行われました。Nginxとiptablesは(up to date)と表示され、何も処理されていませんね。

このように、Chef を用いたサーバーセットアップでは、以下のサイクルを繰り返し実行することで Recipe を充実させ、徐々にセットアップできる範囲を広げていくことができます。

[Recipe作成] -> [Recipe適用] -> [Recipe修正] -> [Recipe適用] -> [Recipe修正] ・・・・

Recipe解説

今回使用したRecipeにコメントを追加してみました。Recipeを作成される際にご参考ください。

Ruby経験者の方はお気づきかと思いますが、Chef の Recipe はRubyスクリプトで記述しています。今回紹介した記法以外にも、Rubyの記述に則っていれば Chef の Recipe に記述することができます。

%w{
    # インストールしたいパッケージ名を記述
    nginx
    mysql-server
}.each do |pkg|
    package pkg do
        action [ :install ] # 指定されたパッケージのインストールを行う
        options "--enablerepo=epel" # yum リポジトリを有効化する。今回はNginxをインストールするため、epleリポジトリを有効化している。
    end
end

%w{
    # 操作対象のサービスを記述
    nginx
    iptables
    mysqld
}.each do |svc|
    service svc do
        supports [ :restart, :reload ] # Chefが操作可能な範囲を記述。start, stop なども記述可。
        action [ :enable, :start ] # サービスの有効化、起動を行う。
    end
end

# iptables の Conf のパス
iptables_conf_path = '/etc/sysconfig/iptables'

# Nginx ための接続許可ポートを記述
allow_port = 80


execute "allow port #{allow_port}" do
    # iptables の Conf に80番ポートへの接続許可が定義されているか確認する。
    # 許可されていない場合は後述されている command を実行する。
    not_if "grep '-A INPUT -p tcp -m state --state NEW -m tcp --dport #{allow_port}' #{iptables_conf_path}"
    # not_if 条件にマッチした場合、 iptables の Conf に80番ポートへの接続許可設定を追加する。
    command "sed -i -e '/:OUTPUT ACCEPT/a-A INPUT -p tcp -m state --state NEW -m tcp --dport #{allow_port} -j ACCEPT' #{iptables_conf_path}"
    # Recipe適用時に「execute "" do ~ end」の定義を実行する。 
    action :run
    # command 実行後に iptables サービスを再起動して設定の再読み込みを行う。
    # supports[] に:restartが定義されていないとRecipeの適用時に失敗するで注意。
    notifies :restart, "service[iptables]"
end

おわりに

chef-zero を利用してみていかがだったでしょうか。

今回の記事ではChefの基本的な動作を学んでいただくため、Recipeを手作業で作成していただきました。

ですが、実のところサードパーティ製のRecipeも公開されているので、そちらを利用する方法も最後に補足しておきます。

サードパーティ製Recipeを使用するメリットは、Recipe作成労力の削減に尽きるのですが、一方で別の課題が生じます。

 ・サードパーティ製Recipeの使い方を覚えなければならない

 ・最新OSの対応に間に合っていないケースがある。

 ・サードパーティ製Recipeが対応している範囲内でしかセットアップできない。

テスト環境を時間を掛けずに構築した場合などはサードパーティ製Recipeを使用してみるのも良いかもしれませんが、うまく動作しないなどのトラブル時に修正方法が分からず時間を費やしてしまうこともあります。

まずは簡単に Recipe を作成する方法を身につけるよりも、Recipeに書かれている内容を理解して独自にRecipeを作成できるように頑張ってみましょう。

そして、独自の Recipe 作成に慣れてきたらサードパーティ製Recipeに手を伸ばし、そのまま使用したり、記述方法の参考にしたり、痒いところに手の届かない箇所を独自に改良したりしてみると良いかもしれません。

問題は解決できましたか?

お役立ち情報

ConoHaではサポートコンテンツの他にも以下のようなお役立ち情報をご用意しております。ぜひご活用ください。