ラベル Chef の投稿を表示しています。 すべての投稿を表示
ラベル Chef の投稿を表示しています。 すべての投稿を表示

2012/01/30

Chefサーバーの容量不足になった時の対策メモ



はじめまして。hiroshiの部下、yoshitoです。


僕の主な仕事は、ここだけの話、hiroshiのゴキゲンをとることですが、稀にコードを書いたり、サーバーをいじったり、hiroshiの弁当を買ってきたりしています。


僕はとくに技術力が高いわけではなく、難しい事は他の方々がさくっとやってくれるので、僕はみなさんがゴキゲンよろしくお仕事ができるようにサポートしています。


技術的なものはあまり書けないと思いますが、社内の雰囲気をお伝えできればと思います。


しかし。
ネタが無いので、今回は技術ネタにしましたさーせん!!!!


:Chefサーバーのディスク容量が増えすぎて困ったですの巻

以前の記事で紹介されているように、DECOLOGではChefというサーバー管理ツールを使ってサーバーを管理しています。
今回は、そのChefサーバーがディスク容量不足になってしまった時のことを紹介します。


DECOLOGのサーバーは、Zabbixというサーバー監視システムで監視されていて、サーバーの状態がおかしくなるとメールを送ってくれたりします。


今回の場合も、
「Chefサーバーのディスク使用量が90%を超えましたよ」
的なアラートメールが届いて、問題が発覚しました。


調べてみると、chef.couchというファイルがHDDのほとんどを占めている状態。




Google先生に聞いてみると、Chefが使っているCouchDBというデータベースシステムのファイルだということがわかりました。


ChefサーバーはCouchDBを使って、クライアントの情報を管理しており、今回はそのデータベースのファイルが大きくなりすぎていたようです。

教訓:
Chefサーバーが容量不足になったら
CouchDBを疑ってみる!
の巻

CouchDBは、ドキュメント管理に特化したデータベースです。(ってここに書いてありました)


特徴として、データが更新されるたびに、新しくリビジョンを作成するという特徴があります。
つまり、過去のデータをまるっととっておくわけです。


Chefで管理しているクライアントの情報がアップデートされるたびに、
CouchDB上ではそのデータが複製されて、情報を更新すれば更新するほどDBは肥大化してしまいます。


そこで、Compactionの出番です。


Compactionは、CouchDBに保存されている過去のデータを削除する機能。
Compactionを実行しましょう!


CouchDBは面白くて、RESTfulなAPIでアクセスできるんです。
URLを叩けば、お手軽にDBを操作できます。

例えばDBの情報を見たければ、Curlコマンドを使って、

$ curl http://localhost:5984

とすると、

{"couchdb":"Welcome","version":"0.11.2"}

こんな感じで情報を取得することができます。

ChefのDBの情報は、こんな感じです。

$ curl http://localhost:5984/chef
{"db_name":"chef","doc_count":3875,"doc_del_count":99,
"update_seq":5139079,"purge_seq":0,
"compact_running":false,"disk_size":455128299901,
 "instance_start_time":"1287986483011849","disk_format_version":5}

らくちんですね。

ということで、早速Compactionを実行してみましょう。

$ curl -H "Content-Type: application/json" -X POST http://localhost:5984/chef/_compact
{"ok":true}

OK!

確認してみましょう。

$ curl http://localhost:5984/chef
{"db_name":"chef","doc_count":3875,"doc_del_count":99,
"update_seq":5139107,"purge_seq":0,
"compact_running":true,"disk_size":455131086952,
"instance_start_time":"1287986483011849","disk_format_version":5}

おおお!
compact_running:true
になってます。うまくいってそうです。

Compactionが終了すると、
compact_running:false
になります。


結果
 Before
$ df
 Filesystem           1K-blocks      Used Available Use% Mounted on
 /dev/sda2            564436604 481904116  53398212  91% /


 After
$ df
 Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda2            564436604  37030504 498271824   7% /

効果絶大。 めでたし めでたし


で、隠してましたが実は僕が紹介した内容は
すべてここに書いてあります。
僕がよくtommyさんにRTFM(*1)って怒られますが、そういうことですね。


