Skip to content

Commit 8a322cd

Browse files
author
Alexander Wiechert
committed
cleanup
1 parent 0f7bb1e commit 8a322cd

File tree

5 files changed

+66
-63
lines changed

5 files changed

+66
-63
lines changed

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,28 @@ This module is compatible with both Terraform (>=1.4) and OpenTofu (>=1.4).
2323
- Monitor **BurstBalance**, **ReadOps**, and **WriteOps** per EBS volume.
2424
- Dynamically set alarm thresholds per volume type (gp2, gp3, io1, io2, st1, sc1).
2525
- Automatically exclude irrelevant alarms (e.g., no BurstBalance on st1/sc1).
26+
- Creates a Cost Category in AWS Cost Explorer to group and track all EBS-related costs.
2627
- Filter volumes by tags (e.g., `Environment = Production`).
2728
- Send alerts to SNS with configurable email subscription.
29+
- Adds CloudWatch Composite Alarms to combine ReadOps, WriteOps, and BurstBalance alerts per EBS volume.
30+
- **Optional CloudWatch dashboard** with dynamic widgets per volume.
2831
- Includes example project and CI workflow with security checks.
2932

3033
---
3134

3235
## Usage
3336

37+
### Least Privilege IAM Policy
38+
39+
Before applying this module, ensure the IAM user or role has at least the permissions defined in [`iam-policy-minimal.json`](./iam-policy-minimal.json).
40+
41+
These include:
42+
- CloudWatch: alarm management, metrics read access
43+
- SNS: topic management, publish/subscribe
44+
45+
This avoids running Terraform with overly broad permissions.
46+
47+
3448
### Real Mode (default)
3549

3650
```hcl
@@ -43,6 +57,11 @@ module "ebs_optimization" {
4357
email_endpoint = "finops-team@example.com"
4458
}
4559
```
60+
61+
### Optional CloudWatch Dashboard
62+
```hcl
63+
enable_dashboard = true
64+
```
4665
Run:
4766
```bash
4867
terraform init
@@ -86,6 +105,24 @@ terraform apply
86105
| sns_topic_name | Name of the SNS topic for alerts | string | "ebs-alerts-topic" |
87106
| email_endpoint | Email address for SNS subscription | string | n/a (required) |
88107
|use_fake_data |Enable fake/test mode (no AWS calls)| bool | false |
108+
|enable_dashboard |Enable CloudWatch dashboard creation| bool |true |
109+
---
110+
### Tagging
111+
112+
This module automatically applies consistent tags to all resources (SNS topics, CloudWatch alarms, dashboards) it creates, making it easier to track costs, ownership, and environments.
113+
114+
The following tags are applied:
115+
116+
| Tag | Description |
117+
|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
118+
| `Environment` | Taken from `var.tag_filter_value`. Ensures the monitoring resources are labeled consistently with the EBS volumes they are watching (e.g., `Production`). |
119+
| `CostCenter` | Taken from `var.cost_center`. Allows cost allocation and reporting by project, team, or budget owner (default: `FinOps`). |
120+
| `ManagedBy` | Fixed tag (`terraform-aws-ebs-optimization`). Indicates the resources are managed by this Terraform module, improving transparency and auditability. |
121+
122+
**Important:**
123+
- The `Environment` tag does not dynamically read the EBS volume’s tags.
124+
- It uses the value you pass as `tag_filter_value` in the module inputs.
125+
- For example, if you filter volumes with `tag_filter_value = "Production"`, the same value is applied as the `Environment` tag on the monitoring resources.
89126

90127
---
91128

examples/basic/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ module "ebs_optimization" {
77
sns_topic_name = "ebs-optimization-alerts"
88
email_endpoint = "finops-team@example.com"
99
use_fake_data = true
10+
enable_dashboard = true
1011
}

main.tf

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -53,66 +53,4 @@ locals {
5353
if contains(["gp2", "gp3", "io1", "io2"], vol.volume_type)
5454
}
5555

56-
}
57-
58-
resource "aws_sns_topic" "ebs_alerts" {
59-
name = var.sns_topic_name
60-
}
61-
62-
resource "aws_sns_topic_subscription" "email_sub" {
63-
topic_arn = aws_sns_topic.ebs_alerts.arn
64-
protocol = "email"
65-
endpoint = var.email_endpoint
66-
}
67-
68-
69-
resource "aws_cloudwatch_metric_alarm" "burst_balance_low" {
70-
for_each = local.ssd_volumes
71-
72-
alarm_name = "ebs-burst-balance-low-${each.key}"
73-
comparison_operator = "LessThanThreshold"
74-
evaluation_periods = 1
75-
metric_name = "BurstBalance"
76-
namespace = "AWS/EBS"
77-
period = 300
78-
statistic = "Average"
79-
threshold = local.alarm_thresholds[each.value.volume_type].burst_balance
80-
dimensions = {
81-
VolumeId = each.key
82-
}
83-
alarm_actions = [aws_sns_topic.ebs_alerts.arn]
84-
}
85-
86-
resource "aws_cloudwatch_metric_alarm" "read_ops_low" {
87-
for_each = local.selected_volumes
88-
89-
alarm_name = "ebs-read-ops-low-${each.key}"
90-
comparison_operator = "LessThanThreshold"
91-
evaluation_periods = 1
92-
metric_name = "VolumeReadOps"
93-
namespace = "AWS/EBS"
94-
period = 300
95-
statistic = "Average"
96-
threshold = local.alarm_thresholds[each.value.volume_type].read_ops
97-
dimensions = {
98-
VolumeId = each.key
99-
}
100-
alarm_actions = [aws_sns_topic.ebs_alerts.arn]
101-
}
102-
103-
resource "aws_cloudwatch_metric_alarm" "write_ops_low" {
104-
for_each = local.selected_volumes
105-
106-
alarm_name = "ebs-write-ops-low-${each.key}"
107-
comparison_operator = "LessThanThreshold"
108-
evaluation_periods = 1
109-
metric_name = "VolumeWriteOps"
110-
namespace = "AWS/EBS"
111-
period = 300
112-
statistic = "Average"
113-
threshold = local.alarm_thresholds[each.value.volume_type].write_ops
114-
dimensions = {
115-
VolumeId = each.key
116-
}
117-
alarm_actions = [aws_sns_topic.ebs_alerts.arn]
118-
}
56+
}

provider.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,13 @@ provider "aws" {
55
skip_credentials_validation = true
66
skip_requesting_account_id = true
77
skip_metadata_api_check = true
8+
9+
default_tags {
10+
tags = {
11+
Environment = var.tag_filter_value
12+
CostCenter = var.cost_center
13+
ManagedBy = "terraform-aws-ebs-optimization"
14+
}
15+
}
16+
817
}

variables.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,22 @@ variable "use_fake_data" {
3131
description = "Enable fake data mode for testing"
3232
type = bool
3333
default = false
34+
}
35+
36+
variable "enable_dashboard" {
37+
description = "Enable creation of a CloudWatch dashboard"
38+
type = bool
39+
default = true
40+
}
41+
42+
variable "cost_center" {
43+
description = "Cost center tag for all resources"
44+
type = string
45+
default = "FinOps"
46+
}
47+
48+
variable "category_name" {
49+
description = "Name of the Cost Category"
50+
type = string
51+
default = "EBS-Volumes"
3452
}

0 commit comments

Comments
 (0)