講師:@tily

Chef Apply と Chef Solo と serverspec とニフティクラウドとニフティクラウドオートメーションβが試せるお得なハンズオンです。


0. 目次

1. 準備

1.1. SSH でサーバーへログイン

Windows の場合

  1. TeraTerm を起動
  2. 「ホスト」に当日配布の IP アドレスを入力
  3. 「TCP ポート」に "22" を入力
  4. 「OK」ボタンをクリック (次の画面が表示されます)
  5. 「ユーザ名」に "root" を入力
  6. 「パスフレーズ」に当日配布のパスフレーズを入力
  7. 「RSA/DSA 鍵を使う」を選択し「秘密鍵」ボタンから当日配布する秘密鍵を指定
  8. 「OK」ボタンをクリック

下記のようなプロンプトが表示されればログイン成功です。

[root@localhost ~]#

Mac OS X の場合

通常の SSH ログインコマンドでログイン可能です。

chmod 600 ncstudy05_private.pem
ssh -i /path/to/ncstudy05_private.pem root@[グローバルIPアドレス]

1.2. Chef Solo のインストール

下記コマンドで一発でインストールすることができます。

# curl -L https://www.opscode.com/chef/install.sh | bash

ちなみにバージョンを固定したい場合は -v で指定したり RPM から直接インストールすることも可能です。

# bash install.sh -v 11.4.4.-2
# rpm -ivh https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-11.4.4-2.el6.x86_64.rpm

正常にインストールが完了したかどうか chef-solo コマンドで確認してみましょう。

# chef-solo
[2013-07-09T17:15:39+09:00] WARN: *****************************************
[2013-07-09T17:15:39+09:00] WARN: Did not find config file: /etc/chef/solo.rb, using command line options.
[2013-07-09T17:15:39+09:00] WARN: *****************************************
Starting Chef Client, version 11.4.0
Compiling Cookbooks...
Converging 0 resources
Chef Client finished, 0 resources updated
# which chef-solo
/usr/bin/chef-solo

Chef 関連のモジュールは /opt/chef 配下にインストールされるので ls で閲覧してみてください。

# ls /opt/chef/bin/
chef-apply  chef-client  chef-shell  chef-solo  erubis  knife  ohai  restclient  shef

2. Chef Apply を試す

2.1. Chef Apply とは

chef gem をインストールすると、chef-apply というコマンドもインストールされます。 chef-solo よりも手軽に Chef の「べき等性」が試せるので、少し触ってみましょう。

2.2. レシピの作成と実行

まずはかんたんなレシピを作成します。 ファイルを作成して中に “hello world” と書き込むだけのものです。

# vi recipe.rb
## 下記内容を書き込みます
file '/var/tmp/test.txt' do
  content "hello, world\n"
end

実行してみます。

# chef-apply recipe.rb
Recipe: (chef-apply cookbook)::(chef-apply recipe)
  * file[/var/tmp/test.txt] action create
    - create new file /var/tmp/test.txt with content checksum 853ff9
        --- /tmp/chef-tempfile20130709-856-1n2lyfc      2013-07-09 17:19:24.658237382 +0900
        +++ /tmp/chef-diff20130709-856-1qjl5ez  2013-07-09 17:19:24.658237382 +0900
        @@ -0,0 +1 @@
        +hello, world

ファイルが作成されたようです。実際に確認してみます。

# ls /var/tmp/test.txt
/var/tmp/test.txt
# cat /var/tmp/test.txt
hello, world

2.3. べき等性の確認

もう一度実行してみます。

# chef-apply recipe.rb
Recipe: (chef-apply cookbook)::(chef-apply recipe)
  * file[/var/tmp/test.txt] action create (up to date)

今度は up to date と表示され何も起きません。これはサーバーがレシピに書かれた内容通りの状態になっていることを Chef が認識し、ファイル作成をスキップしたためです。

このように「何度実行しても結果が同じになる」ような性質を Chef (や構成管理ツール) の世界では「idemponent (べき等)」と呼んでいます。

次にわざと作成されたファイルを書き換えた上で実行してみましょう。

# echo hello nifty cloud > /var/tmp/test.txt
# cat /var/tmp/test.txt
hello nifty cloud
# chef-apply recipe.rb
Recipe: (chef-apply cookbook)::(chef-apply recipe)
  * file[/var/tmp/test.txt] action create
    - update content in file /var/tmp/test.txt from bac308 to 853ff9
        --- /var/tmp/test.txt   2013-07-09 17:28:37.003242663 +0900
        +++ /tmp/chef-diff20130709-2021-umd0np  2013-07-09 17:28:54.504237642 +0900
        @@ -1 +1 @@
        -hello nifty cloud
        +hello, world

