カジュアルに鯖を監視するNewRelic をAmazon Linux に導入
今っぽい感じのSaaS型監視サービス NewRelicを Amazon Linuxに入れてみる。( Newvem とか Server DensityとかPingdomとかもある)
New Relic は、エージェントを監視対象ノードに入れておく点は Zabbix等と変わらないが、監視サーバを構築しないですぐに(無料で)始められる、という点がメリット。
監視対象サーバが少ないシステムだと、監視サーバのコスト・運用負荷がデメリットになるので、CloudWatchを補助する目的で、CloudWatchで取れない Load Average, free memory, Disk UsageといったOS内部の情報をカジュアルに一元管理するのに向いている。
特徴を説明したページはこちら。
で、Amazon Linuxに導入する手順。
そのまえに、 New Relicの無償アカウントを作り、License Keyを取得しておく。AWSでnewrelicを使う場合は、こちらからサインアップ。
AWS & New Relic Server & User Monitoring, Website Optimizer, : New Relic
sudo rpm -Uvh http://yum.newrelic.com/pub/newrelic/el5/x86_64/newrelic-repo-5-3.noarch.rpm sudo yum -y install newrelic-sysmond sudo nrsysmond-config --set license_key=xxxxxxxx sudo /etc/init.d/newrelic-sysmond start
とすれば、監視エージェント nrsysmondが起動し、NewRelicサーバに定期的に監視データを送信し始める。あとは NewRelicのダッシュボードでサーバの情報を見るだけ。
登録されていないサーバからのデータを受信すると、自動でサーバ一覧に表示される。
各サーバをクリックすると、詳細情報が見れる。
アラートの閾値を設定すればメモリやディスクも監視可能。Freeアカウントだと30分しか統計データを保持しないが、通知と割り切れば十分使える。
アプリケーションサーバの場合、各言語毎の監視モジュールを追加で入れることでさらに詳しい情報を監視可能。
PHPの場合は,エージェントがapacheモジュールとして動作し、Proxyデーモン newrelic-daemon を経由してNewRelicサーバにデータが送信される。
sudo yum -y install newrelic-php5 sudo /usr/bin/newrelic-install install sudo cp /etc/newrelic/newrelic.cfg{,.bak} sudo sed -e "s/REPLACE_WITH_REAL_KEY/xxxxxxxxxxxx/" /etc/newrelic/newrelic.cfg | sudo tee /etc/newrelic/newrelic.cfg sudo /etc/init.d/newrelic-daemon restart sudo /etc/init.d/httpd restart
とすると、以下の様な画面を閲覧できる。PHP/DBの処理時間の割合も見える。
DBアクセスの内訳も見える
呼び出しからバックエンドの各処理でどのくらい時間がかかっているか、も可視化できる。
メモ: PinterestとInstagramのAWS利用状況
PinterestもInstagramも成長スピードがものすごい。
AWS SUMMIT NY 2012 のKeyNote中にあったPinterestのパートが記事になっている
Pinterest growth driven by Amazon cloud scalability - Techworld.com
High Scalability - High Scalability - A Short on the Pinterest Stack for Handling 3+ Million Users
Polyglot persistence at Pinterest: Redis, Membase, MySQL • myNoSQL
Pinterest Architecture Numbers • myNoSQL
High Scalability - High Scalability - A Short on the Pinterest Stack for Handling 3+ Million Users
Pinterestの急成長を支えてきたアーキテクチャとは? Pythonで開発しAmazonクラウドで運用 - Publickey
Revealed: Inside super-soaraway Pinterest's virtual data centre • The Register
AWS SUMMIT NY 2012 のビデオの12:30から23:10の間
What Powers Instagram: Hundreds of Instances, Dozens of Technologies - Instagram Engineering
「バックエンドの経験はなかった」Instagram創業者は、どうやってシステムをスケールさせてきたか - Publickey
Amazon Linux用の Zabbix RPMを作る
Amazon Linuxで Zabbix 2.0系を動かすには、現状はソースからコンパイルが必要。@kodai74 さんが公開している RHEL/CentOS用RPMだと、libmysqlclient.soの依存関係で怒られる(Amazon Linuxだと新しすぎるorz)。
てことで、RPMを自前で作っておいて、ばら撒く作戦。
参考にしたのはこのお二人
TNKの気になること: Zabbix 2.0をAmazon Linux上で動かしてみよう
zabbix2.0をAmazonlinuxにインストールしたった。(rpm) - zabbiたんAMIたん
==以下、上記ブログからコマンドラインだけ抜粋==
$ cd $ sudo yum install git $ git clone https://github.com/atanaka7/zabbix-jp-amzn1.git $ sudo yum -y install rpm-build $ sudo yum -y groupinstall 'Development tools' $ sudo yum -y install mysql-devel net-snmp-devel openldap-devel sqlite-devel unixODBC-devel libssh2-devel java-devel curl-devel OpenIPMI-devel postgresql-devel $ sudo yum -y install php-cli php-mbstring php-common php-mysql php-xml php-pdo php-gd php-bcmath php $ wget http://www.zabbix.jp/binaries/relatedpkgs/rhel6/x86_64/fping-2.4b2-16.el6.JP.x86_64.rpm $ wget http://www.zabbix.jp/binaries/relatedpkgs/rhel6/x86_64/iksemel-1.4-2.el6.JP.x86_64.rpm $ wget http://www.zabbix.jp/binaries/relatedpkgs/rhel6/x86_64/iksemel-devel-1.4-2.el6.JP.x86_64.rpm $ sudo yum -y localinstall *.rpm $ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} $ cat <<EOS > ~/.rpmmacros %_topdir /home/ec2-user/rpmbuild %_builddir %{_topdir}/BUILD %_rpmdir %{_topdir}/RPMS %_sourcedir %{_topdir}/SOURCES %_specdir %{_topdir}/SPECS %_srcrpmdir %{_topdir}/SRPMS EOS $ rpmbuild --rebuild ~/zabbix-jp-amzn1/zabbix-2.0.0-1.amzn1.src.rpm $ mkdir ~/zabbix-rpm $ cp ~/rpmbuild/RPMS/noarch/*.rpm ~/zabbix-rpm $ cp ~/rpmbuild/RPMS/x86_64/*.rpm ~/zabbix-rpm
SQS: ワーカープロセスの稼働管理にSupervisordが便利
SQS等のキューを介して非同期に処理を行う Queue Chain パターンを実装する場合、SQSに突っ込む処理はWebアプリ等の処理中に書けばよいので特に考えることはないが、SQSからメッセージを抜いて後続の非同期処理を実行するワーカープロセスをどのように起動管理するか?が肝になる。非同期処理を出来るだけ早く処理したい場合は特に。
JavaならMDB(Message Driven Bean)のような仕組みがすでにあるが、軽量言語(PHP,Pearl, Ruby, Python,etc)向けに何かうまい方法を用意したい。Cronで1分間隔起動だと、処理時間によっては重複起動になるし、そもそも分単位での制御しかできないので出来れば常駐化させたい。言語ごとには解決策があるのかもしれないが、もう少し汎用的な仕組みが欲しい。
で、辿り着いたのが Supervisord というプロセスをデーモン化(daemonize)するデーモン。昔で言うところの daemontools のイメージ。
daemontoolsから改善されている点としては
- 複数の種類のプログラムを一つのSupervisord配下で管理できる
- あるプログラムを任意の数のプロセスだけ起動できる
- 管理ツール( supervisorclt )で各種の情報取得や制御が可能
- Web UIが付いている
- 動的に設定変更が可能
あたりか。
んで、結局どうなるのか?というと
という感じ。上図は、SQSを定期的に監視・取得するプロセス群、CloudWatchを定期的に監視・取得するプロセス群、クローラがいる例。
- 「一定回数だけキューを監視・取得して処理をするスクリプト」を書く
- スクリプトをSupervisordに登録する
- スクリプトを実行するプロセスがSupervisordによって複数起動する。
- 各プロセスはスクリプトを実行する(キュー監視・実行を行為、一定回数ループすると終了)。
- 終了したプロセスのスロットは、Supervisordによって、新しくプロセスが生成される。
あとは、ループごとに行うsleepの間隔と、同時実行プロセス数の調整をすることで、キューの捌きの処理能力をある程度制御出来るようになる。
具体的な例は後ほど。
DynamoDB : PHPのセッション管理に使う
AWS SDK for PHPには、DynamoDBSessionHandlerというセッションを管理するクラスがあるので、比較的楽に導入が可能。
Amazon Linuxでの環境設定
パッケージインストール(DynamoDBアクセス用のCacheとしてAPCも入れる)
$ sudo yum install php php-pear php-xml httpd php-pecl-apc $ sudo pear channel-discover pear.amazonwebservices.com $ sudo pear install aws/sdk
次に、セッション管理ハンドラーを用意
$ sudo vi /var/www/html/dynamosessions.php $ sudo cat /var/www/html/dynamosessions.php <?php date_default_timezone_set('UTC'); require_once '/usr/share/pear/AWSSDKforPHP/sdk.class.php'; $credential = array( 'key' => 'xxxxxxx', 'secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'default_cache_config' => 'apc', ); $dynamodb = new AmazonDynamoDB($credential); $dynamodb->set_region('dynamodb.ap-northeast-1.amazonaws.com'); $handler = $dynamodb->register_session_handler(array( 'table_name' => 'php_session', //デフォルト 'sessions' 'hash_key' => 'id', // デフォルト 'id' 'session_lifetime' => 0, // デフォルト0 'consistent_reads' => true,//デフォルト true(強一貫性) 'session_locking' => false,//デフォルト true (falseにするとI/Oが減る) 'max_lock_wait_time' => '15',// デフォルト30(秒) 'min_lock_retry_utime' => 5000,//デフォルト10000(マイクロ秒) 'max_lock_retry_utime' => 5000,//デフォルト100000(マイクロ秒) )); ?>
上記のスクリプトにあわせて、DynamoDBに、ハッシュキー 「id(String)」を持つテーブル「php_session」を作成する。(スループットは適宜調整)
セッションハンドルとして、作成したDynamoDB用セッションスクリプトをPHPに登録する
$ sudo cp /etc/php.ini /etc/php.ini.bak $ sudo vi /etc/php.ini $ sudo diff /etc/php.ini /etc/php.ini.bak 764c764 < auto_prepend_file = /var/www/html/dynamosessions.php --- > auto_prepend_file = 1248c1248 < session.save_handler = user --- > session.save_handler = files
httpdサーバを再起動する
$ sudo service httpd restart
セッションを使うサンプルコードで確認、DynamoDBのテーブルにデータがあるかも確認。
参考
- DynamoDB for PHP sessions
- Amazon Web Services Blog: Scalable Session Handling in PHP Using Amazon DynamoDB
- 10日で覚えるPHPのキソ 第 10 回 セッション(SESSION) | バシャログ。
- PHP:セッション情報をDBに持つ
- AWS SDK for PHP 1.5.4
- PHP: 実行時設定 - Manual session.save_handler
- PHP: session_set_save_handler - Manual
S3: PHPで バケツの一覧を取得する
Amazon LinuxへのPHPとAWS SDK for PHPのセットアップ
$ sudo yum install php php-pear php-xml $ sudo pear channel-discover pear.amazonwebservices.com $ sudo pear instlal aws/sdk
一覧のコード
<?php error_reporting(E_ALL); require_once '/usr/share/pear/AWSSDKforPHP/sdk.class.php'; ## prepare credential data $credential = array( // set access key id 'key' => 'AKIAIUEYQ', // set secret access key 'secret' => 'GEhkVzpvw' ); ## create S3 client $s3 = new AmazonS3($credential); $s3->set_region(AmazonS3::REGION_TOKYO); ## get buckets list $res = $s3->list_buckets(); $buckets = $res->body->Buckets->Bucket; ## print result foreach($buckets as $b ){ print($b->Name."\n"); } ?>
を list_buckets.php として保存したあと
$ php list_buckets.php
とすると、バケツの一覧が表示される
EC2: S3に画像アップロードするPHPサンプルを作る
パッケージ追加
$ sudo yum install php httpd mysql mysql-server php-mysql php-pear php-xml
$ sudo pear channel-discover pear.amazonwebservices.com $ sudo pear install aws/sdk
セキュリティ設定
$ sudo cp /usr/share/pear/AWSSDKforPHP/config-sample.inc.php /usr/share/pear/AWSSDKforPHP/config.inc.php $ sudo vi /usr/share/pear/AWSSDKforPHP/config.inc.php $ sudo diff /usr/share/pear/AWSSDKforPHP/config-sample.inc.php /usr/share/pear/AWSSDKforPHP/config.inc.php 57c57 < 'key' => 'development-key', --- > 'key' => 'xxxxx', 61c61 < 'secret' => 'development-secret', --- > 'secret' => 'xxxxx',
サーバ起動
$ sudo /etc/init.d/httpd start
ファイルアップロードの準備
$ sudo mkdir /var/www/html/images/ $ sudo chmod -R 777 /var/www/html/images
ファイルのデプロイ
$ cd /var/www/html/ $ git clone git@github.com:understeer/aws.git
- form_upload.php: アップロードのフォームページ
- upload.php: ローカル(/var/www/html/images/)に上げる
- s3upload.php: S3に上げる
- https://github.com/understeer/aws/tree/master/php/s3