カテゴリー別アーカイブ: LAMP[Linux, Apache, MySQL, PHP]

新しいUPSを購入した

 我が家は下手なシステム屋以上にコンピュータやらネットワーク機器やら揃っている。 そんな中で、ベース環境としてUPSは欠かせない存在。
 従来、APCのSmartUPS 1500, 750, 500を利用していたのだけど、この夏の暑さでバッテリーがへたったため、750と500のバッテリー交換が必要な感じになった。
 ちなみに、UPSのバッテリー寿命は温度依存が非常に高い>オムロンのページ
 この夏にエアコン無し・強制空冷(扇風機)環境35度でSmartUPS500は死亡だったが、本体内に冷却ファンのあるSmartUPS1500は死ななかった。 やはり、ファンレスは信用ならないな・・・

 まぁ、そんなわけで、500の方を最近気になっていたリチウムイオン電池タイプのUPSにリプレースしてみた。

 ↑こんなやつ。

 500VAモデルで4万円弱なので、最近の相場だと結構高い感じだけど、買って正解だった。
 第一印象は、その軽量さがすごい。 UPSを通販すると、運送屋のおっちゃんに悪い感じがするわけだけど、こいつはなんと2.2kg、A4ノートPCと変わらない。
 サイズもスモールフォームファクタのマシンと同じ程度、Express5800/S70hfと並べて良い感じ。
 機能的にもかなり良好だ。
 SmartUPSではネットワークマネジメントカードをオプション追加して管理していたわけだけど、こいつは標準でWebインタフェイスがあって、リモートサイトから電源操作ができる(SNMP監視で複数台シャットダウンとかは出来ないが、容量的に複数台接続する物でも無い)
 また、ネットワークをモニタして、ダウンしたときに自動リセットすることが出来る。 安いルータを使っているような環境では、ルータが応答停止してせっかくのリモート管理が出来ないこともあるが、この機能があれば自動的に復旧を試行できる。

 ネットワーク機器用のUPSがGS Pro500、作業部屋とサーバルームがそれぞれSmartUPS750と1500になった。 SmartUPS500は予備で倉庫にしまっておこう。

(415)


カテゴリー: LAMP[Linux, Apache, MySQL, PHP] | 1件のコメント

mondorescue – Linuxシステムのフルバックアップとハード変更

 MondoRescueと言うツールがある。
 Linuxシステムのフルバックアップを行ってDVD等のメディアに保存して、DVDブートでフルリカバリしたり、あるいはファイル単位で復元も出来る便利なツールである。

 今回、開発に利用していたサーバの不調から、新しいサーバにシステム丸ごと移行するためにこのツールを使った。
 同一構成でのリストアでは何も気にすることなく、mondoarchiveコマンドで取ったバックアップをDVDに焼いて、DVDブートして全自動モードを選べばほぼ何も気にすることなく復元されるのだが、今回は、ハードウェアがだいぶ新しい物に変わったのと、非冗長ディスク構成だった環境からRAID1ミラーリング環境へと移行するため、色々と手順が必要だったので記録しておく。

旧環境
HP Proliant ML350 G5
HDD 250GBx2(LVMにより単一ボリューム化[JBOD]) IDE Native
/dev/sda1がブートパーティション
/dev/sda2, /dev/sdb2がVolGroup00のメンバーで、LogVol00がルート、LogVol01がスワップ。
CentOS 5.5 x86_64

新環境
HP Proliant ML110 G7
HDD 2TBx2(ソフトウェアRAID1構成) AHCI
CentOS 5.5 x86_64

 旧環境にてフルバックアップを実施した。
事前準備
MondoRescue導入
wget ftp://ftp.mondorescue.org/rhel/5/x86_64/mondorescue.repo
mv mondorescue.repo /etc/yum.repos.d/
yum install mondo
#バックアップ前にmdadmを入れておかないと、リカバリ時に使えなくて困る
yum install mdadm

バックアップメディアの準備(今回は2TBのHDDを接続して利用、/dev/sdcになった)
fdisk /dev/sdc
#全体をLinuxタイプのパーティションにした
mke2fs /dev/sdc1
mount /dev/sdc1 /mnt/backup

バックアップ実行
mondoarchive -Oi -g -L -N -s 4G -d /mnt/backup -E /mnt

・mondorescue-1.isoをDVDに焼く
・バックアップデータの入ったディスク(/dev/sdc)を新環境に接続

