kikumotoのメモ帳

インフラ・ミドル周りを中心に、興味をもったことを適当な感じで。twitter : @takakiku

Qiitaに書いた記事(2013/10〜2014/01)

ここに書くのは久しぶりです。
最近は、ノウハウ的なのは Qiita に書くようになっているので。

なので、あいた期間に書いた記事を貼っておきます。そんなに書いてないけど。

な感じですね。

YAPC::Asia Tokyo 2013に参加してきました

ブログに書くまでがYPACということで、遅まきながらそのエントリ。
今回個人スポンサーとして参加させていただきました。提灯をいただいてきました。ありがとうございます!

Perlに限らずエンジニアの熱い思いを聴けたすばらしいカンファレンスでした。
ホントいろんな刺激をうけてきた感じがするので、今後のエンジニア/マネージャ(管理じゃなくて)としての日々の活動に活かせていければと思う。

今回はただトークを聞きにいっただけとなりましたが、@barimiさんのLTであったように、確かに何か話すことがこういうカンファレンスを一番楽しむ方法であると思ったので、自分も今後なにか話したいという刺激も受けました。

もっとも直近したこといえば

という感じで、どれも先人の後追いであるので、目新しさがないですね。
でも、興味があるという方がいるならどこかで話してみたいので、@takakiku までお声がけくださいませ。

というにかく、YAPC::Asia Tokyo 2013のスタッフ、スピーカーをはじめ、皆様大変ありがとうございました。
大変すばらしいカンファレンスだったと思います!

来年がどういう開催の形になるのか大変楽しみですし、Perlあまり書かないけれど、なんらかの形で関わればと思います。

YAPCサイコー!

WebPay3分後のあと〜顧客の詳細をまねる〜

WebPay: 開発者向けクレジットカード決済サービスを使う流れになりそうなので、ちょっと実際に試してみることにしたので、そのメモ。

アカウント作って、3分で分かる使い方に従って、課金したり顧客を作ったりした後にダッシュボードを見ると、課金情報とかが表示されるようになっている。
で、顧客の情報をクリックすると顧客の詳細情報が表示されるようになりますが、これをどうプログラムで取得するかについて勉強がてら調べてみた。

今回書いたサンプル的なコードの全体はGistにあげておいた。
Rubyを使いました。

顧客情報の詳細

これは、Customerオブジェクトを取得して、それから直接的に取得できる。
コードは以下のような感じ。

customer = Stripe::Customer.retrieve("cus_c4F1nGgK7eEwegF")

puts "顧客情報の詳細"
puts " ID: #{customer.id}"
puts " 作成日: " + Time.at(customer.created).strftime("%Y/%m/%d %H:%M %Z")
puts " メールアドレス: " + (customer.email ? customer.email : "未登録")
puts " メモ: #{customer.description}"

あまり説明もいらないと思う。

クレジットカード情報

Customerオブジェクトのactive_card属性から情報を取得できる。

card = customer.active_card
puts "クレジットカード情報"
puts " 名前: #{card.name}"
puts " カード番号(下4桁): #{card.last4}"
puts " 有効期限: #{card.exp_month} / #{card.exp_year}"
puts " タイプ: #{card.type}"

カード番号全体は取得できないようになっている。下4桁のみ取得可能。

課金履歴

最初に悩んだのがこの課金履歴。
Customerオブジェクト自体から取得するものではなく、Chargesの方から検索するような感じとなる。

puts "課金履歴"
charges = Stripe::Charge.all(:count => 100, :customer => "cus_c4F1nGgK7eEwegF")
charges.each do |charge|
  puts " 金額 => #{charge.amount} (#{charge.currency}), メモ => #{charge.description ? charge.description : charge.id}, 課金日時 => #{Time.at(charge.created).strftime("%Y/%m/%d %H:%M %Z")}"
end

注:実際は課金履歴が100件以上の場合も考慮して記述する必要がある。

加入中の定期課金プラン

CustomerオブジェクトのSubscriptionオブジェクトから情報を取得する。
またSubscriptionオブジェクト内のPlanオブジェクトからも情報を取得する。