ちなみに、CouchDBの読み方はカウチです。

*1 : Read The Fucking Manualの略。「マニュアル読んで」的な。実際、大抵のことはマニュアルに書いてあります。




2011/06/14

Chefでサーバのセットアップ・管理作業を楽チンにしよう~実践編その2~


前回紹介したスパムメールがさらに進化して「メアド変えたのでよろしく!」的な内容になってて、この人らPDCA実践してるわ―、と感心してしまったhiroshiです。

「3.レシピを書いたりする」の途中で終わった前回の続きです。

phpのインストールに必要なパッケージをインストールするところで終わっていましたので、次はphpのインストールです。

ここでphpをインストールする条件として
  • インストールされてない
  • 規定のバージョンと違う
  • 想定のコンパイルオプションと違う
場合にインストールし直してね、と定義したいと思います。

主なところはこんな感じです。

{chef-repo}cookbooks/php/recipes/default.rb
# バージョンのチェックを行い、バージョンが想定と違っていたらインストールを実行する
# サーバ稼働中の予期しないアップグレードを防ぐため、/usr/local/src/PHP_VERSION_CHECK_REQUIRED
# というファイルが存在する場合のみ処理が行われる。
buildtool_check_version "php" do
  action :check
  input '|/usr/local/bin/php -v'
  regex /^PHP ([0-9.]+)/
  version node[:php][:version]
  only_if "cat /usr/local/src/PHP_VERSION_CHECK_REQUIRED"
  notifies :create, "cookbook_file[/usr/local/src/#{node[:php][:tarball]}]", :immediately
  notifies :install, "buildtool_make_install[php]", :immediately
  pecl_packages.each do |package_name, install_name|
        if node[:php][:extension][package_name.to_sym] then
        notifies :run, "execute[pecl-install-#{package_name}-force]", :immediately
        end
  end
end

# PHPのコンパイルオプションが変わっている場合はインストールを実行する
# サーバ稼働中の予期しない再コンパイルを防ぐため、/usr/local/src/PHP_VERSION_CHECK_REQUIRED
# というファイルが存在する場合のみ処理が行われる。
# ただしPHPがインストールされていない場合は必ずインストールが実行される。
file "/usr/local/src/PHP_CONFIG_OPTION" do
  content node[:php][:config_option]
  only_if "cat /usr/local/src/PHP_VERSION_CHECK_REQUIRED || ! /usr/local/bin/php -v"
  notifies :create, "cookbook_file[/usr/local/src/#{node[:php][:tarball]}]", :immediately
  notifies :install, "buildtool_make_install[php]", :immediately
end

cookbook_file "/usr/local/src/#{node[:php][:tarball]}" do
  action :nothing
  source node[:php][:tarball]
  mode "0644"
end

buildtool_make_install "php" do
  action :nothing
  tarball node[:php][:tarball]
  srcdir "php-#{node[:php][:version]}"
  config_option node[:php][:config_option]
  notifies :restart, "service[httpd]"
end



4ブロックありますが、それぞれ以下の役割です。
  • バージョンチェック
  • コンパイルオプションチェック
  • インストールファイルの展開
  • インストール

最初のブロックのバージョンチェック部分からいってみます。
buildtool_check_version "php" do

とありますが、buildtool_check_versionは自前で定義したResourceです。
自前定義のResourceです。で終わるのもなんなので、ここでまた横道にそれてbuildtoolの説明をサックリしてみたいと思います。

buildtoolもcookbookのひとつです。
{chef-repo}/cookbook/buildtool/
に定義があります。

上述のbuildtool_check_versionについては、
{chef-repo}/cookbook/buildtool/resources/check_version.rb
actions :check
# バージョンチェックをする Resource の定義

attribute :input, :kind_of => String, :required => true
attribute :regex, :kind_of => Regexp, :required => true
attribute :version, :kind_of => String, :required => true
とresourcesに定義をし

