カテゴリー別アーカイブ: プログラミング・開発

Azure Resource Usage APIで課金情報を取得する

| コメントをどうぞ

Azureの課金APIがリリースされていたので触ってみました。

Microsoft Azure リソースの消費を把握する
https://azure.microsoft.com/ja-jp/documentation/articles/billing-usage-rate-card-overview/

Azure Billing REST API Reference (Preview)
https://msdn.microsoft.com/library/azure/1ea5b323-54bb-423d-916f-190de96c6a3c

手順

  1. Azure AD applicationの作成 と アクセストークンの作成
  2. DHCでリクエストを実行

続きを読む

AWSのVPCの予約IPについての勘違い

| コメントをどうぞ

AWSで中にサブネットを複数持つVPCのIPについて勘違いしていたので書きます。

サブネットを作成するとCIDRの最初の4つ(正確には3つ?)最後の1つはAWS側で予約されているので
使えないのはAWSを利用している方ならご存知かと思います。

例えば192.168.0.0/24のCIDRのサブネットの場合、

●192.168.0.0はネットワーク全体を表すのでAWSだからとでなく使えません。
●192.168.0.1はAWS側で予約で使えません。
●192.168.0.2はAWS側で予約で使えません。
●192.168.0.3はAWS側で予約で使えません。
●192.168.0.254はAWS側で予約で使えません。

で、実際に使ってみるとどうやら、

●192.168.0.1はゲートウェイIPになっている模様。
●192.168.0.2はDNSになっている模様。
●192.168.0.3は何やってるかわからない。
●192.168.0.254は何やってるかわからない。

一般的にアドレスの一番最初は大抵DNSとかゲートウェイとかDHCPにしている場合が多いので
納得いきます。最後の1つもゲートウェイにしている場合が多いので納得いきます。

で、サブネットを二つ持つVPCでも各サブネットごとにAWSは予約IPが同じようにあります。
公式サイトにも以下のように書いてあります。

Important

AWS は、各サブネット CIDR ブロックの最初の 4 つの IP アドレスと最後の IP アドレスの両方を
予約します。これらのアドレスをユーザーが使用することはできません。
たとえば、CIDR ブロック 10.0.0.0/24 を持つサブネットの場合、
IP アドレス 10.0.0.0、10.0.0.1、10.0.0.2、10.0.0.255、
および 10.0.0.3 が予約されます。

http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Subnets.html

なので、サブネットを2つ持つVPC、例えば、

ゾーンA:192.168.0.0/25
ゾーンB:192.168.0.128/25

の場合は、

ゾーンAは、192.168.0.0,192.168.0.1,192.168.0.2,192.168.0.3,192.168.0.127
ゾーンBは、192.168.0.128,192.168.0.129,192.168.0.130,192.168.0.131,192.168.0.254

はAWS側で予約されていて使えません。実際に使ってみた経験から、

ゾーンAのゲートウェイは192.168.0.1
ゾーンBのゲートウェイは192.168.0.129

になると推測出来き、実際に確認するとその通りになっています。
次にDNSはこれまでの経験から、

ゾーンAのDNSは192.168.0.2
ゾーンBのDNSは192.168.0.130

と推測出来ます。そして実際に確認すると・・・

ゾーンAのDNSは192.168.0.2
ゾーンBのDNSは192.168.0.2

・・・?ゾーンBにいるのにゾーンAのIPのDNSに聞きにいってる。。
ここで以下の疑問がわきます。

●ゾーンBにいるサーバが名前解決するのにゾーンAのDNSに聞きに行くのは距離が離れている分遅くなるのではないか?

●ゾーンAとゾーンBで冗長化している場合はゾーンAが落ちたらゾーンBのサーバも名前解決出来なくなるではないか?

●ゾーンBの192.168.0.130は何やってるの?DNSじゃないの?

色々ドキュメントを漁る。グーグル先生に聞く。自分であれこれコマンド実行で調べる。
・・・をやってみましたがわかりませんでした。

わからないのでAWSサポートに聞きました。で、回答はこんな感じでした。

DNSはVPCのCIDRの2番目のアドレスです。

