Chef/初心者向けChef入門講座/attributeを使う


attributeを使う

template機能の説明の時にこのようなレシピ(の一部のコード)を作成しました。
template "/etc/ntp.conf" do
  source "etc/ntp.conf.erb"
  notifies :restart, "service[ntpd]"
  action :create
  variables({
    :ntp_servers => [ 'ntp1.jst.mfeed.ad.jp', 'ntp2.jst.mfeed.ad.jp', 'ntp3.jst.mfeed.ad.jp' ]
  })
end
この形だと、ntpサーバーに別の値を入れたい場合はレシピを直接書き換える必要があります。
この、環境によってレシピを直接書き換えなければいけないというのはあまりスマートなやり方ではないようです。

そこで別途環境ごとに異なる値をまとめ、そちらを書き換えることでなるべくソース(レシピ)を維持することができるのがattributeの機能です。
では使ってみます。
まずはtest_cookbook/attributes/default.rbを以下の内容で作成します。
default["test_cookbook"]["servers"] = [ 'ntp1.jst.mfeed.ad.jp', 'ntp2.jst.mfeed.ad.jp', 'ntp3.jst.mfeed.ad.jp' ]
default["test_cookbook"]という連想配列に値を入れていく感じです。
代入先はクックブック名有りの default["test_cookbook"]["servers"] ではなくクックブック名無しの default["servers"] でも良いですが、後で使いにくくなるので基本的にはクックブック名を入れておきましょう。

なお、attributesディレクトリ配下のファイルはどんな名前でも全て読み込まれ、同一の変数がある場合は上書きされるのでご注意下さい。
恐らくdefault.rbが最初に読み込まれた後、その他のファイルはアルファベット順に読み込まれます。
default.rbというファイル名はレシピファイルのdefault.rbとは何の関係もありませんが、基本的にはdefault.rbだけを作っておくのが良いかと思います。

そしてレシピはこのようにします。
template "/etc/ntp.conf" do
  source "etc/ntp.conf.erb"
  notifies :restart, "service[ntpd]"
  action :create
  variables({
    :ntp_servers => node["test_cookbook"]["servers"]
  })
end
先程defaultで格納した値は、レシピからはnodeという連想配列で取り出すことができます。
厳密に言うと、いろいろな箇所で設定したattributeの情報が集められて優先度が高い物が残り、最終的にnodeという連想配列にまとめられてそこから取り出せるという感じです。
当然ですがtemplate以外のリソースからでも利用することができます。

テンプレートはこの形です。
<% @ntp_servers.each do |ntp_server| %>
server <%= ntp_server %>
<% end %>
これで実行すればアトリビュートファイルで設定した内容が反映されます。

しかしこれだけでは単に設定内容を外に出しただけに過ぎません。
attributeを使うことのメリットは、予め環境によって異なる値を持たせておくことができることです。

具体的には、例えば直接インターネットに出られるWebサーバーと、直接インターネットに出られないDBサーバーでntpサーバーを切り替えたいようなケースです。
今の状態ではインターネットに出られるサーバーと出られないサーバーに適用させるごとにattributeを書き換えないといけませんが、環境によってroleを分けておくことで書き換える手間を省くことができます。

例えばこうです。webserverロールを作成します。
# knife role create webserver

{
  "name": "webserver",
  "description": "",
  "json_class": "Chef::Role",
  "default_attributes": {
  },
  "override_attributes": {
    "test_cookbook": {
      "servers": [ "ntp1.jst.mfeed.ad.jp", "ntp2.jst.mfeed.ad.jp", "ntp3.jst.mfeed.ad.jp" ]
    }
  },
  "chef_type": "role",
  "run_list": [
    "test_cookbook"
  ],
  "env_run_lists": {
  }
}
attributeはとりあえず"override_attributes"の中に記述してあります。

なお、"default_attributes"の中に記述した場合はレシピのattributeファイルで指定した default["test_cookbook"]["servers"]の値とマージされ、"override_attributes"の中に記述するとattributeファイルで指定した値は上書き(無視)されます。
明示的にマージしたい場合などにはうまく使い分けることができそうです。

dbserverロールはこのように作成します。
# knife role create dbserver

{
  "name": "dbserver",
  "description": "",
  "json_class": "Chef::Role",
  "default_attributes": {
  },
  "override_attributes": {
    "test_cookbook": {
      "servers": [ "192.168.0.100" ]
    }
  },
  "chef_type": "role",
  "run_list": [
    "test_cookbook"
  ],
  "env_run_lists": {
  }
}

そしてノードごとに異なるロールを設定します。
# knife node run_list add server1 "role[webserver]"
# knife node run_list add server2 "role[webserver]"
# knife node run_list add server3 "role[dbserver]"

attributeには優先順位があり、automatic > force_override > override > normal > force_default > default の順に強いです。
ノード側にはnormalのattributeを設定する箇所がありますが、roleでoverrideを設定していると無視されてしまいます。
# knife node edit [ノード名]
"normal": {
  "tags": [

  ]
},

↓

"normal": {
  "test_cookbook": {
    "servers": [
      "ntp.nict.jp"
    ]
  },
  "tags": [

  ]
},
特定のノードだけ異なる値を使いたい場合は、attributeファイルでは何も指定せず、roleではdefaultを使用し、nodeでnormalを使うようにすれば良いです。

attributeの関係はこちらにドキュメントとしてもまとめられています。
ただ、あまり複雑に使い分けても分かりにくくなってしまうので注意が必要です。




  • 最終更新:2016-01-19 13:34:39

このWIKIを編集するにはパスワード入力が必要です

認証パスワード