terraformamazon-cloudwatchinfrastructure-as-code

How Create CloudWatch Disk Space Alarm for Different Paths Dynamically


I have configured CW agent to send disk space metrics and create an alarm based on that metric. I'm using terraform deploy resources in AWS. Below code is working when I only create alarm for a single path like /var.

resource "aws_cloudwatch_metric_alarm" "EC2_DiskSpace_Alert" {
  count               = terraform.workspace == "prod"  ? var.instance_count : 0 
  alarm_name          = "${terraform.workspace}_${var.name}_${count.index}_EC2_DiskSpace_Alert"
  alarm_description   = "Alert when Disk Space Utilization is above threshold"
  alarm_actions       =  [data.aws_sns_topic.cloudwatch_alerts.arn]
  metric_name         = "disk_used_percent"
  namespace           = "CWAgent"
  statistic           = "Average"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  threshold           = 70
  unit                = "Percent"
  evaluation_periods  = 3
  period              = 5
  treat_missing_data  = "notBreaching"
  tags = {
    Environment = terraform.workspace
  }

  dimensions = {
    "InstanceId"   = aws_instance.i[count.index].id
  }
}

But if I want to create an alarm for each path like /var, / code should be like this.

resource "aws_cloudwatch_metric_alarm" "EC2_DiskSpace_Alert" {
  count               = terraform.workspace == "prod"  ? var.instance_count : 0 
  alarm_name          = "${terraform.workspace}_${var.name}_${count.index}_EC2_DiskSpace_Alert"
  alarm_description   = "Alert when Disk Space Utilization is above threshold"
  alarm_actions       =  [data.aws_sns_topic.cloudwatch_alerts.arn]
  metric_name         = "disk_used_percent"
  namespace           = "CWAgent"
  statistic           = "Average"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  threshold           = 70
  unit                = "Percent"
  evaluation_periods  = 3
  period              = 5
  treat_missing_data  = "notBreaching"
  tags = {
    Environment = terraform.workspace
  }

  dimensions = {
    "InstanceId"   = aws_instance.i[count.index].id
    "ImageId"      = "ami-xx"
    "InstanceType" = "t2-micro"
    "path"         = "/var"
    "device"       = "mapper"
    "fstype"       = "xfs"

  }
}

resource "aws_cloudwatch_metric_alarm" "EC2_DiskSpace_Alert" {
  count               = terraform.workspace == "prod"  ? var.instance_count : 0 
  alarm_name          = "${terraform.workspace}_${var.name}_${count.index}_EC2_DiskSpace_Alert"
  alarm_description   = "Alert when Disk Space Utilization is above threshold"
  alarm_actions       =  [data.aws_sns_topic.cloudwatch_alerts.arn]
  metric_name         = "disk_used_percent"
  namespace           = "CWAgent"
  statistic           = "Average"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  threshold           = 70
  unit                = "Percent"
  evaluation_periods  = 3
  period              = 5
  treat_missing_data  = "notBreaching"
  tags = {
    Environment = terraform.workspace
  }

  dimensions = {
    "InstanceId"   = aws_instance.i[count.index].id
    "ImageId"      = "ami-xx"
    "InstanceType" = "t2-micro"
    "path"         = "/"
    "device"       = "mapper"
    "fstype"       = "xfs"

  }
}

Is there a better way to do it without repeating this block for each path that I want to create an alarm? Like creating a dynamic "dimensions" without hardcoding values? Thank you in advance.


Solution

  • Thank all for the suggestions.

    I was able to make it work using for_each and locals.

    locals {
      paths = {
        "root" : {
          "path"   = "/",
          "device" = "xvda1",
          "fstype" = "ext4",
        },
        "boot_efi" : {
          "path"   = "/boot/efi",
          "device" = "xvda15",
          "fstype" = "vfat",
        }
      }
    }
    
    resource "aws_cloudwatch_metric_alarm" "warning_ec2_diskspace_alert" {
      for_each            = terraform.workspace == "dev" || terraform.workspace == "prod" ? local.paths : {}
      alarm_name          = "${terraform.workspace}_${each.key}_warning_ec2_diskspace_alert"
      alarm_description   = "Alert when Disk Space Utilization is above threshold"
      metric_name         = "disk_used_percent"
      namespace           = "CWAgent"
      statistic           = "Average"
      comparison_operator = "GreaterThanOrEqualToThreshold"
      threshold           = 70
      unit                = "Percent"
      evaluation_periods  = 3
      period              = 60
      treat_missing_data  = "notBreaching"
      tags = {
        Environment = terraform.workspace
      }
    
      dimensions = {
        "InstanceId"   = aws_instance.web[0].id
        "ImageId"      = aws_instance.web[0].ami
        "InstanceType" = aws_instance.web[0].instance_type
        "path"         = each.value.path
        "device"       = each.value.device
        "fstype"       = each.value.fstype
      }
    }