そうなんですか。各サブネットごとに存在するのかと思っていました。予約されているし。
でもVPCのCIDRの2番目のアドレスのみなら遠回りの問題とDNSが存在するゾーンが拠点障害
起きたらまずいのかと・・・。

それに対して以下の回答が。



DNSサーバーは冗長化されていて
特定のVPC サブネット上に
配置されたものではありません。 
Availability Zone で機能します。 
DNS の IP アドレスは仮想的なものとご理解下さい。


だそうです。見かけ上は192.168.0.2に対してゾーンBから名前解決しているように見えても
同じゾーン内にあるDNSに問い合わせいってるとの事です。

自分と同じ勘違いをしている人もいるかもしれませんので共有します。

ゾーンAの192.168.0.2とDNSの仮想IPの192.168.0.2でかぶってるけどどう処理してるんだろう?とかゾーンBからの192.168.0.2のパケットはゾーンB内のIPに変換されているのだろうか?
とか、予約されているIPは何に使われているのだろうか?

などは今もわかりませんが。。(最初のIPはほぼほぼゲートウェイとは思います。)

Amazon SES 利用時、最大送信レート制限に引っかからない方法を考える

| コメントをどうぞ

Amazon SES 利用時、何も考えずメールを大量送信していると以下のようなエラーが出ることがあります。

Maximum sending rate exceeded

最大送信レートを超過したぞ、というエラーメッセージです。

最大送信レートとは

SESのドキュメントには以下のようにあります。

続きを読む

AWS RDSのログ監視をZabbixで。

| コメントをどうぞ

AWSのRDSはCLIツールでログの取得が出来きるのでZabbixサーバにRDSのログを取得して通常のログ監視設定と似たような感じで監視をします。ZabbixでRDSのログ監視をするには以下の条件が必要になります。

● RDSのログを取得できる権限(IAM)を持っていること。
● CLIツールを導入していること。

正確にはCLIツール無くてもプログラム書ける人ならとってこれるようですが、自分のような非プログラマでもAPIにアクセスしてデータを取得できるCLIツールをリリースしてくれているので使わない手は無いです。
CLIツールは複数の言語版がありますが、JAVA版とPython版を使います。

何故2種類使うのか?となりますが、前にJAVA版で色々とCLIツールで監視データ取得したりバックアップ運用していたのですがJAVA版は重いのです。t2.microでZabbixを動かしていたのですが、CLIを使ったスクリプトを複数個動かすとCPULoadがかなり高くなってました。t2.microでZabbixを動かす事自体問題あるのですが、ブラウザでのアクセスは反応遅いけどもその状態で1年くらいZabbixが落ちたりもせずAWSの障害通知メールも飛ばしてくれてたので放置してましたが、去年の4月にチーム編成が変わって同じチームになった人から「Python版使ってますが重いと感じたことないですけど?」と言われて試してみたら「本当だ軽い・・・」今まで使ってたスクリプトをPython版に書きなおして現在に至るまでZabbixサーバが重くなったことはありませんでした。

AmazonLinuxには最初からPython版CLIツールがセットアップされてるくらいだしPython版のみで行こう!

・・・と思ったらログをtail出来る機能がJAVA版にはあったけどpython版はやり方がわからない。もしくは無いかもしれない。。
(aws-cli/1.3.18 Python/2.6.6のバージョンではよくわからなかった。)

その為、いつかPython版でRDSのログtailの方法がわかったらいつでも全部Python版に変更出来る用に最初の部分はPythonコマンドで実行してtailの部分はJAVA版で実行しています。

● Python版CLIインストール
AmazonLinuxなら最初から入っていますが、CentOSではインストールします。yumで入るので楽です。

# yum install python -y
# yum install python-devel -y
# yum install python-setuptools -y
# easy_install pip
# pip install awscli

次に認証に使うファイルが必要なので作成します。AWSのアクセスキーとシークレットアクセスキーを中に記述します。リージョンはRDSが動いているところにします。ファイル名はアカウント/サービスごとに分けると後で楽です。

# vi 任意の名前

[default]
aws_access_key_id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
aws_secret_access_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
region=ap-northeast-1

