2013年6月28日金曜日

CentOS6(SUZ-LAB AMI)のカーネルのアップデート

スズキです。

自分メモです。

まずは、現在のバージョンの確認です。
# uname -a
Linux ip-xxx-xxx-xxx-xxx 2.6.32-358.2.1.el6.x86_64 #1 SMP Wed Mar 13 00:26:49 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

"yum"のアップデートで下記のようにカーネルが場外されている場合は、
# cat /etc/yum
...
exclude=kernel* bash*
次のようにカーネルも対象になるように修正します。
# cat /etc/yum
...
#exclude=kernel* bash*
exclude=bash*

次に、カーネルのアップデートです。
# yum update kernel*
...

起動時に利用するカーネルの変更は、下記の部分を
# cat /boot/grub/menu.lst
...
kernel /boot/vmlinuz-2.6.32-358.2.1.el6.x86_64 ro root=/dev/xvde1
initrd /boot/initramfs-2.6.32-358.2.1.el6.x86_64.img
次のように、アップデートしたカーネルに書き換えます。
# cat /boot/grub/menu.lst
...
kernel /boot/vmlinuz-2.6.32-358.11.1.el6.x86_64 ro root=/dev/xvde1
initrd /boot/initramfs-2.6.32-358.11.1.el6.x86_64.img

ここまでできたら、リブートします。
# reboot
...

すると、アップデートしたカーネルのバージョンになっているはずです。
# uname -a
Linux ip-xxx-xxx-xxx-xxx 2.6.32-358.11.1.el6.x86_64 #1 SMP Wed Jun 12 03:34:52 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

最後に、古いカーネルを削除して終了です。
# yum erase kernel-2.6.32-358.2.1.el6
...

"yum"の設定も下記のように戻しておきます。
# cat /etc/yum
...
exclude=kernel* bash*

近頃、"SUZ-LAB AMI"が進化してない...
--------
http://www.suz-lab.com

2013年6月27日木曜日

RubyでRDSのログをログの監視用にダウンロード

スズキです。

以前、下記でRubyのSDKを利用したRDSのログのダウンロード方法を紹介しました。
RubyでRDSのログ(すべてのファイル)をダウンロード
今回は(似てるのですが)、下記のログのチェックという観点でスクリプトを作ってみました。
  • RDS側のログが更新された時のみ最新のログファイル("mysql-general.log"など)を
    ダウンロードする。
  • ログの更新の判断は"last_written"の時刻を比較する。
  • RDS側のログのローテーションのタイミングとダウンロードのタイミングで
    抜けてしまうログをフォローするために、ログローテーション時には
    一世代前のログ("mysql-general.old"など)もダウンロードする。
  • 最新のはログのサイズが減少したらローテーションしたと判断する。

作成したスクリプトは下記の通りです。
#!/usr/bin/ruby

require 'rubygems'
require 'aws-sdk'

# 初期設定
AWS.config({ :region => 'ap-northeast-1' })
db_instance_identifier = 'suzlab'
filename               = 'general/mysql-general.log'
file_prefix            = '/tmp/general_mysql-general'

# 最新のログファイルの"last_written"を保存するファイルの作成
if !File.exists?(file_prefix + '.last_written') then
    open(file_prefix + '.last_written', 'w').write('0')
end
# 最新のログファイルの"size"を保存するファイルの作成
if !File.exists?(file_prefix + '.size') then
    open(file_prefix + '.size', 'w').write('0')
end

client = AWS::RDS.new.client

# 前回チェック時から更新された最新のログファイルを取得
log_files = client.describe_db_log_files({
    :db_instance_identifier => db_instance_identifier,
    :filename_contains      => filename,
    :file_last_written      => open(file_prefix + '.last_written', 'r').read.to_i + 1
})

# 該当ログファイルが無ければ終了
if log_files.describe_db_log_files.size == 0 then
    exit
end

# 最新のログファイルのダウンロードと更新
additional_data_pending = true
marker                  = '0:0'
while additional_data_pending do
    log = client.download_db_log_file_portion({
        :db_instance_identifier => db_instance_identifier,
        :log_file_name          => filename,
        :marker                 => marker
    })
    File.open(file_prefix + '.log.tmp', "a") do |io|
        if !log.log_file_data.nil? then
            io.print(log.log_file_data)
        end
    end
    additional_data_pending = log.additional_data_pending
    marker                  = log.marker
end
File.rename(file_prefix + '.log.tmp', file_prefix + '.log')

# ローテーションのチェック
if open(file_prefix + '.size', 'r').read.to_i > log_files.describe_db_log_files[0].size then

    # 一世代前のログファイルを取得
    log_files = client.describe_db_log_files({
        :db_instance_identifier => db_instance_identifier,
        :filename_contains      => filename,
    })
    log_files.describe_db_log_files.sort! { |a, b| a.last_written <=> b.last_written }
    log_files.describe_db_log_files.reverse!

    # 一世代前のログファイルのダウンロードと更新
    additional_data_pending = true
    marker                  = '0:0'
    while additional_data_pending do
        log = client.download_db_log_file_portion({
            :db_instance_identifier => db_instance_identifier,
            :log_file_name          => log_files.describe_db_log_files[1].log_file_name,
            :marker                 => marker
        })
        File.open(file_prefix + '.old.tmp', "a") do |io|
            if !log.log_file_data.nil? then
                io.print(log.log_file_data)
            end
        end
        additional_data_pending = log.additional_data_pending
        marker                  = log.marker
    end
    File.rename(file_prefix + '.old.tmp', file_prefix + '.old')

