なんかパッケージ入れたいとかソースから入れたいとかの目的別の逆引きしやすいように。
自分で書く場合の話であって、サードパーティのcookbook使う話は書いてないです。
主にcentosしか使ってないですのでそのつもりでどうぞ。
主に使うリソースはpackageとかbashとかです。リソースのマニュアルは以下などを。
https://docs.chef.io/chef/resources.html
http://matome.naver.jp/odai/2136687268845478601
・yumで入れたい
packageリソース使えばいいです。
package "ntp" do
action [ :install, :upgrade ]
end
複数入れたい場合はrubyのeachメソッドを用います。
%W{ openssl openssl-devel }.each do |pkg|
package "#{pkg}" do
action [ :install, :upgrade ]
end
end
rubyのeachメソッドの説明をすると、
%W{}の中にスペース区切りで対象パッケージを入れます。
.eachの手前に配列変数をおいて食わせるかんじ。
だからまあ、.eachの手前にnode['base_setting']['ssl_packages']
とかのアトリビュートそのまま書いて呼び出しても動きます。
で、doとendの中身が一つのブロックで、
|pkg|
に配列が入れられて、#{pkg}
で変数を呼びだしてつかってるかんじです。
上記の例ではアクションを配列で複数指定しているので、入ってなければinstallされ古ければupgradeされます。
rubyのメソッドを簡単に解説してる以下あたりが分かりやすそうです。
http://dev.classmethod.jp/server-side/chef-vagrant-ruby/
・独自yumリポジトリにパッケージを置いてるのを配って入れたい
opstionsでbaseとかupdatesとかepel等から入らないように調整するなどができます。
package "bash" do
action :upgrade
options "--disablerepo=base,updates"
end
独自リポジトリからカスタマイズビルドしたパッケージを入れたい場合にこのようにします。
・リモートからダウンロードしてからパッケージを明示してyumじゃなくてrpmでいれたい
version = data_bag_item('pkg_versions','innotop')['version']
innotop="innotop-#{version}.noarch.rpm"
baseurl = data_bag_item('pkg_versions','innotop')['url']
remote_file "/usr/local/src/#{innotop}" do
not_if "ls /usr/local/src/#{innotop}"
source "#{baseurl}/#{innotop}"
end
package "innotop" do
action :install
source "/usr/local/src/#{innotop}"
provider Chef::Provider::Package::Rpm
not_if 'rpm -qa|grep innotop'
end
・バージョンを指定したい、オプションでリポジトリを指定したり除外したい
rpm -qi
でパッケージ入ってる情報を調べます(すでに入ってるところで)
$ rpm -qi jdk
Name : jdk Relocations: /usr/java
Version : 1.7.0_55 Vendor: Oracle Corporation
Release : fcs Build Date: 2014年03月18日 03時07分21秒
Install Date: 2014年05月02日 05時39分59秒 Build Host: sc11137388.us.oracle.com
Group : Development/Tools Source RPM: jdk-1.7.0_55-fcs.src.rpm
Size : 202038066 License: http://java.com/license
Signature : (none)
Packager : Java Software <jre-comments@java.sun.com>
URL : URL_REF
Summary : Java Platform Standard Edition Development Kit
Description :
~略~
上記のうちNameがパッケージ名、Versionがバージョンに相当する情報です。
もし、既に入ってるところはない入れて試せない場合には、yum install を打って
実際には入れずにパッケージとバージョンを以下のように確かめます。
# yum install openssl
===============================================================================================
パッケージ アーキテクチャ バージョン リポジトリー 容量
===============================================================================================
更新:
openssl x86_64 1.0.1e-30.el6.11 updates 1.5 M
依存性関連での更新をします。:
openssl-devel x86_64 1.0.1e-30.el6.11 updates 1.2 M
トランザクションの要約
===============================================================================================
アップグレード 2 パッケージ
総ダウンロード容量: 2.7 M
これでいいですか? [y/N]n
そもそもパッケージ名がわからなくてどこにも入ってないならyum search openssl
、
どっかに入ってるコマンドのパッケージが知りたいならrpm -qf /path_to_command
するとよいです。
バージョン指定とオプション指定は以下のようにします。
jdk_version = node['cassandra']['jdk_version']
package 'jdk' do
version "#{jdk_version}"
options "--disablerepo=epel,base,updates"
action :install
end
・ダウンロードして実行権限つけるだけパターン
bash "install jq" do
not_if "ls /usr/bin/jq"
code <<-EOC
curl -o /usr/bin/jq http://stedolan.github.io/jq/download/linux64/jq
chmod +x /usr/bin/jq
EOC
end
・tarアーカイブから展開して入れたい
cookbook_file "/usr/local/src/#{tarfile}" do
not_if "ls /usr/local/src/#{tarfile}"
source "usr/local/src/#{tarfile}"
end
bash "tar-open" do
not_if "ls /usr/local/src/#{server}"
code <<-EOC
cd /usr/local/src
wget #{tarurl} -O #{tarfile}
tar xf #{tarfile}
EOC
end
package "MySQL-client" do
action :install
source "/usr/local/src/#{client}"
provider Chef::Provider::Package::Rpm
not_if 'rpm -qa|grep MySQL-client'
end
※tarアーカイブをcookbook内でない別の場所から持ってきたいならremote_fileリソースを使います。
・make installしたい
事前に開発ツール(yum groupinstall 'Development tools')入ってないとたぶん入らないです
bash "bash-install-git" do
not_if "ls -d /usr/local/src/git-1.9.0"
code <<-EOC
wget https://git-core.googlecode.com/files/git-1.9.0.tar.gz -P /usr/local/src
cd /usr/local/src/
tar zxf git-1.9.0.tar.gz
cd /usr/local/src/git-1.9.0
./configure --prefix=/usr/local/git
make all
make install
ln -sf /usr/local/git/bin/git* /usr/local/bin/
EOC
end
※bashやexecuteリソース内で呼び出した環境変数はリソース内に閉じて引き継ぐことはできません。
一回一回指定する必要があります。(global変数ではなくlocal変数ってかんじです。)
http://qiita.com/taiaraky/items/a3f747fc6528ed6d874e
・gemを入れたい
こんなかんじ、not_if
は時間がかかるから入れてるだけで要らないかもしれない
passenger_version = node['apache']['passenger_version']
gem_package 'passenger' do
not_if "/usr/local/rbenv/shims/gem list|grep passenger|grep #{passenger_version}"
version "#{passenger_version}"
gem_binary '/usr/local/rbenv/shims/gem'
options "--no-rdoc --no-ri"
end
gemでいれるのはmakeとかしてるのでめちゃ時間かかる。出来ればパッケージ化するのが無難。
開発ツール(yum groupinstall 'Development tools')入ってないとたぶん入らないと思う
・gitから入れたい
gitで取得したruby-buildのインストーラを/tmpに置いてbashでインストーラを起動
git "/tmp/ruby-build" do
user node['user']['name']
repository "git://github.com/sstephenson/ruby-build.git"
reference "master"
action :checkout
end
bash "install-rubybuild" do
not_if 'which ruby-build'
code <<-EOC
cd /tmp/ruby-build
./install.sh
EOC
end
・入れた直後に環境変数を途中で読み込んでからなんか入れたい
実行順序の話があります。
http://memo-off.blogspot.jp/2013/06/chefrecipe.html
1.compiling
2.converging
最後にnotifiesに指定されたリソースが実行されるというような順序の実行のされかたをします。
rubyのメソッドは1のcompilingの段階で全部行われてしまうしohaiでとれる値も同じことです。
それゆえ途中で変わった値は2のconvergingの段階で使われないです。
したがってohaiをreloadしたりruby_block内で変数を指定しなおすようなことが必要になるケースがあります。
(notifiesに:immediatelyを指定すると2の書いた準に即時実行にはなります。)
要は、rubyのメソッドはレシピ適用の前に実行されるため、
レシピ適用処理結果を基にした処理をしたい場合はruby_block内に書かないとダメって話等。
ruby_block "initialize_rbenv" do
block do
ENV['RBENV_ROOT'] = node[:rbenv][:root]
ENV['PATH'] = "#{node[:rbenv][:root]}/bin:#{node[:rbenv][:root]}/shims:#{node[:ruby_build][:bin_path]}:#{ENV['PATH']}"
end
action :run
end
rbenv_ruby_version = node[:rbenv][:ruby_version]
bash "set_global_version" do
not_if "/usr/local/rbenv/shims/ruby -v|grep #{rbenv_ruby_version}"
code <<-EOC
rbenv rehash
rbenv global "#{rbenv_ruby_version}"
EOC
end
もし、ruby_blockの中でresouce呼びたい場合メソッドを生やす必要があるので以下リンクを参照ください。
http://qiita.com/sonots/items/8ac33ce011bbfb210edd
・直後にただちにサービスを起動したい
対象リソースの中に以下のようにnotifiesを書く。
notifies :reload, "ohai[reload]", :immediately
notifies :restart, "service[rsyslog]", :immediately
:immediatelyを指定しないとデフォルトでは全てのレシピが適用されたあとにnotifiesに指定した処理が実行される
主に、設定ファイルをtemplateリソースで配って再読み込みしたい時や、
インストール直後に起動したい時なんかにserviceリソースを呼ぶ感じ。
クラスタ組んでて更新でサービスが自動で再起動されてしまうと主系が落ちて待機系にリソースが移ってしまうようなケースではnotifiesかかずに手動がよさそうです。
・設定ファイルやパッケージファイルなどを配りたい
そのまま配布したいなら前述のcookbook_fileを使います
変数を埋め込んでファイルを配りたい場合はtemplateリソースを使います。
以下はdata_bagsからロードして変数に埋め込んだデータをtemplateリソースのvariablesで差し替えてる例。
slappasswd = Chef::EncryptedDataBagItem.load("ldap","slappasswd")
ldappw2 = slappasswd["bindpw"]
template '/etc/phpldapadmin/config.php' do
source 'config.php.erb'
owner 'root'
group 'apache'
mode 0640
variables ({
:bindpw => ldappw2
})
end
ちなみにレシピ上でvariablesで差し替える場合はsourceに指定されてるファイルに以下のように@つけて変数埋め込んでおきます。
$servers->setValue('login','bind_pass','<%= @bindpw %>');
どっかのattributeから差し替える場合は、以下のような感じに<%= %>内にattributeを埋め込んでおきます。
<%= node['ldap']['basedndc1'] %>
・attributeの使い分け等、データをどこから持ってくるかの話
そのリポジトリで共通の一意なデータと暗号化したいデータ、たとえばユーザデータや証明書なんかはdata_bagsで管理するといい。
環境毎に異なる変数はenvironmentsで、webやdb等の役割毎に異なる変数はrolesで、
node毎に異なる変数はnodesで管理するといい。デフォルト値があって複数のenvironmentやroleで共通であって
cookbookに含まれてしまっても問題のないとくに固有じゃないパラメータとかであれば、cookbooks/attributes/default.rbに書いとくといい。
全部jsonで書ける。jsonデータのシンタックスチェックにはjsonlintが便利である。
あとはホスト名とかIPとかcpuコア数とかメモリ搭載量とかohaiというchef同梱の仕組みでとれるホストデータを埋め込むことが可能。
ohaiのデータを呼び出したいならtemplateファイル内で
<%= node['ipaddress'] %>
とかするだけでOKでレシピや他のattribute書くとこになんかかいたりしなくても大丈夫。
cookbook内のattributes/default.rbとかに書くなら、
default['apache']['version'] = '2.xxx'
とか書いたりする
配列もいけます。
default['fluentd']['plugins'] = %w(
fluent-plugin-file-alternative
fluent-plugin-forest
fluent-plugin-rewrite-tag-filter
fluent-plugin-tail-ex
fluent-mixin-config-placeholders
fluent-plugin-parser
fluent-plugin-record-reformer
fluent-plugin-statsd
fluent-plugin-datacounter
fluent-plugin-mackerel
statsd-ruby
jsonpath
)
environments、roles、nodesの下はjson置く感じで、
以下のような感じに。"default_attributes"と"override_attributes"があって優先順位があり
同じ値は同じとこに書くと配列ならマージされたりする。
http://dev.classmethod.jp/server-side/chef/attribute-overrides-pattern/
"base_setting": {
"swappiness": "30",
"tcp_tw_reuse": "0",
"tcp_tw_recycle": "0",
"tcp_fin_timeout": "10",
"tcp_max_syn_backlog": "8192",
"somaxconn": "8192",
"ntp_role": "server",
"logrotate_types": ["ldap"],
"rsyslog_type": "ldap"
},
配列なら[]で囲んでカンマ区切りで書く。
"nic_devices":[
"eth0","eth1"
],
data_bagsはディレクトリ一個しか掘れないので注意。
ディレクトリがバッグというか入れ物にあたる。
暗号化したいデータとかはこのへんに入れます。くわしいことは以下URLらへんで。
http://devlab.isao.co.jp/data_bags_exsample/
http://qiita.com/smallpalace/items/2ada68c2dbbc9065dcc1
とりあえずこのへんで。Ansible版はこちら。