Edited at

AWS EC2でMongoDB Shardingをテストしてみた。

More than 5 years have passed since last update.

awsでmongodbのshardingのテストをするために

ec2のt2.mediumを6台借りて実験。Elastic Ipを使うサーバーは1台だけで

他のサーバーにはAgent Forwardingによりログインする。

各サーバーの容量が8GBなので6台で行っているが、

実験するという目的だけでは、sakuraで一台借りてする方が安価にすみそう。

mongodbのsharding replicationのアーキテクチャーでは、

config-serverはshard-serverとは別のサーバーに3つ必要らしいので、

今回はawsを複数台借りる選択をした。

各awsは8GBしかないので、実験用の場合に限り、

confのjournalをfalseにすることでデフォルトで設定されるjournalログを無効化して、約3.5GB節約できる。


詳細 http://qiita.com/daisuke-3/items/d7e56e8ad788d7150090


しかし、journalをfalseにすると正常に停止しなかった場合に(mongodbを止めずにawsのインスタンスを停止等)データが破損されるので、

後々面倒なことが嫌なので、テスト段階でもjournalは有効にすべきだと判断。


詳細 http://docs.mongodb.org/manual/tutorial/recover-data-following-unexpected-shutdown/



課題

同サーバー別ポートでmongodbを起動する場合のserviceコマンド化。

serviceコマンドでは

/usr/bin/mongod already running. となり、うまくできない。

なので、

/usr/bin/mongod -f /etc/mongod_sh* 起動

kill -KILL PID 停止

と操作していくしかない。


db.shutdownServer()で停止。


アーキテクチャー

IMG_1445 のコピー.jpg

aws1(EIP) ... shard1

aws2 ... shard2

aws3 ... shard3

aws4 ... front, config1

aws5 ... front, config2

aws6 ... front, config3

aws1でsh2,sh3を削除してもdf -hコマンドでみる容量が変わらなかったので、

mongodbを再インスコ。でも、する前と変わらなかったのでそのままjournalをtrueにしてsh1を起動。容量表示変わらず。実際にはスペースは空いているが、表示に問題があるよう。


手順

aws1,aws2,aws3にsh1,sh2,sh3をそれぞれ作成。

aws4にfront,config1を作成。

config1をaws5,aws6へconfig2,config3としてコピー(

既に動いてあるshardとfront,configは止める)。


test環境(config-server1台)からproduction環境(config-server3台)へアップグレードする際の手順のドキュメントにてデータディレクトリコピーと書いてある。

Copy the entire dbPath file system tree from the existing config server to the two machines that will provide the additional config servers.


/etc/init.d/mongod_sh1を作成する際は、

パーミッションに気をつける。実行権限 chmod +x mongod_sh1

まず、認証設定なしで起動。

起動したら、adminユーザー追加。

use admin

db.addUser('root','password')

quit()

して、service mongod_sh1 stop

そして、認証設定追加。 service mongod_sh1 start

use admin

db.auth('root','password')で認証。

認証設定のmongodb.keyfile

openssl rand -base64 753 | sudo tee /etc/mongodb.keyfile

で作成。パーミッションを気をつける。

chown mongodb:mongodb mongodb.keyfile

chmod 400 mongodb.keyfile

※利用するアーキテクチャーに一貫性を持たせるために同じkeyfileを使用する。


設定ファイル


/etc/init.d/mongod_sh1

デフォルトだとmongod -> /lib/init/upstart-jobという風にシンボリックリンクされているが、このupstart-jobは廃止予定らしい(?)ので古い方のSysV initの書き方で設定する。


詳細 http://blog.livedoor.jp/hack_le/archives/25394608.html



#!/bin/sh

### BEGIN INIT INFO
# Provides: mongod_sh1
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts mongod_sh1 (a rails app)
# Description: starts mongod_sh1 (a rails app) using start-stop-daemon
### END INIT INFO

USER=mongodb
PID_FILE="/var/run/mongodb/mongod_sh1.pid"
CMD="/usr/bin/mongod"
ARGS="-f /etc/mongod_sh1.conf"

. /lib/lsb/init-functions

case $1 in
start)
start-stop-daemon --start --chuid $USER --exec $CMD -- $ARGS || true
;;
stop)
start-stop-daemon --stop --signal TERM --pidfile $PID_FILE || true
;;
status)
status_of_proc -p $PID_FILE "$CMD" mongod && exit 0 || exit $?
;;
*)
echo >&2 "Usage: $0 "
exit 1
;;
esac


mongod_sh1.conf


systemLog:
destination: file
path: "/var/log/mongodb/mongod_sh1.log"
quiet: true
logAppend: true
storage:
dbPath: "/var/lib/mongod_sh1"
journal:
enabled: true
processManagement:
fork: true
pidFilePath: "/var/run/mongodb/mongod_sh1.pid"
net:
bindIp: aws1
port: 27017
#replication:
# replSetName: sh1
sharding:
clusterRole: shardsvr
security:
authorization: enabled
keyFile: /etc/mongodb.keyfile


ログインをスクリプト化

bin ディレクトリ作成。

その下にvim mongo_sh1として,実行コマンドを書くことで、

コマンド入力処理を簡易化できる。

./mongo_sh1で実行できる。パーミッションchmod +x mongo_sh1に気をつける。


#!/bin/sh
/usr/bin/mongo aws1:27017/admin

front conf

※chunkSizeが1なのは実験用のため。


systemLog:
destination: file
path: "/var/log/mongodb/mongod_front.log"
quiet: true
logAppend: true
processManagement:
fork: true
pidFilePath: "/var/run/mongodb/mongod_front.pid"
net:
bindIp: aws4
port: 20000
sharding:
configDB: aws4:20001,aws5:20001,aws6:20001
chunkSize: 1
security:
keyFile: /etc/mongodb.keyfile

config conf


systemLog:
destination: file
path: "/var/log/mongodb/mongod_conf1.log"
quiet: true
logAppend: true
storage:
dbPath: "/var/lib/mongod_conf1"
journal:
enabled: true
processManagement:
fork: true
pidFilePath: "/var/run/mongodb/mongod_conf1.pid"
net:
bindIp: aws4
port: 20001
security:
authorization: enabled
keyFile: /etc/mongodb.keyfile

127.0.0.1 ではなく localhost

bindIPをすべてホスト名にしたらいけた。

awsはデフォルトではpingは通さない

securitygroupでICMPを解放する。

bind ip について


ドキュメントより、

net.bindIp

Type: string

Default: All interfaces.

Changed in version 2.6.0: The deb and rpm packages include a default configuration file that sets net.bindIp to 127.0.0.1.

Specifies the IP address that mongos or mongod binds to in order to listen for connections from applications. You may attach mongos or mongod to any interface. When attaching mongos or mongod to a publicly accessible interface, ensure that you have implemented proper authentication and firewall restrictions to protect the integrity of your database.


aws123-4のネットワークの疎通ができていないようなので

ネットワークの設定を行う

同じリージョンであればsecuritygroupしかトラフィックを許可する設定の場所はない。


課題

再起動したら/var/run/mongodb/mongo.pid

のピッドファイルのmongodbディレクトリごと消えてる問題については、

これはubuntuのtmpfsという機能でRAMに書き込まれるからであって

AWSの問題というより、ubuntu側の問題である。

config server


http://docs.mongodb.org/manual/core/sharded-cluster-config-servers/

config-serverは必ずテスト環境では1つ、本番環境では3つ使用します。

そして、shard-serverとは別のサーバーを使用します。

3つのconfig-serverが停止したときconfig-serverを立ち上げるまでmongosは再起してはいけません。

config-serverのバックアップは簡単です。

config-serverとclusterを繋ぐためにCNAMEの設定をしている場合、renameやrenumberしたい場合は全てのmongod,mongosを再起動しなければなりません。


起動の順番、停止は(おそらく逆)

設定を変更したら、mongod -> mongoc -> mongosの順番で起動します。


シャードサーバーを追加する


mongos> sh.addShard("aws1:27017")
mongos> sh.addShard("aws2:27017")
mongos> sh.addShard("aws3:27017")
mongos> sh.status()
追加されているか確認。


テストしてみる

参考:

http://gihyo.jp/dev/serial/01/mongodb/0006?page=2


課題

複数frontサーバーが存在する場合、1つのfrontサーバーをログインしているとき他のサーバーのfrontは立ち上がれなかったような。ReplicaSetの話だっけ・・・


MongoDBについてメモ

こちら(http://www.slideshare.net/akuwano/cyberagentmongodb )より抜粋。


システムアーキテクチャー


  • スキーマレス

    機能追加等が比較的楽。

  • 冗長化(ReplicaSet)

    相互死活監視&投票により冗長性を保つ。最小単位は3台(プライマリ、セカンダリx2)

  • スケーラビリティ(Sharding)

    データをChunkサイズに分割することで各サーバーの負荷分散を行う。


得意なもの


  • データ量が大きすぎない。

  • 書き込みが多過ぎでない。

  • 単位時間あたりの処理データが各シャードのメモリ量を超えない処理は得意。

  • 得意なユースケース


    • ゲーム系webアプリケーション


    • 一時的ログ解析基盤





苦手なもの


  • ほっとデータが無い様なデータの使い方は苦手


    • データ量が爆発的に増える


    • 常に全データへのアクセスを行うような



  • 苦手なユースケース


    • ソーシャル系等のWebアプリケーション


    • 継続的 or 統合的 なログ解析基盤