Skip to content

Commit 985222b

Browse files
author
Alexander Wiechert
committed
add cost category, cost usage, dashboard for cloudwatch, sns and sample ima policy
1 parent 8a322cd commit 985222b

File tree

6 files changed

+220
-0
lines changed

6 files changed

+220
-0
lines changed

cost_category.tf

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
resource "aws_ce_cost_category" "ebs_volumes" {
2+
name = "EBS-Volumes"
3+
rule_version = "CostCategoryExpression.v1"
4+
5+
rule {
6+
value = "EBS"
7+
rule {
8+
dimension {
9+
key = "SERVICE"
10+
values = ["Amazon Elastic Block Store"]
11+
}
12+
}
13+
}
14+
15+
default_value = "Other"
16+
}

cloudwatch_alarms.tf

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
resource "aws_cloudwatch_metric_alarm" "burst_balance_low" {
2+
for_each = local.ssd_volumes
3+
4+
alarm_name = "ebs-burst-balance-low-${each.key}"
5+
comparison_operator = "LessThanThreshold"
6+
evaluation_periods = 1
7+
metric_name = "BurstBalance"
8+
namespace = "AWS/EBS"
9+
period = 300
10+
statistic = "Average"
11+
threshold = local.alarm_thresholds[each.value.volume_type].burst_balance
12+
dimensions = {
13+
VolumeId = each.key
14+
}
15+
alarm_actions = []
16+
}
17+
18+
resource "aws_cloudwatch_metric_alarm" "read_ops_low" {
19+
for_each = local.selected_volumes
20+
21+
alarm_name = "ebs-read-ops-low-${each.key}"
22+
comparison_operator = "LessThanThreshold"
23+
evaluation_periods = 1
24+
metric_name = "VolumeReadOps"
25+
namespace = "AWS/EBS"
26+
period = 300
27+
statistic = "Average"
28+
threshold = local.alarm_thresholds[each.value.volume_type].read_ops
29+
dimensions = {
30+
VolumeId = each.key
31+
}
32+
alarm_actions = []
33+
}
34+
35+
resource "aws_cloudwatch_metric_alarm" "write_ops_low" {
36+
for_each = local.selected_volumes
37+
38+
alarm_name = "ebs-write-ops-low-${each.key}"
39+
comparison_operator = "LessThanThreshold"
40+
evaluation_periods = 1
41+
metric_name = "VolumeWriteOps"
42+
namespace = "AWS/EBS"
43+
period = 300
44+
statistic = "Average"
45+
threshold = local.alarm_thresholds[each.value.volume_type].write_ops
46+
dimensions = {
47+
VolumeId = each.key
48+
}
49+
alarm_actions = []
50+
}
51+
52+
resource "aws_cloudwatch_composite_alarm" "ebs_composite_alarm" {
53+
for_each = local.selected_volumes
54+
55+
alarm_name = "ebs-composite-alarm-${each.key}"
56+
alarm_rule = join(" OR ", compact([
57+
"ALARM(${aws_cloudwatch_metric_alarm.read_ops_low[each.key].alarm_name})",
58+
"ALARM(${aws_cloudwatch_metric_alarm.write_ops_low[each.key].alarm_name})",
59+
contains(keys(local.ssd_volumes), each.key) ? "ALARM(${aws_cloudwatch_metric_alarm.burst_balance_low[each.key].alarm_name})" : ""
60+
]))
61+
62+
alarm_description = "Composite alarm for EBS volume ${each.key}"
63+
alarm_actions = [aws_sns_topic.ebs_alerts.arn]
64+
65+
tags = {
66+
Environment = var.tag_filter_value
67+
CostCenter = var.cost_center
68+
ManagedBy = "terraform-aws-ebs-optimization"
69+
}
70+
depends_on = [
71+
aws_cloudwatch_metric_alarm.read_ops_low,
72+
aws_cloudwatch_metric_alarm.write_ops_low,
73+
aws_cloudwatch_metric_alarm.burst_balance_low
74+
]
75+
}

