Displaying posts tagged with

“サーバ管理”

MySQL MEMORYテーブルのサイズをmuninで監視する

DB内のMEMORYテーブルのサイズを、テーブルごとにグラフ化するための munin プラグインを作ってみました。

mysql_memory_tables_

インストール

munin-node 本体のプラグインディレクトリ(/usr/share/munin/plugins など)にコピーしてください。

設定

ワイルドカードプラグインなので、mysql_memory_tables_{チェック対象となるDB名} という名前でシンボリックリンクを張ってください。

ln -s /usr/share/munin/plugins/mysql_memory_tables_ /etc/munin/plugins/mysql_memory_tables_db1

データを取得するには対象DBの INFORMATION_SCHEMA にアクセスする権限が必要です。プラグイン設定ファイル(/etc/munin/plugin-conf.d/munin-node など)で mysql コマンドに渡すユーザ名・パスワードを指定してください。

[mysql_memory_tables_*]
env.mysqlopts -u cicindela --password=hogehoge

動作確認

munin-run コマンドでテストができます。

# 値の表示
munin-run mysql_memory_tables_db1
 
# グラフ設定情報の表示
munin-run mysql_memory_tables_db1 config

動作が確認できたら munin-node を再起動してください。

WARNING: mismatch_cnt is not 0 on /dev/md0

Software RAID1を組んでいるサーバで、CentOS 5.3 -> 5.4にアップグレードしたところ、週末ごとに次のような警告メールが届くようになった。

/etc/cron.weekly/99-raid-check:

WARNING: mismatch_cnt is not 0 on /dev/md0

/proc/mdstat 等には特に異常などは見当たらないし、構成の異なる複数のサーバで同じ現象が起こったので、ハード的な問題ではないだろうと判断し、忙しかったこともあってそのままにしていた。しかしやはり気持ち悪いので、きちんと調べてみた。

メール中にある通り、この警告は /etc/cron.weekly/99-raid-check というスクリプトから送信されている。このスクリプトを提供しているのは mdadm パッケージで、5.4で更新されている。更新内容はレッドハットのサイトで RHBA-2009:1382-1 として提供されており、99-raid-check について説明しているのは、次の2箇所である。

