Chefで既存手順のレシピを書く1(初期設定)

こんにちは。プラットフォームの小宮です。
前回はChefでレシピを書く前のroleやdata_bagsなどの環境定義について書きました。
今回は既存手順のレシピ化ということで淡々と地味に書いていきたいと思います。

注意:
 scriptリソースを使うときはnot_ifまたはonly_ifを必ず書くこと(複数回実行されないように)
 bash内でcdを書き忘れるとtarの解凍先パスがその後のコマンドの指定と一致しなくなるので注意
 scriptリソースを使うとエラーがまともに出ないので自分でコマンドをたたいて状況を確認する必要がある
 リソースのマニュアルを熟読推奨。

クックブック名とその内容は以下の通り。
 base_setting 初期設定など ★今回ご紹介するレシピはこちらのみです。
 login-users ログインユーザ作成
 httpd web関連設定
 mysqld db関連設定
 munin 統計グラフ設定
 zabbix 監視設定

レシピを書く
・base_settingのレシピを書く
使いまわしやすさを意識した結果細かく分割して書くことにしました。
☆バックアップディレクトリ作成レシピ
[shell]# cd site-cookbooks/base_setting/recipes/
# for i in bkup_dir hosts sysctl disable ntpd ntpdate mail logrotate ;do touch $i.rb ;done
# vi bkup_dir.rb
directory ‘/etc/.backup/’ do
owner ‘root’
group ‘root’
mode ‘0755’
action :create
end[/shell]

ホスト名については特に変えたりしてないのですが、
AWSだと以下のような方法もあるようです。NAMEタグと同じにしてくれるもの。
はじめての cloud-init:hostname を Name タグのものにそろえる
ただしこの方法を使うにはEC2-TOOLSをセットアップしAWS鍵情報とか渡すためにdatabags使うようレシピが必要そうです。
台数少なくてVagrant使っているなら以下のようにVagrantfile内でスクリプト渡して設定してもいいかもしれない。
[shell]$script = <<SCRIPT
host=uname -n
if [ "$host" != "xxx-web03" ];then
echo xxx-web03 > /proc/sys/kernel/hostname
sed -i ‘s/HOSTNAME=[^=]*/HOSTNAME=xxx-web03/g’ /etc/sysconfig/network
date > /etc/vagrant_provisioned_at
fi
SCRIPT
web.vm.provision :shell, :inline => $script
end[/shell]
あとはhostnameをdatabagsで管理してnetworkをtemplateで変数埋め込んでnodeでattributeで設定するとか?
networkだけだと再起動必須なのでsysctlとかechoとかでパラメータ渡したいけどレシピの書き方がぱっと思いつかないです。

☆hostsを配布したうえでlocalhostの部分をattributeで設定するレシピ
[shell]# mkdir /root/chef-repo/site-cookbooks/base_setting/templates/default/etc
# cp -p /etc/hosts /root/chef-repo/site-cookbooks/base_setting/templates/default/etc/hosts.erb
# vi hosts.rb
template ‘/etc/hosts’ do
owner ‘root’
group ‘root’
source ‘etc/hosts.erb’
end

# ohai hostname
[
"xxx-stg01"
]
# vi /root/chef-repo/site-cookbooks/base_setting/templates/default/etc/hosts.erb
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 <%= node[‘hostname’] %> localhost.localdomain localhost
::1 localhost6.localdomain6 localhost6

# VIP
10.0.0.252 xxx-db-w-vip
10.0.0.200 xxx-stg01 # 54.249.xx.xx
10.0.0.201 xxx-web01
10.0.0.221 xxx-db01[/shell]

Ohai参考:OhaiとはChefに同梱されたOSプラットフォーム毎の違いを吸収して各パラメータを取得してくれるコマンド
Chef の Common Automatic Attributes
Cookbook Refactoring and Extracting Logic into Rubygems
Ohaiでとれるnodeの値を使うならnodeやroleなどでattribute定義しなくて大丈夫なようです。

☆sysctl.confをattributeで設定するレシピ

まずレシピを書く
[shell]# cp -p /etc/sysctl.conf /root/chef-repo/site-cookbooks/base_setting/templates/default/etc/sysctl.conf.erb
# vi sysctl.rb
Encoding.default_external = Encoding::UTF_8
template "/etc/sysctl.conf" do
owner ‘root’
group ‘root’
source ‘etc/sysctl.conf.erb’
mode 0644
# variables({
# :swappiness => 30,
# :tcp_tw_reuse => 0,
# :tcp_tw_recycle => 0,
# :tcp_fin_timeout => 0,
# :tcp_max_syn_backlog => 1024,
# :somaxconn => 1024
# })
end