cost_usage.tf

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
resource "aws_cur_report_definition" "ebs_report" {
2+
report_name = "ebs-cost-usage-report"
3+
time_unit = "DAILY"
4+
format = "Parquet"
5+
compression = "Parquet"
6+
additional_schema_elements = ["RESOURCES"]
7+
s3_bucket = aws_s3_bucket.cur_bucket.id
8+
s3_region = var.aws_region
9+
s3_prefix = "cur/ebs-report"
10+
report_versioning = "CREATE_NEW_REPORT"
11+
}
12+
13+
resource "aws_s3_bucket" "cur_bucket" {
14+
bucket = "finops-obs-optimisation-cur-bucket"
15+
}
16+
17+
resource "aws_s3_bucket_policy" "cur_bucket_policy" {
18+
bucket = aws_s3_bucket.cur_bucket.id
19+
20+
policy = jsonencode({
21+
Version = "2012-10-17",
22+
Statement = [{
23+
Sid = "AWSBillingPermissions"
24+
Effect = "Allow"
25+
Principal = {
26+
Service = "billingreports.amazonaws.com"
27+
}
28+
Action = "s3:GetBucketAcl"
29+
Resource = aws_s3_bucket.cur_bucket.arn
30+
},
31+
{
32+
Sid = "AWSBillingPutObject"
33+
Effect = "Allow"
34+
Principal = {
35+
Service = "billingreports.amazonaws.com"
36+
}
37+
Action = "s3:PutObject"
38+
Resource = "${aws_s3_bucket.cur_bucket.arn}/*"
39+
}]
40+
})
41+
}
42+
43+
resource "aws_athena_database" "cur_database" {
44+
name = "cur_database"
45+
catalog_name = aws_athena_data_catalog.cur_catalog.name
46+
comment = "Athena database for CUR analysis"
47+
bucket = aws_s3_bucket.cur_bucket.id
48+
}
49+
50+
resource "aws_athena_named_query" "ebs_query" {
51+
name = "ebs_cost_analysis"
52+
database = aws_athena_database.cur_database.name
53+
query = <<EOF
54+
SELECT line_item_resource_id, product_product_name, line_item_unblended_cost
55+
FROM cur_database.cur_table
56+
WHERE product_product_name = 'Amazon Elastic Block Store'
57+
EOF
58+
description = "Query to analyze EBS costs"
59+
}

dashboard.tf

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
resource "aws_cloudwatch_dashboard" "ebs_dashboard" {
2+
count = var.enable_dashboard ? 1 : 0
3+
dashboard_name = "ebs-optimization-dashboard"
4+
5+
dashboard_body = jsonencode({
6+
widgets = flatten([
7+
for vol_id, vol in local.selected_volumes : [
8+
{
9+
type = "metric"
10+
width = 6
11+
height = 6
12+
properties = {
13+
metrics = [
14+
["AWS/EBS", "BurstBalance", "VolumeId", vol_id]
15+
]
16+
period = 300
17+
stat = "Average"
18+
region = var.aws_region
19+
title = "BurstBalance ${vol_id}"
20+
}
21+
},
22+
{
23+
type = "metric"
24+
width = 6
25+
height = 6
26+
properties = {
27+
metrics = [
28+
["AWS/EBS", "VolumeReadOps", "VolumeId", vol_id],
29+
[".", "VolumeWriteOps", ".", ".", { "yAxis" : "right" }]
30+
]
31+
period = 300
32+
stat = "Sum"
33+
region = var.aws_region
34+
title = "Read/Write Ops ${vol_id}"
35+
}
36+
}
37+
]
38+
])
39+
})
40+
}

iam-policy-minimal.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Effect": "Allow",
6+
"Action": [
7+
"cloudwatch:PutMetricAlarm",
8+
"cloudwatch:DeleteAlarms",
9+
"cloudwatch:DescribeAlarms",
10+
"cloudwatch:GetMetricData",
11+
"cloudwatch:GetMetricStatistics",
12+
"sns:Publish",
13+
"sns:CreateTopic",
14+
"sns:Subscribe",
15+
"sns:DeleteTopic",
16+
"sns:GetTopicAttributes"
17+
],
18+
"Resource": "*"
19+
}
20+
]
21+
}

sns.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
resource "aws_sns_topic" "ebs_alerts" {
2+
name = var.sns_topic_name
3+
}
4+
5+
resource "aws_sns_topic_subscription" "email_sub" {
6+
topic_arn = aws_sns_topic.ebs_alerts.arn
7+
protocol = "email"
8+
endpoint = var.email_endpoint
9+
}

0 commit comments

Comments
 (0)