fluentdで一旦ログ集約してみた話

うちの会社には事業の一つとして、レンタルサーバー事業のインフラ周りの運用や構築があります。

運用は私が率先として実施しているので、よくこんなお問い合わせを受けることがあります。

– ユーザーさんからある宛先にメールしたけど、届いていないようだから調査してほしい。
– メールがエラーで返ってきてしまった。
– 迷惑メールが大量に送信されている可能性がある。
– メーリングリスト宛に送ったら、一部の宛先にとどかない。

などなど、今回はメールだけ書きましたが所謂レンタルサーバーにありがちなお問い合わせが多数上がってきます。

調査するときはとってもアナログでそれぞれのサーバーにログインして、シェルのワンライナーをコピペしまくるわけです。

とっても非効率なので、なんとかならないものかと調べてたところfluentdにたどり着きました。
そこで、まずはログを集約して、perlなりシェルスクリプトで調査を楽にすることを目的として検証することに。

これがとても便利で、かなる簡単に導入することができるのがわかり、本番サーバーの幾つか限定して導入してみました。
容量に余裕ありまくるバックアップサーバーを受け口として、ログを転送させてみてます。

fluentdはリアルタイム性が低い代わりに、サーバー負荷を減らし、ある程度バッファにためてログを転送してくれます。
これはインフラエンジニア的にはすっごい助かりますね。iowaitで死んだとかたまにあるので、ログ集約で負荷とかかけたくないですし。

実際に動作みてもイイ感じです。
バッファためるので本当に取れてるか不安になりますが、ちゃんと取れてます。

image

はい、その通り。
できたらmongodbにつっこんだり、elastic searchに渡してkibanaで表示させたりしたいですが、まずは集約して使ってみることですね。

細かい話しはいずれ。

以上です。

今更感満載だけどMySQLのdumpリストアを検証してみる

とっても今更感あるし、他にも書いている人たくさんいるけど、別名でリストアとかってあんまり書かれていないので、テストして残しておこうと思います。

 

テストケース1:mysqldumpで特定のデータベースをバックアップして、別名でリストアしてみる。

まず、testdb01というデータベースを作る。
そして、t_nameというテーブルにid4までのデータをインサートする。
その後、下記コマンドでtestdb01だけdumpを取得します。

# mysqldump -u root -p testdb01 > testdb01.sql

つぎに、testdb02という新しい空のデータベースを作成し、testdb01を更新してみる。
その後、

# mysql -u root -p testdb02 < testdb01.sql

その結果が以下の通りです。

mysql> use testdb01;

mysql> select * from t_name;

+——+——-+
| id | name |
+——+——-+
| 1 | hoge1 |
| 2 | hoge1 |
| 3 | hoge1 |
| 4 | hoge1 |
| 5 | hoge2 |
+——+——-+
5 rows in set (0.01 sec)

mysql> use testdb02;

mysql> select * from t_name;
+——+——-+
| id | name |
+——+——-+
| 1 | hoge1 |
| 2 | hoge1 |
| 3 | hoge1 |
| 4 | hoge1 |
+——+——-+
4 rows in set (0.00 sec)

ちゃんとtestdb01は更新されずに、testdb02にdumpで取得した時の状態になっています。

 

テストケース2:mysqldumpで全てのデータベースを取得して、特定のデータベースへリストアしてみる。

テストケース1で作ったtestdb01が存在している状態とします。
この状態で、下記コマンドで全データベースのdumpを取得します。

# mysqldump -u root -p –events -x –all-database > alldump.sql

つぎにtestdb01のデータベースを下記SQLで更新しちゃいます。

mysql> insert into t_name(id,name) values(6,’hoge01′),(7,’hoge01′),(8,’hoge01′);

いまの時点でdumpデータと既存データベースに差異が発生します。
つぎにtestdb02を作成します。

mysql> create database testdb02;

この状態で先ほどのalldump.sqlをテストケースと同じようにtestdb02に流してみます。

mysql -u root -p testdb02 < alldump.sql

結果は以下のとおりです。

