SlackへのAWS料金通知を(ほぼ)Step Functionsの機能だけで作ってみた
大阪オフィスの小倉です。
プライベートのAWSアカウントをAWS Organizationsで管理するようになったのですが、
それに伴って従来使っていたSlack料金通知が活用しづらくなってしまいました。
長年お世話になってきたのは以下のブログです。
ということで、以下の要件に従い、Step Functionsで作り直してみました。
- 基本の仕様は上記ブログを踏襲
- マルチアカウント環境で、アカウント別と合計の料金を通知したい
- Lambdaを使わずに実装したい
できたもの
実装はマネジメントコンソールで行った後、以下の機能でCloudFormationテンプレートにExportしています。
以降、Step Functionsの実装部分を紹介していきます。
日付の編集
EventBridge Schedulerから送られる日付を利用して、集計日付のFrom-Toを作ります。
- 基本は当月の月初日〜本日
- ただし、本日が月初日の場合、前月の月初日〜前月末日
編集処理は、先日対応が発表されたJSONataを使いました。
入力のtime
の値を使って、
{
"version": "0",
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"detail-type": "Scheduled Event",
"source": "aws.scheduler",
"account": "xxxxxxxxxxxxx",
"time": "2024-12-10T00:00:00Z",
"region": "ap-northeast-1",
(省略)
}
From-Toを作ります。
{
"start_date": "2024-12-01",
"end_date": "2024-12-10"
}
JSONataはプログラミング言語としての機能を備えているので、変数、条件分岐、ループなどが使えます。
うるう年の判定とかあるので、だいぶ力技です。。。
サービス料金をアカウント毎に集計
組織の管理アカウント上でGetCostAndUsage APIを実行すると、
配下のアカウントの料金情報もまとめて取得できますが、ResultsByTime.Groups
という配列の中に全アカウント分入ってしまうので、 こちらもJSONataで編集・集計します。
APIの出力は以下イメージですが、
{
"DimensionValueAttributes": [
{
"Attributes": {
"description": "account-1"
},
"Value": "111111111111"
},
{
"Attributes": {
"description": "account-2"
},
"Value": "222222222222"
},
(略)
],
"GroupDefinitions": [
{
"Key": "LINKED_ACCOUNT",
"Type": "DIMENSION"
},
{
"Key": "SERVICE",
"Type": "DIMENSION"
}
],
"ResultsByTime": [
{
"Estimated": true,
"Groups": [
{
"Keys": [
"111111111111",
"AWS Cost Explorer"
],
"Metrics": {
"AmortizedCost": {
"Amount": "0.58",
"Unit": "USD"
}
}
},
{
"Keys": [
"111111111111",
"AWS Lambda"
],
"Metrics": {
"AmortizedCost": {
"Amount": "0.0000123252",
"Unit": "USD"
}
}
},
(略)
}
このように、アカウント毎にまとめてみました。
{
"accounts": [
{
"accountId": "111111111111",
"description": "account-1",
"totalCost": "2.13 USD",
"services": {
"AWS Cost Explorer": "0.18 USD",
"AWS Secrets Manager": "0.11 USD",
"EC2 - Other": "0.09 USD",
"Amazon Route 53": "0.5 USD",
"Amazon Simple Storage Service": "1.04 USD",
"Tax": "0.2 USD"
}
},
{
"accountId": "222222222222",
"description": "account-2",
"totalCost": "0.32 USD",
"services": {
"AWS Cost Explorer": "0.18 USD",
"AWS Secrets Manager": "0.11 USD",
"Tax": "0.03 USD"
}
},
{
"accountId": "333333333333",
"description": "account-3",
"totalCost": "0.41 USD",
"services": {
"AWS Cost Explorer": "0.37 USD",
"Tax": "0.04 USD"
}
}
],
"total": "2.86 USD"
}
あとは、アカウント毎にMapステートで処理してあげます。
まとめ
JSONataがサポートされたことで、従来Lambdaで行っていた編集処理をStep Functions内で完結させることができました。
JSONataは今回利用した書き方だけでなく、クエリによる配列やオブジェクトの操作、ソートや集計、各種関数を利用することが出来るので、
ステート入出力の編集処理は恐らくJSONataでほぼ対応できるのではないでしょうか。
Web上にPlaygroundも多数あり、ブラウザからすぐ試すことも出来ますので、
少しでも気になる方は是非JSONataのドキュメントを確認してみてください。