AWS Price List APIから欲しい情報だけ抜き取るAPIをAPI Gateway + Lambdaで作った
この記事はAWS Advent Calendar 2015の11日の記事です。
経緯
それは昨日(2015-12-10)の出来事でした。
全世界待望(?)の料金を取得するための公式APIが公開されました。
過去にこんなのやこんなのを作って、公式HPで使っているデータソースのJSONのURLやフォーマットが変わる度に(´・ω・`)ショボーンとしてきた身としては、「これは!!」となったわけです。
で、喜び勇んで試しに叩いてみたら
@marcy_terui RDSで26MB。。でけぇよ!
— Michael H. Oshita (@ijin) 2015, 12月 10
100万行超えのJSONやばすぎでしょw
— Masashi Terui (@marcy_terui) 2015, 12月 10
そんなこんなで
@ayakomuro たしかに。ほしいやつだけ返してくれる簡易APIでラップするの良いですね!
— Masashi Terui (@marcy_terui) 2015, 12月 10
みたいな話になったので勢いで作ってみましたよと。
成果物
ソース
APIドキュメント(swagger-ui)
フィードバックはGitHubの方からお願いします :-)
エラー処理とか雑なんでエラー時に普通にスタックトレースとか返ってくるので、Issueに貼り付けてやってくださいw
使い方
APIドキュメント見れば大枠はわかると思うので、ここでは各属性の指定方法を説明したいと思います。
とりあえずコマンドからのサンプルを貼っておきます。これをベースに説明したいと思います。
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '[{ "key": "instanceType", "value": "m4.4xlarge" }, { "key": "location", "value": "US West (Oregon)" }, { "key": "operatingSystem", "value": "Linux" }] ' 'https://eaoftu7rfi.execute-api.us-east-1.amazonaws.com/public/v1/offer/AmazonEC2?term=OnDemand'
Method
POSTのみに対応します(CORS対応のためにOPTIONも叩くことはできます)
URL
まず、ベースとなるのが以下の部分です。
https://eaoftu7rfi.execute-api.us-east-1.amazonaws.com/public/v1/offer/
次に、その後の AmazonEC2
の部分がサービスを示します。それぞれ何が使えるかは本家のAPIに準拠します。
なので、以下の offerCode
で何が使えるか確認できます。
https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/index.json
そして、クエリストリングの term
で購入方式を指定します。ここは、確認した範囲では OnDemand
or Reserved
しかないようです。EC2やRDS等以外の Reserved
の概念が存在しないサービスについては OnDemand
を指定してください。
Body
JSONフォーマットで各プロダクトの属性名が key
、その内容を value
で指定します。それぞれの内容は公式APIのデータが以下のようになっており、その中の attributes
の内容がそのまま該当します。
{ "formatVersion" : "v1.0", "disclaimer" : "This pricing list is for informational purposes only. All prices are subject to the additional terms included in the pricing pages on http://aws.amazon.com. All Free Tier prices are also subject to the terms included at https://aws.amazon.com/free/", "offerCode" : "AmazonRDS", "version" : "20151001000000", "publicationDate" : "2015-11-15T04:02:20Z", "products" : { "FNR4GZ675EW5UXJW" : { "sku" : "FNR4GZ675EW5UXJW", "productFamily" : "Database Instance", "attributes" : { "servicecode" : "AmazonRDS", "location" : "US West (Oregon)", "locationType" : "AWS Region", "instanceType" : "db.t2.small", "currentGeneration" : "Yes", "instanceClass" : "Burstable performance instances", "vcpu" : "1", "memory" : "2", "piopsOptimized" : "No", "networkPerformance" : "Low", "engineCode" : "10", "databaseEngine" : "SQL Server", "databaseEdition" : "Express", "deploymentOption" : "Single-AZ", "usagetype" : "USW2-InstanceUsage:db.t2.small", "operation" : "CreateDBInstance:0010" } },
複数の条件は全て AND
で繋がります。指定された条件を全て満たすデータが返却されます。
結果
上記コマンドの結果は以下のようになります。
[ { "product": { "sku": "8YGPZRQEKSSY8VWV", "productFamily": "Compute Instance", "attributes": { "enhancedNetworkingSupported": "Yes", "currentGeneration": "Yes", "operation": "RunInstances", "instanceType": "m4.4xlarge", "vcpu": "16", "storage": "EBS only", "location": "US West (Oregon)", "memory": "64 GiB", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "networkPerformance": "High", "usagetype": "USW2-HostBoxUsage:m4.4xlarge", "processorArchitecture": "64-bit", "tenancy": "Host", "servicecode": "AmazonEC2", "dedicatedEbsThroughput": "2000 Mbps", "instanceFamily": "General purpose", "locationType": "AWS Region", "licenseModel": "No License required", "preInstalledSw": "NA", "clockSpeed": "2.4 GHz", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "operatingSystem": "Linux" } }, "price": [ { "sku": "8YGPZRQEKSSY8VWV", "termAttributes": {}, "effectiveDate": "2015-12-01T00:00:00Z", "offerTermCode": "JRTCKXETXF", "priceDimensions": { "8YGPZRQEKSSY8VWV.JRTCKXETXF.6YS6EN2CT7": { "description": "$0.000 per Linux m4.4xlarge Dedicated Host Instance hour", "pricePerUnit": { "USD": "0.0000000000" }, "rateCode": "8YGPZRQEKSSY8VWV.JRTCKXETXF.6YS6EN2CT7", "endRange": "Inf", "beginRange": "0", "appliesTo": [], "unit": "Hrs" } } } ] }, { "product": { "sku": "ZPAH28S2QQZ64QB5", "productFamily": "Compute Instance", "attributes": { "enhancedNetworkingSupported": "Yes", "currentGeneration": "Yes", "operation": "RunInstances", "instanceType": "m4.4xlarge", "vcpu": "16", "storage": "EBS only", "location": "US West (Oregon)", "memory": "64 GiB", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "networkPerformance": "High", "usagetype": "USW2-DedicatedUsage:m4.4xlarge", "processorArchitecture": "64-bit", "tenancy": "Dedicated", "servicecode": "AmazonEC2", "dedicatedEbsThroughput": "2000 Mbps", "instanceFamily": "General purpose", "locationType": "AWS Region", "licenseModel": "No License required", "preInstalledSw": "NA", "clockSpeed": "2.4 GHz", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "operatingSystem": "Linux" } }, "price": [ { "sku": "ZPAH28S2QQZ64QB5", "termAttributes": {}, "effectiveDate": "2015-12-01T00:00:00Z", "offerTermCode": "JRTCKXETXF", "priceDimensions": { "ZPAH28S2QQZ64QB5.JRTCKXETXF.6YS6EN2CT7": { "description": "$1.109 per Dedicated Usage Linux m4.4xlarge Instance Hour", "pricePerUnit": { "USD": "1.1090000000" }, "rateCode": "ZPAH28S2QQZ64QB5.JRTCKXETXF.6YS6EN2CT7", "endRange": "Inf", "beginRange": "0", "appliesTo": [], "unit": "Hrs" } } } ] }, { "product": { "sku": "BMEYUTP658QKQRTP", "productFamily": "Compute Instance", "attributes": { "enhancedNetworkingSupported": "Yes", "currentGeneration": "Yes", "operation": "RunInstances", "instanceType": "m4.4xlarge", "vcpu": "16", "storage": "EBS only", "location": "US West (Oregon)", "memory": "64 GiB", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "networkPerformance": "High", "usagetype": "USW2-BoxUsage:m4.4xlarge", "processorArchitecture": "64-bit", "tenancy": "Shared", "servicecode": "AmazonEC2", "dedicatedEbsThroughput": "2000 Mbps", "instanceFamily": "General purpose", "locationType": "AWS Region", "licenseModel": "No License required", "preInstalledSw": "NA", "clockSpeed": "2.4 GHz", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "operatingSystem": "Linux" } }, "price": [ { "sku": "BMEYUTP658QKQRTP", "termAttributes": {}, "effectiveDate": "2015-12-01T00:00:00Z", "offerTermCode": "JRTCKXETXF", "priceDimensions": { "BMEYUTP658QKQRTP.JRTCKXETXF.6YS6EN2CT7": { "description": "$1.008 per On Demand Linux m4.4xlarge Instance Hour", "pricePerUnit": { "USD": "1.0080000000" }, "rateCode": "BMEYUTP658QKQRTP.JRTCKXETXF.6YS6EN2CT7", "endRange": "Inf", "beginRange": "0", "appliesTo": [], "unit": "Hrs" } } } ] } ]
制限事項
ざっくり構築方法
1. ソースを取得
git clone git@github.com:willyworks/aws-price-api.git
2. Lambda functionをデプロイ
virtualenv -p /path/to/python2.7 .venv . .venv/bin/activate pip install -r requirements.txt lamvery deploy
デプロイは拙作のこちらを使ってます。詳しくはLambda縛り Advent Calendar 2015の16日で書きたいと思ってます。
3. Amazon API Gateway Swagger ImporterでAPIを定義する
Amazon API Gateway Swagger ImporterでAPIを一発で定義する | Developers.IO
4. Lambda functionの紐付けとMapping Templates設定
こんな感じ。
Mapping Templates↓
{ "offer" : "$input.params('offer')", "term": "$input.params('term')", "condition": $input.json('$') }
4. CORS設定
5. Deploy API!!
所感など
- Price List API生で使うのツラい
- 変更通知がSNSで受けれるらしいし、データストアに突っ込んで通知をトリガーに更新させることを想定してる?
- LambdaもAPIのデータ受け取るのに一番時間かかってる。Lambdaから叩ける低レイテンシなキャッシュほしい。*2
- Reservedで期間指定できるようにしたり、もうちょっとAPIの改善もしたいかも
というわけで
以上です!当初は以下のどちらかにしようと思ってましたが、予定を変更してお送りしました!
この辺はまたの機会に!
個人事業主になりました
念のためはじめに言っておきますが会社は辞めてないですよ
色々書いて、最後のオチに持ってこようかとも思ったんですが、万が一の誤解を解くのが面倒なのでw
経緯
まず、私の勤めている会社で今年の春ぐらいかな?副業が解禁されました。
で、最近とある方面から個人としてお仕事のお話をいただけることがあって、その中で確定申告が必要な収入に達したので、確定申告の方法を調べていたら、どうやら副業でも個人として確定申告が必要なら個人事業主になった方が節税になるという情報を得て、ちょっとやってみようかなと思い立ったわけです。副業の対象に個人事業主は想定されていなかったんですが、試しに相談してみたら規定を見なおしてOKもらえました。会社に感謝です。
まあ、今現在安定して月収5万~10万円の保証なんてどこにもないわけですが・・・
正直、節税は割りとついでの意味合いで、こうやって形にすることで本業外で色々と動きやすくなると良いなーという想いがあったりする感じです。
どんな感じで働くの?
とりあえずは本業に影響を与えないことが前提なので、平日はフルタイムで出社して働いているので、休日や夜間がメインとなります(連絡くらいは多少遅れることはあるかもしれませんが、もちろんできます。手を動かすのはという感じ)なので、正直なかなか厳しいだろうなーとは思ってはいます。。。
何ができるの?
- クラウド(主にAWS、GCP勉強中)インフラ設計・構築
- Chef等を用いた所謂自動化・DevOps等の開発・運用フロー改善
- インフラからアプリケーションコードまで踏み込んだパフォーマンスチューニング
- PHP,Pythonを用いたアプリケーション開発(Go, Rubyもちょっとだけできます)
- 上記に関わるコンサルティングや技術支援
特に上の3つはそこそこできる方だと思っています。少なくとも道内では「この人には敵わない」って人は思い浮かばないです(勝っているとは言っていない)
特に、本業でもDeveloperとArchitect的なロールの両方をやっているので、インフラからアプリケーションまで含めて全体として最適なアーキテクチャを組んだりアプリケーションの設計をすることは普段から心がけていて、そのあたりはあまり他の人にはないバリューの出せるポイントかなーなんて思ったりしています。
なんか、こうやって自分の宣伝するのって恥ずかしいですねw
自分を見つめなおす良い機会になった気もしますがw
屋号は?
形だけに近くとも、せっかくの機会なので付けました。
Willyworks(ウィリーワークス)です。よろしくお願いします。
Willyの語源は学生時代にやっていたアメリカンフットボールのポジションの通称から取ってます。
正確にはWeak-side Linebacker(WLB)といい、簡単に言うと人数が少ない方(Weak-side)を広く守りつつ、時に鋭く前線に突っ込む(Blitz)みたいなポジション(僕の認識では)です。なんとなく自分の仕事にも当てはまるかなと感じたので。イギリス英語のスラングかなんかでアレな意味があるらしいですが。。。worksはそれっぽい感じで語呂が良かったのでw
というわけで
フルタイムじゃないので相談しづらいでしょうが、何かありましたらお気軽にご相談くださいませ。
Infrastructure as Code Casual 札幌 #0を開催しました。 #infracode_sap
はじめに
題の通り、やりました。 infracode-sapporo.connpass.com
満員御礼、出席率ほぼ100%で、とても盛り上がりました。
参加していただいた皆様、ありがとうございました!
その雰囲気はこちらからどうぞ。 togetter.com
一年くらい、やるやる詐欺してたのが、やっと重い腰が上がった形になります。
まあ、雰囲気や個々の発表なんかはTogetterやら、他の方のブログなんかを見てもらうとして、振り返りをしておこうと思います。
成り立ち
まあ、これにもなんとなく書いてるんですけど。
www.slideshare.net兎にも角にも、身の回りにInfra as Codeを実践してる人が少ない。北海道で真面目にやってるは自分だけなんじゃないかと思ってしまうほどに少ない。なので、話し相手が居ないのである。
話し相手を見つけたい、増やしたい。それもやってて楽しい形で。
ということで、前々から札幌にCasual文化を持ち込みたかったというのもあり、ああいった形になった。
あとはやっぱり、一人でやると辛いので身近に一緒にやってくれる人がいたことが大きい。
何故発表を「推奨」としたのか、クオリティを問わないのか
これまでの経験上(それほど多くはないものの)、勉強会的なものを楽しくて実りあるものとするために必要なものは「多様性」であると思う。色んなバックグラウンドを持つ人が、色んな話をすることで、色んな刺激が生まれる。それによって様々な意見や議論が飛び交って、盛り上がる。
また、完成された話ではなく「これからどんなことをしたいか」や「どんな話が聞きたいか」等も可とした。これには2つの目的がある。
- 実践に繋げる
分からないことや聞きたいことを聞ける場所があるというのは、実践する上でとても助けになるのではないかと思っている。自分自身、誰にも聞ける人が居ないというのは中々に辛いものがあった。
必ずしも、予め内容が決められた勉強会なんかでは聞きたいことが聞けるとは限らない。だから、聞きたいことがあるなら言ってほしい、それも大声で。そうすれば、きっと誰かが返してくれるはず。
そして、そうやって誰かに返してもらった人はきっと、次は発信する立場になってくれるんじゃないかと思う。そうやって、喋りたい人ばっかりが集まるようになるときっと、もっと楽しいはずだと思うし、自然とレベルも上がると思う。 - 議論の喚起
ある程度見込んだことであったものの、今回は本当にこれを実感した。お酒の勢いもあってとても良い雰囲気で様々なやり取りが行われ、それによって大いに盛り上がった感がある。
要は、同じ興味を持った人が集まって、好きなようにワイワイ楽しくやりながらも、実りある形にするにはこういう形も良いのではないか。と思ったという感じである。
最後に
とにかく、楽しかった。今回のは厳密には勉強会ではないけど、そういったものでこんなに楽しかったのは凄い久しぶりだったと思う。またやってくれというありがたいお言葉もいただいているし、自分自身もまたやりたいと思っているので、たぶんまたやります。
某氏は毎月とか言っていたけど、最近ちょっと忙しくなってきたし、2,3ヶ月後くらいかな。それこそ、次もまた @hokkai7go が帰ってくるタイミングでも良いかもしれない。
今回はかなり強引に開催まで持っていったので、事前の調整不足で色々と配慮しないといけない所が出てきてしまっているので、それ次第という感じもする。
とりあえず、参加していただいた皆様、ありがとうございました!またよろしくお願いします!
特定のAMIイメージの最新情報を簡単に取得できるGemを作りました
背景
まず、この辺の記事がネットで流れてきました。
「へー、便利だなー」と思った反面、以下の様なことを感じました。
「こんな複雑なシェル覚えられる気がしない」
「これ、分かったとしてその後どうするの?コピペ?」
ということで、より使いやすくプログラマブルな形で取れると良いかなと思い作ってみました。
やってることは至極単純なので、昼休み中に何とか終わったw
amino | RubyGems.org | your community gem host
使い方
$ gem install amino $ pry [1] pry(main)> require 'amino' => true [2] pry(main)> Amino('name' => 'amzn-ami-hvm-*-gp2', 'virtualization-type' => 'hvm').last.image_id => "ami-1ecae776"
簡単ですね :-)
この例では、リージョンはus-east-1
になってます。
リージョンや認証情報はaws-sdk
を使っているので、同じ方法で変更できます。
第2引数に以下の様にHashで渡すとその場で指定もできます。
Amino( {'name' => 'amzn-ami-hvm-*-gp2', 'virtualization-type' => 'hvm'}, {'region' => 'ap-northeast-1', 'aws_key_id' => 'xxxxxxxx', 'aws_secret_key' => 'XXXXXX'} )
たぶん、使わないと思いますがfirst
も一応ありますw
これ、もしかして
Kumogata先生と組み合わせたらめっちゃ便利なんじゃね?
既存システムでインフラのコード化を行う意義
はじめに
大抵、インフラのコード化を始めるのって新規システムとかになると思います。
たしかに、最初からやる方が途中からやるのに比べて遥かに敷居が低く、費用対効果も高いと言えると思います。
まあ、インフラのコード化に限らず、TDDとかもそうです。
新しいことを始めるのは最初からの方がやりやすい。
これが、既存システムの場合は
- 今動いているものが壊れたらどうする?
- 既に出来上がっちゃってるものにそんなにコストかけてやる必要ない
とかいう感じで、コストやリスクと得られるメリットを天秤にかけた結果、敬遠されがちなのかなと思います。
たぶん、比較対象のメリットは以下の様なものでしょう。
- 自動化による人的コスト減
- 再現性のあるインフラによる追加開発やメンテナンスの効率と質の向上
- モチベーションアップ
でも、やったことがある人には判るかもしれませんが、実はもっと重要なメリットというか、意義があるんです。
それは何か
それは、今まで見えなかったものが見えるようになることです。
インフラをコード化していくとはどういうことなのか
特に僕が多くの場面で使っているChef
だとそうなのですが、そのシステムを構成しているコンポーネントを洗い出し、分類し、依存関係を整理して、コードという形で定義していくという作業です。
そして、見えてくるものがある
例えば以下の様なものです。
- 役割を負い過ぎているサーバ
- 役割が重複しているサーバ
- 実は無くても良くて潰しちゃってコストを下げられるサーバ
- 耐障害性に不安があるサーバ
- 依存関係が複雑で追加開発や保守作業の足を引っ張りそうなサブシステム
- サービスが停止する原因となりそうな障害
他にも細かい所では、致命的なバグや脆弱性を内包したバージョンのまま動かしてるミドルウェアとかが見つかったりすることもありますが、まあそれはコード化特有っていう話ではなく二次的なものですね。
見えてくると改善できる
今までなんとなく動いていてなんとなくそのままでいたものが、見えてくることによって改善できるようになります。
そうなると、特に今後もある程度長く続くであろうシステムであれば、十分にコード化を進める意義があると思いませんか?
新規システムでもそうです。はじめからちゃんとやっておくと、全体を俯瞰して把握しやすくなり、改善計画を立てやすくし、成長スピードを速められます。
そのために
上述しましたが、そのシステムを構成しているコンポーネントを洗い出し、分類し、依存関係を整理して、コードという形で定義していくという作業をちゃんとやる必要があります。
これは、ある程度の「設計」や「実装」のノウハウが必要になります。
YAPCではその辺りをお話してみたいなと思っているので、気になる方は是非SNSなどでシェアして応援お願い致します!
以上、ステマですいません。。。
Google Spreadsheet Add-on「AWS Priceing Helper」を新しいリザーブド購入オプションに対応させました #jawsug
もっと早くやれよ、今更かよ、って話なんですが。。。
AWS Priceing Helper #とは
Google SpreadsheetにAWSの料金見積もりをするために、料金を勝手に埋めてくれる便利なカスタム関数群を追加するアドオンです。
詳しくは、今更見られるとちょっと恥ずかしい昔書いたブログをば。
blog.memolib.com
追加した関数群
- EC2_LINUX_RI_NO_AD
- EC2_LINUX_RI_PART_AD
- EC2_LINUX_RI_ALL_AD
- EC2_WINDOWS_RI_NO_AD
- EC2_WINDOWS_RI_PART_AD
- EC2_WINDOWS_RI_ALL_AD
- EC2_LINUX_RI_NO_HOUR
- EC2_LINUX_RI_PART_HOUR
- EC2_LINUX_RI_ALL_HOUR
- EC2_WINDOWS_RI_NO_HOUR
- EC2_WINDOWS_RI_PART_HOUR
- EC2_WINDOWS_RI_ALL_HOUR
関数名の意味
- 末尾
AD
はAdvanced payment
で前払い金額 - 末尾
HOUR
はまんま時間課金の金額 NO
がNo Upfront
なので前払いなしPART
がPartial Upfront
なので一部前払いALL
がAll Upfront
なので全額前払いなし
ちな、時間課金の金額は公式ページには乗ってない情報だったりします。
月額が書いてあるので1年に均して割返せば分かるんですけど(っていうかアドオンでもそうやって出してる)
なぜ今更?
転職して自分で見積もりとかあんまりやらなくなっちゃったので。。。
と思ってたら、こんな感じになりまして。
けっこうな規模の見積もりレビューしてくれってSimple Monthly Calculatorのリンク送られてきて、クソ見づらいから某アレをちゃんと整備して展開すべきか…ってなってる
— Marcy Terui (@marcy_terui) 2015, 4月 14
あと、Google SpreadsheetのAPI的な制限に引っかかるようになっちゃった部分とかがあっt(モゴモゴ
ちなみに
ダウンロード数とかけっこう多い割に使ってる人ほとんどみたことないので、
最近GithubのStarとかPRくれたのも外人さんだし、海外で意外と使われてるみたいですw
どうぞ、ご査収ください。
IaaSのNetworkのINには課金せず、OUTにだけ課金するのは、とても理にかなった手法なんじゃないかと今更気が付きましたが何か?
とても今更感があるけど、、、「何を今更」と思ったらここで読むのをやめましょう。
ついったに書くには長くなりそうなので、落書きしてみる。
要は
INに課金しないことで、副次的に他の課金を促進できる
理由
INには多くの場合にOUTが伴う
これは言わずもがな。INがあればOUTが当然期待できる。
分かりやすいのがWebシステムで、リクエストに対してレスポンスが必ずある。
ここまでは良い。
ただ、INに対して、必ず同等のOUTがあるわけではないので、
一見するとNW帯域を消費するのはどちらも一緒で非効率なようにも感じる。
では、OUTが無い場合に起こっていることはなにか?
INがあるのにOUTが無い、あるいは出て行く量が少ない場合、内部では何が起こっているか?
内部に貯める
情報が入ってくるのに出て行かないということは、入ってきた情報を内部に貯めるということになる。
つまり、ストレージ料金が発生する。計算する
入ってくる量に対して、出て行く量または貯める量が少なくなる場合、多くのケースでそこには計算が発生する。
圧縮、分析、サマライズ、などなど。これらには必ずと言ってよいほど計算処理が必要になる。
つまり、コンピュート料金が発生する。
つまりどうなるか
INに課金しないことで「とりあえず入れとけ」的な発想を促進できる。
また、計算に料金がかかるのは当然的な意識が大半の人にはあると思うので、それなら「潤沢な計算能力を活かそう」という流れができあがる。
例えるなら
魅力的な入場無料のテーマパークで、退場時にお金が取られる。
じゃあ、せっかくだから長く遊んでいこうかってなるけど、中で生活する以上、飲食代やホテル代がかかる。そんな感じでよくできてるなあと思いました。まる。