LoginSignup
47
50

More than 5 years have passed since last update.

これからはじめるChefのチュートリアル 基本編

Last updated at Posted at 2015-12-02

はじめに

次の現場でChefを使う可能性が出てきたので、ちょっと真面目にレシピを書き残しておく。
前回は以下の事を記載しました。

これらの記事はまとまった記事では無いので、今回はしっかりまとめた記事を書きます。
最終的には企業レベルで使える(と思われる)レシピの書き方を記事にしていきます。

※本記事はMacを使って確認をしてます。
※本記事はChef-Soloについて書いてます。

事前準備

事前に以下のものを入れておいてください。

  • VirtualBox
  • Vagrant

最終的にはAWSのAmazon-Linuxへ環境構築する想定で進めますので、上記を入れずに直接Amazon-Linuxを使用しても問題ありません。
Dockerなどの仮想OSを使っても問題ありません。
→DockerでChefを流す実験をしてみました。

  • Homebrew
  • Ruby
  • Bundle(rubyのGem)

Homebrewは無理に入れる必要はありませんが、Macで行う場合は入れておいた方が良いです。
Rubyははじめに入っているものでも問題ありません。

$ gem install bundle

こちらを行なっておいてください。

仮想OSの準備

Chefは冪等性(平たく言うと、何度実施しても同じ結果になる事)が保証されていますが、いきなり本番でテストするのは危険が伴います。
(なぜなら、自分が作ったレシピに冪等性が保証されていると言う確証が無いためです。)
ですので、仮想OSもしくはAWSの無料枠などを準備します。

以下にVagrantを使った仮想OS構築の手順を記載しておきます。

mkdir opscode-centos65
cd opscode-centos65
vagrant init opscode-centos-6.5 http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box

起動前に設定内容を書き換えます。
(SSHでアクセスできれば良いので、適当に設定します。)

vi Vagrantfile

内容を以下のように書き換えます。

Vagrant.configure(2) do |config|
  # コメントアウトを外します。(必要に応じてIPアドレスを変更してください。)
  config.vm.network "private_network", ip: "192.168.33.10"
end

仮想OSを起動してSSHでアクセスできるようにします。
※以下の例はchef-centos65と言う名前でアクセス出来るようにしてます。

$ vagrant up
$ vagrant ssh-config --host chef-centos65 >> ~/.ssh/config

念のためSSHでアクセスできる事を確認します。
アクセス後にsudoが使用できることを確認します。

$ ssh chef-centos65
$ sudo ls
$ exit

仮想OSは環境構築のテストでしか使用しないので、最後のSSH接続+SUDOができていればどのような環境でもOKです。

Chefリポジトリの準備

ここからが本番です。
仮想OSのディレクトリとは別にChef用のディレクトリを用意します。

$ mkdir chef-rep
$ cd chef-rep

必要なプログラムをインストールします。

$ vi Gemfile

以下の内容を記載します。

source "https://rubygems.org"

gem 'chef', '~> 12.0'
gem 'knife-solo'
# 公開されているレシピを使用するために必要
gem 'berkshelf'
# 暗号化が必要な場合は以下のGemも入れる。(今回は使わない。)
gem 'knife-solo_data_bag'

プログラムをインストールします。
他のプログラムに影響しないように、vendorへ入れます。

$ bundle install --path=vendor/bundle

Chefのリポジトリを作成する。

$ bundle exec knife solo init .

これでChefのリポジトリが出来上がりました。
以下の処理はこのディレクトリを使って行なっていきます。

Berkshelfの設定

Chefはクックブックの中にレシピを作成していきます。
構図のイメージとしては以下のような感じです。

・カレーライスのクックブック
 ・標準レシピ
 ・和風カレーライスレシピ
 ・インドカレーレシピ
 ・タイカレーレシピ
・鍋のクックブック
 ・ポン酢で作るおいしい鍋のレシピ
 ・闇鍋の作り方レシピ

これらのクックブックを作っていくのですが、自分でこれらのクックブックを全て作るのは大変です。
クックパッドのようにレシピがまとまってれば、それを使いたいものです。
その要望に応えたものがBerkshelfになります。

今回はこれを使います。
では、早速設定しましょう。

$ vi Berksfile

すでにファイルが作成されていると思います。
以下のように変更します。

source "https://supermarket.getchef.com"

cookbook 'yum-epel'
# rbenvのクックブック内にレシピがあるので、不要かも・・・。
cookbook 'ruby_build'
cookbook 'rbenv'
# 例えばimagemagickのクックブックを使いたい場合は以下のように設定する。
cookbook 'imagemagick'

定義したクックブックをインストールします。

$ bundle exec berks install

~/.berkshelf/cookbooks/にクックブックが作成されてます。

環境構築 その1 冪等性について

ここまで設定した内容を実際に仮想OSへ反映させます。
サーバーを指定する場合はnodesの中に記載します。

