🔶 はじめに
LambdaでSlackにAWSの利用料金を投稿する(Node.js)で、AWS料金をSlackに投稿するついでに、節約可能な月額料金も提示した方が親切かと思い、おまけで調べました。
🔷 Trusted Advisor
AWSの利用中のサービスをチェックして、推奨の設定を提案してくれるサービス。
https://console.aws.amazon.com/trustedadvisor/home
その中に、「コスト最適化」という項目があり、こちらで提示してくれる「月額料金節約の可能性」の金額を、今回は取得します。
🔶 Lambda関数の実装
🔷 ポリシー設定
Lambda関数で節約可能な月額料金を取得するには、AWS SDKのSupportクラスのdescribeTrustedAdvisorCheckSummaries
とdescribeTrustedAdvisorChecks
を使います。
そのためには、Supportへのフルアクセス権限を持つAWSSupportAccessポリシーをアタッチします。(以下のJSONで設定してもOK)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"support:*"
],
"Resource": "*"
}
]
}
権限は最小にしたいところですが、現時点(2019/03/29)では、Supportは細かい権限設定はできないようです。
AWS Support does not let you allow or deny access to individual actions; therefore your policy must use the "Action": "support:*" to use the AWS Support Center or to use the AWS Support API.
参考:Actions, Resources, and Condition Keys for AWS Support
🔷 実装
- 処理を簡単に言うと、
describeTrustedAdvisorChecks
で一旦、コスト関係のアドバイスを全件取得して、その中に含まれるアドバイス情報のIDのみを拾って配列を作ります。 - 次に、
describeTrustedAdvisorChecks
に生成したアドバイスのIDの配列を渡すと、アドバイス毎に節約金額を含む情報を返してくれるので、金額を合計する。 - 注意点として、最初に
new AWS.Support({region:'us-east-1'});
と定義しているように、Supportクラスはリージョンを明示的に指定しないとエラーになります。
const AWS = require('aws-sdk');
const support = new AWS.Support({region:'us-east-1'});
exports.handler = async (event) => {
return await getAdvice();
};
/**
* Support APIからコスト削減のアドバイス取得処理
*
* @return AWSから取得したコスト削減のアドバイス
*/
function getAdvice() {
console.log(`■□■□ getAdvice : Support APIからコスト削減のアドバイス取得処理 ■□■□`);
return new Promise(
(resolve, reject) => {
let idArr=[];
let savingAmount = 0;
/* アドバイス毎のIDの取得 */
support.describeTrustedAdvisorChecks({ language: "ja"}, (err, adviceData) => {
if (err) {
console.error(err, err.stack);
reject("");
}
console.log(JSON.stringify(adviceData));
for(let i=0; i<adviceData.checks.length; i++) {
idArr.push(adviceData.checks[i].id);
}
/* アドバイスのID毎に提示されている、概算月間節約額の取得 */
support.describeTrustedAdvisorCheckSummaries({ checkIds: idArr}, (err, savingsData) => {
if (err) {
console.error(err, err.stack);
reject("");
}
console.log(JSON.stringify(savingsData));
for(let j=0; j<savingsData.summaries.length; j++) {
if(savingsData.summaries[j].hasFlaggedResources) {
savingAmount = savingAmount + savingsData.summaries[j].categorySpecificSummary.costOptimizing.estimatedMonthlySavings;
}
}
resolve(`概算月間節約額の合計${Math.round(savingAmount*100)/100}$`);
});
});
}
);
}
🔶 テスト
ここまで上手く設定できていたら、Lambda関数を実行すると、以下のように出力されます。
🔶 まとめ
このように、ID取る → 金額とる → 合計する と、ちょっと面倒というだけで、難易度は簡単なので、試してみてください。