mysql> use testdb02;
Database changed
mysql> show tables;
Empty set (0.00 sec)

mysql> use testdb01;
Database changed
mysql> select * from t_name;
+——+——-+
| id | name |
+——+——-+
| 1 | hoge1 |
| 2 | hoge1 |
| 3 | hoge1 |
| 4 | hoge1 |
| 5 | hoge2 |
+——+——-+
5 rows in set (0.00 sec)

 

つまり、mysqldumpのallで取得したdumpファイルそのままでデータベース名を指定してリストアすると、dumpで取得した全てのデータが、dumpのデータまでロールバックしてしまうのです。
実行時に新しいデータベース名にしたとしても、エラーが出ません。
テストケース2の方法でリストアすると、既にデータベースがある場合はCREATE DATABASEは発行せず、テーブルのDROP,CREATEを実行するようにdumpファイルに記載があります。
これを知らないと結構面倒くさいことになる場合があります。

 

テストケース3:テストケース2の失敗を鑑みて、dumpファイルを修正して別名のデータベースへリストアしてみる。

テストケース2で作成したデータベースを使用します。
いまはこんな状態です。

mysql> use testdb01;
mysql> select * from t_name;
+——+——-+
| id | name |
+——+——-+
| 1 | hoge1 |
| 2 | hoge1 |
| 3 | hoge1 |
| 4 | hoge1 |
| 5 | hoge2 |
+——+——-+
5 rows in set (0.00 sec)

mysql> use testdb02;
Database changed
mysql> select * from t_name;
ERROR 1146 (42S02): Table ‘testdb02.t_name’ doesn’t exist

テストケース2と同じように全体のdumpデータを取得します。

# mysqldump -u root -p –events -x –all-databases > alldump2.sql

testdb02にリストアしたいのですが、testdb01まで更新されてしまわないかの確認のため、testdb01のデータを更新かけます。

mysql> insert into t_name(id,name) values(6,’hoge3′),(7,’hoge3′),(8,’hoge3′);
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0

mysql> select * from t_name;
+——+——-+
| id | name |
+——+——-+
| 1 | hoge1 |
| 2 | hoge1 |
| 3 | hoge1 |
| 4 | hoge1 |
| 5 | hoge2 |
| 6 | hoge3 |
| 7 | hoge3 |
| 8 | hoge3 |
+——+——-+
8 rows in set (0.00 sec)

この状態でquitで抜けて、dumpを編集します。

# cp -p alldump2.sql alldump2.sql.org
# vi alldump2.sql


— Current Database: `testdb01`

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `testdb01` /*!40100 DEFAULT CHARACTER SET latin1 */;

USE `testdb01`;


— Table structure for table `t_name`