・新環境の構成を実施
新環境を先のDVD(mondorescue-1.isoのもの)からブートする。
 ブート時の選択でexpertで起動する。
 ハードディスクは/dev/sda, /dev/sdbにアレイ構築用、/dev/sdcにバックアップデータの入ったディスクが存在する状態。

fdisk /dev/sda
fdisk /dev/sdb
#/dev/sda1, /dev/sdb1を100MのLinux RAID Autodetect(type:fd)として作成、アクティブマークする。
#/dev/sda2, /dev/sdb2に残りを割り当て、同じくLinux RAID Autodetectにする。

mdadm –create –level=1 –metadata=0.9 –raid-devices=2 /dev/md0 /dev/sd[ab]1
mdadm –create –level=1 –metadata=0.9 –raid-devices=2 /dev/md1 /dev/sd[ab]2
#metadata1.2だとブートできなかった

lvm pvcreate /dev/md1
lvm vgcreate VolGroup00 /dev/md1
lvm lvcreate -L 1.8T -n LogVol00 VolGroup00
lvm lvcreate -L 8G -n LogVol01 VolGroup00
mke2fs -j /dev/md0
mke2fs -j /dev/VolGroup00/LogVol00
mkswap /dev/VolGroup00/LogVol01

#fstabを修正する
vi /etc/fstab
/dev/VolGroup00/LogVol00 / ext3 defaults,noatime
/dev/VolGroup00/LogVol01 swap swap defaults
/dev/md0 /boot ext3 defaults
#LABEL=boot /boot だったのを /dev/md0に変更

#mondoが使うマウントリストを修正
vi /tmp/mountlist.txt
/dev/md0 /boot ext3 0 /boot
/dev/md1 lvm lvm
/dev/VolGroup00/LogVol00 / ext3 lvm
/dev/VolGroup00/LogVol01 swap swap lvm

#リストアプログラムを起動する
mondorestore
モード選択>Interactive
ソース選択>Hard disk
プレフィクス設定>mondorescue
ディスクの場所の入力>/dev/sdc1
ディスクタイプの入力>ext3
External…? > Yes
ISO Mode – path > /
#プログラムがバックアップデータをマウントする
#マウントリストの編集画面やディスク構成関連の情報が出るが、先の手順で事前設定済みなので以下の通り進める
SaveMount List? > Yes
Do you want erase and partition your hard drives? No
Do you want format your hard drives? No
Do you want me to restore all of your data? Yes
#ファイルリストア処理が行われる(400GBで10時間程度かかった)
Initialize bootloader? No
#ブートローダを再構築しないといけないが、手動で実行するのでNo
#コマンドラインに落ちる

mkdir /mnt/root
mount /dev/VolGroup00/LogVol00 /mnt/root
mount /dev/md0 /mnt/root/boot
mdadm –examine –scan > /mnt/root/etc/mdadm.conf
#mdadm.confが無いとブート時にmdを見失う
chroot /mnt/root
mount /proc
#/proc/mdstatが無いとraid関係モジュールがmkinitrdで入ってこないので、必ず/procをマウントする
cd /boot
vi grub/device.map
#デバイスマッピングで/bootデバイスを指定しておく
(hd0) /dev/md0

vi grub/grub.conf
#grub設定のrootデバイス kernelオプションでrd_NO_DMやrd_NO_MDがある場合は削除する
#rootオプションを確認する(root=/dev/mapper/VolGroup00-LogVol00)、LVMがうまくいかないときは、rd_LVM_LV=VolGroup00/LogVol00とrd_LVM_LV=VolGroup00/LogVol01を追記する。

古い初期ファイルをリネームする
#grub.confにあったinitrdのファイル
#…はカーネルバージョン、2.6.el5.x86_64とか
mv initrd-…img initrd-…img.old
同名で新しい初期ファイルを構築する
mkinitrd -v -f initrd-…img …

ブートセクタを仕込む
grub
device (hd0) /dev/sda
root (hd0,0)
install /grub/stage1 (hd0) /grub/stage2 p /grub/grub.conf

device (hd0) /dev/sdb
root (hd0,0)
install /grub/stage1 (hd0) /grub/stage2 p /grub/grub.conf
quit

ctrl+dでchrootを抜けて、shutdown -hする。
 ブートに使ったDVDや、バックアップデータのドライブを外して起動できることを祈りつつ電源On。

 まとめると簡単だが、諸々、設定しなきゃいけない項目、しなくても良い項目があったりして難しかった印象だ。
 この手順をベースにすれば、非RAIDからRAID、RAIDから非RAIDへの移動も出来る。
 お名前.com VPS(KVM)等、VPSでは基盤側が冗長化されているから、VPS上では単純ディスク構成であるが、そこで構築した環境を物理サーバに持ってきたいみたいな場合、非RAIDtoRAID構成のV2P(仮想から物理へ)変換を行わなければならないので、この手順をメモっておく。