{chef-repo}/cookbook/buildtool/providers/check_version.rb
action :check do
  begin
    versionstring = IO.read(new_resource.input)
    if new_resource.regex =~ versionstring
      version = $1
      if version != new_resource.version
        Chef::Log.info("Version check for #{new_resource.name}: expected=#{new_resource.version}, actual=#{version}")
        new_resource.updated_by_last_action(true)
      end
    else
      Chef::Log.info("Version check failed: '#{versionstring}' is not match #{new_resource.regex}")
      new_resource.updated_by_last_action(true)
    end
  rescue
    Chef::Log.info("Version check failed: #{$!}")
    new_resource.updated_by_last_action(true)
  end
end
とprovidersに実際の動作を記述します。

providersにあるnew_resourceにはresourcesで定義したattributeがあり、その中身は
buildtool_check_version "php" do
  action :check
  input '|/usr/local/bin/php -v' #ココ!
  regex /^PHP ([0-9.]+)/     #ココ!
  version node[:php][:version]  #ココ!
と、利用時に指定した値が入ります。

このあたりの構成が分かれば、check_version.rbが何しているかはrubyがわからなくてもなんとなくわかるかと思います。ぼくもrubyわかんないし。

ちなみに最後の
version node[:php][:version]


{chef-repo}cookbooks/php/attributes/default.rb
default[:php][:version] = "5.x.x"
default[:php][:tarball] = "php-" + default[:php][:version] + ".tar.bz2"
default[:php][:config_option] = "--with-libdir=lib64 \
~後略~
とここに書いた値が基本的には入ります。node[]で取れるの値ですが、設定できる場所は複数箇所あって優先順位があるので気をつけてください。詳しくは公式のこの辺を参照してみてください。

あと、気づいた人もいると思いますが、このbuildtool自体もRecipeの1つなのでbuildtool_check_versionをここで使うには、事前に
include_recipe "buildtool"
しておく必要があります。

と、横道にそれてたら、このブロックの最初の5行まで追えたので次は

only_if "cat /usr/local/src/PHP_VERSION_CHECK_REQUIRED"
ですね。

これはこのブロックのコメントに書いてあるとおりです。

いやー、コメントっていいですね!

ちなみにウチで「変数宣言」とかいうコメント書いたらグラウンド10週か腕立て200回させられるので注意してください。しかもグラウンド探すところからですからけっこうキツイです。


あっ、もうだめ!今日はここまででカンベンしてください!


では、またまた続きは次回に!

2011/05/30

Chefでサーバのセットアップ・管理作業を楽チンにしよう~実践編その1~