script "sysctl -p" do
interpreter "bash"
user "root"
code <<-EOL
/sbin/sysctl -p
EOL
end[/shell]

※日本語が含まれる設定ファイルをtemplateリソースで扱う場合、エンコードを指定する必要がある
variablesを用いる場合はtemplateファイル内で@つけて呼び出す必要がある

変数を埋め込んだ設定ファイルをおく
[shell]# vi /root/chef-repo/site-cookbooks/base_setting/templates/default/etc/sysctl.conf.erb
—–
# swap発生しづらくする
vm.swappiness = <%= node[‘base_setting’][‘swappiness’] %>
# LVS(DSR)参照分散対象の場合にarpを返さない設定
#net.ipv4.conf.all.arp_ignore = 1
#net.ipv4.conf.eth0.arp_ignore = 1
#net.ipv4.conf.all.arp_announce = 2
#net.ipv4.conf.eth0.arp_announce = 2
# TCPのfinwaitをリサイクル、タイムアウト値を短くする(SOAP利用時は無効にすること)
net.ipv4.tcp_tw_reuse = <%= node[‘base_setting’][‘tcp_tw_reuse’] %>
net.ipv4.tcp_tw_recycle = <%= node[‘base_setting’][‘tcp_tw_recycle’] %>
net.ipv4.tcp_fin_timeout = <%= node[‘base_setting’][‘tcp_fin_timeout’] %>
# 超えるとsynが捨てられるキュー数の上限を広げる
net.ipv4.tcp_max_syn_backlog = <%= node[‘base_setting’][‘tcp_max_syn_backlog’] %>
net.core.somaxconn = <%= node[‘base_setting’][‘somaxconn’] %>
# TCPのキープアライブの間隔やリトライ回数などの調整
net.ipv4.tcp_keepalive_intvl = 3
net.ipv4.tcp_keepalive_probes = 2
net.ipv4.tcp_keepalive_time = 10
—–[/shell]

attributesにデフォルト値を定義しておく
[shell]# vi site-cookbooks/base_setting/attributes/default.rb
—–
# attribute of base_setting.conf.erb
default[‘base_setting’][‘swappiness’] = "30"
default[‘base_setting’][‘tcp_tw_reuse’] = "0"
default[‘base_setting’][‘tcp_tw_recycle’] = "0"
default[‘base_setting’][‘tcp_fin_timeout’] = "60"
default[‘base_setting’][‘tcp_max_syn_backlog’] = "4096"
default[‘base_setting’][‘somaxconn’] = "4096"
—–[/shell]