# chef-centos65は「ssh chef-centos65」でアクセスできる名前をつけます。
$ vi nodes/chef-centos65.json

実施するレシピを記載します。
クックブックのみを指定した場合は、クックブックの中のdefault.rbが使われます。
とりあえずBerkshelfで落としてきたrbenvをインストールする設定を書きます。

{
  "run_list": [
    "rbenv"
  ]
}

実行する前に、対象サーバーがChef-Soloを実行できるように対象サーバーへChef-Soloをインストールします。

$ bundle exec knife solo prepare chef-centos65

実際にrbenvを入れます。

$ bundle exec knife solo cook chef-centos65

コンソールを見ていると、自分が設定していないyumなどがインストールされていく様子がみられます。
chefの素晴らしいところはこのような依存関係を解決してくれるところです。

実際にインストールされているか確認してみます。

$ ssh chef-centos65
$ rbenv -v
rbenv 0.4.0-210-gf0e8bdc

次にインストールできるRubyのバージョンを確認します。

$ rbenv install --list
rbenv: no such command `install'

しかし、installコマンドは使えません。
ruby_buildを入れ忘れたためです。

先ほどのnodesファイルを書き直します。

# SSHから抜けます。
$ exit
$ vi nodes/chef-centos65.json

これで先ほどのファイルを以下のように書き直します。

{
  "run_list": [
    "rbenv",
    "ruby_build"
  ]
}

再度環境設定を行います。

$ bundle exec knife solo cook chef-centos65

さて、今度はどうでしょうか?

$ ssh chef-centos65
$ rbenv install --list
Available versions:
  1.8.6-p383
  ...
  topaz-dev

今度は入っている事が確認できました。
このように、設定を変更してcookを行っても環境が壊れる事なく同じ結果が反映されます。
試しにvagrant destroyvagrant upをしてcookを再度行っても同じ結果になります。
これが冪等性です。

この性質があるため、複数台のサーバーに対してcookを行うと同じ設定のサーバーを量産する事ができます。

環境構築 その2 レシピを作る

では肝心のrubyコマンドは使えるでしょうか?

$ ruby -v
-bash: ruby: コマンドが見つかりません

残念ながらまだrubyは使えません。

$ rbenv install [rubyバージョン]

上記のコマンドを行えばrubyは入りますが、サーバー内で何かしらの作業を行ってしまうとchefの良さがなくなります。
もし5台のサーバーに対して環境構築を行う場合には、5台のサーバーに入って上記のコマンドを打たなければなりません。

これはchefの利便性や冪等性の観点から見ても、NGであることは明らかです。

これを解決するためのレシピを作りましょう。

# SSHから抜けます。
$ exit

現状を確認します。

$ ls -l cookbooks
$ ls -l site-cookbooks

確認するとcookbooksに様々なファイルが存在してることがわかります。
これはknifeの中身を見るとわかります。

$ cat .chef/knife.rb 
cookbook_path    ["cookbooks", "site-cookbooks"]
node_path        "nodes"
role_path        "roles"
environment_path "environments"
data_bag_path    "data_bags"
#encrypted_data_bag_secret "data_bag_key"

knife[:berkshelf_path] = "cookbooks"
Chef::Config[:ssl_verify_mode] = :verify_peer if defined? ::Chef

この中のknife[:berkshelf_path] = "cookbooks"Berkshelfが使用するクックブックを指定しているためです。
また、cookbook_path ["cookbooks", "site-cookbooks"]にクックブックのパスが定義されていることからsite-cookbooksに自分のレシピを作れば良いことがわかります。

早速作っていきましょう!

$ bundle exec knife cookbook create ruby -o site-cookbooks/

rubyのバージョンを指定するためのクックブックとしてrubyを作成します。
作成したら中身を記載します。

$ vi site-cookbooks/ruby/recipes/default.rb

内容を記載します。

# インストールするバージョンを指定します。
rbenv_ruby "2.2.3" do
  ruby_version "2.2.3"
  # グローバルとして使用するかを定義します。
  global true
end

nodeに追加します。

$ vi nodes/chef-centos65.json

最後にrubyを追加します。

{
  "run_list": [
    "rbenv",
    "ruby_build",
    "ruby"
  ]
}

サーバーに反映させます。

$ bundle exec knife solo cook chef-centos65

rubyをインストールするため実施には時間がかかります。

$ ssh chef-centos65
$ ruby -v
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
$ exit

rubyがインストールされました。

環境構築 その3 依存関係

このレシピにはいくつか問題があります。
例えばnodes/chef-centos65.jsonの順番を間違えてしまったり、書き忘れた場合はどうなるでしょうか?

nodes/chef-centos65.json
{
  "run_list": [
    "ruby",
    "rbenv",
    "ruby_build"
  ]
}

または以下のケース

nodes/chef-centos65.json
{
  "run_list": [
    "ruby"
  ]
}

このように記載されても実行できるように、依存関係を記載しておきます。

site-cookbooks/ruby/recipes/default.rb
# 使用するレシピを事前に記載しておきます。
include_recipe "rbenv"
include_recipe "ruby_build"
# レシピも指定する場合は以下の記述になる。
#include_recipe "rbenv::default"
#include_recipe "ruby_build::default"

# インストールするバージョンを指定します。
rbenv_ruby "2.2.3" do
  ruby_version "2.2.3"
  # グローバルとして使用するかを定義します。
  global true
end

さらに使用するレシピのデフォルト値を読み込むために以下を記載します。

site-cookbooks/ruby/metadata.rb
depends "rbenv"
depends "ruby_build"

これでnodeが以下のような状態になっていても実行されるようになります。

nodes/chef-centos65.json
{
  "run_list": [
    "ruby"
  ]
}

シンプルになりましたね!
実際に仮想OSを作り直して、上記の状態でcookをしても同じ状態になることを確認してください。

参考

include_recipeだけでは読み込み先のattributesが読み込まれない

注釈

実際に使用する際は、ここまで行う必要はほとんどありません。
しかし、こういう方法もあるということを覚えておくとレシピの書き方に幅が出てきます。

環境構築 その4 汎用化

さて、このレシピにはまだ問題があります。
それはRubyのバージョンが2.2.3というように固定されてしまっていることです。

今のままでは良いかもしれませんが、将来的に新しいRubyのバージョンを入れる事を考えるとこのままではよろしくありません。

各レシピに設定値を受け渡せれれば問題が解決します。
chefでは以下の記述を行う事で設定値を記載できます。

nodes/chef-centos65.json
{
  "ruby": {
    "version": "2.2.3"
  },
  "run_list": [
    "ruby"
  ]
}

上記で設定した値を使用して構築できるようにレシピを書き直します。

site-cookbooks/ruby/recipes/default.rb
include_recipe "rbenv"
include_recipe "ruby_build"

rbenv_ruby node["ruby"]["version"] do
  ruby_version node["ruby"]["version"]
  global true
end

ではサーバーに反映してみましょう!
(反映を確認する場合は、Rubyのバージョンを2.2.2などにすると確認ができます。)

$ bundle exec knife solo cook chef-centos65

このままでも良いのですが、せっかくrbenvを使っているのに固定されたバージョンしか設定できないのは不便です。
以下のようなパラメーターを受け付けれるように変更しましょう。

nodes/chef-centos65.json
{
  "ruby": {
    "versions": [
      {
        "version": "2.2.3",
        "global": "true"
      },
      {
        "version": "2.2.2"
      }
    ]
  },
  "run_list": [
    "ruby"
  ]
}

レシピも変更します。
ついでに必ず使うgemであるbundleも入れておきます。

site-cookbooks/ruby/recipes/default.rb
include_recipe "rbenv"
include_recipe "ruby_build"

node['ruby']['versions'].each { |v|
  # 指定バージョンのrubyをインストール
  rbenv_ruby v['version'] do
    ruby_version v['version']
    global true if v["global"]
  end

  # bunldleを設定する。
  rbenv_gem "bundler" do
    ruby_version v['version']
  end
}

設定を反映させてみましょう!

$ bundle exec knife solo cook chef-centos65

レシピの初期値

このレシピを使うときには必ずrubyのバージョンを指定する必要があります。
しかし、実際にレシピを使う時にバージョンはあまり重要ではない局面もあります。

そういう時にまでバージョンを指定を強制すると使い勝手の悪いレシピが出来上がってしまいます。

nodes/chef-centos65.json
{
  "run_list": [
    "ruby"
  ]
}

この状態でも実行できるように以下のファイルを作成します。
ここで指定した値がデフォルトで使用されます。

site-cookbooks/ruby/attributes/default.rb
default["ruby"]["versions"] = [{"version" => "2.2.3", "global" => true}]

参考

ruby_rbenvのgithub

ところでrbenv_rubyコマンドとかってどこに定義されているのだろうか・・・。
レシピに存在しないのに使える・・・というところが謎である。。。

まとめ

いかがだったでしょうか?
基本的な使い方に関してはこの記事の内容だけで十分使えると思います。
しかし、ここまでの内容ではまだ企業で使うためには不十分な内容となってます。

本当は環境構築のその5以降も書いていこうと思ったのですが、思ったよりも長くなってしまったので今回の記事を基本編として次回の記事を応用編で書いていこうと思います。

応用編を実践すればより使いやすいChefのレシピが書けるようになると思いますので、ご期待ください!

次は・・・

これからはじめるChefのチュートリアル 応用編を書きましたのでこちらも続けてやってみてください!

筆者について

筆者はTownsoftを屋号に活躍(?)しているフリーランスです。
お仕事の依頼なども受けてますので、お気軽にご連絡ください。

47
50
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
50