(2196)


カテゴリー: LAMP[Linux, Apache, MySQL, PHP], サーバ設定 | コメントをどうぞ

PHPを更新したらWPが止まった

 PHPをremiリポジトリから更新したらこのWPが止まってしまった。
 エラーログを確認すると、

PHP Fatal error : Call-time pass-by-reference has been removed

と言うメッセージ。

 PHPでのレファレンス渡しは

function func($var, &$ref){

}

の様に関数定義時に&記号を前置して書くとレファレンス(関数内部で$refに変更を加えると、呼出元の変数が変化する)になる。

 コールタイムレファレンスは

function func($var, $ref){

}

に対して、

func($a, &$b);

のようにしてコールして、呼び出し側でレファレンス渡しを要求する動き。
 レファレンスで処理したい場合と、したくない場合がある関数で使えば便利なのかもしれないけど、セキュリティ的問題点もある実装形式。
 で、新しいPHPでは、実行時レファレンスが無くなったので、プログラムを修正しないと動作しない。

 今回はWPプラグインのSEO CONTENT CONTROLプラグインに該当記述があり、更新版も存在しなかったので、プラグインを外して対応した。

(279)


カテゴリー: LAMP[Linux, Apache, MySQL, PHP] | コメントをどうぞ

old_passwordsの罠

 お名前.com VPS(KVM)に新サイトを展開していて、MySQLで作ったユーザがログインできない状態が発生した。

 MySQLはデフォルトリポジトリから導入して、設定ファイルは特別な記述をせず展開。
 CREATE USER文でユーザを作って、パスワードも設定。
 これでできあがったユーザでログインしようとすると失敗する。 Host値を書き換えてみたりするがダメ。

 何だろうな-、と思って、mysql.userテーブルを眺めてみると、既存ユーザのpasswordは16桁で、新しいユーザは41桁だった。
 16桁って言うのはMySQL4.1以前のハッシュ値で、4.1からは標準が41桁になっている(先頭に、旧ハッシュと新ハッシュを識別するための*記号が付与されていて、実際は40桁)
 mysql cliでSELECT PASSWORD(‘hoge’);してみると、41桁が帰ってくる。 でも、41桁ハッシュのアカウントは全てアクセス不能で16桁の物だけアクセスできる。

 試しにmy.cnfのmysqldセクションで、old_passwords=0を明示的に指定してrestartしてみると、41桁ハッシュのアカウントでログイン可能&16桁ハッシュのアカウントでもログイン可能となった。
 試しにold_passwords=1を明示的に指定すると・・・41桁ハッシュでも16桁ハッシュでもログイン可能であった。

・・・あれ?
 old_passwordsを明示的に指定してやらない場合、16桁ハッシュのアカウントしか認証できず、0でも1でも指定してやればどちらでも認証できる。 と言う、変な結果(不定値の条件バグだね)
 じゃあ、old_passwords値は無視されているのかというとそんなこともなく、
・0の場合はPASSWORD関数が生成するハッシュが41桁になる
・1の場合はPASSWORD関数が生成するハッシュが16桁になる
と言う動きをしていた。

 作成したユーザで認証できない場合、設定ファイルのold_passwords値をチェックしてみると良いと言うメモ。

(1160)


カテゴリー: MySQL | タグ: , | コメントをどうぞ

nginxでクライアントの接続調整をする

 リスティング広告を出していたりすると、出稿時に大量のアクセス(確認クローラ)が来てサイトの負荷が急上昇することがあるよね。

 さくらVPSお名前.com VPS(KVM)の2GBプランくらいでWordpress位の重さのページを素のまま表示させると、毎秒20アクセスとかで一杯一杯になる。

 そんな時は、nginxのリクエスト制御を使うと裏側の負荷上昇を穏やかにできる。

map $http_user_agent $ualimited{
    default ”;
    ~*googlebot 1;
    ~*msnbot 2;
    ~*bingbot 2;
    ~*slurp 3;
    …
}
limit_req_zone $ualimited zone=uazone:10m rate=10r/s;
server {
    …
    location / {
        …
        limit_req zone=uazone burst=200;
    }
}

 limit_req_zoneで、$ualmitedをキーにして、uazoneゾーンを毎秒10リクエストに制限する定義を作っている。
 で、ロケーション / に、limit_reqで定義したuazone制限を適用している。