DROP TABLE IF EXISTS `t_name`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `t_name` (
`id` int(11) DEFAULT NULL,
`name` text
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;


— Dumping data for table `t_name`

LOCK TABLES `t_name` WRITE;
/*!40000 ALTER TABLE `t_name` DISABLE KEYS */;
INSERT INTO `t_name` VALUES (1,’hoge1′),(2,’hoge1′),(3,’hoge1′),(4,’hoge1′),(5,’hoge2′);
/*!40000 ALTER TABLE `t_name` ENABLE KEYS */;
UNLOCK TABLES;


— Dumping events for database ‘testdb01

dumpファイルにtestdb01と記載されている所があります。
ここをtestdb02に書き換えてしまいます。
というかCREATE文は「–」でコメントアウトしちゃいます。
なので、

USE `testdb01`;

USE `testdb02`;

でもいいですし、testdb02ではなくて、testdb03にしたい場合は、

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `testdb01` /*!40100 DEFAULT CHARACTER SET latin1 */;

USE `testdb01`;

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `testdb02` /*!40100 DEFAULT CHARACTER SET latin1 */;

USE `testdb02`;

にしてみます。

今回は、testdb02にリストアしてみることにします。
リストアするときはオプションの指定が必要なので注意します。
また、存在しないデータベースだとエラーになるので、別名のデータベース名が存在しない場合は先にcreate databaseで作っておく必要があります。
今回は既に空のtestdb02があるので問題ありません。

# mysql -u root -p testdb02 < alldump2.sql

mysql> use testdb01;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from t_name;
+——+——-+
| id | name |
+——+——-+
| 1 | hoge1 |
| 2 | hoge1 |
| 3 | hoge1 |
| 4 | hoge1 |
| 5 | hoge2 |
| 6 | hoge3 |
| 7 | hoge3 |
| 8 | hoge3 |
+——+——-+
8 rows in set (0.00 sec)

testdb01のデータは上書きされておりません。

mysql> use testdb02;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from t_name;
+——+——-+
| id | name |
+——+——-+
| 1 | hoge1 |
| 2 | hoge1 |
| 3 | hoge1 |
| 4 | hoge1 |
| 5 | hoge2 |
+——+——-+
5 rows in set (0.00 sec)

testdb02にdumpで取得したtestdb01のデータがインサートされております。
このようにすることで、MySQLのdumpをリストアが行えるようになります。

 

以上です。
とても基本的なところではありますが、実は結構はまりやすい個所なので、しっかりとdumpのオプションを理解した上でリストアするようにした方が良いですね。

オンラインストレージBOXをCentOS6でマウントして、バックアップストレージとして使う。

最近ではとても数えきれないほどのクラウド型のオンラインストレージがあります。
私自身は正直5GBとかだけのオンラインストレージに価値を見いだせず、ほとんど使用していなかったのですが、
オンラインストレージの活用方法として、「サーバーからマウントして、データをバックアップ」という方法があることを知りました。

イメージ的にはAWSのS3とかみたいに、WebサーバーとかからS3をAPIを使用してマウントして、ストレージとして
使うみたいなのだと、人によってはイメージしやすいかもしれません。

今回対象として選んだのは「BOX」
https://app.box.com/login

無料で10GBまで使用できるし、ほかに使用する予定もないのでバックアップストレージとして使えるか検証してみました。
まず、サーバーから使用するので、どうやって自動化するか。
BOXとして専用のWEBUI以外にサポートとしているのはFTPとWEBDAVだそう。
FTPで都度アップロードしても良いのですが、WEBDAVでマウントできればrsycnコマンドなどで差分バックアップができるので、そちらで探してみました。
そしたらやはりいました。
CentOS6.4からWEBDAVでBOXをマウントされている方が。
http://doroidpanic.com/?p=646

こちらの方の情報を参考にしつつ、自分でやってみました。
いかが作業手順です。

※事前にepelのレポジトリを導入しておく。

—-
[root@]# yum install davfs2
[root@]# mkdir /mnt/box
[root@]# cd /etc/davfs2/
[root@]# cp -p davfs2.conf davfs2.conf.`date +%Y%m%d`
[root@]# vi davfs2.conf
# use_locks 1
use_locks 0

[root@]# cp -p secrets secrets.`date +%Y%m%d`
[root@]# vi secrets
※以下追記
### BOX
https://dav.box.com/dav メールアドレス パスワード

[root@]# cp -p /etc/fstab /etc/fstab.`date +%Y%m%d`
[root@]# vi fstab
※以下追記
###BOX
https://dav.box.com/dav /mnt/box davfs defaults 0 0

[root@]# mount -a
[root@]# df -h
※以下があればOK
Filesystem Size Used Avail Use% Mounted on
https://dav.box.com/dav
10G 0 10G 0% /mnt/box

やはりオンラインストレージなので、速度制限があるようで1〜2MB/s程度しか出ないようですが、正直言って十分です。
これにrsyncで差分バックアップするようなスクリプトを設置してあげて、週次程度で1ヶ月分くらいバックアップしておけば、バッチリです。
テストしてみましたが、全く問題ありませ。
商用ストレージとしては使用できなくても、バックアップストレージとしては十分!
これは目からウロコです。
自宅サーバーも、なにかGoogle DriveとかDropBoxとかでも同じようにマウントできたら、バックアップストレージとして活用してみようと思ってます。

自宅サーバーやVPS借りられている方にオススメです。