MyCSS

2010/03/23

Amazon EBSとRightAwsを使って自動バックアップ環境を構築する はてなブックマークに追加

Amazon EBSとは、EC2にアタッチする事の出来る外部ボリュームです。以下に素晴らしい解説記事があります。
要は外付けハードディスクなのですが、魅力的なのがボリューム毎に丸ごとバックアップが取れるという点です。これを定期的に実行しておけば、いざという時のバックアップになりますので、夜も良く眠れますw
※ちなみに、上記記事ではコマンドラインでの操作となっていますが、AmazonのGUIコンソールからもボタン一発でスナップショットが取れます。

バックアップは定期的に取らないと意味が無いので、自動化したい所です。自動バックアップの記事はいくつか見つけましたが、Ruby版が見つからなかったので自分で作りました。そのメモを残しておきます。

参考にさせていただいた記事:

やりたい事
定期的にEBSのバックアップを取る。その際、履歴を残しておく。古い履歴は自動削除されるようにする。

やった事
上記の参考にさせていただいたスクリプトをもとに、Ruby版を考えてみました。
RubyでAWSのAPIにアクセスするためには、RightAwsが主流だと思いますので、そちらを使います。

gemで配布されていますので、

sudo gem install right_aws

でインストール完了です・・と言いたい所ですが、これだと最新版が落ちてこないので、手動でgemパッケージを作って、ローカルからインストールしました。

git clone http://github.com/rightscale/right_aws.git
cd right_aws
rake gem
sudo gem install pkg/right_aws-1.11.0.gem

gemコマンドでインストール出来るバージョンは、サポートするAWS APIのバージョンがちょっと古めです。別にそれでも問題はありませんが、新しいAPIですとスナップショットにdescriptionを残す事が可能になります。
「このスナップショットはどのボリュームのスナップショットなのか?」
という事をdescriptionにメモっておけば、管理が大変楽になります。

スクリプト本体
require 'rubygems'
require 'right_aws'

AWS_ACCESS_KEY = 'XXXXXXXX'
AWS_SECRET_KEY = 'YYYYYYYY'

unless ARGV.size == 3 then
  puts 'Usage: ebs_snapshot.rb <num> <volume-id> <volume-label>'
  exit 0
end

history   = ARGV[0].to_i # 履歴はいくつ残しておくか?
vol_id    = ARGV[1]      # スナップショットを取るEBSのボリュームID
vol_label = ARGV[2]      # スナップショットのメモ(description)

# descriptionを生成
# この場合だと、vol_labelに時刻をくっつけたものになります
t = Time.now
desc = "#{vol_label} #{t.strftime('%Y/%m/%d %H:%M:%S')}"

# スナップショットを取る
ec2 = RightAws::Ec2.new(AWS_ACCESS_KEY, AWS_SECRET_KEY)
ec2.create_snapshot(vol_id, desc)

# 保存してあるスナップショットで、目的のボリュームIDを持つものだけのリストを作る
snapshots = []
ec2.describe_snapshots.each do |snapshot|
  if vol_id == snapshot[:aws_volume_id] then
    snapshots << snapshot
  end
end

# 履歴分を残して古いスナップショットを削除
snapshots = snapshots.sort_by { |snapshot| snapshot[:aws_started_at] }.reverse
snapshots.each_with_index do |snapshot, i|
  unless i < history then
    ec2.delete_snapshot(snapshot[:aws_id])
  end
end

もし、自前でgemを作るのが難しい場合は、descriptionをサポートしないAPIになってしまいますが、上記のスクリプト23行目の
ec2.create_snapshot(vol_id, desc)

ec2.create_snapshot(vol_id)
にしてあげれば動作します。 これをcronに仕込んでやればOKです。
sudo crontab -e

*/30 * * * * /path/to/ebs_snapshot.rb 3 vol-12345678 "hogehoge data volume"
この設定ですと、ボリュームIDが「vol-12345678」のものを、30分おきにバックアプする事になります。

2010/03/18

nanorcを一発インストール はてなブックマークに追加

Linux環境でのテキストエディタはviかEmacsか?という感じですが、自分はヘタレプログラマーなので、GNU nanoを愛用しています。
コードを書くのはもっぱらIDEやGUIのエディタなので、nanoを利用するのは、サーバー上の設定ファイルを書き換えたりするくらいです。
でも、そうはいっても、何も設定していないデフォルトの状態で作業するのも結構な苦行ですし、複雑な設定ファイルだとテキストの色づけが欲しくなってきます。

nanorcについて
nanoの初期設定は/etc/nanorcあたりに入っていると思いますが、自分自身の設定を作りたい場合、ホームディレクトリに.nanorcを置けば良い事になっています。(設定の内容は試験運用中なLinux備忘録 nanoの設定に解りやすく書かれています。)

色づけに関しては、デフォルトでいくつかサンプルが入っている場合も多いのですが、正直言って足りません。だからといって、自分で書くのはしんどいので避けたい所ですが、みんな大好きGoogle Codeに大量のnanorcを発見しました。今回ありがたく使わせてもらったので、その作業をメモっておきます。(置いてくれた人どうもありがとう、ってここで叫んでも気がつかないか。)

nanosyntax - Project Hosting on Google Code

nanorcを取り込む
単純に欲しいnanorcをダウンロードして、それを~/.nanorcにincludeしてやれば良いだけです。たとえば、Ruby用のnanorcを~/.nanorc.d/に保存した時は

