きっかけ
chef-solo
には why-run
オプション(-W)があるけど knife solo
からどうやってやるのかなって思っていました
出来ました
knife solo cook ${user}@${host} -W
chef-solo
と同じように -W
を付ければ良い感じでした。
以上
簡単ですが、メモ。
chef-solo
には why-run
オプション(-W)があるけど knife solo
からどうやってやるのかなって思っていました
knife solo cook ${user}@${host} -W
chef-solo
と同じように -W
を付ければ良い感じでした。
簡単ですが、メモ。
vagrant
でも test-kitchen
でもイケることをあえて別な方法でやってみるvagrant
の provisioning
コマンドで同じことをやれますtest-kitchen
でも良いかと思います
コンポーネント | 名前 |
---|---|
OS | Ubuntu 13.04(Ubuntu Server) |
CI ツール | altria |
仮想環境 | LXC |
chef-solo
を使って実行altria
で捕捉するすべてを書くとながーくなるのでポイントを幾つか。
sudoers
の設定を弄る。
コンテナへの接続の際に known_hosts
への追加登録を確認されるステップをスキップする設定を /home/altria/.ssh/config
に設定する。
今回は Debian 6(squeeze)
を環境として用意する。
そして、必要な apt パッケージを導入しておく。
その他、以下のような設定を行なっておく。
root
ユーザーの authorized_keys
に登録しておく/etc/hosts
とかに設定でも良いかも)仕込みをしておいたコンテナは lxc-clone
でコンテナを複製する際のオリジナルコンテナとしておく。
ワークステーション側で以下のようなディレクトリ構成の cookbook
作成環境を用意する。
$ tree git/chef/ -L 3 git/chef/ └── cookbooks ├── .git #=> 後述 ├── chef.json #=> run_list を記載 └── test1 #=> Cookbook ├── CHANGELOG.md ├── README.md ├── attributes ├── definitions ├── files ├── libraries ├── metadata.rb ├── providers ├── recipes ├── resources └── templates 10 directories, 4 files
ちょっと特殊な対応として run_list
が記述された chef.json
をテストを行う cookbook
ごとに書き換える必要がある。また、それぞれの cookbook
と同じディレクトリに設置しておく。(この辺りは要改善)
cookbooks
ディレクトリ以下で git init
を実行する。git init
を実行後、cookbooks/.git/hooks
以下のようなに post-commit
を設置する。
ジョブを新規登録して、以下のような内容のスクリプトを作成して適当なディレクトリ(/home/altria/bin/
)に
何もしない recipe
を書いてテストを行なってみる。
本当に何もしていない。
odokumi の実行は git commit
コマンドで始める。
git commit -m "modified."
以下のようにローカルのリポジトリに対してコミットが走った後で cookbooks
ディレクトリ全体が odokumi サーバーに転送され、altria
にジョブのビルドが要求される。
test build rsync done... {"id":16,"status":null,"started_at":null,"finished_at":null,"job_id":1,"output":null,"created_at":"2013-08-18T00:35:15.398+09:00","updated_at":"2013-08-18T00:35:15.398+09:00","properties":{},"incremental_id":16} cookbook request done... [master 0018f64] modified 1 file changed, 1 insertion(+), 6 deletions(-)
altria
で odokumi のビルドが走る。
cookbook
が LXC コンテナに正常に適用される。
recipe
等にシンタックスエラーがあった場合には見事にコケる。
コケた場合には LXC コンテナの削除は行われず、ログインして詳細な調査が出来るようにしている。
odokumi 環境を構築していて気づいた点、改善点等。
redis-server
が固まって、それに引きずられて altria
自身が固まってしまうことがあったlxc-info
で存在しないコンテナ名を指定しても STOPPED
等と表示されてしまうので、lxc-info
でコンテナの動作確認する場合には注意する使うツールとしては...
altria
LXC
Chef
でも Ansible
でもイケるようにあらかじめ altria
のジョブに LXC
コンテナを起動して knife solo prepare
を叩いて knife colo cook
までを実行するジョブを登録しておく。
altria
に登録された job を起動みたいな感じ。
サーバー構築直後と、運用開始後についての作業を整理してみる。尚、サーバーの構築に関しては chef
や ansible
等のツールを利用し、監視ツールとしては cacti
を利用している環境を想定する。
serverspec
による構築直後のチェック(標準的な設定の確認)等、ざっくりと現在の自分が行なっている作業も含め書いてみたが、今回はサーバー構築直後の 01 から 03 あたりまでをひと通りやってみて可能性を探ってみることにする。
Jenkins
先生に色々と頑張って頂くことを前提に以下のようなフローとなる。
Jenkins
に serverspec
実行のビルドを API を使ってオーダーserverspec
の実行結果を解析して正常であれば cacti
にホストを登録cacti
からホストの監視が開始されるserverspec
の実行のトリガーはサーバー側の rc.local
等に設定されている為、サーバーが再起動すると毎回実行される構築直後、再起動毎で serverspec
でテストする手順については割愛し、さらに jenkins
の API を叩いて serverspec
を実行する方法についてはこちらにて検証を行なっており、細かい設定はあるものの実装は可能。
Cacti がコマンドラインから扱えることと Jenkins
のビルド結果を解析して次のビルドをキックするか、一つのジョブ内でシェルを複数書けるのでそれを利用する手もある。
ジョブのパラメータを使いまわせるということで、後者の一つのジョブ内でシェルを複数書くように設定してみた。登録したシェルスクリプトは以下の通り。
テストする為の spec ファイルは以下の通り。
とりあえずは Cacti でのグラフ生成に必要な snmpd
が稼働していることを確認する。他にも各環境に応じて適宜テストを書く。
ビルドが成功を以って、以下が成功している。
serverspec
用の spec ファイルの生成
Cacti
にて登録したホストの監視が開始されている。
引き続きの目標として...
serverspec
でのテスト項目を煮詰めていくChef
や Ansible
等でサーバーを一から構築して試してみる等を試していくつもり。
とてもシンプル。
コマンド | 機能 | メモ |
---|---|---|
knife lxc server list |
コンテナの一覧を取得 | 一応、動く |
knife lxc server create |
コンテナを作成して run list に記載された cookbook を実行する | cucumber-chef の古いバージョンに依存していて動かない |
knife lxc server delete |
コンテナの削除 | 一応、動く |
インストールは gem で一発。
sudo gem install knife-lxc --no-ri --no-rdoc -V
上記のメモにある通り cucumber-chef
の 1.0.4 までに含まれている handy
というモジュールに knife lxc server create
が依存している関係でインストール当初は動作しなかった為、knife lxc server create
の該当部分をコメントアウトして動作させた。
とりあえずは knife lxc server list
を試してみた。
ようやく本題。
knife lxc server list
を試している過程でコンテナの IP が表示出来るのに表示されていなかったので調査をしてみた。
$ knife lxc server list Lxc containers list Name Ip centos-test1 centos1
knife lxc においてコンテナの IP アドレス取得はコンテナのコンフィグファイルから取得してきている。以下は lxc_server_list.rb"
の一部抜粋。
コンフィグファイルは環境によって異なる。尚、Debian wheezy の場合には /var/lib/lxc/コンテナ名/config
となるが、そもそも、IP アドレスを決め打ちで記載してはいないので IP の取得はこの方法では難しい。
ググると...こちらでは dnsmasq
のリリースした記録(/var/lib/misc/dnsmasq.leases
)を cat するのがシンプルでイイよって書かれていたので試してみた。
cat /var/lib/misc/dnsmasq.leases
を実行すると...
1374364571 de:33:db:24:0f:45 192.168.8.84 * *
おお、ちゃんと IP が...しかし、この場合コンテナとの関連付けをどのようにハンドリングするか悩ましいところ。さらに、こちらには、コンテナに対して任意のコマンドを投げることが出来る lxc-attach
というコマンドを使って you should be able to
とあったので lxc-attach
も試してみた。
結論から言うと、lxc-attach
はカーネルの 3.8 以降で動作するらしく、それ以下の環境だと動作しないようで lxc 0.9.0~alpha3-2
ですら動作しないことを @ten_forward さんに教えて頂いた。
@inokara lxc-attach は kernel 3.8 以降しか動かないですねー :-)
— TenForward (@ten_forward) 2013, 7月 20
lxc-attach
の動作については @ten_forward さんのブログ記事が詳細に記載されていて解り易かった。記事にも書かれているように、カーネル 3.8 以下な環境(手元の Debian wheezy(3.2.0-4-amd64))
で lxc-attach すると、以下のようなエラーとなってしまう...
lxc-attach: No such file or directory - failed to open '/proc/14854/ns/pid' lxc-attach: failed to enter the namespace lxc-attach: No such file or directory - failed to open '/sys/fs/cgroup//lxc/lxc/centos1/tasks'
残念。ちなみに、カーネル 3.8 な Ubuntu 13.04 だと見事に動作することを確認している。
現時点、現環境(カーネル 3.8 以下)でホスト側からコンテナの IP アドレスを取得する手段としては...
方法 | 課題 |
---|---|
コンテナのコンフィグに IP を決め打ち | コンテナを DHCP 環境で IP 取得させる場合にどうするか? |
dnsmasq.leases を確認する | IP とコンテナの関連付けをどうするか? |
しか無さそう...前途、多難。
${chef-repo}/site-cookbooks/manage_user/recipes/manage_user.rb
${chef-repo}/data_bags/users/user.json
パスワードは openssl passwd -1 "your_password"
で作成すると良いでしょう。
rsyslog.conf
を調整して mail.log の日付フォーマットを Jul 13 17:45:37
となっているのを 2013-07-11T07:01:44.698907+09:00
に変更した上で fluentd でパースさせてた。
Debian に fluentd をパッケージからインストールしてみる。gem
からインストールする場合には既存の ruby 環境を弄らずに導入する方法を模索する。
日付のフォーマットを従来のフォーマット(Jul 13 17:45:37
のようなフォーマット)でも fluentd でパースさせるには format
にて以下のような正規表現で記述する。
format /^(?<time>[^ ]* [^ ]* [^ ]*)
これは fluentd の Input Plugin
である in_tail
プラグインドキュメントにちゃんと記述されていた...。恥ずかしい限りです。ということで、format
を修正して以下のような fluent.conf
を作成した。
修正後は redis にも以下のように登録されるようになった。
有難い日本語のドキュメントに紹介されていた方法通りに deb パッケージに td-agent
を導入する。ドキュメントからの抜粋となるが Debian 6 系の場合には以下のようにインストールする。尚、ドキュメントに記載されているように Ubuntu 12.04 LTS / Precise
と Ubuntu 10.04 LTS / Lucid
のみサポートしているようだ。
curl -L http://toolbelt.treasure-data.com/sh/install-ubuntu-lucid.sh | sh
上記は /etc/apt/sources.list.d/treasure-data.list
に新しい apt リポジトリを登録し、td-agent
の deb パッケージをインストールする。インストールに際しては curl
と sudo
が必要となるので予めインストールしておく。
尚、td-agent
は fluentd
の安定版という立ち位置のプロダクトで、こちらにその違いが明記されている。
deb パッケージで導入すると init.d
以下に起動スクリプトが設置されると共に /usr/lib/fluent
以下に組み込みの ruby 等がインストールされる。
root@host:/usr/lib/fluent# tree -L 2 . ├── jemalloc │ ├── bin │ ├── include │ ├── lib │ └── share └── ruby ├── bin ├── include ├── lib └── share 10 directories, 0 files
プラグインのインストールは以下のようにして組み込みの gem
を利用してインストールすることになる。
/usr/lib/fluent/ruby/bin/gem install fluent-pluをgin-redis --no-ri --no-rdoc -V
また、インストールしたプラグインは /usr/lib/fluent/ruby/lib/ruby/gems/1.9.1/gems
以下にインストールされる。
板前には嬉しいことに td-agent
をセットアップする cookbook が提供されているので利用してみる。尚、こちらも deb パッケージと同様に Ubuntu と CentOS 、RedHat 環境のみのサポートとなっているようなので Debian 環境での利用はお試しの範囲で...。
利用に際しては apt
と yum
の cookbook が必要となるので予め用意した上で、以下のように run_list
を用意する。
当然ながら Debian 6.0.7(squeeze)だとうまくインストールが終わらかなったので Debian 環境(今んとこ squeeze のみ)でパッケージがインストール出来るように修正したものを pull request してみた。
以下の部分を追記してみた。
手元の検証環境では上記を追記した cookbook で td-agent
をインストールすることが出来た。やはり、ここでも ohai
サマサマ。働きモノの ohai
です。
導入を試すことからちゃんと運用してくように引き続き検証を進めていくべ。
名前は変だけどこちらにアップした。特に凝ったこともせず、attribute
と template
を使ったもの。次期バージョンでは、以下を検討する。
今回、cookbook の作成にあたり serverspec のテストを作った後で cookbook を作っていったので、テストドンブリスペシャルということでアーカイブに同梱してみた。
こんな感じ。テストが全部通ればインストール出来たってことで。
恥ずかしながら、これまでは master ブランチをジャンジャンバリバリ cookbook を弄っていたが、それはアカンらしいので作業用のブランチを作って作業した。master ブランチから fork した後で...
git clone https://github.com/inokappa/redis_2_cookbook.git cd redis_2_cookbook git checkout -b newfeature
以後は newfeature
ブランチで作業を続ける。
いい感じで出来たところで newfeature
ブランチに push する。
git push origin newfeature
push した後で pull request を以下のように送ってみた。
自作自演なので悪い組織の片棒を担ぐような気分になってしまう。
自作自演の pull request に応えるべく master ブランチに merge する。
そして、最後に git push
して完了。ただし、上記の手順はベストプラクティスでは無いと思われるので引き続き勉強する。
タイムリーにこちらに紹介された方法で簡単に登録出来た。(但し、こちらでアカウントを作成して API キー
をこちら生成してダウンロードしておく必要がある)
knife cookbook site share redis_2_cookbook ${category} -o ${my-cookbook-path} -u ${usre-name}
取得した API キー(xxxxx.pem)は以下のように knife.rb
に記載しておいても良い。(上記の例は knife.rb
に記載されていることを前提としている。)
current_dir = File.dirname(__FILE__) client_key "#{current_dir}/xxxxx.pem"
正常に登録されると以下のようなページが出来た。ヤッター。
README がグチャグチャなので後で書き直したい...
以下を参考にさせて頂きました。
knife solo
が動かなくなってしまったので --verbose オプションをつけて実行したknife solo
を実行する環境の solo.rb
をそのまま rsync で転送しており、適切に cookbook_path
等が設定されていないと...
Chef::Exceptions::CookbookNotFound: Cookbook setup not found. If you're loading setup from another cookbook, make sure you configure the dependency in your metadata
と怒られる。
はい。すいません。
ということで、上記のように solo.rb
をちゃんと書くこと。
run_list
に記載された cookbook 以外に knife.rb
に指定した cookbook_path
以下に保存されている cookbook を全部 rsync
しているみたい。
以下、knife solo
を実行する環境の cookbook_path
に保存された cookbook 達。
$ tree -L 1 my-cookbooks my-cookbooks ├── ansible_install_cookbook ├── db_benchmark ├── hoge_cookbook ├── lamp ├── mariadb_install_cookbook ├── memcached ├── mysql_install_cookbook ├── redis_1_cookbook ├── redis_2_cookbook └── setup
以下、knife solo
によって chef-solo
が実行される環境の cookbook_path
に保存された cookbook 達。
# pwd /tmp/chef-solo # tree -L 1 my-cookbooks/ my-cookbooks/ ├── ansible_install_cookbook ├── chef_solo_patches ├── db_benchmark ├── hoge_cookbook ├── lamp ├── mariadb_install_cookbook ├── memcached ├── mysql_install_cookbook ├── redis_1_cookbook ├── redis_2_cookbook └── setup
ん、run_list
に書かれた cookbook だけを転送するんぢゃなかったのね。初めて知りました。
knife-solo を二回目に実行しようとした際に以下のようなエラーとなってしまう。
ERROR: RuntimeError: Couldn't find Chef >=0.10.4 on xxx.xxx.xxx.xxx
尚、この現象は Debian 環境のみで確認したが、他の OS 環境でも発生するかもしれない。(調査中)
原因は knife solo を実行する際にデフォルトで対象 node の chef-solo バージョンを以下のようにチェックするが、
sudo chef-solo --version
が実行される際 sudo
コマンドの出力結果として、
sudo: unable to resolve host xxxxxxxxxxxx
と出力されてしまっている為。
chef-solo のバージョン判断を行なっているのが knife-solo-0.2.0/lib/chef/knife/solo_cook.rb
の以下の記述。
sudo: unable to resolve host xxxxxxxxxxxx
となってしまった場合には v
には ["sudo", " unable to resolve host inokappa2\r\nChef", " 11.4.4\r\n"]
こんな感じで値が入ってしまい v[0].strip == 'Chef'
が成立しない為 chef_version
に値が入らない。
対策として一番手っとり早いのが --no-chef-check
オプションを使う。
もしくは /etc/hosts
にホスト名を追加する。
127.0.1.1 ${hostname}
検証の結果、以下の条件を全て満たす場合に sudo コマンドを実行すると sudo: unable to resolve host xxxxxxxxxxxx
となり knife solo 側で chef-solo のバージョン判定が出来なくなるようだ。