※burstは、待ち行列の設定。 これが設定されていないと、リミットに達した時点で503エラーとなる。 burstが設定されていると、その値までのリクエストを待ち行列に突っ込んで、逐次処理することができる(burstを超えれば503になる) クローラが来た時にエラーを表示させると評価に問題が出るので、エラーではなく処理を遅延させて、正しく応答させる。
 limit_req_zoneの第一引数の値ごとにカウントするので、通常は$binary_remote_addrとかにして、リモートIPごとに制限するわけだけど、クローラは複数IPでガンガン来るので、ユーザエージェントで判別したいので、mapを使っている。
 if文で制限を直接設定できなかったので、UserAgent文字列から数値型にマッピングして、定義されているUAの場合に数値を与えて、それ以外の時は空にしてある。

 Wordpressであれば、/wp-content以下のファイルはスタティックで処理負荷が軽いので

    location / {
        …
        limit_req zone=uazone burst=200;
    }
    location /wp-content {
        …
    }

のように、wp-contentのロケーションを切れば、wp-content以下には要求制限がかからなくなる。

 前回のプロクシキャッシュを有効化して、

proxy_cache_path /dev/shm/c levels=1:2 keys_zone=cachezone:512m;
server{
    location / {
        …
        limit_req zone=uazone burst=200;
    }
    location /wp-content {
        …
        proxy_cache cachezone;
    }
}

のようにすれば、wp-content以下のスタティックファイルだけキャッシュすることができる。

(740)


カテゴリー: サーバ設定 | コメントをどうぞ

nginxのプロクシの裏側キャッシュを制御する

 nginxと裏のサーバ間のキャッシュを設定する。
 nginxのproxyでキャッシュする場合は、proxy_cacheを設定する。

proxy_cache_path /dev/shm/c levels=1:2 keys_zone=cachezone:512m;
server {
    location / {
        proxy_cache cachezone;
        proxy_pass http://appservers;
    }
}

 proxy_cache_pathでキャッシュの置き場所、置き方等を定義して、proxy_cacheでキャッシュ領域を割り当てる。
 で、この場合、プロクシを通過したデータを512Mまでキャッシュする。

 nginxでは細かい設定ができるのがイイね。

proxy_cache_path /dev/shm/c levels=1:2 keys_zone=cachezone:512m;
server {
    location / {
        set $dontcache 1;
        if ($request_filename ~* ".*\.jpg$"){
            set $dontcache 0;
        }
        if ($request_filename ~* ".*\.png$"){
            set $dontcache 0;
        }
        proxy_cache_bypass $dontcache;
        proxy_cache cachezone;
        proxy_pass http://appservers;
    }
}

 こうすると、要求されたファイル名がjpg, pngで終わるときしかキャッシュしない(proxy_cache_bypassに与えた値が0以外であるとき、キャッシュ機構をバイパスする)
 if文なので、$http_user_agent を使えばBOTと通常クライアントで異なる制御をしたりできる。
 また、特定のクッキーを持っている時だけバイパスするということも可能なので、開発ユーザにクッキーを食べさせておいて、該当クッキーをチェックするようにすると便利。

if ($cookie_author ~ “true”){
    set $dontcache 1;
}

みたいなこともできるし、そもそも、$cookie_author を 1/0 で制御するなら

proxy_cache_bypass $dontcache $cookie_author;

でも大丈夫。

(476)


カテゴリー: サーバ設定 | コメントをどうぞ

nginxで、入り口でまとめて認証をかける

 リリース前のサイトを本番環境でテストするとき、認証をかけたりするよね。
 DNSラウンドロビンとかLVSでバランシングしているときは、各ホストに.htaccessと.htpasswd書いたりするわけだけど、nginxでバランシングしている場合は、nginxの設定ファイルにまとめてかける。

server {
listen 80;
server_name hoge.tld;

location / {
auth_basic “auth”;
auth_basic_user_file “/usr/share/nginx/.htpasswd”;
proxy …
}
}

みたいな感じ。

nginxで認証を要求せず、裏のサーバが認証要求した場合には裏の認証要求が通る。
両方で認証を要求すると同じユーザ名:パスワードのセットで認証出来れば通るけど、それ以外の時は認証不能になる。

(332)


カテゴリー: サーバ設定 | コメントをどうぞ