include "~/.nanorc.d/ruby.nanorc"

と~/.nanorcに書いてあげれば、Rubyのファイルを編集するときこのように幸せになれます。

nanosyntax - Project Hosting on Google Codeには大量のnanorcがあるので、基本的には必要なものだけを取り込むべきでしょうけど、いちいち見極めるのも面倒なので、こんなスクリプトを書きました。これで一発でダウンロードと設定が完了します。

cd ~
mkdir .nanorc.d
wget -A nanorc -l 1 -r -nd -np -P .nanorc.d http://nanosyntax.googlecode.com/svn/trunk/syntax-nanorc/

# エラーになるファイルを除外
rm ~/.nanorc.d/aptsrclist.nanorc
rm ~/.nanorc.d/sources_list.nanorc
rm ~/.nanorc.d/etcportage.nanorc

ls -1 .nanorc.d | sed -e 's|.*|include "~\/.nanorc.d/&"|' > .nanorc

エラーになるファイルを除外とありますが、これは自分の環境(Ubuntu Server 9.10)で問題になったものです。

2010/03/16

Railsのログをsyslog-ngで集約する はてなブックマークに追加

Railsのログをsyslog-ngを使って一カ所にまとめる手順をメモしておきます。
使用前

ここにRailsのサーバーが3台あります。前段にはロードバランサーが立っています。ログはデフォルトの場所にバラバラに記録されるので、記録としては相当使いにくいものになります。
使用後

ログ集計用のログサーバーを別途立てます。Railsアプリはsyslog経由でログを記録するようにします。syslogにはsyslog-ngを使い、Railsアプリが出したログはudp経由でログサーバーに随時転送するようにします。
今回は例として、ポート番号を5140番とします。
ログサーバーはudp:5140を見張っていて、ログが流れてきたらファイルに書き出すという算段です。

導入
そもそもなんでsyslog-ngなのか?という点に関してですが、個人的には導入のしやすさでした。もちろんその他も多くの利点があると思います。

作業としては、syslog-ngのインストールと設定、RailsアプリをSyslogLogger経由でのロギングに変更するだけです。既に運用が始まったものでも、結構簡単に移行出来ると思います。

今時syslog-ngを導入するには、パッケージで一発インストールでしょうから、お決まりの呪文を唱えましょう。※Ubuntu Linux Server 9.10で試しています。
sudo apt-get install syslog-ng
当たり前だけど、Railsサーバー、ログサーバーとも両方行います。

次に、RailsアプリのロギングをRubyのLoggerから、SyslogLoggerへ切り替えます。といってもやる事は簡単で、gemでインストールして、ちょこっと設定を変えるだけです。
sudo gem install SyslogLogger

config/environment.rbに以下の記述を追記します。
Rails::Initializer.run do |config|
  # (中略)
  config.gem 'SyslogLogger', :lib => 'syslog_logger'
  # (中略)
end
今回の想定では本番環境のみsyslogでロギングしたいので、config/environments/production.rbに下記を追記します。最初の行に書いておいた方が良いでしょう。
require 'syslog_logger'
RAILS_DEFAULT_LOGGER = SyslogLogger.new "rails_app"
rails_appはRailsアプリのログである事を識別するためのラベル(プログラム名)です。これはsyslog-ngで使用します。(rails_appというのは例です。解りやすいものにする方が良いでしょう。)


syslog-ngの設定(Railsアプリ側)
syslog-ngの設定そのものは簡単です。Railsアプリのサーバーではログをudpでログサーバーに向けて流す設定を行います。
syslog-ngの設定ファイルは、Ubuntuの場合だと
/etc/syslog-ng/syslog-ng.conf
にありますので、コイツに追記してやる事にします。
destination dr_rails_app {
    udp("192.168.1.100" port(5140));
};

filter f_rails_app {
    program(rails_app);
};

log {
    source(s_all);
    filter(f_rails_app);
    destination(dr_rails_app);
};
ここでは便宜的に、ログサーバーのIPアドレスを192.168.1.100としています。
destinationとfilterを定義して、それをlogでまとめるという感じです。
destinationは、見ての通り192.168.1.100へudpの5140ポートで送ると記述します。
filterはRailsアプリ側で指定したラベル(プログラム名)を記述します。
logの中の、source(s_all)というのは、Ubuntuだと全てのメッセージソースという事でデフォルトで定義されているものです。(これは環境によって書き方が変わってくる部分だと思います。)syslogがうけたログで、rails_appというラベルの付いたものだけを抽出し、それをログサーバーに送るという記述になっています。


syslog-ngの設定(ログサーバー側)
次にログサーバー側の設定です。
source s_rails_app {
    udp(ip("0.0.0.0") port(5140));
};

destination df_rails_app {
    file("/var/log/rails/production.log");
};

filter f_rails_app {
    program(rails_app);
};

log {
    source(s_rails_app);
    filter(f_rails_app);
    destination(df_rails_app);
};
sourceは自分自身のudp:5140です。
destinationはログの書き出し場所をファイルパスで示しています。
filterはRailsアプリ側で指定したラベル(プログラム名)を記述します。
これらをまとめて、logの中に記述します。

セキュリティの絡みでもっとやるべき事があるとは思いますが、基本的な事はこれだけです。
ログの取りこぼしが絶対あってはならないものであれば、udp経由での通信は厳しいので避けるべきです。

参考にさせていただいたサイト: