Nov 19, 2009
高可用性ロードバランサーを nginx + heartbeat で作る
ロードバランサーの可用性を高めるために、アクティブスタンバイ構成で、アクティブ系が落ちたらスタンバイ系に引き継げるようにする。
構築環境
- サーバー機
-
- NIC × 2 枚 (推奨 4 枚)
- RAID: 1, (推奨 0 + 1)
- 電源ボード × 2 (予算があれば)
- 仮想化ソフトウェア: VMWare ESXi 4.0
- 仮想化ソフトウェア (VMWare ESXi 4.0) の設定
-
- NIC は 2 枚 1 組でフェイルオーバーするように設定
- ネットワーク × 2 (NIC 2 枚構成の場合は VLANを作成)
-
- VM Network: 既存 (デフォルト)
- HA Network: 新規追加
- ロードバランサー用ゲストOS (Ubuntu Server 9.10: 各サーバに1 台ずつ追加)
-
- ディスク: 4G程度 (Ubuntu Server の最小ハードウェア要件は 1G)
- コア数: 2
- メモリ: 4G
- ネットワーク × 2
-
- VM Network に接続された NIC
- HA Network に接続された NIC
| ネットワーク | アクティブ (lb01) | スタンバイ (lb02) |
|---|---|---|
| eth0 (heartbeat 監視用) | 192.168.0.2 | 192.168.0.3 |
| eth1 (管理用) | 172.16.0.2 | 172.16.0.3 |
| サービス用 | 172.16.0.1 (実際にサービスを提供する IP) | |
インストールと設定
- パッケージ類のインストール (nginx と heartbeat)
ロードバランサーとして利用する nginx と、クラスタリングするための heartbeat をインストールする
sudo aptitude install nginx heartbeat
- nginx の自動起動をやめる
sysv-rc-conf などを利用し、各ランレベルでの自動起動を停止しておく
※ sysv-rc-conf をインストールしていない場合は以下でインストールできるsudo sptitude install sysv-rc-conf
- hosts ファイルに各サーバを登録する
sudo vi /etc/hosts
192.168.0.2 lb01 192.168.0.3 lb02
※ お互い ping 試験 - /etc/ha.d/ha.cf の作成
テンプレートがあるので、作業用ディレクトリーに複製、及び編集
監視対象を指定sudo cp /usr/share/doc/heartbeat/ha.cf.gz . sudo gzip -d ha.cf.gz sudo vi ha.cf
コメントを外したり、記入したりなどするkeepalive 2 deadtime 30 warntime 10 initdead 120 udpport 694 ucast eth0 192.168.0.[2-3] # 相手のIPアドレス auto_failback on node lb01 node lb02 use_logd yes
/etc/ha.d/ へ配置するsudo cp ha.cf /etc/ha.d/
- /etc/ha.d/haresources の作成
これもテンプレートから
アクティブ系、IP、サービス名を指定
sudo cp /usr/share/doc/heartbeat/haresources.gz . sudo gzip -d haresources.gz sudo vi haresources
lb01 IPaddr::172.16.0.1/24 nginx
/etc/ha.d/ へ配置するsudo cp haresources /etc/ha.d/
- /etc/ha.d/authkeys の作成
これもテンプレートからsudo cp /usr/share/doc/heartbeat/authkeys . sudo vi authkeys
auth 3 3 md5 Hello!
/etc/ha.d/ へ配置し、root ユーザからのアクセスのみ許可するようにする (これしてなくて heartbeat 起動時に怒られた)sudo cp authkeys /etc/ha.d/ chmod 600 /etc/ha.d/authkeys
- lb01 -> lb02 の順で heartbeat を起動
sudo /etc/init.d/heartbeat start
- フェイルオーバーの試験とか
ifconfig とかでeth1:0 に サービス IP 172.16.0.1 が引き継がれていれば成功。
Nov 10, 2009
mozilla labs より raindrop を試してみた
mozilla LABS に raindrop という新プロジェクトが先月 (Oct 2009) 登場しました。raindrop は mozilla messaging の開発チーム (thunderbird など) が Web 上のメッセージングサービスに関する革新的な実験をするのが目的だそうです。バックエンドは、CouchDB、及び (Twisted) Python です。せっかく仕事で CouchDB を触ったので、インストールしてみることに。
機能は大きく分けて、2 つにわかれています。
- Web 上のメッセージングサービス (gmail, imap mail, twitter, skype, etc...) の情報を収集、蓄積する機能
- 集約した情報を表示、操作するためのユーザインタフェース機能
mozilla LABS に、そのアーキテクチャーを解り易く解説された画像が掲載されていました。
インストール (OS: ubuntu - その他の OS へのインストールは公式ドキュメントを参照)
- raindrop ソースコードのダウンロード
# mercurial をインストールしていない方は mercurial を取得 sudo apt-get install mercurial cd /usr/src/ sudo hg clone -r 0.1 http://hg.mozilla.org/labs/raindrop
- python ライブラリー類のインストール
必要なライブラリーは、setuptools, twisted, PyOpenSSL, Skype4Py, python-twitter, simplejson, feedparser, paisley です。setuptools を入れている場合は、以下のコマンドで一発でライブラリー類をいれてくれます。sudo python raindrop/server/python/check-raindrop.py --configure
上記のコマンドを実行する前に PyOpenSSL を個別に apt-get 経由でインストールしておく (私の環境では setuptools ではうまくいきませんでした)。sudo apt-get install python-pyopenssl
- raindrop 設定ファイルを作成
ホームディレクトリー配下に .raindrop というファイルを作成し、Web メッセージングサービスの認証情報をセットします。これは、Web インターフェース上から実行できるように開発中とのことです。。vi ~/.raindrop
ファイルには以下のように記載しました。実際に作成する際は、本家ドキュメントで最新版を確認した方がいいと思います。[couch-local] host=localhost port=5984 [account-gmail-username] proto=imap kind=gmail username=[gmail アドレス] password=[gmail パスワード] ssl=True [account-twitter-username] proto=twitter kind=twitter username=[twitter ID] password=[twitter パスワード] [account-skype-username] proto=skype kind=skype username=[skype ID] password=[skype パスワード] [account-rss-feed] proto=rss uri=[購読したい feed URL]
- raindrop の起動
sudo python raindrop/server/python/run-raindrop.py sync-messages --max-age=2days
Web メッセージングサービスを巡回し、ガンガンメッセージを収集します。
http://127.0.0.1:5984/raindrop/inflow/index.html で raindrop UI にアクセスできます。
以下のような UI が起動します。
画像は解説付きで picasa にアップロードしました。
Nov 7, 2009
ubuntu に mongodb をインストール - with pymongo / vs couchdb
一段落ついたので、couchdb に引き続き mongodb もインストールしてみた。環境は同じく VMWare 上の ubuntu。シングルサーバ、シングルクライアント (python) な環境で比較することに。
というのも、設定に誤りがあるためか、 couchdb が期待できるようなパフォーマンスが出なかったため。100 万件のデータを insert 処理するストレステスト (本番バッチ処理環境を考慮) をしているのですが、途中で conflict -> socket error -> down になってしまう。途中 sleep を入れると socket error は出なくなるけど、それだと遅いのと、なんだか気持ち悪い。前ポストで書いたように、0.8.0, 0.11.0b, 0.10.0 で試したけど、結果は同じでした。何が悪いのだろう・・・。
気は取り直して、mongodb は期待する結果が得られたので、インストールと pymongo 経由での処理方法です。
- 依存パッケージ類のインストール
sudo aptitude install tcsh git-core scons g++ sudo aptitude install libpcre++-dev libboost1.37-dev libreadline-dev libmozjs-dev
- git から mongodb のダウンロードとインストール (/opt/mongo へ)
cd /usr/src/ git clone git://github.com/mongodb/mongo.git cd mongo sudo scons all sudo scons --prefix=/opt/mongo install
- mongo ユーザの追加
sudo adduser --system --home /opt/mongo/ --no-create-home --shell /bin/bash --group --gecos "mongoDB Administrator" mongo
- db データディレクトリーの追加とパーミッション設定
sudo mkdir -p /data/db sudo chown -R mongo:mongo /data/ sudo chmod a+x /data/db/
データディレクトリは任意だけど、デフォルトのパスは上記のディレクトリになってる - デーモン monbod の起動
sudo /opt/mongo/bin/mongod
もしデータディレクトリを別の場所にしている場合は、--dbpath オプションで渡してやるsudo /opt/mongo/bin/mongod --dbpath /path/to/db
バックグラウンドプロセスで起動するために、末尾に "&" をつけてやる。
もし、そのまま起動してしまった場合は <Ctrl>+z でプロセスを停止し、 bg でバックグラウンドプロセスに放り込む
正常に起動した場合は、以下のようなメッセージが標準出力に表示される。Fri Nov 6 11:43:02 Mongo DB : starting : pid = 3558 port = 27017 dbpath = /data/db master = 0 slave = 0 32-bit ** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data ** see http://blog.mongodb.org/post/137788967/32-bit-limitations for more Fri Nov 6 11:43:02 *** warning: spider monkey build without utf8 support. consider rebuilding with utf8 support Fri Nov 6 11:43:02 db version v1.1.3-, pdfile version 4.5 Fri Nov 6 11:43:02 git version: 9ecceafbca1c0f88ec69aa659f12a7098f563095 Fri Nov 6 11:43:02 sys info: Linux wb01 2.6.28-16-generic #55-Ubuntu SMP Tue Oct 20 19:48:24 UTC 2009 i686 Fri Nov 6 11:43:02 waiting for connections on port 27017
- mongodb の停止
mongo プロンプトからやるか ps からプロセスIDを取得して kill するらしい。プロンプトでやろう (笑sudo /opt/mongo/bin/mongo > use admin switched to db admin > db.shutdownServer() Fri Nov 6 11:55:57 terminating, shutdown command received Fri Nov 6 11:55:57 dbexit: Fri Nov 6 11:55:57 shutdown: going to flush oplog... Fri Nov 6 11:55:57 shutdown: going to close sockets... Fri Nov 6 11:55:57 shutdown: waiting for fs... Fri Nov 6 11:55:57 shutdown: closing all files... Fri Nov 6 11:55:57 closeAllFiles() finished Fri Nov 6 11:55:57 shutdown: removing fs lock... Fri Nov 6 11:55:57 dbexit: really exiting now ERROR: Client::shutdown not called! server should be down... Fri Nov 6 11:55:57 trying reconnect to 127.0.0.1 Fri Nov 6 11:55:57 reconnect 127.0.0.1 ok Fri Nov 6 11:55:57 JS Error: Error: error doing query: failed (anon):99 > exit bye [3]- Done sudo /opt/mongo/bin/mongod
- pymongo のインストール (setuptools を使う)
sudo easy_install pymongo
- pymongo を使ってみる (pymongo のドキュメント通りにやってみる)
>>> from pymongo.connection import Connection >>> connection = Connection("localhost", 27017) Fri Nov 6 12:02:30 connection accepted from 127.0.0.1:29390 #2 Fri Nov 6 12:02:30 end connection 127.0.0.1:29390 >>> db = connection.test >>> db.name() u'test' >>> db.my_collection Collection(Database(Connection('localhost', 27017), u'test'), u'my_collection') >>> db.my_collection.save({"x": 10}) Fri Nov 6 12:03:12 connection accepted from 127.0.0.1:29646 #3 Fri Nov 6 12:03:12 allocating new datafile /data/db/test.ns, filling with zeroes... ObjectId('4af391f07ad5bd0fc4000000') >>> Fri Nov 6 12:03:12 done allocating datafile /data/db/test.ns, size: 16MB, took 0.102 secs Fri Nov 6 12:03:12 allocating new datafile /data/db/test.0, filling with zeroes... Fri Nov 6 12:03:13 done allocating datafile /data/db/test.0, size: 64MB, took 0.55 secs Fri Nov 6 12:03:13 building new index on { _id: ObjId(000000000000000000000000) } for test.my_collection... Fri Nov 6 12:03:13 Buildindex test.my_collection idxNo:0 { name: "_id_", ns: "test.my_collection", key: { _id: ObjId(000000000000000000000000) } } Fri Nov 6 12:03:13 done for 0 records 0.257secs Fri Nov 6 12:03:12 insert test.my_collection 913ms >>> db.my_collection.save({"x": 8}) ObjectId('4af392067ad5bd0fc4000001') >>> db.my_collection.save({"x": 11}) ObjectId('4af392107ad5bd0fc4000002') >>> db.my_collection.find_one() {u'x': 10, u'_id': ObjectId('4af391f07ad5bd0fc4000000')} >>> for item in db.my_collection.find(): ... print item["x"] ... 10 8 11最初に my_connection にアクセスした際に、test バイナリーファイルが作成されるみたいですね。
適当に connection.foo, db.bar とかやっても動きます。
- couchdb は CPU 使用率やメモリ使用率は少ないです。それと比較すると mongodb はストレステストの間中 99.9% の CPU を消費していました
- couchdb はストレスをかけると comflict -> socket error -> down になりましたが、mongodb は落ちずにより高速に処理できました
ちょっと今回の検証では couchdb を使いこなせなかった感じです。とりあえず、mongodb を使うことにしましたが、 couchdb についてももうちょっと勉強したいと思います。あっ tokyo tyrant も。
Nov 5, 2009
CentOS に Django をデプロイ - with python2.6, mod_python, mysql
Ubuntu でしか作ったことなかったけど、CentOS 5 系 で Django をデプロイしてみる
- とりあえずパッケージを最新に更新
# yum update
- python 2.6 のインストール
CentOS ってデフォルトでは 2.4 なんですね。2.6.4 をソースから入れる。まず zlib, sqlite を入れる。sqlite いれないと import sqlite3 できない# yum install zlib zlib-devel sqlite-devel
python ソースのダウンロードとビルド、インストール# wget http://python.org/ftp/python/2.6.4/Python-2.6.4.tgz # tar xvfz Python-2.6.4.tgz # cd Python-2.6.4
/opt/python2.6 にインストール。path は個人的な趣味。 --enable-shared オプションを追加する# ./configure --prefix=/opt/python2.6 --with-threads --enable-shared
Setup ファイルで zlib のところのコメントを外す。# vi Modules/Setup --- #zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz +++ zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz
# make # make install
- python 2.6 環境設定 (2.4 と共存させる)
パス周りを設定# vi /etc/ld.so.conf.d/opt-python2.6.conf # /sbin/ldconfig # sudo ln -s /opt/python2.6/bin/python /usr/bin/python2.6 # cd
個人的な趣味で、PATH は.bash_profile, alias は .bashrc にセット# vi .bash_profile --- PATH=$PATH:$HOME/bin +++ PATH=$PATH:$HOME/bin:/opt/python2.6/bin/ # vi .bashrc +++ alias python='python2.6'
# source ~/.bash_profile # source ~/.bashrc
確認# python2.6 -V Python 2.6.4 # python -V Python 2.6.4
- setuptools のインストール
オプションで python の path を渡す# wget http://pypi.python.org/packages/2.6/s/setuptools/setuptools-0.6c11-py2.6.egg # sudo sh setuptools-0.6c11-py2.6.egg --prefix=/opt/python2.6
- PIL のインストール
# yum install libjpeg-devel freetype* # wget http://effbot.org/media/downloads/Imaging-1.1.7b1.tar.gz # cd Imaging-1.1.7b1 # python setup.py build # python setup.py install
インストールをテスト# python selftest.py -------------------------------------------------------------------- PIL 1.1.7b1 TEST SUMMARY -------------------------------------------------------------------- Python modules loaded from ./PIL Binary modules loaded from /opt/python2.6/lib/python2.6/site-packages/PIL -------------------------------------------------------------------- *** PIL CORE support not installed *** TKINTER support not installed --- JPEG support ok --- ZLIB (PNG/ZIP) support ok *** FREETYPE2 support not installed *** LITTLECMS support not installed -------------------------------------------------------------------- Running selftest: --- 57 tests passed.
- Django のインストール
easy_install さまさま# sudo easy_install Django Installed /opt/python2.6/lib/python2.6/site-packages/Django-1.1.1-py2.6.egg
- MySQL, MySQL-python のインストール
エンコードは utf8 に。# yum install mysql-devel # vi /etc/my.cnf +++ [mysql] default-character-set = utf8 +++ # /etc/init.d/mysqld start
起動時にサービスが開始されるように設定# /sbin/chkconfig --levels 235 mysqld on
python ドライバを入れておく# easy_install MySQL-python
- MySQL の設定
# mysqladmin -u root password 'パスワード'; # mysqladmin -u root -h localhost password 'パスワード'; # mysql -u root -p Enter password: mysql> CREATE DATABASE mysite; Query OK, 1 row affected (0.36 sec) mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysite | | mysql | | test | +--------------------+ 4 rows in set (0.00 sec) mysql> CREATE USER mysiteuser IDENTIFIED BY 'パスワード'; Query OK, 0 rows affected (0.00 sec) mysql> GRANT ALL PRIVILEGES ON mysite.* TO mysiteuser IDENTIFIED BY 'パスワード'; Query OK, 0 rows affected (0.00 sec) mysql> GRANT ALL PRIVILEGES ON mysite.* TO mysiteuser@localhost IDENTIFIED BY 'パスワード'; Query OK, 0 rows affected (0.00 sec) mysql> quit Bye # mysql -u mysiteuser -p Enter password: mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysite | | test | +--------------------+ 3 rows in set (0.00 sec) mysql> use mysite; Database changed mysql> show tables; Empty set (0.00 sec) mysql> quit Bye
- Apache, mod_python のインストール
# yum install httpd-devel # wget http://ftp.kddilabs.jp/infosystems/apache/httpd/modpython/mod_python-3.3.1.tgz # tar xvzf mod_python-3.3.1.tgz # cd mod_python-3.3.1 # ./configure --with-python=/opt/python2.6/bin/python --with-apxs=/usr/sbin/apxs # make
- Apache, mod_python の設定
- URL: http://domain.com/mysite/
- admin URL: http://domain.com/mysite/admin/
- media URL: http://domain.com/media/
- django プロジェクト (settings.py) のデプロイ先: /var/www/django/mysite
- media の展開先: /var/www/html/media
- log の保存先: /var/log/django/
admin media は /path/to/django/contrib/admin/media/ を /var/www/html/ 内に ln-s でシンボリックリンクを作成し、 chown しておく# mkdir /var/www/django/mysite # mkdir /var/www/django/mysite/.python-eggs # chown apache:apache -R /var/www/django/ # chmod a+x /var/www/django/ # mkdir /var/www/html/media # chown apache:apache -R /var/www/html/ # mkdir /var/log/django/mysite # chown apache:apache -R /var/log/django/ # chmod a+x /var/log/django/ # vi /etc/httpd/conf.d/python.conf +++ <Location /mysite> SetHandler python-program PythonPath "sys.path + ['/var/www/django']" PythonHandler django.core.handlers.modpython PythonOption django.root /mysite SetEnv PYTHON_EGG_CACHE /var/www/django/mysite/.python-eggs SetEnv DJANGO_SETTINGS_MODULE mysite.settings PythonDebug On </Location> +++ /etc/init.d/httpd reload - アプリケーションのデプロイと起動 SCP なり FTP なり git なり easy_install なりなんでもいいので、アプリケーションを /var/www/django/mysite/ に置く。syncdb したら動きます。
# cd /var/www/django/mysite/ # settings.py syncdb
admin User を shell で作る
shell でやる
# python manage.py shell >>> from django.contrib.auth.models import User >>> user = User(username='admin', email='foo@bar.com', password='パスワード') >>> user.is_active=True >>> user.is_staff=True >>> user.is_superuser=True >>> user.save()
/mysite/admin を IP アドレスでアクセス制御する
/etc/httpd/conf.d/python.conf を以下のようにする。
<Location "/mysite/">
SetHandler python-program
PythonPath "sys.path + ['/var/www/django']"
PythonHandler django.core.handlers.modpython
PythonOption django.root /mysite
SetEnv PYTHON_EGG_CACHE /var/www/django/mysite/.python-eggs
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug On
</Location>
<LocationMatch "/mysite/admin/">
Order deny,allow
Deny from all
Allow from "ipaddress"
</LocationMatch>