RoleのJSONファイルにdefault_attributeを追記する
[shell]# head -15 roles/admserver.json
{
"name":"admserver",
"json_class":"Chef::Role",
"description":"",
"chef_type": "role",
"default_attributes":{
"base_setting": {
"swappiness": "0",
"tcp_tw_reuse": "0",
"tcp_tw_recycle": "0",
"tcp_fin_timeout": "60",
"tcp_max_syn_backlog": "8192",
"somaxconn": "8192"
}
},

# head -15 roles/webserver.json
{
"name":"webserver",
"chef_type": "role",
"json_class":"Chef::Role",
"default_attributes":{
"base_setting": {
"swappiness": "30",
"tcp_tw_reuse": "0",
"tcp_tw_recycle": "0",
"tcp_fin_timeout": "60",
"tcp_max_syn_backlog": "4096",
"somaxconn": "4096"
}
},
"override_attributes":{},

# head -15 roles/dbserver.json
{
"name":"dbserver",
"json_class":"Chef::Role",
"chef_type": "role",
"description":"",
"default_attributes":{
"base_setting": {
"swappiness": "0",
"tcp_tw_reuse": "1",
"tcp_tw_recycle": "1",
"tcp_fin_timeout": "10",
"tcp_max_syn_backlog": "8192",
"somaxconn": "8192"
}
},[/shell]

☆色々無効にするレシピ
selinux無効、不要サービスとcron停止、yumupdate時kernel除外、ipv6無効、のdisableレシピをまとめて書きます

まず設定ファイルをfilesの下にディレクトリ掘って置いておくなど
パラメータ固定のファイルはfilesに置く。
変数を使う場合はtamplatesに置く
[shell]# grep disable /etc/selinux/config|grep -v ‘#’
# mkdir -p /root/chef-repo/site-cookbooks/base_setting/files/default/etc/selinux
# cp -p /etc/selinux/config /root/chef-repo/site-cookbooks/base_setting/files/default/etc/selinux/
# tail /etc/yum.conf
# echo "exclude=kernel*" >> /etc/yum.conf
# cp -p /etc/yum.conf /root/chef-repo/site-cookbooks/base_setting/files/default/etc/
# egrep "ipv6|net-pf" /etc/modprobe.conf
# vi /etc/modprobe.conf
alias net-pf-10 off
alias ipv6 off
options ipv6 disable=1
# cp -p /etc/modprobe.conf /root/chef-repo/site-cookbooks/base_setting/files/default/etc/
# chkconfig –list|grep 3:on
# ls -l /etc/cron.daily/
# ls -l /etc/cron.weekly/
# mkdir -p /root/chef-repo/site-cookbooks/base_setting/files/default/etc/{cron.daily,cron.weekly,logrotate.d,mail}
# mkdir -p /root/chef-repo/site-cookbooks/base_setting/files/default/rpms
# mkdir -p /root/chef-repo/site-cookbooks/base_setting/files/default/etc/postfix
# cp -p /etc/cron.daily/makewhatis.cron /root/chef-repo/site-cookbooks/base_setting/files/default/etc/cron.daily/
# cp -p /etc/cron.daily/mlocate.cron /root/chef-repo/site-cookbooks/base_setting/files/default/etc/cron.daily/
# cp -p /etc/cron.daily/prelink /root/chef-repo/site-cookbooks/base_setting/files/default/etc/cron.daily/
# cp -p /etc/cron.weekly/makewhatis.cron /root/chef-repo/site-cookbooks/base_setting/files/default/etc/cron.weekly/
# ll /root/chef-repo/site-cookbooks/base_setting/files/default/etc/cron.*
# cp -p /etc/ntp.conf /root/chef-repo/site-cookbooks/base_setting/files/default/etc/
# vi /root/chef-repo/site-cookbooks/base_setting/files/default/etc/ntp.conf
# cp -p /etc/logrotate.d/syslog /root/chef-repo/site-cookbooks/base_setting/files/default/etc/logrotate.d/
# cp -p /opt/src/rpms/{dovecot*,postfix*,xinetd*} /root/chef-repo/site-cookbooks/base_setting/files/default/rpms/
# cp -p /etc/postfix/main.cf /root/chef-repo/site-cookbooks/base_setting/files/default/etc/postfix/
# cp -p /etc/postfix/vmailbox /root/chef-repo/site-cookbooks/base_setting/files/default/etc/postfix/
# cp -p /etc/dovecot.conf /root/chef-repo/site-cookbooks/base_setting/files/default/etc/
# scp -Cp xxx-db02:/etc/mail/submit.cf /root/chef-repo/site-cookbooks/base_setting/files/default/etc/mail/[/shell]

レシピを書く
[shell]# vi disable.rb
cookbook_file ‘/etc/selinux/config’ do
source ‘etc/selinux/config’
owner ‘root’
group ‘root’
mode 0644
end

cookbook_file ‘/etc/yum.conf’ do
source ‘etc/yum.conf’
owner ‘root’
group ‘root’
mode 0644
end

cookbook_file ‘/etc/modprobe.conf’ do
source ‘etc/modprobe.conf’
owner ‘root’
group ‘root’
mode 0644
end

%W{ip6tables iptables messagebus kudzu}.each do |pkg|
service pkg do
ignore_failure true
action [:disable, :stop]
end
end

cookbook_file ‘/etc/cron.daily/makewhatis.cron’ do
source ‘etc/cron.daily/makewhatis.cron’
owner ‘root’
group ‘root’
mode 0000
end

cookbook_file ‘/etc/cron.daily/mlocate.cron’ do
source ‘etc/cron.daily/mlocate.cron’
owner ‘root’
group ‘root’
mode 0000
end

cookbook_file ‘/etc/cron.daily/prelink’ do
source ‘etc/cron.daily/prelink’
owner ‘root’
group ‘root’
mode 0000
end

cookbook_file ‘/etc/cron.weekly/makewhatis.cron’ do
source ‘etc/cron.weekly/makewhatis.cron’
owner ‘root’
group ‘root’
mode 0000
end[/shell]

不要サービス停止の参考
serviceリソースのマニュアル
CentOSの要らないサービスを無効にするレシピ
ignore_failureをつけないと、パッケージが見つからない時点でエラーで止まってしまいます。

☆時刻同期のレシピ
サーバ側:
[shell]# vi ntpd.rb
package "ntp" do
action :install
end

service "ntpd" do
supports :status => true, :restart => true, :reload => :true
action [ :enable, :start ]
end

cookbook_file "ntpd.conf" do
path "/etc/ntp.conf"
source "etc/ntp.conf.erb"
owner "root"
group "root"
mode 0644
notifies :reload, ‘service[ntpd]’
end[/shell]

クライアント側(ntpdate)
[shell]# vi ntpdate.rb
cron "ntpdate" do
minute "0"
hour "*"
day "*"
month "*"
weekday"*"
command "/usr/sbin/ntpdate -bs 10.0.0.93"
action :create
end[/shell]
※ntpdateでの強制的な修正について納得いかない場合はクライアントにもntpdを入れるでよいかと思います。
cronリソースのマニュアル

☆mail設定レシピ
MTA側:
[shell]# vi mail-postfix.rb
filename = "postfix-2.3.3-2.3.el5_6.x86_64.rpm"
cookbook_file "/tmp/#{filename}" do
source "rpms/#{filename}"
mode 0644
end

package "postfix" do
action :install
source "/tmp/#{filename}"
provider Chef::Provider::Package::Rpm
end

script "backup_postfix_config" do
not_if ‘ls /etc/postfix/main.cf.org’
interpreter "bash"
user "root"
code <<-EOL
cp -p /etc/postfix/main.cf{,.org}
EOL
end

cookbook_file "/etc/postfix/main.cf" do
source "etc/postfix/main.cf"
mode 0644
end

user "vmailmgr" do
home "/home/vmailmgr"
shell "/bin/false"
uid 5000
groups 5000
end

directory ‘/var/spool/vmail’ do
owner ‘root’
group ‘mail’
mode 0775
action :create
end

dirpath = ‘/var/spool/vmail’
%W{webmaster, admin, info, root, ad}.each do |dir|
directory "#{dirpath}/dir" do
owner ‘vmailmgr’
group ‘vmailmgr’
mode 0755
action :create
end
end

cookbook_file "/etc/postfix/vmailbox" do
source "etc/postfix/vmailbox"
mode 0644
end

script "create_mailbox_map" do
not_if ‘ls /etc/postfix/vmailbox.db’
interpreter "bash"
user "root"
code <<-EOL
postmap /etc/postfix/vmailbox
touch /etc/postfix/valiases
postmap /etc/postfix/valiases
ln -sf /usr/sbin/sendmail.postfix /etc/alternatives/mta
EOL
end

service "sendmail" do
ignore_failure true
action [ :disable, :stop ]
end

service "postfix" do
supports :status => true, :restart => true, :reload => :true
action [ :enable, :start ]
end

# vi mail-dovecot.rb
filename = "dovecot-1.0.7-7.el5_7.1.x86_64.rpm"
cookbook_file "/tmp/#{filename}" do
source "rpms/#{filename}"
mode 0644
end

package "dovecot" do
action :install
source "/tmp/#{filename}"
provider Chef::Provider::Package::Rpm
end

script "backup_dovecot_config" do
not_if ‘ls /etc/dovecot.conf.org’
interpreter "bash"
user "root"
code <<-EOL
cp -p /etc/dovecot.conf{,.org}
EOL
end

cookbook_file "/etc/dovecot.conf" do
source "etc/dovecot.conf"
mode 0644
end

cookbook_file "/etc/dovecot_v.passwd" do
source "etc/dovecot_v.passwd"
mode 0644
end

filename = "xinetd-2.3.14-16.el5.x86_64.rpm"
cookbook_file "/tmp/#{filename}" do
source "rpms/#{filename}"
mode 0644
end

package "xinetd" do
action :install
source "/tmp/#{filename}"
provider Chef::Provider::Package::Rpm
end

cookbook_file "/etc/xinetd.d/dovecot" do
source "etc/xinetd.d/dovecot"
mode 0644
end

service "xinetd" do
supports :status => true, :restart => true, :reload => :true
action [ :enable, :start ]
end[/shell]

※パスワードファイルを作成する作業は対話なのでレシピ化できない。作ってあったものを送る。
 おおむね3分クッキングのように設定しておいたファイルを送ってパッケージ入れて起動して有効にして後から設定追加されたらリロードしてるだけです。

メールクライアント側:
[shell]# vi mail-client.rb
cookbook_file "/etc/mail/submit.cf" do
source "etc/mail/submit.cf"
mode 0644
end[/shell]

☆ログローテートレシピ

[shell]# vi logrotate.rb
cookbook_file ‘/etc/logrotate.d/syslog’ do
source ‘etc/logrotate.d/syslog’
owner ‘root’
group ‘root’
mode 0644
end[/shell]
初期値から変えてるのは世代数と圧縮するかどうかなど。

ひとまず今回はここまでです。
見ていただいてありがとうございました。
つづきはログインユーザ追加のレシピの予定です。この調子だと長いシリーズものになりそう。。

おすすめ記事