AWS Cost and Usage Reports(CUR)をTerraformで作成する
AWS Cost and Usage Reports(AWSのコストと使用状況レポート、以下CUR)は、AWSのコストやリソースの使用状況をS3やRedshiftにアップロードしてくれる機能です。EC2インスタンスIDなどのリソース単位を含めることができるため、コストの追跡が容易になります。
Cost Explorerと異なり、EC2以外のAWSサービスのリソースも含まれます。1日1回以上、S3にアップロードされるので、自分たちの使い慣れたBIツールなどで分析・可視化することができます。
AWSマネジメントコンソールからCURを設定することが多いのですが、今回はTerraform(一部CloudFormation)で作成する方法を紹介します。
プロバイダの設定
今回は、CURのデータを保存するS3バケットを東京リージョン(ap-northeast-1)に作成します。
後述しますが、CURを作成するためには、us-east-1リージョンにもプロバイダを設定する必要があるため、エイリアスを使用します。
provider "aws" {
region = "ap-northeast-1"
}
# For using AWS CUR
provider "aws" {
region = "us-east-1"
alias = "us-east-1"
}
S3バケットの作成
CURのデータを保存するS3バケット(example-billing-report
)を作成します。
resource "aws_s3_bucket" "cur" {
bucket = "example-billing-report"
force_destroy = false
}
resource "aws_s3_bucket_policy" "cur" {
bucket = aws_s3_bucket.cur.bucket
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Sid = "EnableAWSDataExportsToWriteToS3AndCheckPolicy",
Effect = "Allow",
Principal = {
Service = [
"billingreports.amazonaws.com",
"bcm-data-exports.amazonaws.com",
],
},
Action = [
"s3:GetBucketPolicy",
"s3:PutObject",
],
Resource = [
aws_s3_bucket.cur.arn,
"${aws_s3_bucket.cur.arn}/*",
],
Condition = {
StringEquals = {
"aws:SourceArn" = [
"arn:aws:cur:us-east-1:${data.aws_caller_identity.self.account_id}:definition/*",
"arn:aws:bcm-data-exports:us-east-1:${data.aws_caller_identity.self.account_id}:export/*",
],
},
StringLike = {
"aws:SourceAccount" = data.aws_caller_identity.self.account_id
}
},
},
],
})
}
S3バケットポリシーは、従来のCURだとこちらのドキュメントになりますが、AWS Data Exports(AWS CUR 2.0)の利用も見据えて、上記のようにしています。
CURの作成
aws_cur_report_definition
リソースで定義しますが、us-east-1
リージョンで作成する必要があるのが注意です。
Amazon AthenaでCURのデータをクエリすることを想定しているため、Parquet形式で出力するようにしています。
locals {
# CURでParquet形式で出力する場合は、S3パスが必須なため指定する
s3_prefix = "hoge"
}
resource "aws_cur_report_definition" "cur" {
provider = aws.us-east-1
report_name = "${var.app}-report"
time_unit = "DAILY"
format = "Parquet"
compression = "Parquet"
additional_schema_elements = ["RESOURCES"]
s3_bucket = aws_s3_bucket.cur.bucket
s3_region = var.region
s3_prefix = local.s3_prefix
additional_artifacts = ["ATHENA"]
refresh_closed_reports = false
report_versioning = "OVERWRITE_REPORT"
}
この状態でterraform apply
を実行すると、S3バケットとCURが作成されます。CURが有効になるまで最大24時間かかります。
CloudFormationスタックの実行
CURが有効になった後、Amazon AthenaでCURデータをクエリできるようにするため、AWSから提供されているCloudFormationスタックを実行します。このCloudFormationテンプレートはS3バケットに配信されており、以下のリソースを作成します。
- AWS Lambda関数
- AWS Glue Crawler
- AWS Glue Database
S3にCURデータ(Parquetファイル)が配信されると、AWS Lambda関数がトリガーされ、AWS Glue Crawlerによって、Parquetファイルを参照し、Glue Data Catalogが更新され、Athenaでクエリできるようになる仕組みです。
次のようにCloudFormationスタックを定義し、terraform apply
を実行します。
resource "aws_cloudformation_stack" "cur_athena" {
name = "cost-and-usage-report-athena"
template_url = "https://${aws_s3_bucket.cur.bucket}.s3.amazonaws.com/${local.s3_prefix}/${aws_cur_report_definition.cur.report_name}/crawler-cfn.yml"
capabilities = ["CAPABILITY_IAM"]
}
まとめ
次回はAWS Data Exports(CUR 2.0)について紹介したいと思います。
Discussion