認証ファイルの場所を設定します。

# export AWS_CONFIG_FILE=任意の名前で作成したファイル

コマンドのタブ補完が効かないので効くようにします。毎回補完出来るように.bash_profileに書いておくのも良さそうです。

# complete -C aws_completer aws

セットアップがうまく行ったかか確認します。ログファイルがずらっと表示されればうまく行っています。

# aws rds describe-db-log-files --db-instance-identifier RDS名 --output text

            UNIXエポック  ファイル名     
DESCRIBEDBLOGFILES      1425877196000   error/postgresql.log.2015-03-09-04      4470072
DESCRIBEDBLOGFILES      1425880791000   error/postgresql.log.2015-03-09-05      5148177
DESCRIBEDBLOGFILES      1425884399000   error/postgresql.log.2015-03-09-06      581115
DESCRIBEDBLOGFILES      1425887996000   error/postgresql.log.2015-03-09-07      105250
DESCRIBEDBLOGFILES      1425888531000   error/postgresql.log.2015-03-09-08      36301

「–output」で指定した形式で表示してくれます。「table」と指定するとteble形式、「text」と指定するとテキスト形式で表示してくれます。何も指定しないと「json」形式で表示されて見にくいです。(jqとかかまさないと見づらい)

● JAVA版CLIセットアップ
JAVA版CLIのセットアップ方法はこのブログでも他の人が紹介されているので省略します。(手抜き)

RDSのログをtailするだけだとAWS側で定期的(1時間ごと?)にローテされて見失うので一定間隔で
ログが新しくなったかチェックして最新のログを吐き出すスクリプトを作成します。

●RDSログをtailするスクリプト

#!/bin/sh

# EC2-APITools settings
export JAVA_HOME=/usr

# keys
export AWS_CREDENTIAL_FILE=クレデンシャルファイルのPATH
export AWS_CONFIG_FILE=configファイルのPATH

# RDS CLI setting
export AWS_RDS_HOME=/usr/local/rds
export EC2_REGION="ap-northeast-1"
export PATH=$PATH:$JAVA_HOME/bin:$AWS_RDS_HOME/bin

COMMAND=スクリプトの絶対PATH
DBINSTANCEID=RDSの名前
LOGDIR=ログを保管するPATH

LOG=`aws rds describe-db-log-files --db-instance-identifier $DBINSTANCEID --output text| awk  '{ print $2"\t"$3"\t"$4 }' | awk '{print substr($0,1,length($1)-3)"\t"$2"\t"$3}' | awk '{ print strftime("%Y/%m/%d %H:%M:%S",$1)" "$2" "$3 }' | tail -1 | awk '{print $3}'`

LOGFILENAME=`echo $LOG | sed 's/[a-z]*\///g'`

rds-watch-db-logfile $DBINSTANCEID --log-file-name  $LOG > ${LOGDIR}/$LOGFILENAME 2>&1 &


C=0
while [ $C = 0 ]

do

LOG2=`aws rds describe-db-log-files --db-instance-identifier $DBINSTANCEID --output text| awk  '{ print $2"\t"$3"\t"$4 }' | awk '{print substr($0,1,length($1)-3)"\t"$2"\t"$3}' | awk '{ print strftime("%Y/%m/%d %H:%M:%S",$1)" "$2" "$3 }' | tail -1 | awk '{print $3}'`

if [ $LOG != $LOG2 ];then

pgrep -f $LOG | xargs kill -9

$CMDPATH

fi

sleep 300

done

AWS側のローテはおそらく一時間に一回くらいのようですが、スクリプト内では5分に一回チェックして
新しくなったら新たにログファイルを作り直してtailするようにしています。
このスクリプトをバックグラウンドで動かしっぱなしにして
あとはこのログをZabbixでログ監視すればRDSのログ監視が可能になります。

問題点として、古いファイルを消すようにしていないのでローテ後のログファイルが溜まっていく事と、
JAVAのCLIはやっぱり重い事です。

あと、身も蓋もないですが、RDSのログをリアルタイムで監視したいという要件自体がほぼほぼ無いです。

