ファイルのコピーを試してみました

Chefでcookbook内でファイルをコピーしてみました。サーバ上のファイルをコピーするときと利用するリソースが違うのでまとめておきます。

サーバ上のファイルをコピーする場合

以下のような設定でできる気がします。

file "/tmp/pochi.txt" do
  content IO.read("/etc/hosts")
end

Cookbook内のファイルをコピーしたい場合

${COOKBOOK_DIR}/files/default/hoge ってファイルがあった場合以下のように利用できます。

cookbook_file "/tmp/pochi.txt" do
  source "hoge"
end

templateリソースを試しました

前回の続きをやります。まずはchef-client呼び出して"hello, chef!"ですかね。

Hello, chef

表示専用cookbookを作ります。

$ knife cookbook create MESSAGE

作成されたMESSAGEのディレクトリにいき、${MESSAGE_DIR}/recipes/default.rbを以下のように記述します。

template "/tmp/pochi.txt" do
  source "pochi.txt.erb"
  # nothing, create, delete, touth, create_if_missing!のどれかを指定
  # create => 既存ファイルがあっても上書き(バックアップはとってくれるみたい)(defaultはこれ)
  # delete => templateで指定されたファイルを削除
  # touch => 既存ファイルがない場合のみファイルを作成
  # create_if_missing => 多分touchといっしょ
  action :touch  
end

次に、${MESSAGE_DIR}/templates/default/pochi.txt.erbを以下のように記述します。

Hello, chef!

このrecipeをアップロードしてsptoss1のrun_listに追加します。

$ knife cookbook upload -o /var/chef/cookbooks/ -a
$ knife node run_list add sptoss1 "recipe[MESSAGE]" 

実行してみます。

$ sudo chef-client

/tmp/pochi.txtにファイルができていることを確認します。

$ cat /tmp/pochi.txt
Hello, chef!

Hello, chef! 完成です。

変数使ってみる

とりあえず、固定ファイルをおけるようになったので次は変数を試してみます。

${MESSAGE_DIR}/recipes/default.rbを以下のように変更します。

template "/tmp/pochi.txt" do
  source "pochi.txt.erb"
  variables :name => node[:dog_name] #=> 変数設定
  action :create
end

変数の設定は${MESSAGE}/attributes/default.rbに以下を記述します。

dog_name "pochi"

次に、${MESSAGE_DIR}/templates/default/pochi.txt.erbを以下のように変更します。

Hello, chef!
Set variables: dog name is <%= @name %>

これでcookbookをアップロードし直してchef-clientをたたくとファイルの中身に変数が入っていることが確認できます。

templateブロック?での設定をまとめておきます

  • source
    • テンプレートのデフォルトファイルを指定します
  • variables
    • 変数を指定する
  • owner
    • ファイルの所有ユーザ
  • group
    • ファイルの所有グループ
  • mode
    • ファイルのモードを指定できます(ex. 0755)
  • action
    • nothing, create, delete, touchのいずれかを指定

ChefでApacheをインストールできるのは遠いなぁ。

webuiのパスワード忘れてしまったとき

忘れたときにした対応をメモ。

コードをいじる

${chef-server-webui}/app/controllers/user.rbっていうとこに以下のメソッドがある。

  def login_exec
    begin
      @user = Chef::WebUIUser.load(params[:name])
      raise(Unauthorized, "Wrong username or password.") unless @user.verify_password(params[:password])
      complete
    rescue => e
      Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
      @user = Chef::WebUIUser.new
      @_message = { :error => "Could not complete logging in." }
      render :login
    end   
  end

ここのraise部分をコメントアウトして再起動するとユーザ名のみでログインできる。

Apacheをchef経由でインストールできるようにする

運用管理ツール?「Chef」をいろいろ使ってみますの続きです。
Apacheをchef経由でインストールできるとこまでがんばりたいです。

復習