subscription = customer.subscription
puts "加入中の定期課金プラン"
puts " ステータス: " + (subscription ? "加入中" : "プランに加入していません。")
puts " プラン: #{subscription.plan.name}#{subscription.plan.amount} / #{subscription.plan.interval})"
puts " 次回の課金日: " + Time.at(subscription.current_period_end + 1).strftime("%Y/%m/%d %H:%M %Z")

少なくとも次回に課金があるかのチェックは必要なはず。
その上で、次回の課金日がこの方法でよいのか疑問。だけど、この次回の課金日という明示的な情報がないので、これが一番妥当そう。

定期課金の請求情報

これはChargesと同様にInvoicesから検索するような感じとなる。

puts "定期課金の請求情報"
invoices = Stripe::Invoice.all(:count => 100, :customer => "cus_c4F1nGgK7eEwegF")
invoices.each do |invoice|
  puts " 金額 => #{invoice.total} (#{invoice.currency}), ID => #{invoice.id}, 請求日時 => #{Time.at(invoice.date).strftime("%Y/%m/%d %H:%M %Z")}"
end

とりあえずざっとこんな感じで、ダッシュボードで表示される情報と同等なデータを得ることができた。
つづく(?)

hbstudy41に参加してきた

ブログに書くまでが勉強会ということで、hbstudy#41 x IDCFクラウドハンズオン - connpass に参加して、あとLTもしてきました。

もくもくとコードを書いていく(どちらかというと写経ですが)というスタイルでの勉強会でしたが、非常に充実したものとなりました。

講師の方がいろいろハマってくれた(?)おかげて、勉強会らしく皆で問題を解決しながら進んでいる感じもあったよかったです。

自分的にはFabricどころかPython自体もほぼ初めてで、Pythonに少し戸惑いつつも、なんとか最後までたどりついた感じです。

Fabricは、Chefともまた目的が違う感じは受けましたが、便利ツールを構築するにはよいフレームワークなのかもしれませんね。普段がPythonなら、これは多分使うでしょう。

で、IDCFクラウドを別途いじっていたので、その要望をかねてLTさせてもらいました。
資料を公開しておきます。


要望LT後、中の人から耳寄りな情報をいただけたりと、LTした甲斐がありました。
LTするといいことありますね。
ネタと参加する機会があれば今後もなにか話していきたいですね。
もっとも自分は人の後ろを歩いている感じなので、最新の情報を提供するなんてことはできなさそうなので、自分のやり方や困っているところを話す感じになるかな。そんなことぐらいしか話せないけど。。。

最後にこの場をかりて、hbstudyのスタッフ、IDCFのスタッフに感謝いたします。ありがとうございました。

Apacheのログで、リクエスト時間をマイクロ秒で表示する方法

ApacheのLogFormatで %t を指定すると、リクエストの時間が表示されますよね。

複数のサーバのログを集めて結合すると、時間が秒レベルなのでソートしても微妙に順番が変になったりします。

なので、秒より精度の高い時間を出力しようと思いました。
使っているのが Apache2.2系なこともあり、2.2のカスタムログ書式を眺めても、特にミリ秒とかマイクロ秒で出力できる感じなかったので、調べて見つけたのが

でした。
なるほどと思い、とりあえず mod_log_config.c がやっていることを見てみようと、なぜか手元には 2.4.3 のソースがあったのでそちらを見てみました。