ファイルが書き換わったことを認識して Chef がレシピ通りの状態に復元してくれたことが確認できたと思います。

今度は recipe.rb 自体のほうを書き換えた上で Chef 実行してみます。

# vi recipe.rb
## world を chef に書き換えた
file '/var/tmp/test.txt' do
  content "hello, chef\n"
end
# chef-apply recipe.rb
Recipe: (chef-apply cookbook)::(chef-apply recipe)
  * file[/var/tmp/test.txt] action create
    - update content in file /var/tmp/test.txt from 853ff9 to 5b8079
        --- /var/tmp/test.txt   2013-07-09 17:28:54.557365556 +0900
        +++ /tmp/chef-diff20130709-2432-3waga3  2013-07-09 17:31:54.521237988 +0900
        @@ -1 +1 @@
        -hello, world
        +hello, chef

この場合にもサーバーの状態がレシピに記述された状態とは異なるので変更が適用されます。

このように、サーバーに変更が反映されるのは、下記の 2 つの場合のみです。

  • サーバーの状態がレシピと異なってしまった場合
  • レシピ自体が更新された場合

3. Chef Solo で WordPress レシピ開発

3.1. Chef Solo 用の設定ファイル配置

それでは簡易版ではなく、本格的な Cookbook をダウンロードして実行してみましょう。

まずは準備として Chef Solo が cookbooks 置き場として利用するディレクトリを作成しておきます。

mkdir -p /var/chef/cookbooks

あと、少し煩雑ですがこの後の手順で knife cookbook site install コマンドを利用するために、/var/chef/cookbooks を git レポジトリにしておきます。

yum install -y git
cd /var/chef/cookbooks
git init .
touch README
git add README
git commit -m "add readme."

3.2. WordPress レシピのダウンロード

それでは、Opscode のコミュニティサイトから knife コマンドを利用して wordpress cookbook をダウンロードしましょう。

下記のコマンドを実行します。

# knife cookbook site install wordpress
## wordpress および wordpress が依存

/var/chef/cookbooks を見てみると、いくつかの cookbooks がインストールされているのが分かります。

# cd /var/chef/cookbooks
# ls
README  apache2  build-essential  mysql  openssl  php  wordpress  xml

自動でブランチも切られているので、オリジナルの cookbook との差分を確認しながら cookbook を開発することができます。

# git branch
  chef-vendor-apache2
  chef-vendor-build-essential
  chef-vendor-mysql
  chef-vendor-openssl
  chef-vendor-php
  chef-vendor-wordpress
  chef-vendor-xml

3.3. レシピ実行

cookbooks が正常にダウンロードできたので、実行してみます。

まずは設定ファイルを作成します。

# vi dna.json
## 下記の内容を書き込む
{
  "run_list": ["recipe[wordpress]"],
  "mysql": {
    "server_root_password": "password",
    "server_debian_password": "password",
    "server_repl_password": "password"
  }
}

上記ファイルを指定して chef-solo を実行してみます。

# chef-solo -j dna.json

ずらずらと Chef のログが流れはじめます。しばらくして下記のようなメッセージが表示されたら実行完了です。

## これより上のログは省略
Recipe: apache2::default
  * service[apache2] action restart
    - restart service service[apache2]

Recipe: wordpress::default
  * log[wordpress_install_message] action write

Chef Client finished, 109 resources updated

当日配布するグローバル IP アドレスをブラウザに張り付けてみましょう。

WordPress のインストール画面が表示されたら成功です。

4. レシピのテストを書く

4.1. serverspec のインストール

せっかくなので、たった今行った動作確認の作業を今話題の serverspec で自動化してみましょう。

まず gem コマンドでインストールするため、Chef Solo をインストールしたときについてきた gem にパスを通しておきます。

# export PATH=$PATH:/opt/chef/embedded/bin/
# gem -v
1.8.24

serverspec をインストールします。

# gem install serverspec

serverspec-init というコマンドがインストールされます。

このコマンドでテストのひな形を作ります。 backend type (SSH 経由でテストするかローカルでテストするか) を聞かれるので、今回は「2) Exec (local) 」を選択しましょう。

(もちろんニフティクラウドのサーバーは SSH 経由でもテスト可能です。)

# serverspec-init
Select a backend type:

  1) SSH
  2) Exec (local)

