Amazon ElasticBeanstalkインスタンスをNewRelicでモニタリングする

NewRelicのServersデータ収集用のデーモンをインストールします。
プログラミング言語とか関係なく「.ebextensions」に設定ファイルを置くだけ。
Node.jsでもJavaでも同じ設定ファイルが使えます。

configファイルを作成

設定ファイルの書き方とか置き方とかは前回と同様です。
「.ebextensions」配下にインストール用の「newrelic.config」を配置します。

Install and start newrelic daemon on Amazon ElasticBeanstalk

あとはデータが収集されるので管理画面から確認します。

f:id:yustam:20140409142133p:plain

参考:Installation: RedHat and CentOS - New Relic Documentation

Node.js on ElasticBeanstalkインスタンス上にキャッシュ用のRedisを設置する

前回に続きBeanstalkネタですがBeanstalkでは構成管理ツールのような起動時に環境の初期化を行う機能が備わっています。
EC2 インスタンス上のソフトウェアのカスタマイズ - AWS Elastic Beanstalk

Node.jsのアプリケーションをホスティングするだけでなくRedisをインストールしてみました。

サンプルアプリケーションの入手

こちらからダウンロードします。展開すると以下の様な構成になっているので、

nodejs-sample/
 ├─ app.js
 ├─ index.html
 ├─ package.json
 └─ .ebextensions/
       └─ logging.config

configファイルを作成

「.ebextensions」配下にRedisインストール用の「redis.config」を配置します。

Install Redis on Elastic Beanstalk

設定はインスタンスタイプなど合わせて変更します。

アプリケーションの配備

コマンドラインツールもありますがそのままzip圧縮して配備することも出来ます。
Windowsの場合はフォルダを選択して圧縮するとapp.jsが見つからずに起動に失敗が
してしまうのでapp.jsと同じ階層のファイルを全選択して圧縮します。

f:id:yustam:20140219144509p:plain

失敗した場合は「Logs」から「Snapshot Logs」を確認します。

Tomcat on ElasticBeanstalkへCloudWatchカスタムメトリクスを簡単に追加する

今までEC2でゴリゴリ作っていたのですが最近ElasticBeanstalkの便利さに気付き始めました。
初期の頃に少しだけ触って初心者向けの機能だと今まで侮っていたのですがEclipseプラグインも発達してサクサク開発できるので楽しいです。

ElasticBeanstalkでJava Webアプリケーションを構築する場合はTomcatを使用する事になりますが、デフォルトではCloudWatchに正常/異常のチェックしかできません。 EC2のメトリクスではメモリ使用量が見れないしカスタムメトリクスって面倒くさいという方に以下の設定がオススメです。

ManagementConsoleからアプリケーションの設定で"JVM command line options"が設定できるので以下の文字列を設定します。

-Dcom.amazonaws.sdk.enableDefaultMetrics
 =metricNameSpace=MyBeanstalkApp,
  includePerHostMetrics,
  cloudwatchRegion=ap-northeast-1

metricNameSpacecloudwatchRegionは必要に応じて変更してください。
しばらく待つとCloudWatchの"Custom Metrics"にデータが収集されファイルディスクリプタ/メモリ使用量/スレッド数などが観測できるようになります。

細かい設定などは以下の記事などを参考にしてください。
Metric Configuration in AWS SDK for Java - AWS Developer Blog - Java

ImportError: No module named _ssl

GoogleAppEngineのローカルデバッグ環境でDropboxSDKを使用した際に以下のエラーが発生した

ERROR    2013-11-02 07:21:59,539 cgi.py:121] Traceback (most recent call last):
 (中略)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 60, in <module>
    import _ssl             # if we can't import it, let the error propagate
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/devappserver2/python/sandbox.py", line 867, in load_module
    raise ImportError('No module named %s' % fullname)
ImportError: No module named _ssl

_ssl」というモジュールがないのが原因のようだがデフォルトではモジュール一覧に含まれていないようなので、 エラーメッセージに書かれている「sandbox.py」を修正する

