まえがき
こんにちはじょにーです。夏休みの自由研究です。
前から触ってみたかったItamaeと、Serverspecによるテストを行える環境を作ってみました。
こえむさんによる
Itamae + Serverspec でサーバ構築・テスト自動化 総仕上げ! | こえむの編集後記
こちらを参考に(というかほぼそのままなぞって)CentOS7にてItamaeとServerspec によるインフラ構築を試した記録です。
ほぼそのままなぞっただけですので、本来は記事として書くようなことでもないのですが、
特に予備知識なくそのままなぞった際に、うまくく動かないところがありましたので、トライアンドエラーを繰り返してかつそのまま記載しています。そのあたりの試行の参考になればいいなという感じです。
手順
IDCFクラウドにてCentOS7.1の仮想サーバーを2台準備しました
- admin01
- node01
上記にログインして進めていきます。
admin01を作業環境として、
node01にmysqlとhttpd、phpをインストール&テスト という使い方をしてみます。
まずはadmin01にログインし、
rubyのバージョンが2.0以上であることを確認します
[root@admin01 ~]# ruby -v ruby 2.0.0p598 (2014-11-13) [x86_64-linux]
admin01のhostsにnode01のローカルIPを記載します
[root@admin01 ~]# vi /etc/hosts (10.3.0.222 node01 を追記。IPアドレスはIDCFクラウドの管理画面より確認) [root@admin01 ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 10.3.0.222 node01
手順に従って、Itamae, Serverspecをインストールして準備します
[root@admin01 ~]# mkdir work [root@admin01 ~]# cd work/ [root@admin01 work]# gem install bundler Fetching: bundler-1.10.6.gem (100%) Successfully installed bundler-1.10.6 Parsing documentation for bundler-1.10.6 Installing ri documentation for bundler-1.10.6 1 gem installed [root@admin01 work]# vim Gemfile [root@admin01 work]# cat Gemfile # Gemfile source "https://rubygems.org" gem "rake" gem "itamae" gem "serverspec" [root@admin01 work]# bundle install
レシピを書いてみます
レシピ配置用のディレクトリを作っておきます
[root@admin01 work]# mkdir recipes [root@admin01 work]# mkdir recipes/mysqld [root@admin01 work]# mkdir recipes/httpd
お手本通りにmysqldのレシピを作成します
[root@admin01 work]# vi recipes/mysqld/mysqld.rb
[root@admin01 work]# cat recipes/mysqld/mysqld.rb
# recipes/mysqld/mysqld.rb
MYSQL_PASSWORD=node[ENV['TARGET_HOST']]['mysqld']['password']
execute "yum -t -y install http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm"
%w{
mysql-community-client
mysql-community-devel
mysql-community-server
}.each do |pkg_name|
package pkg_name do
action :install
end
end
service "mysqld" do
action [ :enable, :start ]
end
execute "mysql -u root -e \"SET PASSWORD=PASSWORD('#{MYSQL_PASSWORD}');\""
execute "mysql -uroot -p#{MYSQL_PASSWORD} -e \"DELETE FROM mysql.user WHERE User='';\""
execute "mysql -uroot -p#{MYSQL_PASSWORD} -e \"DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');\""
execute "mysql -uroot -p#{MYSQL_PASSWORD} -e \"DROP DATABASE test;\"; echo"
execute "mysql -uroot -p#{MYSQL_PASSWORD} -e \"DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'\""
execute "mysql -uroot -p#{MYSQL_PASSWORD} -e \"FLUSH PRIVILEGES;\""
続いて、httpdのレシピです
[root@admin01 work]# vi recipes/httpd/httpd.rb
[root@admin01 work]# cat recipes/httpd/httpd.rb
# recipes/httpd/httpd.rb
%w{
httpd
php
php-gd
php-mbstring
php-xml
php-pdo
php-mysql
}.each do |pkg_name|
package pkg_name do
action :install
end
end
template "/etc/php.ini" do
source "php.ini.erb"
end
service "httpd" do
action [ :enable, :start ]
end
execute "firewall-cmd --permanent --add-service=http"
execute "firewall-cmd --reload"
execute "setsebool -P httpd_can_network_connect 1"
php.iniはとりあえずローカルにあったものを持ってきてみました
[root@admin01 work]# cp /etc/php.ini ./recipes/httpd/php.ini.erb
手順に従ってServerspecのテストを持ってきます
[root@admin01 work]# mkdir -p spec/mysqld [root@admin01 work]# cd spec/mysqld [root@admin01 mysqld]# wget https://raw.githubusercontent.com/koemu/webapp_mook_servertest/master/spec/saito-hb-vm007/mysql_spec.rb 中略 2015-08-13 15:56:12 (209 MB/s) - `mysql_spec.rb' へ保存完了 [1093/1093] [root@admin01 mysqld]# cd ../../ [root@admin01 work]# mkdir -p spec/httpd [root@admin01 work]# cd spec/httpd [root@admin01 httpd]# wget https://raw.githubusercontent.com/koemu/webapp_mook_servertest/master/spec/saito-hb-vm007/httpd_spec.rb 中略 2015-08-13 15:56:33 (341 MB/s) - `httpd_spec.rb' へ保存完了 [1777/1777] [root@admin01 httpd]# cd ../../ [root@admin01 work]# cd spec [root@admin01 spec]# wget https://raw.githubusercontent.com/koemu/webapp_mook_servertest/master/spec/spec_helper.rb 中略 2015-08-13 15:56:51 (136 MB/s) - `spec_helper.rb' へ保存完了 [679/679] [root@admin01 spec]# cd ..
Rakefileを整えてみます
[root@admin01 work]# wget https://raw.githubusercontent.com/koemu/webapp_mook_itamae_demo/master/Rakefile 2015-08-13 15:59:16 (192 MB/s) - `Rakefile' へ保存完了 [1004/1004]
properties.jsonを書きます
[root@admin01 work]# vi properties.json
[root@admin01 work]# cat properties.json
{
"node01": {
"ssh_user": "root",
"ssh_port": 22,
"roles": ["mysqld", "httpd"]
}
}
sshの設定をします
[root@admin01 work]# vi ~/.ssh/config [root@admin01 work]# cat ~/.ssh/config Host node01 HostName node01 User root IdentityFile ~/.ssh/hoge.key
確認をします
[root@admin01 work]# bundle exec rake -vT rake aborted! LoadError: cannot load such file -- json /root/work/Rakefile:2:in `require' /root/work/Rakefile:2:in `<top (required)>' (See full trace by running task with --trace) [root@admin01 work]#
あれ、怒られましたね
jsonを入れます
[root@admin01 work]# gem install json
Fetching: json-1.8.3.gem (100%)
Building native extensions. This could take a while...
ERROR: Error installing json:
ERROR: Failed to build gem native extension.
/usr/bin/ruby extconf.rb
mkmf.rb can't find header files for ruby at /usr/share/include/ruby.h
Gem files will remain installed in /usr/local/share/gems/gems/json-1.8.3 for inspection.
Results logged to /usr/local/share/gems/gems/json-1.8.3/ext/json/ext/generator/gem_make.out
さらに怒られました Gemfileでやってみよう
[root@admin01 work]# vi Gemfile [root@admin01 work]# cat Gemfile # Gemfile source "https://rubygems.org" gem "json" gem "rake" gem "itamae" gem "serverspec" [root@admin01 work]# bundle install
なんか入ったっぽい
再度確認します
[root@admin01 work]# bundle exec rake -vT rake aborted! LoadError: cannot load such file -- json/pure /usr/share/gems/gems/json-1.7.7/lib/json.rb:60:in `require' /usr/share/gems/gems/json-1.7.7/lib/json.rb:60:in `rescue in <module:JSON>' /usr/share/gems/gems/json-1.7.7/lib/json.rb:57:in `<module:JSON>' /usr/share/gems/gems/json-1.7.7/lib/json.rb:54:in `<top (required)>' /root/work/Rakefile:2:in `require' /root/work/Rakefile:2:in `<top (required)>' (See full trace by running task with --trace)
ありゃ、今度はjson/pureがないそうです
Gemfileに書き足して再度bundle installします
[root@admin01 work]# vi Gemfile [root@admin01 work]# cat Gemfile # Gemfile source "https://rubygems.org" gem "json" gem "json_pure" gem "rake" gem "itamae" gem "serverspec" [root@admin01 work]# bundle install
なんか入ったっぽい
再再度確認します
[root@admin01 work]# bundle exec rake -vT rake itamae:node01 # Run itamae to node01 rake serverspec:node01 # Run serverspec to node01
OKでしたね
いよいよitamaeの実行とテストです
[root@admin01 work]# bundle exec rake itamae:node01 serverspec:node01 bundle exec itamae ssh -h node01 -u root -i -p 22 -j properties.json recipes/mysqld/mysqld.rb recipes/httpd/httpd.rb INFO : Starting Itamae... INFO : Loading node data from /root/work/properties.json... /usr/local/share/gems/gems/net-ssh-2.9.2/lib/net/ssh.rb:224:in `start': Authentication failed for user root@node01 (Net::SSH::AuthenticationFailed)
おっと 中略しますが鍵認証で接続できてませんでした
Rakefileをよく読むと鍵の指定をしているようなので、properties.jsonに鍵の指定を追記します
[root@admin01 work]# vi properties.json
[root@admin01 work]# cat properties.json
{
"node01": {
"ssh_user": "root",
"ssh_port": 22,
"private_key": "~/.ssh/hoge.key",
"roles": ["mysqld", "httpd"]
}
}
再度実行してみます
[root@admin01 work]# bundle exec rake itamae:node01 serverspec:node01 (中略) /root/work/recipes/mysqld/mysqld.rb:2:in `load': undefined method `[]' for nil:NilClass (NoMethodError)
ということで、ちょっと謎のエラーが出て解決できないので、切り分けも含めてmysqldの実行とテストを後回しにします
properties.jsonからmysqldを削除
[root@admin01 work]# vi properties.json
[root@admin01 work]# cat properties.json
{
"node01": {
"ssh_user": "root",
"ssh_port": 22,
"private_key": "~/.ssh/hoge.key",
"roles": ["httpd"]
}
}
httpdのみの設定で、実行してみます
[root@admin01 work]# bundle exec rake itamae:node01 serverspec:node01
bundle exec itamae ssh -h node01 -u root -i ~/.ssh/hoge.key -p 22 -j properties.json recipes/httpd/httpd.rb
INFO : Starting Itamae...
INFO : Loading node data from /root/work/properties.json...
INFO : Recipe: /root/work/recipes/httpd/httpd.rb
INFO : package[httpd] installed will change from 'false' to 'true'
INFO : package[php] installed will change from 'false' to 'true'
INFO : package[php-gd] installed will change from 'false' to 'true'
INFO : package[php-mbstring] installed will change from 'false' to 'true'
INFO : package[php-xml] installed will change from 'false' to 'true'
INFO : package[php-pdo] installed will change from 'false' to 'true'
INFO : package[php-mysql] installed will change from 'false' to 'true'
INFO : diff:
INFO : --- /etc/php.ini 2015-06-24 06:20:23.000000000 +0900
INFO : +++ /tmp/itamae_tmp/1439455347.5930629 2015-08-13 17:42:27.843020664 +0900
INFO : @@ -210,7 +210,7 @@
INFO : ; http://php.net/short-open-tag
INFO : short_open_tag = Off
INFO :
INFO : -; Allow ASP-style <% %> tags.
INFO : +; Allow ASP-style tags.
INFO : ; http://php.net/asp-tags
INFO : asp_tags = Off
INFO :
INFO : service[httpd] enabled will change from 'false' to 'true'
INFO : service[httpd] running will change from 'false' to 'true'
INFO : execute[firewall-cmd --permanent --add-service=http] executed will change from 'false' to 'true'
ERROR : stdout | [91mFirewallD is not running[00m
ERROR : Command `firewall-cmd --permanent --add-service=http` failed. (exit status: 252)
ERROR : execute[firewall-cmd --permanent --add-service=http] Failed.
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-core-3.3.2/lib:/usr/local/share/gems/gems/rspec-support-3.3.0/lib /usr/local/share/gems/gems/rspec-core-3.3.2/exe/rspec --pattern spec/\{httpd\}/\*_spec.rb
.......FF....
Failures:
1) Apacheのインストール PHPのインストール php.iniの設定を変更している Php config "date.timezone" value should eq "Asia/Tokyo"
Failure/Error: its(:value) { should eq "Asia/Tokyo" }
expected: "Asia/Tokyo"
got: ""
(compared using ==)
# ./spec/httpd/httpd_spec.rb:38:in `block (5 levels) in <top (required)>'
2) Apacheのインストール PHPのインストール php.iniの設定を変更している Php config "mbstring.internal_encoding" value should eq "UTF-8"
Failure/Error: its(:value) { should eq "UTF-8" }
expected: "UTF-8"
got: ""
(compared using ==)
# ./spec/httpd/httpd_spec.rb:42:in `block (5 levels) in <top (required)>'
Finished in 1.32 seconds (files took 0.26656 seconds to load)
13 examples, 2 failures
Failed examples:
rspec ./spec/httpd/httpd_spec.rb:38 # Apacheのインストール PHPのインストール php.iniの設定を変更している Php config "date.timezone" value should eq "Asia/Tokyo"
rspec ./spec/httpd/httpd_spec.rb:42 # Apacheのインストール PHPのインストール php.iniの設定を変更している Php config "mbstring.internal_encoding" value should eq "UTF-8"
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-core-3.3.2/lib:/usr/local/share/gems/gems/rspec-support-3.3.0/lib /usr/local/share/gems/gems/rspec-core-3.3.2/exe/rspec --pattern spec/\{httpd\}/\*_spec.rb failed
テストはちゃんと動いたようです。ということはmysqldのレシピに問題がありそうです。あとで見てみましょう。
ひとまず、httpdのテスト結果の方はどうかというと、ローカルに適当に置いてあったphp.iniなのでテストと差分があります。
php.iniを修正します
[root@admin01 work]# vi recipes/httpd/php.ini.erb date.timezone = Asia/Tokyo mbstring.internal_encoding = UTF-8
再度実行してみます
[root@admin01 work]# bundle exec rake itamae:node01 serverspec:node01
bundle exec itamae ssh -h node01 -u root -i ~/.ssh/hoge.key -p 22 -j properties.json recipes/httpd/httpd.rb
INFO : Starting Itamae...
INFO : Loading node data from /root/work/properties.json...
INFO : Recipe: /root/work/recipes/httpd/httpd.rb
INFO : diff:
INFO : --- /etc/php.ini 2015-08-13 17:42:27.843020664 +0900
INFO : +++ /tmp/itamae_tmp/1439455835.036678 2015-08-13 17:50:35.053458574 +0900
INFO : @@ -875,7 +875,7 @@
INFO : [Date]
INFO : ; Defines the default timezone used by the date functions
INFO : ; http://php.net/date.timezone
INFO : -;date.timezone =
INFO : +date.timezone = Asia/Tokyo
INFO :
INFO : ; http://php.net/date.default-latitude
INFO : ;date.default_latitude = 31.7667
INFO : @@ -1663,7 +1663,7 @@
INFO : ; Some encoding cannot work as internal encoding.
INFO : ; (e.g. SJIS, BIG5, ISO-2022-*)
INFO : ; http://php.net/mbstring.internal-encoding
INFO : -;mbstring.internal_encoding = EUC-JP
INFO : +mbstring.internal_encoding = UTF-8
INFO :
INFO : ; http input encoding.
INFO : ; http://php.net/mbstring.http-input
INFO : execute[firewall-cmd --permanent --add-service=http] executed will change from 'false' to 'true'
ERROR : stdout | [91mFirewallD is not running[00m
ERROR : Command `firewall-cmd --permanent --add-service=http` failed. (exit status: 252)
ERROR : execute[firewall-cmd --permanent --add-service=http] Failed.
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-core-3.3.2/lib:/usr/local/share/gems/gems/rspec-support-3.3.0/lib /usr/local/share/gems/gems/rspec-core-3.3.2/exe/rspec --pattern spec/\{httpd\}/\*_spec.rb
.............
Finished in 0.70656 seconds (files took 0.26856 seconds to load)
13 examples, 0 failures
php.iniの内容が書き換わり、テストを全部通過することが出来ました。これでhttpdについてはOKですね。
さてmysqldの方に戻ってみましょう レシピの設定で怪しかったところを変えます
[root@admin01 work]# vi /root/work/recipes/mysqld/mysqld.rb MYSQL_PASSWORD="TESTPASSWORD"
mysqldのテストを行うように、properties.jsonを書き換えます
[root@admin01 work]# vi properties.json
[root@admin01 work]# cat properties.json
{
"node01": {
"ssh_user": "root",
"ssh_port": 22,
"private_key": "~/.ssh/hoge.key",
"roles": ["mysqld"]
}
}
mysqldの実行とテストと行います
[root@admin01 work]# bundle exec rake itamae:node01 serverspec:node01
bundle exec itamae ssh -h node01 -u root -i ~/.ssh/hoge.key -p 22 -j properties.json recipes/mysqld/mysqld.rb
INFO : Starting Itamae...
INFO : Loading node data from /root/work/properties.json...
INFO : Recipe: /root/work/recipes/mysqld/mysqld.rb
INFO : execute[yum -t -y install http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm] executed will change from 'false' to 'true'
INFO : package[mysql-community-client] installed will change from 'false' to 'true'
INFO : package[mysql-community-devel] installed will change from 'false' to 'true'
INFO : package[mysql-community-server] installed will change from 'false' to 'true'
INFO : service[mysqld] running will change from 'false' to 'true'
INFO : execute[mysql -u root -e "SET PASSWORD=PASSWORD('TESTPASSWORD');"] executed will change from 'false' to 'true'
INFO : execute[mysql -uroot -pTESTWASSWORD -e "DELETE FROM mysql.user WHERE User='';"] executed will change from 'false' to 'true'
INFO : execute[mysql -uroot -pTESTWASSWORD -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');"] executed will change from 'false' to 'true'
INFO : execute[mysql -uroot -pTESTWASSWORD -e "DROP DATABASE test;"; echo] executed will change from 'false' to 'true'
INFO : execute[mysql -uroot -pTESTWASSWORD -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%'"] executed will change from 'false' to 'true'
INFO : execute[mysql -uroot -pTESTWASSWORD -e "FLUSH PRIVILEGES;"] executed will change from 'false' to 'true'
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-core-3.3.2/lib:/usr/local/share/gems/gems/rspec-support-3.3.0/lib /usr/local/share/gems/gems/rspec-core-3.3.2/exe/rspec --pattern spec/\{mysqld\}/\*_spec.rb
.......F
Failures:
1) MySQLのインストール MySQLにrootユーザでログインできる Command "mysql -uroot -phbadmin -e "SELECT user FROM mysql.user"" exit_status should eq 0
Failure/Error: its(:exit_status) { should eq 0 }
expected: 0
got: 1
(compared using ==)
# ./spec/mysqld/mysql_spec.rb:40:in `block (4 levels) in <top (required)>'
Finished in 0.70786 seconds (files took 0.25649 seconds to load)
8 examples, 1 failure
Failed examples:
rspec ./spec/mysqld/mysql_spec.rb:40 # MySQLのインストール MySQLにrootユーザでログインできる Command "mysql -uroot -phbadmin -e "SELECT user FROM mysql.user"" exit_status should eq 0
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-core-3.3.2/lib:/usr/local/share/gems/gems/rspec-support-3.3.0/lib /usr/local/share/gems/gems/rspec-core-3.3.2/exe/rspec --pattern spec/\{mysqld\}/\*_spec.rb failed
一応ちゃんとテストまでできましたね。ということはnodeのあたりがうまく動いていなかったようですが、、、ruby全然わかりませんので誰か詳しい方教えてください><
さて今回のテストでFailedになった箇所を見てみますと、MySQLにrootでログインできなかった ということで、一番肝心なところがコケていたわけですが……。
テストの方を再度確認してみると
describe "MySQLにrootユーザでログインできる" do
describe command('mysql -uroot -phbadmin -e "SELECT user FROM mysql.user"') do
its(:exit_status) { should eq 0 }
end
end
とのことで、パスワードが違いますね。
-phbadmin ってこれ、いろいろ大丈夫かしらw
パスワードを書き換えます
[root@admin01 work]# vi spec/mysqld/mysql_spec.rb
describe command('mysql -uroot -pTESTPASSWORD -e "SELECT user FROM mysql.user"') do
再度実行。
[root@admin01 work]# bundle exec rake itamae:node01 serverspec:node01
bundle exec itamae ssh -h node01 -u root -i ~/.ssh/hoge.key -p 22 -j properties.json recipes/mysqld/mysqld.rb
INFO : Starting Itamae...
INFO : Loading node data from /root/work/properties.json...
INFO : Recipe: /root/work/recipes/mysqld/mysqld.rb
INFO : execute[yum -t -y install http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm] executed will change from 'false' to 'true'
ERROR : stdout | Loaded plugins: fastestmirror, remove-with-leaves, show-leaves
ERROR : stdout | mysql-community-release-el7-5.noarch.rpm | 6.0 kB 00:00
ERROR : stdout | Examining /var/tmp/yum-root-cdVUFD/mysql-community-release-el7-5.noarch.rpm: mysql-community-release-el7-5.noarch
ERROR : stdout | /var/tmp/yum-root-cdVUFD/mysql-community-release-el7-5.noarch.rpm: does not update installed package.
ERROR : stdout | Error: Nothing to do
ERROR : Command `yum -t -y install http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm` failed. (exit status: 1)
ERROR : execute[yum -t -y install http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm] Failed.
/usr/bin/ruby -I/usr/local/share/gems/gems/rspec-core-3.3.2/lib:/usr/local/share/gems/gems/rspec-support-3.3.0/lib /usr/local/share/gems/gems/rspec-core-3.3.2/exe/rspec --pattern spec/\{mysqld\}/\*_spec.rb
........
Finished in 0.36045 seconds (files took 0.27488 seconds to load)
8 examples, 0 failures
…無事通りました!この書き方ですと毎回executeでinstallしようとしてしまいますが、、、仕方ないですかね。
ともあれ、これでひとまず基礎的なところは追えたかと思います。
最近は仕事のほうでサーバーをちゃんと触る機会がなかなか少なくなって来てまして、久々に楽しかったです。rubyはわからんけど!w
余裕があれば後日、対象サーバーを増やしたりなどのバリエーションを試そうと思います。
僕のお財布にも余裕があるとたくさん増やせるのですが。。。まぁいいでしょうw