* LinuxのソフトウェアRAIDスタックでは、データスクラビングがサポートされています(RAIDアレイのディスクを読み取って不良セクタを検索し、不良セクタが見つかると、他のディスクやパリティの情報を使用して、不良セクタを正常なデータで書き直します)。しかし、mdadmパッケージはこの機能を利用していませんでした。今回のパッケージは、cronジョブが/etc/cron.weeklyに追加されており、ディスクをチェックして不良セクタがないかどうかを確認し、見つかった場合は修復します。(BZ#233972)

* 今回のアップデートでは、mdadmに冗長アレイでの「データスクラビング」を可能にする新しい機能が追加されています。データスクラビングでは、冗長アレイ内のドライブ上で不良セクタが検索され、見つかった場合は他のドライブのデータを使用して修正されます。それによって、読み取りエラーを返すセクタは再構築されます。注:この新しいパッケージでは、データスクラビングはデフォルトでオンになっています。この機能は週1回実行され、実行中にある程度のパフォーマンス低下を引き起こす場合があります。パフォーマンス上の理由でこの機能を無効にしたい場合、アレイに対して実行されるチェックのタイプを管理したい場合、あるいは、どのアレイをチェックするかを制御したい場合は、/etc/sysconfig/raid-checkファイルを編集します。オプションを設定する方法の詳細は、そのファイルにコメントとして含まれています。(BZ#513200)

「データスクライピング(Data Scrubbing)」とは何か、なぜ重要なのかについては、ここで示されているBugzilla #233972およびその先のリンクに説明がある(一箇所リンクが切れているのはRAID/Software – GEntoo Linux Wikiだと思われる)。

データスクライピングを実行するには、root権限で次のコマンドを実行する。これによって不良セクタが検出され、自動的に修復される。99-raid-check が実行するのも、まさにこのコマンドである(少なくともデフォルトの設定においては)。

echo check > /sys/block/mdX/md/sync_action

ではこのコマンドと、問題の mismatch_cnt とはどう関係するのか。/etc/sysconfig/raid-check のコメントを読むと次のように書いてある。

If it finds good sectors that contain bad data (meaning that the data in a sector does not agree with what the data from another disk indicates the data should be, for example the parity block + the other data blocks would cause us to think that this data block is incorrect), then it does nothing but increments the counter in the file /sys/block/$dev/md/mismatch_count.

つまりセクタ自体は正常だが、中に入ってるデータがディスク間で異なる場合に mismatch_cnt が増加するということらしい。

ならば mismatch_cnt が 0 でないということは、ただちにRAIDが正常に機能していないことを意味するのだろうか?いろいろなMLの投稿などを読む限り、少なくとも swap パーティションを含むRAIDデバイスにおいては、全く正常であっても各ディスク間の内容が異なり得る…すなわち mismatch_cnt が0でないことがあり得るようだ。では swap を含まないパーティションの場合は?私の(また他のCentOS利用者の)ように、/boot のみを含む md0 の場合は?……これがよく分からない。この投稿を読む限り、ある種の状況においてはそうしたことも起こり得る、とのことである。

もしそうした状況に該当するなら。mismatch_cnt が 0 でなくとも、異なっているのは実際にはファイルシステムからアクセス不能な部分であって、システムの運用には影響しないのであれば。修復する方法はある。check の代わりに repair を使うことである。

#このコマンドを実行する前に以下の説明をよく読んでください!!
echo repair > /sys/block/mdX/md/sync_action

ただし /etc/sysconfig/raid-check には、次のような恐ろしいコメントが書いてある(強調は私による)。

The repair option does the same thing, but when it encounters a mismatch in the data, it automatically updates the data to be consistent. However, since we really don’t know whether it’s the parity or the data block that’s correct (or which data block in the case of raid1), it’s luck of the draw whether or not the user gets the right data instead of the bad data.

というわけで、以下は「それでも自己責任でこの方法に賭けるぜ!」という方のみ読んでください。

まず各デバイスの mismatch_cnt の値をチェックしておく。

cat /sys/block/md0/md/mismatch_cnt

そして repair を実行する。

sudo sh -c 'echo repair > /sys/block/md0/md/sync_action'

進行状況は /proc/mdstat で確認できる。

cat /proc/mdstat

repair を実行しただけでは mismatch_cnt は更新されないので、もう一度 check を実行する。進行状況はやはり /proc/mdstat で確認できる。

sudo sh -c 'echo check > /sys/block/md0/md/sync_action'

終了したら mismatch_cnt をチェックして、0 になっているか確認する。

cat /sys/block/md0/md/mismatch_cnt

……

参考にしたサイトははてブの mismatch_cnt タグにまとめてあるので、この記事に書いてあることを鵜呑みにせず、自分で調べ自分で判断するようお願いします。

XREA+からエックスサーバーに移転

XREAが重過ぎて使い物にならなくなったので、エックスサーバーに移転した。ここを選んだ理由は

  • PHP5, MySQL5が使える
  • 比較的値段が安い(X10プランで月額1050〜1260円)
  • ネット上の口コミでは速度に対する評価が高い
  • “ハズレ”を引いたときの救済措置簡単サーバ移動機能がある
  • SSHが使えないので、派手なことをするヤツは少ないだろうという希望的観測

今のところ速度には満足。サーバの管理画面も使いやすい(若干パワーユーザ向けだが)。WordPressも問題なく移転できた。

WordPressの移転にはいろいろな方法があるようなので、私の方法も紹介しておく。最も原始的かつ確実な方法で行った。

エックスサーバーでの下準備

  1. 管理画面「MySQL設定」で新しいMySQLデータベースとMySQLユーザを作る
  2. 「ドメイン設定」で独自ドメインを登録する
  3. できればここで /etc/hosts ファイルを書き換えてきちんとアクセスできることを確認しておく。WebサーバのIPアドレスは「DNSレコード設定」で確認できる

旧データのバックアップと修正

  1. XREAの管理画面「データベース」で「保存」ボタンを押してバックアップを作成する
  2. 作成されたmysql.dumpおよびサイトの全ファイルをローカルにコピーする
  3. wp-config.php を開き、データベース設定をエックスサーバーのものに書き換える

エックスサーバーにアップロード

  1. 管理画面からphpMyAdminにログインして、mysql.dumpを実行
  2. ドキュメントルートに全ファイルをコピー
  3. 例によって /etc/hosts を書き換え、WordPressが正常に動くことを確認

あとはDNSを変更すればOK。

mymemcheckをCentOSで動かす

サーバ/インフラを支える技術』に載っていた mymemcheck を試してみようと思って CentOS 5 上で実行してみたところ、いくつかの Perl モジュールが足りなくて動かなかった。例によって rpmforge で検索してみたら、やはり見つかった。

sudo yum --enablerepo=rpmforge install perl-Readonly perl-UNIVERSAL-require

相変わらず便利過ぎるぜ rpmforge。

mod_dosdetector の使い方

サーバ/インフラを支える技術』で知ったDoS攻撃判定モジュール mod_dosdetector の使い方。mod_dosdetecotr のバージョンは 0.2、環境は Apache 2.2.3 @ CentOS 5。

改造版も公開しています。

インストール

wget http://ncu.dl.sourceforge.net/sourceforge/moddosdetector/mod_dosdetector-0.2.tar.gz
tar xvzf mod_dosdetector-0.2.tar.gz
cd mod_dosdetector-0.2
make
sudo make install

httpd.conf 設定例

# 実際にはこの一行は make install で追加される
LoadModule dosdetector_module modules/mod_dosdetector.so
 
DoSDetection     on
DoSPeriod        5
DoSThreshold     10
DoSHardThreshold 25
DoSBanPeriod     30
DoSTableSize     100
DoSIgnoreContentType  image|javascript|css

DoS判定の肝となる数値は DoSPeriod, DoSThreshold, DoSHardThreshold, DoSBanPeriod の4つで、上の例ではだいたい次のような意味になる:

  1. 同一IPアドレスから5秒間に10回以上のアクセスがあった場合「DoS攻撃の疑いあり」と見なし、その後30秒間のアクセスに対しては環境変数 SuspectDoS をセットする(値は”1″)
  2. さらに5秒間のアクセス回数が25回に達した場合、「激しいDoS攻撃の疑い」と見なし、環境変数 SuspectHardDoS もセットする(値は”1″)
  3. 初めに「DoS攻撃の疑いあり」と判定してから30秒が経過したら、次のアクセスでもう一度判定をやり直す。直近5秒のアクセスが10回を下回っていれば、疑いは晴れる

アクセス数の計測はファイルの種類・有無を問わずに行われるため、デフォルトではページ内の画像やCSSなども計測対象となってしまう。それらを除外したい場合は、DoSIgnoreContentType ディレクティブで除外したいファイルの MIME type を正規表現で指定しておく(ファイル名(URL)ではないので注意)。各種画像ファイル・JavaScript・CSSファイルを除外したい場合は上例のように設定しておけば良い。

ただし多くの環境では拡張子 ico に対する MIME type の指定は行われていないはずなので、そのままだと favicon.ico が text/plain 等と見なされて除外されない(.ico に限らず、未設定の場合は httpd.conf の DefaultType になる)。次のように AddType を追加しておけば image と判定される。

AddType  image/vnd.microsoft.icon  .ico

ちなみにこれがアイコンファイルの正式な MIME type である。

DoS攻撃に対する防御設定

mod_dosdetector が行うのはあくまでも攻撃の”検出”だけなので、防御する方法はまた別に設定する必要がある。多くの場合は mod_rewrite と併用することになるだろう。例えば「激しいDoS攻撃の疑い」なアクセスに対してステータスコード503 + 静的なHTMLを返す場合は次のように設定する(Apache 2.2 only)。

RewriteEngine On
RewriteCond %{ENV:SuspectHardDoS} =1
RewriteRule .*  - [R=503,L]
 
ErrorDocument 503 /server_is_busy.html

しかし現実には、攻撃の判定とその後の防御は、匙加減が難しい。どの程度のアクセスを攻撃と見なすかはサイトによって千差万別だろうし、あまりに頻繁・過剰な反応をしてしまうとユーザが離れてしまう。

そこで個人的には、まず厳し目の設定を行って、ログを取ってみることをおすすめする。「DoS攻撃の疑いあり」なアクセスを普通のログと分けて記録するには次のように設定する。

LogFormat "%{SuspectHardDoS}e %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" dos_suspect
CustomLog logs/dos_suspect_log dos_suspect env=SuspectDoS

ログの行頭に環境変数 SuspectHardDoS が記録されるため、どのような経過をたどって「疑いあり」から「激しい攻撃の疑い」へと移行したかも分かる。

後はこの記録を見つつ、通常のアクセスが引っかからないような適当な設定を探ることになる。もしサーバリソースの都合上、どうしても通常のアクセスが引っかてしまう可能性があるのなら、その時は防御方法をより穏当なものに設定することもできる(このあたりの柔軟性は mod_dosdetector の設計の妙だと思う)。

その他

上で触れなかったディレクティブについて少々:

DoSDetection
DoS判定機能の有効・無効を設定。on で有効
DoSTableSize
クライアントの追跡記録の最大保存数。この数値を大きくすればより多くのクライアントを同時に追跡できるが、メモリ使用量と負荷が上昇する
DoSShmemName
クライアントの追跡記録を保存しておくための共有メモリの名前。普通は設定する必要は無いはず

最後に

素晴らしいソフトウェアをオープンソースとして公開してくださった田中慎司さん(そして株式会社はてな)に感謝!

Apache 2.2ではmod_rewriteのRフラグで任意のステータスコードを返せる

昔Apache 2.0系で試したときは無理だったのに、2.2系ではできるようになっていたのか。

mod_rewriteで503 – Do You PHP はてな

上エントリーで引用されているドキュメントは古くて、現在は次のような記述に置き換わっている。

While this is typically used for redirects, any valid status code can be given here. If the status code is outside the redirect range (300-399), then the Substitution string is dropped and rewriting is stopped as if the L flag was used.

mod_rewrite – Apache HTTP Server

『このフラグは通常リダイレクトのために用いられるが、任意の妥当なステータスコードを指定することができる。もしリダイレクト以外のステータスコード(すなわち300〜399以外)が指定された場合、置換文字列は無視され、さらにLフラグが指定されたときと同じようにURLの書き換えが停止される。』

つまりリダイレクトもURLの書き換えも行われないので、デフォルトのエラー画面以外を表示するには ErrorDocument ディレクティブで指定しておく必要がある。

RewriteEngine On
RewriteCond %{some_condition} =1
RewriteRule .*  - [R=503]
 
ErrorDocument 503 /server_is_busy.html

ソースに付属している文書(CHANGES)によれば、この仕様に変わったのはバージョン2.1.1。Bugzillaで以下のような議論も見つけた。

In the <300, >=400 cases, one can think of this as [R{esponse}=nnn} as opposed to [R{edirect}], and it really harms nothing to overload it.

Bug 45478 – R flag in RewriteRule does not honor 400 and 500 range error code

Redirect の ‘R’ ではなく Response の ‘R’ と見なしてくれ、と。なるほど…。

BlockHosts の導入

ブルートフォースアタックからの防衛ツール BlockHosts 導入手順。環境は CentOS 4。

インストール

rpmで導入する場合

wget http://www.aczoom.com/tools/blockhosts/BlockHosts-2.4.0-1.noarch.rpm
sudo rpm -Uvh BlockHosts-2.4.0-1.noarch.rpm

もしくはソースからインストールする場合

wget http://www.aczoom.com/tools/blockhosts/BlockHosts-2.4.0.tar.gz
tar xvzf BlockHosts-2.4.0.tar.gz
cd BlockHosts-2.4.0
sudo python setup.py install

どちらの方法を使っても、設定ファイルは /etc/blockhosts.cfg にインストールされるし、ログローテーションのための設定ファイル /etc/logrotate.d/blockhosts もインストールされる。

/etc/blockhosts.cfg の設定

まずは最低限の設定を行う。CentOS ならほとんどの場合はデフォルトで良いと思うが、

HOSTS_BLOCKFILE = "/etc/hosts.allow"
WHITELIST = [ "127.0.0.1", "192\.168\.2\..*", ]
LOGFILES = [ "/var/log/secure", ]

このあたりは明示的に設定しておいた方が良いと思う。WHITELIST に追加する設定は自分の環境にあわせて。

/etc/hosts.allow に設定追加

こちらもまずは最低限の情報を書いて、動作確認をする。

#---- BlockHosts Additions
#---- BlockHosts Additions

この状態で以下のコマンドを実行し、正しく解析結果が表示されることを確認。

sudo blockhosts.py --verbose --dry-run

次に –dry-run オプションを外し、/etc/hosts.allow の書き換えが正しく行われることを確認する(BlockHosts Additions の間に情報が書き込まれる)。

sudo blockhosts.py --verbose

最後に /etc/hosts.allow の末尾に blockhosts.py の起動設定を追加する。以下は一例

sshd: ALL: spawn /usr/bin/blockhosts.py --verbose --echo "%c-%s" >> /var/log/blockhosts.log 2>&1 : allow

その後の設定

ほとんどの設定は /etc/blockhosts.cfg の中でも、blockhosts.py のコマンドラインオプションとしても(つまり /etc/hosts.allow の中でも)設定できる。詳しくは blockhosts.cfg の中のコメントや blockhosts.py –help を参照。

試していないが、「ipblock」の設定を行うことで、TCP/IP レベルでのブロックも行えるようだ。ip コマンドで無効なルートを設定するか、iptables でフィルタリングするか選べるらしい。blockhosts.cfg より:

#IPBLOCK = "" # (default)
#IPBLOCK = "ip route" # or use full path "/sbin/ip route"
#IPBLOCK = "iptables" # or use full path "/sbin/iptables"
# "ip route": Do TCP/IP blocking using route commands to setup null-routes.
#    ip route add  via 127.0.0.1
# "iptables": Do TCP/IP blocking, using iptables packet filtering.
#    iptables --append blockhosts --source  -j DROP

cciss経由で取得したHDDの温度をmuninでグラフ化

CCISS (HP/Compaq Smart Array Controller) に接続された HDD の SMART 情報を読み出し、温度を munin の hddtemp_smartctl プラグインでグラフ化する。

cciss に対応する smartmontools は 5.38 以降(stable)。CentOS 5.3 では標準でこのバージョンがインストールされるが、あいにく対象サーバはCentOS 4だったので、ソースからインストールした。

tar xvzf smartmontools-5.38.tar.gz
cd smartmontools-5.38
./configure
make
sudo make install

/usr/local/sbin に新たにインストールされた smartctl を使用して、温度その他の情報が取得できることを確認。以下表示例。

$ sudo /usr/local/sbin/smartctl -A -d cciss,0 /dev/cciss/c0d0
smartctl version 5.38 [i686-pc-linux-gnu] Copyright (C) 2002-8 Bruce Allen
Home page is http://smartmontools.sourceforge.net/

Current Drive Temperature:     26 C
Drive Trip Temperature:        65 C
Manufactured in week 50 of year 2006
Recommended maximum start stop count:  10000 times
Current start stop count:      19 times
Elements in grown defect list: 0

続いてmunin のプラグイン設定ファイル(/etc/munin/plugin-conf.d/hddtemp_smartctl )に設定を追加する。デバイス名の後に _[番号] を付けるのがポイント。

[hddtemp_smartctl]
user root
env.smartctl    /usr/local/sbin/smartctl
env.drives      cciss/c0d0_0 cciss/c0d0_1
env.type_cciss/c0d0_0  cciss,0
env.type_cciss/c0d0_1  cciss,1

これで値が取得できるようになる…のだが、うまくグラフが表示されない。デバイス名に / が含まれているのがまずいらしいので、プラグインファイル /usr/share/munin/plugins/hddtemp_smartctl を少し改造。munin-node-1.2.5用のパッチを置いておく。

こんな感じで表示されるようになる。

hddtemp_smartctlによるグラフ表示

hddtemp_smartctlによるグラフ