$ sudo vi /Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/devappserver2/python/sandbox.py

_WHITE_LIST_C_MODULES」に「_ssl」を追加するだけで大丈夫でした。
変更前(754行目辺り)

_WHITE_LIST_C_MODULES = [
     'array',
     '_ast',
     'binascii',
(省略)

変更後

_WHITE_LIST_C_MODULES = [
     '_ssl',
     'array',
     '_ast',
     'binascii',
(省略)

AppEngineのランチャーから再起動すると問題なくDropboxSDKが使えるようになりました。
Windowsの開発環境でも同様の現象が確認できましたが同じ手順で解決。

デプロイするときは「app.yml」に「ssl」を追加します。

libraries:
- name: ssl
  version: "latest"

Chromeの「Secure Shell」を使用してAmazonEC2に接続する

Secure ShellChromeからSSHするアプリ。
Windowsの開発環境では普段TeraTermを使用しているのですが、
接続先も保存できて便利そうなので試しに使ってみました。

公開鍵を作成

EC2に接続する際に使用する秘密鍵から公開鍵を生成します。

>ssh-keygen -y -f keyname.pem > keyname.pub

秘密鍵の名前を変更

Secure Shellに鍵を登録する際は「xxxxx」「xxxxx.pub」という名前で
セットにしないと正しく登録されないので名前を変更します。

>cp keyname.pem keyname

Secure Shellで接続

「Import...」から上で作成した「keyname」「keyname.pub」を選択し
「Identity」に「keyname」が表示されればOK。SSH接続します。

f:id:yustam:20130917103548p:plain

f:id:yustam:20130917103555p:plain

DynamoDB Localをaws-java-sdkから操作

ダウンロードと起動

Additional Tools and Libraries For Amazon DynamoDB - Amazon DynamoDB
ここまでは公式ドキュメントに載ってる通り。

$ java –Djava.library.path=. -jar DynamoDBLocal.jar

aws-java-sdkから呼び出す

基本的にエンドポイントを"http://localhost:8000"にするだけ。
アクセスキーとリージョンはDBファイル名に使われるので好きな名前で。
以下で動かすと"AccessKey_us-east-1.db"という名前のファイルが作成された

public static void main(String[] args) {
    String accessKey = "AccessKey";
    String secretAccessKey = "SecretKey";
    AWSCredentials cre = new BasicAWSCredentials(accessKey, secretAccessKey);
    AmazonDynamoDBClient client = new AmazonDynamoDBClient(cre);
    client.setEndpoint("http://localhost:8000");
}

動作確認

String tableName = "DynamoTest";

// テーブル一覧
System.out.println(client.listTables());

// テーブル作成
List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();
keySchema.add(new KeySchemaElement().withAttributeName("HogeId").withKeyType(KeyType.HASH));
AttributeDefinition attrDef = new AttributeDefinition().withAttributeName("HogeId").withAttributeType(ScalarAttributeType.S);
ProvisionedThroughput pt = new ProvisionedThroughput().withReadCapacityUnits(10L).withWriteCapacityUnits(5L);
System.out.println(client.createTable(new CreateTableRequest(tableName, keySchema).withAttributeDefinitions(attrDef).withProvisionedThroughput(pt)));

// アイテム追加
Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
item.put("HogeId", new AttributeValue("AAAA"));
item.put("foo", new AttributeValue("valueA"));
item.put("bar", new AttributeValue().withSS(Arrays.asList("valueB", "valueC")));
System.out.println(client.putItem(new PutItemRequest(tableName, item)));

// アイテム取得
Map<String, AttributeValue> key = new HashMap<String, AttributeValue>();
key.put("HogeId", new AttributeValue("AAAA"));
System.out.println(client.getItem(new GetItemRequest(tableName, key)));

// アイテム更新
Map<String, AttributeValueUpdate> attributes = new HashMap<String, AttributeValueUpdate>();
attributes.put("bar", new AttributeValueUpdate(new AttributeValue().withS("valueD"), AttributeAction.PUT));
System.out.println(client.updateItem(new UpdateItemRequest(tableName, key, attributes)));

// スキャン
System.out.println(client.scan(new ScanRequest(tableName)));

// アイテム削除
System.out.println(client.deleteItem(new DeleteItemRequest(tableName, key)));

// テーブル削除
System.out.println(client.deleteTable(new DeleteTableRequest(tableName)));

実行結果

{TableNames: [],}
{TableDescription: {AttributeDefinitions: [{AttributeName: HogeId,AttributeType: S}],TableName: DynamoTest,KeySchema: [{AttributeName: HogeId,KeyType: HASH}],TableStatus: ACTIVE,CreationDateTime: Fri Sep 13 14:12:03 JST 2013,ProvisionedThroughput: {NumberOfDecreasesToday: 0,ReadCapacityUnits: 10,WriteCapacityUnits: 5},TableSizeBytes: 0,ItemCount: 0,}}
{}
{Item: {HogeId={S: AAAA,}, foo={S: valueA,}, bar={SS: [valueB, valueC],}},}
{}
{Items: [{HogeId={S: AAAA,}, foo={S: valueA,}, bar={S: valueD,}}],Count: 1,ScannedCount: 1,}
{}
{TableDescription: {AttributeDefinitions: [{AttributeName: HogeId,AttributeType: S}],TableName: DynamoTest,KeySchema: [{AttributeName: HogeId,KeyType: HASH}],TableStatus: ACTIVE,CreationDateTime: Fri Sep 13 14:12:03 JST 2013,ProvisionedThroughput: {NumberOfDecreasesToday: 0,ReadCapacityUnits: 10,WriteCapacityUnits: 5},TableSizeBytes: 0,ItemCount: 0,}}

Amazon Elastic Transcorderメモ

今のところ使う予定は無いのですが試しに使って見ました。
思ったより変換速度が早くかなり良いサービスだと思います。
ジョブの設定が少しわかりづらかったので使い方をメモ。

パイプライン作成

S3にテスト用のバケットを1つ作成してInput及びOutputに同じバケットを設定しました。
ここは特に難しくないため割愛します。

ジョブ作成

出力の設定が複数あって分かりづらかったのでいろいろ試行錯誤しました。
以下に設定項目と設定例を示します。

設定名 設定例 説明
Pipeline pipeline-test 作成したパイプライン名
Input Key input/test.m4v 変換対象のファイル。バケット名を除くパスを設定
Output Key Prefix output/test- すべての出力ファイルの接頭辞。"/"が必須

存在しないファイルを指定するなど設定を誤ると実行時にエラーとなります。
ジョブがエラーで終了するのですが原因を確認する方法がないようなので注意です。

設定名 設定例 説明
Preset System preset : Web 変換後の出力形式を選択。Presetから選択。
Output Key video/test.mp4 変換後の出力ファイルのキー。"/"も使用可
Create Thumbnails Yes サムネイルを出力するか(Yes or No)
Thumbnail Filename Pattern thumb/web-{count} サムネイル出力ファイルのキー。"/"も使用可

出力先のフォルダ構成

上の設定例でジョブを実行した場合には以下の出力となります。

bucket/input test.mp4
bucket/output/test-video test.mp4
bucket/output/test-thumb web-00001.png
bucket/output/test-thumb web-00002.png
bucket/output/test-thumb web-00003.png
bucket/output/test-thumb web-00004.png

Watermark機能

動画にJPEGまたはPNG画像を被せる機能があるので試してみました。
使い方は簡単で上記の設定のあとWatermarkを有効にして同じバケット内にある
Watermark用の画像を選択するだけです。(バケット名は含めない)

設定名 設定例
Input Key for Preset Watermark Id BottomRight watermark/test.png

大きめの画像を指定してみたのですがかなり小さめに出ました。
サイズの指定は出来ないみたいです。