Reputation: 10460
I used the AWS Console to set up a Cloud Watch alarm that will send my team a slack notification and reboot the affected EC2 instance, when the EC2 instance fails a StatusCheck fails.
Here's what the actions look like in the AWS console:
Now I want to write a terraform module that will set this up for me. Here is what I have so far:
cloudwatch_metric_alarm/main.tf
locals {
name = format("%s_ec2-instance-down-alarm", var.name_prefix)
}
resource "aws_cloudwatch_metric_alarm" "ec2-instance-alarm" {
name = local.name
description = var.alarm_description
schedule_expression = var.schedule_expression
tags = merge(map("Name", local.name), var.extra_tags)
alarm_name = local.name
comparison_operator = var.comparison_operator
evaluation_periods = var.evaluation_periods
namespace = var.namespace
metric_name = var.metric_name
period = var.period
statistic = var.statistic
threshold = var.threshold
dimensions = {
InstanceId = var.instance_id
}
alarm_actions = [var.alarm_actions]
}
cloudwatch_metric_alarm/variables.tf
variable "extra_tags" {
type = map
default = {}
}
variable "name_prefix" {
type = string
}
variable "comparison_operator" {
type = string
default = "GreaterThanOrEqualToThreshold"
}
variable "evaluation_periods" {
type = number
default = 1
}
variable "namespace" {
type = string
default = "AWS/EC2"
}
variable "metric_name" {
type = string
default = "StatusCheckFailed"
}
variable "period" {
type = string
default = "60"
}
variable "statistic" {
type = string
default = "Average"
}
variable "threshold" {
type = string
default = "1"
}
variable "instance_id" {
type = string
}
variable "alarm_actions" {
type = list(string)
}
variable "alarm_description" {
type = string
default = "This alarm will send a slack notification if the bastion host because unresponsive."
}
My question what do I pass in for alarm_actions
in my parent module. Here's the pertinent of the parent main.tf
:
... other stuff ...
module "my-cloudwatch-metric-alarm" {
source = "./cloudwatch_metric_alarm"
alarm_actions = [???]
}
... other stuff ...
I have no idea what I am suppose to pass in as the alarm_actions
.
What am I suppose to pass in?
Thanks!
UPDATE and NOTE to Self.
I was getting the error message
Error: Creating metric alarm failed: ValidationError: Invalid use of EC2 action. An EC2 action can only be used if the alarm is monitoring an EC2 instance.
The cause of this error was this line were I misspelled InstanceId
:
InstatnceId = var.instance_id
Upvotes: 2
Views: 4121
Reputation: 200446
First, your var.alarm_actions
is already a list, so adding brackets around it like [var.alarm_actions]
is going to create a list of lists, which is going to cause errors. You just need to pass it directly to the resource like:
alarm_actions = var.alarm_actions
For the first value you need to pass in that list, you need the ARN of the SNS topic you want to send the notifications to. You would find that in the AWS SNS console. If Terraform is managing the SNS topic for you, then you should have access to the topic ARN in Terraform already. Alternatively you could look it up via a datasource by topic name.
For the second value, it is a special ARN that indicates to CloudWatch to reboot the instance being monitored. It looks like this: arn:aws:automate:<region>:ec2:reboot
. For example if your infrastructure is in us-east-1 then the ARN would be arn:aws:automate:us-east-1:ec2:reboot
. You could construct that dynamically in your Terraform code based on the region Terraform is deploying to by using the aws_region datasource in the Terraform AWS provider.
Your final code may look something like this:
data "aws_sns_topic" "alerts" {
name = "Your Topic Name"
}
data "aws_region" "current" {}
module "my-cloudwatch-metric-alarm" {
source = "./cloudwatch_metric_alarm"
alarm_actions = [
data.aws_sns_topic.alerts.arn,
"arn:aws:automate:${data.aws_region.current.name}:ec2:reboot"
]
}
Upvotes: 2