Select number: 2     ## 2 を入力

 + spec/
 + spec/localhost/
 + spec/localhost/httpd_spec.rb
 + spec/spec_helper.rb
 + Rakefile

4.2. httpd のテストを修正

この状態で rake spec コマンドを実行すると、デフォルトで作成された httpd のテストが失敗します。

# rake spec
/opt/chef/embedded/bin/ruby -S rspec spec/localhost/httpd_spec.rb
.....F

Failures:

  1) File "/etc/httpd/conf/httpd.conf"
     Failure/Error: it { should contain "ServerName localhost" }
       grep -q -- ServerName\ localhost /etc/httpd/conf/httpd.conf
       expected File "/etc/httpd/conf/httpd.conf" to contain "ServerName localhost"
     # ./spec/localhost/httpd_spec.rb:18:in `block (2 levels) in <top (required)>'

Finished in 0.06117 seconds
6 examples, 1 failure

Failed examples:

rspec ./spec/localhost/httpd_spec.rb:18 # File "/etc/httpd/conf/httpd.conf"
rake aborted!
/opt/chef/embedded/bin/ruby -S rspec spec/localhost/httpd_spec.rb failed

Tasks: TOP => spec
(See full trace by running task with --trace)

今回はドメイン取得は行わないので、ServerName のテストは削除しておきます。

削除した上、rake spec で F が表示されなくなったら、次へ進みましょう。

4.3. mysqld のテストを作成

httpd_spec.rb を参考に、mysqld のテストを書いてみます。

下記が確認できるようにしましょう。

  • mysql-server パッケージがインストールされていること
  • mysqld デーモンが有効化されていること (chkconfig mysqld on されていること)
  • mysqld デーモンが起動していること
  • 3306 ポートが LISTEN していること
# vi ./spec/localhost/mysqld_spec.rb

(回答例はこちら:https://gist.github.com/tily/5990140)

4.4. wordpress のテストを作成

次に、serverspec のドキュメント を参照しながら、 下記を確認できるようにしてみます。

  • http://localhost/wp-admin/install.php にアクセスすると "Welcome to the famous five minute WordPress installation process!" という文字列が表示されること
# vi ./spec/localhost/wordpress_spec.rb

(回答例はこちら:https://gist.github.com/tily/5990140)

4.5 進んだ使い方

HTML 出力
# rake spec SPEC_OPTS="--format html"
JUnit 形式の XML (Jenkins で利用可能) へ変換
# gem install ci_reporter

# vi Rakefile
## 下記行を追加
require 'ci/reporter/rake/rspec'

# rake ci:setup:rspec spec
## spec/reports 配下に XML ファイルが生成される

このような仕組みにより、こんな使い方をすることが可能。

  • 既存のサーバーで定期的に serverspec を実行し HTML 出力結果をメールで通知
  • Jenkins で定期的にニフティクラウドのサーバーを立ち上げ serverspec のテスト結果を出力

参考:

5. CloudAutomation β で自動化!

5.1. レシピのアップロード

(ここからは API キーが必要な関係で講師のデモになります。)

これまで作った cookbooks をニフティクラウドにアップロードします。

例:https://some.ncss.nifty.com/cookbooks.tgz

5.2. JSON ファイル作成

今回のハンズオンで使った dna.json をそのまま JSON テンプレートの中に指定することができます。

{
  "run_list": [
      "recipe[nc::dependency_resolver]",
      "recipe[nc::manager_store]",
      "recipe[nc::manager]"
  ],
  "nc": {
    "resource": {
      "security_group": [
        {"name": "wordpressfw"}
      ],
      "security_group_ingress": [
        {"name": "wordpressfw", "from_port": 80, "cidr_ip": "0.0.0.0/0"},
        {"name": "wordpressfw", "from_port": 22, "cidr_ip": "0.0.0.0/0"}
      ],
      "instance": [
        {
          "instance_id"   : "wordpress",
          "image_id"      : 26,
          "instance_type" : "mini",
          "security_group": "wordpressfw",
          "key_name"      : "yoursshkey",
          "chef_solo": {
            "json_attributes": {
              "run_list":["recipe[wordpress]"],
              "mysql": {
                "server_root_password"  : "password",
                "server_debian_password": "password",
                "server_repl_password"  : "password"
              }
            },
            "recipe_url": "ここに cookbooks の URL を書く"
          }
        }
      ]
    }
  }
}

5.3. コントロールパネルから実行

あとはコントロールパネルの「CloudAutomation β」機能から上記 JSON を実行するだけです。


以上、ご参加ありがとうございました。