AngularJSでUI BootstrapのTooltipをValidationに連動させて表示させる

| コメントをどうぞ

AngularJSには強力なフォームのバリデーション機能があり、任意のタイミングでエラーメッセージを表示することができます。
このエラーメッセージをバリデーションの状態に連動してUI BootstrapのTooltipに表示したいとき、どうすればよいでしょうか。

まずは思い付く方法で

まずは最初に思い付いた方法で実装してみます。
ツールチップはtooltip-enableディレクティブで有効/無効を切り替えられるので、バリデーションに失敗したときだけ有効にして表示するようにしてみました。

index.html

...

<form name="form" style="width:500px;" ng-class="{'has-error': form.value1.$dirty && form.value1.$invalid}">
  <table class="table">
    <tr>
      <th>お名前(20文字まで)</th>
      <td>
        <input type="text" class="form-control input-sm" name="value1" ng-required="true" ng-model="value1" tooltip="20文字以下で入力して下さい" tooltip-enable="form.value1.$dirty && form.value1.$invalid" ng-maxlength="20">
      </td>
    </tr>
  </table>
</form>

...

app.js

angular.module('app', ['ui.bootstrap']);

結果

バリデーションエラー時にinputにマウスカーソルを乗せることでツールチップが表示されるようになりました。

tooltip1

しかし、これではinputにマウスカーソルを乗せるまでエラーの内容が分かりませんし、マウスカーソルを離すとツールチップが消えてしまうのでイマイチです。
これは、ツールチップの表示を切り替えるデフォルトのトリガーイベントがmouseenter/mouseleaveとなっているためです。

tooltip.js

...

  // Default hide triggers for each show trigger
  var triggerMap = {
    'mouseenter': 'mouseleave',
    'click': 'click',
    'focus': 'blur',
    'none': ''
  };

...

.directive('tooltip', [ '$tooltip', function($tooltip) {
  return $tooltip('tooltip', 'tooltip', 'mouseenter');
}])

...

tooltipのカスタムトリガーとカスタムディレクティブで実現する

Plunker
今回はバリデーションの状態変化に応じて自動的にツールチップを表示したいので、自由に使えるカスタムトリガーが必要になります。

まずは、適当なconfigセクションで$tooltipProvider.setTriggers()を使ってカスタムトリガーを定義しましょう。$tooltipProvider.setTriggers()の引数には、表示イベント名をプロパティ名、非表示イベントをそのプロパティの値として持つオブジェクトを指定します。

app.js


var app = angular.module('app', ['ui.bootstrap', 'app.directives']);

// 追加
app.config(['$tooltipProvider', function ($tooltipProvider) {
  $tooltipProvider.setTriggers({
    'show': 'hide'
  });
}]);

これで要素がshowイベントを受け取った時にツールチップが表示されるようになりました。

次に、このトリガーを発火するための仕組みを作ります。

AngularJSのバリデーション機能は、バリデーション対象として指定したモデルの値の変化に応じてリアルタイムに実行され、実行結果がスコープにセットされるようになっています。上記index.htmlの例だと、form.value1.$invalidform.value1.$validのboolean値を読むことでバリデーションの状態を取得することができます。

今回はtooltipディレクティブを拡張するカスタムディレクティブを用意して、その中でform.value1.$invalidを監視することで、バリデーションの状態が切り替わった時にshowイベントまたはhideイベントを発生させてツールチップの表示を切り替えるようにしました。

directives.js


angular.module('app.directives', [])

// ツールチップ本体に付加されるディレクティブ
// デフォルトのものをそのまま流用
.directive( 'myTooltipPopup', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
    templateUrl: 'template/tooltip/tooltip-popup.html'
  };
})

