Create: 2013/08/13
LastUpdate: 2013/08/13
ここでは、Chef11を使用して、段階的にLAMP環境を構築していきます。
今回は、前回の「 [CentOS6][Chef] ChefでLAMP構成をつくる9 - OSアカウントの作成」に引き続き、任意のユーザでスクリプトを実行するレシピを追加します。
Chef11のテスト環境の詳細については、「メニュー」を参照してください。
[テスト環境]
- 管理サーバ
192.168.1.67(chetos6g) ・・・ Chefサーバ + ワークステーション - 管理対象
192.168.1.68(centos6h) ・・・ ノード
前回同様、テスト駆動開発のように、まずテストケースを作成してからレシピを作成し、実際にノードで実行する前に Cookbook が期待する動作を行うかテストすることにします。
Chefのレシピの書き方や、Chefspecのテストケースの書き方は、以下を参考にしました。
- 入門Chef Solo - Infrastructure as Code を読みながらChef Soloで遊べるようになるまで
- Cookbookテストフレームワーク「ChefSpec」
- chefspecチートシート
- Cucumber, ChefSpecとchefでテスト駆動のサーバ構築管理
- ChefのScript(bash)リソースでflagsを使って例外停止
今回使用する管理対象のノードは、前回までのレシピを実行した状態になっています。
今回作成する新しいレシピでは、app01ユーザで、テスト用のbashスクリプトを実行することにします。
1.Cookbook 作成
以下、管理サーバに chefユーザでログインして、Chefのワークステーションで作業します。
1.1.ひな形の作成
今回、"sandbox" という名称で新しくcookbookを作成するので、ひな形を用意します。
$ cd ~/chef-repo/cookbooks $ knife cookbook create sandbox $ knife cookbook create_specs sandbox
1.2.Chefspec のテストケース追加
以下のファイルにChefspecのテストケースを作成します。
- ~/chef-repo/cookbooks/sandbox/spec/default_spec.rb
require 'chefspec' describe 'sandbox::default' do let (:chef_run) { ChefSpec::ChefRunner.new.converge 'sandbox::default' } it 'should create bashrc' do expect(chef_run).to create_cookbook_file '/home/app01/.bashrc' file = chef_run.cookbook_file('/home/app01/.bashrc') expect(file.mode).to eq "0644" expect(file).to be_owned_by('app01', 'appgrp') end it 'should create example.sh' do expect(chef_run).to create_cookbook_file '/home/app01/example.sh' file = chef_run.cookbook_file('/home/app01/example.sh') expect(file.mode).to eq "0744" expect(file).to be_owned_by('app01', 'appgrp') end it 'should exec shell' do expect(chef_run).to execute_bash_script 'execute_shell' end endapp01ユーザのホームディレクトリに ".bashrc" と、テスト用スクリプトの "example.sh" を作成し、このテスト用スクリプトを実行しているかチェックします。
1.3.レシピ修正
以下のファイルにレシピを作成します。
- ~/chef-repo/cookbooks/sandbox/recipes/default.rb
"example.sh" は、1回しか実行できないようにするため、ログファイル(example.log)が存在したら実行しないようにします。
# # Cookbook Name:: sandbox # Recipe:: default # # Copyright 2013, YOUR_COMPANY_NAME # # All rights reserved - Do Not Redistribute # cookbook_file "/home/app01/.bashrc" do source "bashrc" owner "app01" group "appgrp" mode "0644" end cookbook_file "/home/app01/example.sh" do source "example.sh" owner "app01" group "appgrp" mode "0744" end bash "execute_shell" do user "app01" code <<-EOH /home/app01/example.sh EOH not_if "test -f /home/app01/example.log" endChefspecのテストケースを実行してレシピをチェックします。
結果が、以下のように "0 failures" であればOKです。
$ cd ~/chef-repo/cookbooks $ rspec -fd --color sandbox sandbox::default should create bashrc should create example.sh should exec shell Finished in 0.28809 seconds 3 examples, 0 failures
2.4.cookbook_file の作成
以下のCookbook に同梱するファイルを作成します。
- ~/chef-repo/cookbooks/sandbox/files/default/bashrc
- ~/chef-repo/cookbooks/sandbox/files/default/example.sh
# .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # User specific aliases and functions export TEST_WORD="xxxxxxxxxxxxxxxx""example.sh" の内容は、以下のとおり。
#!/bin/bash exec > /home/app01/example.log echo "***************** START" echo "----------------- pwd" pwd echo "----------------- whoami" whoami echo "----------------- id" id echo "----------------- env" env echo "***************** END" exit 0
2.5.metadata の変更
以下のファイルを修正して Cookbookの metadata 変更します。
- ~/chef-repo/cookbooks/users/metadata.rb
name 'sandbox' maintainer 'blue21' maintainer_email 'canopus@blue21.ddo.jp' license 'All rights reserved' description 'Installs/Configures sandbox' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '0.1.0'Foodcritic で Cookbookの全体的なチェック(文法、矛盾など)をします。
以下のように何も表示されなければOKです。
$ cd ~/chef-repo/cookbooks $ foodcritic ./sandbox
2.6.CookbookをChefサーバに登録
作成した Cookbook をChefサーバにアップロードします。
$ cd ~/chef-repo/cookbooks $ knife cookbook upload sandbox Uploading sandbox [0.1.0] Uploaded 1 cookbook.
3.ノードの Run List にレシピを追加
今回も、WebUIは使わずに、knifeコマンドを使用します。
管理サーバのワークステーションで以下のように実行します。
$ knife node run_list add centos6h 'recipe[sandbox]' centos6h: run_list: role[LAMP] recipe[mysql::database] recipe[users] recipe[sandbox]"centos6h" はノード名、"recipe[sandbox]" はレシピ名です。
4.ノードでレシピの実行
管理対象のノードに、root ユーザでログインして作業します。
以下のようにコマンドを実行して、レシピを実行します。
# /opt/chef/bin/chef-client Starting Chef Client, version 11.4.4 resolving cookbooks for run list: ["apache", "php", "mysql", "mysql::database", "users", "sandbox"] Synchronizing Cookbooks: - sandbox - users - mysql - apache - php Compiling Cookbooks... Recipe: mysql::database * chef_gem[ruby-mysql] action install (up to date) Converging 22 resources Recipe: apache::default * package[httpd] action install (up to date) * template[/etc/httpd/conf/httpd.conf] action create (up to date) * service[httpd] action enable (up to date) * service[httpd] action start (up to date) Recipe: php::default * package[php] action install (up to date) * package[php-mysql] action install (up to date) * package[php-mbstring] action install (up to date) * package[php-gd] action install (up to date) * template[/etc/php.ini] action create (up to date) Recipe: mysql::default * package[mysql] action install (up to date) * package[mysql-server] action install (up to date) * template[/etc/my.cnf] action create (up to date) * service[mysqld] action enable (up to date) * service[mysqld] action start (up to date) Recipe: mysql::database * link[/tmp/mysql.sock] action create (up to date) * chef_gem[ruby-mysql] action install (up to date) * mysql_database[appdb] action create (up to date) * mysql_database_user[app_user] action create (up to date) * mysql_database_user[app_user] action grant Recipe: users::default * group[appgrp] action create (up to date) * user[app01] action create (up to date) * user[app02] action remove (up to date) Recipe: sandbox::default * cookbook_file[/home/app01/.bashrc] action create - create a new cookbook_file /home/app01/.bashrc --- /home/app01/.bashrc 2013-08-13 14:13:33.328900857 +0900 +++ /var/chef/cache/cookbooks/sandbox/files/default/bashrc 2013-08-13 14:10:29.829900537 +0900 @@ -6,3 +6,4 @@ fi # User specific aliases and functions +export TEST_WORD="xxxxxxxxxxxxxxxx" * cookbook_file[/home/app01/example.sh] action create - create a new cookbook_file /home/app01/example.sh --- /tmp/chef-tempfile20130813-21151-1ivfnlf 2013-08-13 14:15:54.576900543 +0900 +++ /var/chef/cache/cookbooks/sandbox/files/default/example.sh 2013-08-13 14:15:54.575900543 +0900 @@ -0,0 +1,21 @@ +#!/bin/bash + +exec > /home/app01/example.log + +echo "***************** START" + +echo "----------------- pwd" +pwd + +echo "----------------- whoami" +whoami + +echo "----------------- id" +id + +echo "----------------- env" +env + +echo "***************** END" + +exit 0 * bash[execute_shell] action run - execute "bash" "/tmp/chef-script20130813-21151-1lv5qme" Chef Client finished, 4 resources updated適用済みのレシピは、何も行われていません。(up to date)
/home/app01に ".bashrc" と "example.sh" が作成され、"example.sh" が実行されたことが確認できます。
"example.sh" の実行結果は、以下のとおり。
# cat /home/app01/example.log ***************** START ----------------- pwd / ----------------- whoami app01 ----------------- id uid=10001(app01) gid=0(root) groups=10001(appgrp),0(root) ----------------- env HOSTNAME=centos6h SHELL=/bin/bash TERM=xterm HISTSIZE=1000 SSH_CLIENT=192.168.1.2 64697 22 SSH_TTY=/dev/pts/0 LC_ALL=C USER=root LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36: PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/opt/chef/embedded/bin:/opt/chef/embedded/bin MAIL=/var/spool/mail/root PWD=/ LANG=ja_JP.UTF-8 HISTCONTROL=ignoredups HOME=/root SHLVL=4 LOGNAME=root SSH_CONNECTION=192.168.1.2 64697 192.168.1.68 22 LESSOPEN=|/usr/bin/lesspipe.sh %s G_BROKEN_FILENAMES=1 _=/bin/env ***************** ENDこの結果を見ると、実行時の uid は app01ユーザ ですが、環境変数やグループは rootユーザのものです。ディレクトリも、app01 ユーザのホームディレクトリには移動していません。
app01 ユーザでログインして実行しているわけではないようです。(このページ参照)
app01 ユーザでログインして実行させるには、rootユーザで "su" コマンドを使用したほうが良さそうです。
レシピのスクリプト実行箇所を以下のように修正して、アップロードします。
bash "execute_shell" do code <<-EOH su - app01 -c /home/app01/example.sh EOH not_if "test -f /home/app01/example.log" end"example.log" を削除して、再度、レシピを実行すると以下のとおり。
# rm ./example.log
# /opt/chef/bin/chef-client
Starting Chef Client, version 11.4.4
resolving cookbooks for run list: ["apache", "php", "mysql", "mysql::database", "users", "sandbox"]
Synchronizing Cookbooks:
- sandbox
- users
- mysql
- apache
- php
Compiling Cookbooks...
Recipe: mysql::database
* chef_gem[ruby-mysql] action install (up to date)
Converging 22 resources
Recipe: apache::default
* package[httpd] action install (up to date)
* template[/etc/httpd/conf/httpd.conf] action create (up to date)
* service[httpd] action enable (up to date)
* service[httpd] action start (up to date)
Recipe: php::default
* package[php] action install (up to date)
* package[php-mysql] action install (up to date)
* package[php-mbstring] action install (up to date)
* package[php-gd] action install (up to date)
* template[/etc/php.ini] action create (up to date)
Recipe: mysql::default
* package[mysql] action install (up to date)
* package[mysql-server] action install (up to date)
* template[/etc/my.cnf] action create (up to date)
* service[mysqld] action enable (up to date)
* service[mysqld] action start (up to date)
Recipe: mysql::database
* link[/tmp/mysql.sock] action create (up to date)
* chef_gem[ruby-mysql] action install (up to date)
* mysql_database[appdb] action create (up to date)
* mysql_database_user[app_user] action create (up to date)
* mysql_database_user[app_user] action grant
Recipe: users::default
* group[appgrp] action create (up to date)
* user[app01] action create (up to date)
* user[app02] action remove (up to date)
Recipe: sandbox::default
* cookbook_file[/home/app01/.bashrc] action create (up to date)
* cookbook_file[/home/app01/example.sh] action create (up to date)
* bash[execute_shell] action run
- execute "bash" "/tmp/chef-script20130813-22412-1yke2mf"
Chef Client finished, 2 resources updated
"example.sh" だけ実行されました。"example.sh" の実行結果は、以下のとおり。 "~/.bashrc" も読み込まれたようです。(赤字部分で確認)
# cat example.log
***************** START
----------------- pwd
/home/app01
----------------- whoami
app01
----------------- id
uid=10001(app01) gid=10001(appgrp) 所属グループ=10001(appgrp)
----------------- env
HOSTNAME=centos6h
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
USER=app01
TEST_WORD=xxxxxxxxxxxxxxxx
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/app01/bin
MAIL=/var/spool/mail/app01
PWD=/home/app01
LANG=ja_JP.UTF-8
HISTCONTROL=ignoredups
HOME=/home/app01
SHLVL=2
LOGNAME=app01
LESSOPEN=|/usr/bin/lesspipe.sh %s
G_BROKEN_FILENAMES=1
_=/bin/env
***************** END
■ 補足
以下のようにすると、レシピで環境変数を設定したり、初期ディレクトリを指定することもできます。
bash "execute_shell" do user "app01" group "appgrp" cwd "/home/app01" environment 'HOME' => '/home/app01', 'USER' => 'app01' code <<-EOH . /home/app01/.bashrc /home/app01/example.sh EOH not_if "test -f /home/app01/example.log" end