AWS Lambdaで毎日料金を取得する
TL;DR
AWSのダッシュボード見たほうが早い
はじめに
監視しようがしてなかろうが、どのみちAWSのコンソールを常に開いている人にとっては、AWSのダッシュボード見たほうが正確で早いです。
しかし、そこまでAWS漬けでもない人にとってはいちいちAWSのコンソールを開き、料金やインスタンスの稼働状況を確認するのは面倒です。そこでSlackに稼働状況を監視して通知するAWS Lambdaの関数を定義して、楽して監視するようにします。
やりたいLambda関数の疑似コード
- EC2の全インスタンスを取得する
- タグ情報を取得し、稼働状態を列挙する
- CostExplorerから料金情報を取得する
- 現時点の料金を出力
- 現時点の料金を日数で割り、月の日数倍して予想価格を出す
料金は直近の1日分料金を取得し、その金額を月の残りの日数分足したほうが正確ですが、これはこれで1日だけ異様に活発だった時等に瞬間風速に引きずられてそこまで正確じゃないので、今回は今までの平均が一番平均に近いという事にします。
AWS Lambdaでの関数の作成
Lambdaの関数作成(Hello worldする物)は他にいくらでも情報があるので、そちらを参照ください。
権限周りの問題がでなければ、何か見るよりAWSの画面みたほうがわかりやすいです。
関数の作成のため、ユーザーにはiam:PassRoleの権限が必要でした。
関数自体のロールの権限は、以下を付与しました。
実際にコードに書いたメソッドと同じ名前の定義があるので、拡張する場合は適宜追加が必要です。
"ec2:DescribeInstances",
"ce:GetCostAndUsage"
nodejsでのAWS sdkの使い方
node.jsからAWS SDKを使う際は、以下にAPIの一覧があります。
ほとんどの場合aws cliの記法が正しく、ドキュメントが豊富です。
node.jsであっても同じように書けるので、aws cliの操作を参考にnodeに移行したほうが作りやすいと思います。
APIドキュメントは何がどう返ってくるのか説明があまりなく、これだけみて作るはかなり難しいと思います。
例えば、ローカル環境等で開発する場合~/.aws/credentialsを作成したり、AWS.credentialsでトークンを設定します。
AWS Lambdaで実行する場合は、AWS.credentialsで権限上書きをしようとしても、関数に割り当てたロールの権限で自動的に初期化され書き換えが行えず、初期化処理も勝手に終わるので、適当に書いてもなんか動きます。
実コード
実物
Lambdaへの展開
展開にあたり、aws-sdkはLambda上に既に存在しているため、それ以外のnode_modulesをZIP化してアップロードする必要があります。
アップロードは「コードエントリタイプ」の「.zipファイルをアップロード」から行うことが出来ます。
nodejsにとって必要なlockファイル等は不要です。また、package.jsonをLambda上でいい感じに「npm install」的な事をするという事は出来ません。
エントリポイント
node.jsの場合、LambdaのエントリーポイントはLambda設定パネルの「ハンドラ」の定義に従って動作するため、デフォルトの「index.handler」の場合、以下が動作します。
- index.js
- export.handler の関数
そのため、今回のコードの場合以下が動作します。
# index.js
exports.handler = (event, context, callback) => {
...
result = ec2_status();
...
result = costExplorer_status();
...
}
個々の関数の処理
hanlder関数から呼び出した関数は以下のaws cliの操作を受け持ちます。
- ec2_status
- aws ec2 describeInstances
- costExplorer_status
- aws costexplorer getCostAndUsage
処理そのものは返ってくるJSONを掘ってるだけなのでそんなに見どころはないです。
内容を元にslackのpayloadを作成し、slackのhookにPOSTしています。
出力例
Lambdaの駆動トリガー
関数のトリガーは、Lambdaの「トリガーを追加」から行います。
スケジュール実行の場合は「CloudWatch Events」から定義することができ、cron記法で記載することで定時実行されます。
まとめ
30日動かしても1円行かないので助かります。