end

# "last_written"と"size"を更新(ファイルに出力)
open(file_prefix + '.last_written', 'w').write(log_files.describe_db_log_files[0].last_written)
open(file_prefix + '.size', 'w').write(log_files.describe_db_log_files[0].size)

実行すると、下記のようにログなどのファイルが出力されます。
# ll /tmp/
-rw-r--r-- 1 root root    13  6月 27 13:44 2013 general_mysql-general.last_written
-rw-r--r-- 1 root root 55086  6月 27 13:44 2013 general_mysql-general.log
-rw-r--r-- 1 root root 75503  6月 27 13:00 2013 general_mysql-general.old
-rw-r--r-- 1 root root     5  6月 27 13:44 2013 general_mysql-general.size

あとは、このログをNagiosで監視すれば...
(ログチェックのポジションのリセットなどは改めて考えないといけないけど...)
--------
http://www.suz-lab.com

2013年6月26日水曜日

CentOS6にAWSのRubyのSDKをインストール("ruby-devel"も必要だったので...)

スズキです。

今更の話題ですが、CentOS6に"yum"で"rubygems"をインストールして、
さらに"gem"で"aws-sdk"をインストールした場合に、少し引っかかったので、
メモとして残しておきます。

まず、"yum"で"rubygems"のインストールです。
# yum -y install rubygems
...

次に、"gem"で"aws-sdk"のインストールですが、ここでエラーが発生してしまいました。
# gem install aws-sdk
Building native extensions.  This could take a while...
ERROR:  Error installing aws-sdk:
 ERROR: Failed to build gem native extension.

/usr/bin/ruby extconf.rb
mkmf.rb can't find header files for ruby at /usr/lib/ruby/ruby.h

Gem files will remain installed in /usr/lib/ruby/gems/1.8/gems/nokogiri-1.5.10 for inspection.
Results logged to /usr/lib/ruby/gems/1.8/gems/nokogiri-1.5.10/ext/nokogiri/gem_make.out

エラーログを確認してみると、Rubyのヘッダファイルが足りないようです。
# cat /usr/lib/ruby/gems/1.8/gems/nokogiri-1.5.10/ext/nokogiri/gem_make.out
/usr/bin/ruby extconf.rb
mkmf.rb can't find header files for ruby at /usr/lib/ruby/ruby.h

ということで、"ruby-devel"も"yum"でインストールします。
# yum -y install ruby-devel
...

再度、"aws-sdk"をインストールすると、今度は無事にインストールできました。
# gem install aws-sdk
Building native extensions.  This could take a while...
Building native extensions.  This could take a while...
Successfully installed nokogiri-1.5.10
Successfully installed json-1.8.0
Successfully installed aws-sdk-1.11.3
3 gems installed
Installing ri documentation for nokogiri-1.5.10...

No definition for parse_memory

No definition for parse_file

No definition for parse_with

No definition for get_options

No definition for set_options
Installing ri documentation for json-1.8.0...
Installing ri documentation for aws-sdk-1.11.3...
Installing RDoc documentation for nokogiri-1.5.10...

No definition for parse_memory

No definition for parse_file

No definition for parse_with

No definition for get_options

No definition for set_options
Installing RDoc documentation for json-1.8.0...
Installing RDoc documentation for aws-sdk-1.11.3...

6月のブログ数は一桁になりそう...(まずい...)
--------
http://www.suz-lab.com

2013年6月16日日曜日

VarnishでHTTPのアクセス(S3)をHTTPSのアクセス(S3)にリダイレクト

スズキです。

以前紹介した下記の合わせ技です。

概要は、こんな感じです。



設定ファイル(/etc/varnish/default.vcl)は、こんな感じです。
backend default {
    .host = "localhost";
    .port = "80";
}

sub vcl_recv {
    if(req.http.host == "www.suz-lab.com") {
        if(req.http.X-Forwarded-Proto == "https") {
            set req.backend   = suzlab;
            set req.http.host = "www.suz-lab.com.s3-website-ap-northeast-1.amazonaws.com";
            set req.request   = "GET";
            return(lookup);
        }
    }
    return(error);
}

sub vcl_error {
    if(req.http.host == "www.suz-lab.com") {
        if(req.http.X-Forwarded-Proto != "https") {
            set obj.http.Location = "https://" req.http.host req.url;
            set obj.status = 301;
        }
    }
    return(deliver);
}

backend suzlab {
    .host = "www.suz-lab.com.s3-website-ap-northeast-1.amazonaws.com";
    .port = "80";
}

今回、SSLターミネーションはELBで実施していますが、近頃リリースされた下記の
CloudFrontでのターミネーションの方が、今後はいいかもしれません。(未検証)
Amazon CloudFrontが独自SSL証明書とルートドメインホスティングをサポート

6月初ブログ...(俺は今まで何をしてたんだろう...)
--------
http://www.suz-lab.com