前回やったとこは、以下のことです。

  • Chef-Clientをインストール
  • Chef-Serverをインストール
  • Chef-Serverを動かしてChef-Server-Webuiから動作できることを確認
  • COOKBOOKのサンプルを作る
  • Roleのサンプルを作る

なので以下のコマンドをうつと結果がかえってきます。

$ knife role show example
{
  "name": "example",
  "description": "Example role for the chef repository",
  "json_class": "Chef::Role",
  "default_attributes": {
  },
  "override_attributes": {
  },
  "chef_type": "role",
  "run_list": [
    "recipe[zsh]",
    "recipe[screen]",
    "recipe[git]"
   ]
}

nodeにrun_listを追加する

どうもこのままではchef-clientを実行しても実行されないようです。
なのでnodeにrun_listを追加してみます。

$ chef-client
#=> Node sptross1 has an empty run listと出力される
$ knife node list #=> nodeの確認
[
 "sptoss1"
]
$ knife node show sptoss1 -r #=> nodeのrun_list一覧確認
{
  "run_list": [
  ]
}
$ knife node run_list add sptoss1 "role[example]"
{
  "run_list": [
    "role[example]"
  ]
}
$ chef-client
#=> ERROR発生

とりあえずchef-clientが何かできるようになったようです。

nodeからrun_listを削除

一回run_listを消してみます。これはただのテストというか試してみたいだけです。

$ knife node run_list remove sptoss1 role[example]
{
  "run_list": [
  ]
}

いちいちjsonを返してくれるあたりが素敵です。

nodeの作成/削除

knifeコマンドが気になって仕方がなくなってきたのでnodeの作成/削除もテストしておきます。

$ knife node create pochi --editor=emacs
#=> nodeの設定ファイルが開くのでデフォルトのまま保存
Created(or updated) node[pochi]
$ knife node list
[
  "sptoss1",
  "pochi",
]
$ knife node delete pochi
#=> 確認コンフォームが出てくるので"y"を入力
Deleted node[sysmngra]!
$ knife node list
[
  "sptoss1"
] 

knifeコマンドマスタ

  • knife node list
    • nodeの一覧を返す
  • knife node show #{node_name} [OPTIONS]
    • node_nameで指定したnodeの情報を返す
    • -rオプションを利用するとrun_listのみ返す
  • knife node run_list remove #{node_name} #{role_name}
    • node_name内のrole_nameをrun_listから削除する
  • knife node create #{node_name} [OPTIONS]
    • node_nameで指定したnodeを新しく作成する
    • 環境変数にEDITORを指定していない場合optionに"--editor=emacs"などつけないとエラーがおこる
  • kinfe node delete #{node_name}
    • nodeを削除する
  • knife node edit #{node_name} [OPTIONS]
    • nodeの設定ファイルを編集する。
    • 環境変数にEDITORを指定していない場合optionに"--editor=emacs"などつけないとエラーがおこる
  • knife role list
    • roleの一覧を返す
  • knife role create #{role_name} [OPTIONS]
    • node_nameで指定したnodeを新しく作成する
    • 環境変数にEDITORを指定していない場合optionに"--editor=emacs"などつけないとエラーがおこる
  • knife role delete #{role_name}
    • role_nameで指定したroleを削除する
  • knife role show #{role_name} [OPTIONS]
    • role_nameで指定したroleの詳細を返す
  • knife role edit #{role_name} [OPTIONS]
    • role_nameで指定したroleを編集する
    • 環境変数にEDITORを指定していない場合optionに"--editor=emacs"などつけないとエラーがおこる
  • knife cookbook list
    • cookbookの一覧を返す
    • uploadしてないCOOKBOOKは表示されない(管理対象でない)
  • knife cookbook show #{cook_book} [OPTIONS]
    • cook_bookで指定した情報を返してくれる。何もOPTIONを指定しないと多分cook_bookのバージョンしかでない
    • バージョンを指定すると結構細かい情報が返される。
    • バージョン指定かつJSONのキーを指定するとそれに対応した値をかえす
  • knife cookbook create #{cook_book}
    • cook_bookで指定したCOOKBOOKを作成する
  • knife cookbook upload -o #{cook_book_dir}
    • OPTION: -s => chef-serverのURL
    • OPTION: -u => ユーザを指定
    • OPTION: -o => COOKBOOKのディレクトリ
    • OPTION: -a => 対象ディレクトリ以下全てのCOOKBOOKを登録する
  • knife cookbook delete #{cook_book} VERSION
    • cook_bookで指定されたcookbookを削除する
    • -yオプションつけると確認聞かれない

運用管理ツール?「Chef」をいろいろ使ってみます

Puppetとよく比較されるChefですが個人的にはPuppetの書き方がどうしてもなじめなかったのでChefをインストールしてみました。
ChefのWikiでインストール方法に書いてあるのでそこまではスキップします。(couchDBとかapache-solrとかRabbitMQとかMerbとか結構大変です。インストールだけみるとPuppetのが簡単だと思います。)

※今回chef-serverも自分のとこにいれようとしてます。chefの開発元がchef-serverをクラウド上に提供しているものは利用しません。(ただ、そっちを利用する方が簡単だと思います)
※参考サイト:http://wiki.opscode.com/display/chef/Hello+World+example

環境及び前提

COOKBOOKを作ってみます

まずはcookbookと呼ばれるものを作ってみます。
gitを前提としているのでopscodeさんが提供してくれてくれるレポジトリからcloneかけるのが一般的ですが僕が今回試した環境はそれができなかったので一度ダウンロードしてもってきてからgit initしました。

$ mkdir $CHEF_REPO/.chef
$ touch $CHEF_REPO/.chef/knife.rb

knife.rbを以下のように設定します。

cookbook_copyright "pochi_black"
cookbook_email "pochi.black@gmail.com"
cookbook_lisence "apachev2"
node_name "pochi" #=> OSのユーザ名

ここまでくると、cookbookが作成できるはずです!

$ cd $CHEF_REPO
$ knife cookbook create COOKBOOK
** Creating cookbook COOKBOOK
** Creating README for cookbook: COOKBOOK
** Creating metadata for cookbook: COOKBOOK

あんまりわかってないけどできました。/var/chef/cookbooks以下にそれっぽいものができました。

Chef-clientを動かしてみます

まだChef-Clientの設定を全く行ってないので起動できません。
sudo chef-clientとたたこうものならたちまちChef::Exceptations::PrivateKeyMissing Exceptionが発生します。
このあたりから独力でやるのは限界なのでid:rx7先生の教科書をたよりにします。

設定ファイルを生成する

最初に設定ファイル作れといわれてるようなので作ってみます。

$ cd $CHEF_REPO
$ knife configure client ./client-config

こうするとそれっぽいファイル(client.rbとvalidation.pem)ができるのですが、/etc/chef/validation.pemがありませんておこられますがここは無視しようと思います。
(先に/etc/chefディレクトリ作っておくとなにもいわれないようです)

chefの設定ディレクトリにコピー
$ cp -r $CHEF_REPO/client-config /etc/chef

さて本家のWikiではここでknife node listってうつと何も登録されてませんよという画面が出ましたが、私の環境では、client.pemがないよっていわれました。/etc/chef/validation.pemが悪い気がしてきたので以下のような設定をしてみます。

$ openssl genrsa -des 32 > /etc/chef/validation.pem
$ openssl rsa -in /etc/chef/validation.pem -out /etc/chef/validation.pem

それでもdata too large for key sizeとエラーが出ました。これはどうもopensslの制約ぽいです。

Chef-Serverを動かしてみます

いろいろ本家サイトをみているとどうもChef-Serverを自前で動かす場合は、Server側でユーザの管理が必要な気がしてきたので動かしてみます。(これが動かないとchef-clientもきっと動けないんでしょう)

${COUCHDB_DIR}/couchdb #=> couchdbの起動
${RABBITMQ_DIR}/rabbitmq-server start #=> rabbitmqの起動
${RABBITMQ_DIR}rabbitmqctl add_vhost /chef
${RABBITMQ_DIR}rabbitmqctl add_user chef testing
${RABBITMQ_DIR}rabbitmqctl set_permissions -p /chef chef ".*" ".*" ".*"
${GEM_BIN_PATH}/chef-solr-indexer #=> chef-solr-indexerの起動
${GEM_BIN_PATH}/chef-solr #=> chef-solrの起動
${GEM_BIN_PATH}/chef-server #=> chef-serverの起動

couchdbが動いていなくてエラーが発生しました。

couchdbを動かしてみます

couchdbだったので気づかなかったのですが起動がうまくいってなかったようです。
エラーを調べた結果以下のようなメッセージがでていました。

{'EXIT',
"libicuuc.so.44: cannot open shared object
file: No such file or directory"}

いろいろ調べた結果、以下の設定で動くようです。

$ LD_LIBRARY_PATH=/usr/local/lib
$ couchdb

また、デフォルトでは5984ポートで起動するのでそれも変更しておきます。
$COUCHDB_DIR/etc/couchdb/local.ini内にある[httpd]のportを設定して再度起動すればOKです。

再度chef-serverを動かしてみます

$ chef-server -e production

動きました。ぱちぱちぱち。
オプション(-e)はRailsでいうとRAILS_ENV(3.0ならRACK_ENVかな?)です。Merb昔ちょっと触ってたので懐かしいです。Merbのデフォルト起動ポートは4000ですね。

chef-server-webuiを動かしてみます

$ chef-server-webui -e production -p 8082

chef-serverで4000ポート使っているのでchef-server-webuiは違うの使いましょう。ここも何事もなく動きました。アクセスしてみるとデフォルトの初期ユーザ名とパスワードがレイアウト右に書いてあるのでそれでログインできます。

もう一回chef-clientに戻ってみます

nodeリストを見てみます。

$ chef-client
$ knife node list
[
 "server1"
]

うまく動いているようです!序盤で出たものはchef-serverがうまく動いていれば問題ないということにしておきます。
現状のknife.rbはこんな感じです。

loglevel :info
log_location STDOUT
node_name 'server1'
client_key '/opt/ruby/chef/repo/.chef/client.pem'
validation_client_name 'chef-validator'
validation_key '/etc/chef/validation.pem'
chef_server_url 'http://localhost:4000'
cache_type 'BasicFile'
cache_options(:path => '/opt/ruby/chef/repo/.chef/checksums')

ここまででやっとインストールができたという感じでしょうか。やっぱり環境構築が大変ですね。

COOKBOOKを使えるようにしてみます

やっと何となく動きそうな環境ができたので一番最初に作成したCOOKBOOKを登録してみます。
(knife cookbook upload -hでいろいろ出てきますけど)

$ knife cookbook upload -s http://localhost:4000/ -u sptoss1 -o /var/chef/cookbook/ -a
#=> chef-server(http://localhost:4000)に対してsptoss1ユーザ権限で/var/chef/cookbook以下にある全てのcookbookを登録してねというコマンドだと思います

Upload complete!が出力されればうまくいってるはずです。

Roleを作ってみましょう

本家Wikiの手順にのってるので作成してみます。

# ${CHEF_REPO}/roles/example.rb

name "example"
description "Example role for the chef repository"
run_list("recipe[zsh]", "recipe[screen]", "recipe[git]")

うーん、run_listには覚えのないrecipeが並んでる・・・

$ rake roles #=> roleを登録

ここで、403がでちゃいました。サーバ側のログをみるとapplication.rbのis_adminが影響しているみたい。
GUIからユーザをadminに変更するとうまくいきました。roleを設定するときはadminじゃないとだめみたいです。chef-server-apiのmerbアプリ一通りみればいろいろわかりそうな気がしてきました。