// tooltipディレクティブを拡張するカスタムディレクティブ
.directive('myTooltip', ['$tooltip', '$timeout', function ($tooltip, $timeout) {
  // tooltipのインスタンスを作成する
  var tooltip = $tooltip( 'myTooltip', 'myTooltip', 'show' );
  var originalCompile = angular.copy(tooltip.compile);
  tooltip.scope = {myTooltipShow : "&"}

  // compileを拡張
  tooltip.compile = function(element, attrs, scope){
    // オリジナルのLink function
    var originalLink = originalCompile(element, attrs);

    // linkを拡張
    var link = function(scope, element, attrs) {
      // my-tooltip-show属性の値を監視する
      scope.$watch(scope.myTooltipShow, function (val) {
        if (val) { // 評価値がtrueならばshowイベントを発生させる
          $timeout(function() {
            element.triggerHandler('show');
          });
        }else{ // 評価値がfalseならばhideイベントを発生させる
          $timeout(function() {
            element.triggerHandler('hide');
          });
        }
      });
      // オリジナルのlinkを実行する
      originalLink(scope, element, attrs);
    }
    return link;
  }
  return tooltip;
}])

index.html

...

<input type="text" class="form-control input-sm" name="value2" ng-required="true" ng-model="value2" my-tooltip-show="form.value2.$dirty && form.value2.$invalid" my-tooltip="20文字以下で入力して下さい" ng-maxlength="20">

...

これで、バリデーションの状態がエラーになった時点でツールチップが表示され、正常になった時点で非表示になるようになりました。
my-tooltip-showform.value2.$dirtyを加えているのは初期状態でツールチップが表示されるのを抑制するためです。

今回作成したものはPlunkerにデモを用意していますので、ご利用ください。
http://plnkr.co/edit/ynywEEpNvlx0iSA2bUpI?p=preview

AWS ECSで insecureレジストリ(非SSL)を参照したい

| コメントをどうぞ

お盆も過ぎまして、ここ最近はなんだか涼しく感じるTokyoです。
そろそろ夏休みシーズンも終わりですね。
私はというもの8月は業務に明け暮れ、9月に夏休みがずれました。

がはは!俺が勝ち組だ!

どうも、DiceK Mikamiです。
 
 
今回は、AWS ECS(EC2 Container Service)にて、非SSLレジストリからイメージを取得するTipsをご紹介したいと思います。
続きを読む

Angular.jsで、アップロードするファイルをcontrollerでも使えるようdirectiveを自作する

| コメントをどうぞ

ちまたにはAngular.jsのファイルアップロードのモジュールがたくさんあるのですが、シンプルで単機能なものが欲しく、自作しました。
ファイルの内容が、

<input type="file"> → directiveのchangeイベント → controller

の順で渡るところのコードです。
controllerでその後サーバーにアップロードするところは省きます。

前提のコード

下記のように、ファイルをアップロードするコードがあるとします。
index.htmlの中で、upload.htmlをincludeしています。
upload.htmlの中ではmy-sectionというdirectiveをtranscludeで使い、またtype=”file”のinputタグがあります。
続きを読む

HTMLとJavaScriptでEC2インスタンスを起動する

| コメントをどうぞ

AWSのSDKは様々な言語向けに用意されていますが、サーバーサイドの実装なしでAWSのAPIを叩く場合の選択肢として、AWS SDK for JavaScriptがあります。
http://aws.amazon.com/jp/tools/

ただ、他のSDKと違って対応しているサービスが限られています。
利用可能なサービスはS3、SQS、SNS、DynamoDBなどで、EC2は対象ではありませんでした。

EC2をサポート

6月24日のリリースで、In the BrowserにEC2がこっそり追加されていました。
http://aws.amazon.com/releasenotes/SDK/JavaScript/5873934951898767

6月18日のリリースにはEC2はありませんね。
http://aws.amazon.com/releasenotes/SDK/JavaScript/3577030144306744

HTMLファイルだけでEC2を起動

続きを読む

Amazon SESの送信制限を解除する(SandBoxの外へ移動する)

| コメントをどうぞ

所用で Amazon SES を使う機会があり、送信制限解除について調べました。

最近になって申請フォーマットが変わったという話も聞くので、参考までにメモしておきます。

目的

Amazon SES は最初は SandBox 上で動作しており、以下の送信制限がある。

  • 事前に登録したメルアド以外には送信できない
  • 1日当たり200通までしか送信できない
  • 1秒当たり1通までしか送信できない

本運用開始にあたり、この制限を解除したい。

手順