昨日1日ケータイでアラートメール以外に受け取った唯一のメールを紹介します。
「
この前はありがとう!!久々メッチャ楽しかった~
みんながいる前だったからちょっと恥らっちゃったけど、2人っきりだったら私も同じ気持ちだったょ(はぁと

恥ずかしいけど・・・

次は2人っきりで会えませんか??

返事楽しみに待ってます(はぁと
」

「え?誰?誰?これ?」ってどんなに心当たりがないシチュエーションでも、とりあえずその可能性を記憶に見出そうとするのが男なんだなあ、と、スパム道の奥深さを知ったhiroshiです。

前回に引き続きChefについてです。

今回は、DECOLOGで実際に使っているrecipeや運用を紹介しながらの実践編です。
※この記事の元になるChefのAPIのバージョンはv0.9.12です。

その前に、いろいろ準備します。クイックスタートあたりを読んでクイックに準備しましょう。
この辺は環境依存も多いと思うし、僕やってないから華麗に通り過ぎて次行きます。

あと、このくらいの英語は翻訳サイトとか使わずに読めるようになっておいたほうが幸せになれると思います。逃げちゃだめだ!

さて、クイックに準備できたら始めます。

前回の記事でもちょっと触れましたが、chefはソフトウェア単位で扱うイメージです。
なので、今回はphpを題材にしてみます。

phpをchefで扱うまでの手順をおおざっぱに書くと
  1. cookbookを作る
  2. 必要ファイルを調達する
  3. レシピを書いたりする
  4. chef-soloでテストする
  5. cookbookをchefサーバにアップする
  6. gitにコミットしとく
という感じでしょうか。ウチの場合。


1.cookbookを作る
まず、cookbookを作ります。chefで管理するソフトの数だけcookbookを作っていくことになります。

無理やり料理に当てはめると、
この料理人(chef)は食材(ソフトウェア)ごとにレシピ(recipe)をまとめた料理帳(cookbook)を管理しているようです。

さあ、うまいこといったつもりになったところでさっそく実行です。
rake new_cookbook COOKBOOK=php
※ただし「knife cookbook create」を使えと怒られます。が、knifeコマンドはあらかじめセットアップをしておかないと正しく動作しないので、今回はこれで。

とします。すると{chef-repo}/cookbook/php配下にじゃららーと以下のようなディレクトリとファイルが作られます。
attributes
definitions
files
libraries
providers
recipes
resources
templates
metadata.rb
README.rdoc
いらないものもたくさんあるので、いらないことに気づいたタイミングで消したらいいと思います。

ここはこれで終わりです。


2.必要ファイルを調達する
本当にphpだけだったら、php-5.3.x.tar.bz2とphp.iniだけあればいいかと思います。

php-5.3.x.tar.bz2は
{chef-repo}/cookbook/php/files/default
直下に置いておきます。

php.iniはphp.ini.erbという名前にして
{chef-repo}/cookbook/php/templates/default
直下に置いておきます。

いったん終わりです。

3.レシピを書いたりする
ここに書いていきます。
{chef-repo}/cookbook/php/recipes/default.rb

さっきから各所で「default」が目につきますが、細かいことはあとで気にすることにして、ここはおとなしくdefault.rbに書いていきます。

さて、どこから書いていくかですが、その前にchefがどういうものかおさらいします。

chefは
「手でやってたセットアップ手順をrubyで記述すると、定期的にその手順の結果の状態になっているかチェックして、そうなってなければその状態にしようとする」
ツールです。

なので、手でやってた手順をそのまま記述していくことになります。

chef導入以前、DECOLOGではphpをシェルスクリプトでインストールしてたのですが、その内容は大まかにいうと
  • apacheをソースからインストール
  • phpをソースからインストール
  • pearのライブラリいろいろいれる
  • peclのライブラリいろいろいれる
といった感じでした。apacheありきです。

なので、apacheのインストールからやることになりますが、apacheも1つのソフトウェアなのでcookbookから作っていくことになります。というわけで、今回はすでにapacheのcookbookはできあがっている前提で進めます。


まずはapacheありきのphpなのでapacheのセットアップを行います。
include_recipe "apache"
こんな感じでapacheのレシピを発動させます。

次に、phpのconfigオプションで使うことになるrpmパッケージをインストールしておきます。
package "curl-devel"
package "libjpeg-devel"
package "libpng-devel"
~後略~

ここででてくるpackageというのはchef側で用意してくれている便利コマンドみたいなもので、「Resource」と呼ばれています。

<Resource>
Recipe内で行う操作を抽象化して宣言文ぽくしたもの。パッケージ管理、デーモン管理、ファイル管理、コマンド実行などが用意されている。
前回のエントリ参照

Resourceはいろんなのがあるのでhttp://wiki.opscode.com/display/chef/Resourcesに目を通しておくとよいと思います。

DECOLOGの場合はOSがCentOS環境なので、特に何も指定してなければyum installしてくれることになります。



・・・ああっ、もうガッツが足りなくなってきました。まだまだ途中ですが、最後まで書こうとするとこの倍くらいになってしまうので続きはまた次回にさせてください><


よろしくお願い申し上げます。

2011/05/23

Chefでサーバのセットアップ・管理作業を楽チンにしよう~構成編~


どうもhiroshiです。こんなに更新が早くてすみません。

今回もChefについてです。

前回の選定編に続いて、今回はChefの構成を見てみます。もちろんこれも「tommy report in Oct. 2010」からの抜粋です。

5/26 追記)この記事はv0.9.12に基づいてます。

Chefの構成の概要図
こんな感じです。


ツール群
<chef-server>
情報を集約して管理するサーバプロセス。各ClientとはJSON/RESTスタイルで通信する。

<chef-client>
設定を適用する各マシンにインストールされるデーモン。定期的にchef-serverをポーリングして、その内容に従ってレシピを実行する。

<chef-solo>
サーバ無しでレシピを実行するツール。

<knife>
chef-serverに登録されている情報の取得・変更を行うツール。切り刻むよ。

<webui>
chef-serverのWebインターフェース。なんか上手くログインできないので無視。


ということでうちではwebui使ってません。「それは大いなる損失だよ!」ということがありましたら是非教えてください。


主な構成要素
<Cookbook>
Recipe,Template,Attributeなどをひとまとめにしたディレクトリ。ソフトの種類毎に作るのがお約束ぽい。

<Recipe>
実行内容の定義本体。RubyのDSLで記述する。

<Resource>
Recipe内で行う操作を抽象化して宣言文ぽくしたもの。パッケージ管理、デーモン管理、ファイル管理、コマンド実行などが用意されている。


<Template>
設定ファイルを生成するためのテンプレート。中身は eRuby。


<Attribute>
環境依存の処理を吸収するための変数。


<File>
バイナリファイルなど、単にコピーして使うためのファイルを置くところ。


<Metadata>
Cookbookの説明とかのメタ情報。


<Role>
複数のRecipeをまとめて「役割」として定義するためのもの。


<Node>
chef-serverから見た管理対象のマシンのこと。


<run_list>
Nodeに対して適用するRoleやRecipeを指定したリスト。


<Client>
chef-serverにアクセスするツール類のこと。


なんやらいっぱいありますが、すぐ慣れます。寄生獣の後藤も「何事も慣れだ」と言ってました。これ、言うの2回目ですね。
とにかくRecipeです。普通7割くらいRecipe書くのに時間使います。
TemplateとFileは使い分けが若干微妙なところがでてくるかもしれませんが、書き換え可能なファイル(つまりテキストファイル)はTemplate、そうじゃないのはFileというルールでやってます。

例えばapacheなら、http-2.2.xx.tar.bz2はFileだし、httpd.confはTemplateの下に置いとくって感じです。


Attributeについて
レシピで使える属性値は大きく2種類に分かれます。
  1. Nodeの属性値。Nodeから収集した様々なパラメータ(IPとか)がツリー状のデータとして取得できるので、レシピで条件分けに使う。またknifeコマンドでも参照できる。
  2. 自前で設定する属性値。
    1. デフォルト値はCookbookのattributes/*.rbで定義する。
    2. RoleやNodeに対して、デフォルトの設定値を上書きする値を設定できる。これで一部のマシンだけ別設定みたいなことが実現できる。
1についてですが、具体的にはこんな感じです。
$knife node show {domain}
~前略~
    "platform_version": "5.x",
    "fqdn": "hoge.example.jp",
~中略~
    "domain": "xxx.xxx.xx",
    "os": "linux",
    "idletime": "13 days 13 hours 28 minutes 20 seconds",
    "network": {
      "default_interface": "eth0",
      "interfaces": {
        "lo": {
          "flags": [
            "UP",
            "LOOPBACK",
            "RUNNING"
          ],
          "addresses": {
            "::1": {
              "scope": "Node",
              "prefixlen": "128",
              "family": "inet6"
            },
            "127.0.0.1": {
              "netmask": "255.0.0.0",
              "family": "inet"
            }
          },
          "mtu": "16436",
          "encapsulation": "Loopback"
        },
        "eth0:xxx.xxx": {
          "flags": [
            "UP",
            "BROADCAST",
            "RUNNING",
            "MULTICAST"
          ],
~後略~
該当ホスト上でコマンド打ったら取れるような情報は全部入ってるんじゃないでしょうか。

例えば以下はapacheのconfファイルですが、まいど自FQDN名を設定するところがありますが、そんなときにこんな感じで使えます。
# Server port for sending active checks
ServerRoot      "/usr/local/apache"
ServerName      <%= node[:fqdn] %> ←ココ!!

2について、たとえば基本的にapacheのバージョンは2.2.xxを利用する、ということにします。そういう場合、cookbook/apache/attributes/default.rbに
default[:apache][:version] = "2.2.xx"
と書いておいて、apacheのrecipeに
buildtool_make_install "apache" do
  action :install
  tarball node[:apache][:tarball]
  srcdir "httpd-#{node[:apache][:version]}" ←ココ!!
  config_option configure_option()
  not_if {check_compile_setting}
  notifies :create, "template[/etc/httpd/httpd.conf]"
  notifies :restart, "service[httpd]"
end
と書いておけば、基本的にはこの2.2.xxのapacheをインストールさせることができます。

「そんなんじゃ、わかんねーよ!」って思った方、、、、ですよねー。そうだと思います。。
とりあえず、現時点ではなんとなく、で通り過ぎていただければ幸いです。。

ちょっと今回はこのあたりで切り上げます。

次回は、適当なcookbookを例に取って説明ができたらいいな、という「実践編」を書きたいと思いますが、その際、またこの「構成編」の内容をちょくちょく振り返りつつになる気がします。

chefって、一回やってみないと全体像が見えにくいんですよねー。ぼくは3回くらいやってようやく見えてきました><


というわけで、最後に女子力上げたところでまた次回にさせてください~。

2011/05/16

Chefでサーバのセットアップ・管理作業を楽チンにしよう~選定編~



>>hiroshiの母でございます。この度は(ry

最近お会いしたエンジニアの方から「他社さんのブログとかは規模や難易度が凄過ぎて真似できないことが多いんですが、DECOLOG TECH BLOGは僕らでも利用できるレベルのネタが多いので助かってます!」と言われて今まで感じたことのないキモチになったhiroshiです。

今回はChefのお話です。

去年の10月くらいの話だったんですが、「あっちのwebサーバとこっちのwebサーバ、設定微妙に違くね?」みたいなことが発覚し(いや、前から知ってたけど)、それ自体はその時点で大きな問題ではなかったんですが、「このままだといつかなんかやるよね」と危機感を覚え、システムの構成管理ができるようなツール探しをしました。

つまり、Chefとは上記ような問題点が解決できるツールで、パッケージやミドルウェア(って同じ?)を定義した状態に保ってくれるツールです。「定義した状態に保つ」ということは、定義したソフト等が入っていなかったらインストールしてくれたりするのです!!

オープンソースなものだと他にはPuppetというのがあります。

かねてよりPuppetの存在は存じていたので「じゃあ、噂のPuppetがいけそうか調べてみるかー」といった感じでミツバチの銀の弾丸tommyが調査担当になりました。鉄砲作成を依頼するとキャノン砲ができあがるのがtommyさんです。Puppetを調べてもらったらChefを見つけてきてPuppetと比較してくれました。

以下、「tommy report in Oct. 2010」です。

共通点

  • サーバクライアント構成。構成情報をサーバマシンで一括管理して、各クライアントマシンに配信する。
  • マシンに役割(WebサーバとかDBサーバとか)を設定して、その役割に必要なアプリのインストールとか設定ファイルなどをひとまとめにして管理できる。
  • マシンごとの設定の差異などは変数として管理できる。
  • 設定ファイルはテンプレートから生成できる。マシンごとに一部の値を変えるとか。
  • LDAP連携。LDAP上で各マシンの役割を定義できるみたい。
  • Subversion/Git連携(詳細はまだよく調べてない)。
  • Ruby製。



比較表



※間違っている部分もあるかもだし、当時まとめたものなのでもう変わっているところもあるかもです。

なぜChefにしたか
機能的にはそれほど差はないようでした。
決定打となったのは
tommy「ぶっちゃけChefの方が設定書きやすそうなのでだんぜん好印象ですねー。」
というコメントでしょうか。

その当時の時点で管理対象サーバは400台を超えていたし、稼働しているミドルウェア等もたくさんありました。だから、設定が書きやすいという点は重要なところです。
また、最初にChefの調査導入というフロンティア役を担ったtommyが「設定書きやすそう」っていうんだからChefだね!という感じで決めました。


というわけで今回はChef導入のきっかけのお話でした。次回以降は、Chefの構造や実際の設定例などについて書きたいと思います。

では!