そしたら、なんかこんなコードが。

        else if (!strncmp(fmt, "usec", 4)) {
            fmt += 4;
            if (!*fmt) {
                fmt_type = TIME_FMT_ABS_USEC;
            }
            else if (!strcmp(fmt, "_frac")) {
                fmt_type = TIME_FMT_ABS_USEC_FRAC;
            }

ん?マイクロ秒レベルで出力できる感じじゃん。
ということで、2.4のドキュメント見てみるも、何も書いてない。
とりあえず、英語版を、ということで見てみると、

the following format tokens are supported:
sec	number of seconds since the Epoch
msec	number of milliseconds since the Epoch
usec	number of microseconds since the Epoch
msec_frac	millisecond fraction
usec_frac	microsecond fraction

ちゃんと書いてあるじゃないですか。
ということで、Apache2.4 以降では LogFormat に

%{usec}t

と書くと、リクエストの時間がエポックからのマイクロ秒でログ出力されます。(スイマセン、知りませんでした。)

が、今使っているのは2.2系。
2.4のmod_log_config.cそのままはさすがにビルドできなかったので、この部分だけ抜き出したmod_log_config.c を作りました。こちら

ということで、これをhttpdのソースのmodules/loggersにコピーして

$ apxs -c mod_log_config.c
$ su
# apxs -i mod_log_config.la

という感じで apxs でビルド・インストールすれば、2.2でも同じようにマイクロ秒で出力できるようになりました。

これで、少し解析が楽になる。

kickstartのpostscript処理をコンソール出力するメモ

kickstartのpostscript処理ですがリアルなマシンだと

にあるように、chvt すればいんだけど、KVM仮想マシンにインストールするときはこれでは動作しない。

シリアルコンソールに出力しているので、結局、上記を参考にキックスタートファイルに

%post
exec < /dev/tty3 > /dev/ttyS0

yum -y update

のようにしたらできた。

これでいいのかよくわからない。
正しい方法あればコメントいただけるとうれしいです。

SpotInstance + ENI(固定IP)in VPC で財布に優しいテスト環境を作る

久しぶりの更新です。

Amazon VPCのいいところの1つは、固定プライベートIPを設定できるところですよね。
で、ちょうど固定プライベートIPで作業する必要があったので、オンデマンドm1.smallをVPC内に数インスタンス起動してたのですが、そこそこ費用がいってしまいました。
t1.microはまだVPCで使えないし、SpotInstanceだと固定プライベートIP指定で起動できないし、オンデマンドm1.smallでもそこそこ費用いくしと悩んでいたのですが、Elastic Network Interface(ENI)を使うことで、財布に優しい環境をつくることができました。
以下、やったことのメモです。

まずVPCを作っておきます。たとえば CIDR 10.0.0.0/16 で作って、Subnet を 10.0.0.0/24 としておく。このあたりは Wizardのデフォルト通りでOK。
で、もう1つSubnetを作っておく。ここでは10.0.1.0/24としておく。

この状態で、SpotInstanceを10.0.0.0/24で起動する。この10.0.0.0/24に接続するeth0はdhcpにより動的にIPが定まる。一応、このインスタンスに直接アクセスするために、EIPも割り当てておく。

ここで10.0.1.0/24に接続するENIをIP指定(例:10.0.1.11)で作成し、作成したインスタンスにアタッチする。インスタンスでは/etc/sysconfig/network-scripts/ifcfg-eth1(Amazon Linuxの場合)に

DEVICE=eth1
BOOTPROTO=static
IPADDR=10.0.1.11
NETMASK=255.255.255.0
ONBOOT=yes
TYPE=Ethernet

を記述し、ネットワークを再起動する。これで、このSpotInstanceは固定プライベートIPが使える。

そして、この状態でAMIを作って、以降はこのAMIからSpotIntanceを起動し、同じ固定IPを持つENIをアタッチすればSpotInstanceであっても特定のサブネットに対しては常に同じIPを持つ環境を容易に再現できるようになる。

これで、財布に優しい固定プライベートIP環境ができたので実験がしやすくなりました。Yeah!

これLTネタになるかな?いや、ショボすぎだろ。

ところで

SpotInstanceはm1.mediumってお得感がありますよね。東京リージョンだとこのブログ書いている時点で

タイプ オンデマンド スポット
m1.small $0.092 $0.041
m1.medium $0.184 $0.058

という価格。割引率もm1.mediumの方がいいですし、$1=\80とすれば、スポットの価格差は1時間あたり1.36円。
オンデマンドのm1.smallより安いし、この価格差ならコスパ的にm1.mediumかなって感じで、m1.mediumのSpotInstanceをよく使ってます。

価格も安定していて、m1.smallだと

な感じですが、m1.mediumだと

な感じ。
まぁたまーに跳ね上がるのはSpotInstanceってことで割り切れば、m1.mediumの方が突然落とされる確率は低そうですね。今後はどうなるかわかりませんが。。。