AWSのマネジメントコンソールにログインし、以下のURLへ移動。

http://aws.amazon.com/ses/extendedaccessrequest/

以下のフォームが表示されます。

aws_increase_request

 

  1. CC
    この申請に関する通知のCCを送るメールアドレス。IAMユーザーでは必須。
  2. 内容
    「サービス制限の増加」のままでOK。
  3. 制限タイプ
    「SES送信制限」のままでOK。
  4. リクエスト1
    リージョンを選択し、増加を希望する制限項目を選択する。
    「希望する一日あたりの送信クォータ」は、24 時間当たりに送信できる E メールの最大数。
    「希望する最大送信レート」は、1 秒当たりにアカウントから受け付ける E メールの最大数。
    SandBoxよりは大きくしておきましょう。
  5. メールの種類
    メールの用途を「取引」「システム通知」「サブスクリプション」「マーケティング」「その他」から選択。
    素直に用途を書きます。
  6. ウェブサイトのURL
    任意です。
  7. 私はAWSサービス利用規約と AUP に準拠してメールを送信します
    「はい」にします。「いいえ」だと多分通りません。
  8. 私は明確にリクエストされた受信者にのみメールを送信します
    「はい」にします。「いいえ」だと多分通りません。
  9. バウンスや苦情を処理するプロセスがあります
    「はい」にします。「いいえ」だと多分通りません。
  10. 申請理由の説明
    申請理由をしっかり書きましょう。

以上を入力し終えたら、[送信]をクリックします。

これで1~2日ほどで承認メールが届くと思われます。SandBoxモードは解除され、任意の宛先にメールを送信することができるようになります。

AWS EC2が本当に良いのか考えてみた

| コメントをどうぞ

先週の土・日・月とアメリカはラスベガスでEVO 2015が開催されましたね。
Eスポーツという分野において日本人選手が多く活躍するのはとても嬉しい限りです。
次は、冬のCapcom Cupでしょうか、楽しみですね。
どうでもいいですが、大きな大会の後になると新しいアーケードコントローラーが欲しくなります。
私だけでしょうか?
どうも、DiceK Mikamiです。
 
 
さて今回は、個人でAWS EC2を運用するにあたり、どれくらいコストをかければ良いかについて考えてみました。

個人でVPS環境を扱うとしても、正直ビタ一文支払いたくないものです。
とは言いましても、必要であるならばコストを支払わざる得ないのが現実。
AWSには料金シミュレーターがあるのですが、まぁピンとこないですね。
そうなると実際にお金を払ってみて、計測するしかないなぁということでやってみました。

環境:

  • t2.micro: インスタンス
  • EBS(マグネティック8GB): ハードディスク
  • EIP: 固定IP

その他の付帯条件:

  • OS: CoreOS(システムはDockerで運用)
  • ドメイン: お名前.comの年間100円のもの
  • 同時利用数: 10〜50(実測値〜想定値)
  • 利用目的: チャットシステム、コンテンツ(画像など)アップロードシステムの稼働

 

awsec2pay_001

画像は1ヶ月分の料金詳細です。
EBSやEIPなどは固定費用なので、料金の変動部分は主にインスタンス稼働による料金のみとなります。
目的として仲間内で週末にプライベートなチャット空間を利用するというところにありましたので、月4回/5時間程度といったところですね。
使用感としては、10人程度ならばマシンも悲鳴をあげませんでしたし、ネットワークが遅いということもありませんでした。
まぁ、個人で1万人オーダーくらいになるとネットワークが遅すぎてやってられなくなると思いますが、、、
使い方などにもよると思いますが、それほど極大なリクエストが発生しないようなシステムであれば、楽に運用していけるのでパフォーマンスはそれほど気にする必要もないかと思います。
 
 

結論

拡張性のあるVPS環境を600円程度(2015/07現在)で用意できるのは魅力的。
ただし、毎日のように使うパワーユーザーでそれほどITに詳しくないならレンタルサーバーで良い。
Dockerコンテナを運用できるレンサバが登場し始めれば、メリットが薄くなる。
やはり、AWSは大規模運用に限るということでしょうかね。