简体   繁体   中英

How to link an AWS CloudWatch Alarm to an AWS Route53 Health Check using Terraform?

I am currently setting up an AWS CloudWatch Alarm detecting the health status of my server with Terraform . The health status is checked with an AWS Route 53 Health Check. My .tf file is :

resource "aws_cloudwatch_metric_alarm" "val1-alarm" {
  alarm_name = "val-alarm"
  comparison_operator = "LessThanOrEqualToThreshold"
  evaluation_periods = "2"
  metric_name = "HealthCheckStatus"
  namespace = "AWS/Route53"
  period = "60"
  statistic = "Minimum"
  threshold = "0"
  dimensions {
    HealthCheckId = "${aws_route53_health_check.val1-hc.id}"
  }
  alarm_description = "This metric monitor whether the server is down or not."
  insufficient_data_actions = []
}

resource "aws_route53_health_check" "val1-hc" {
  fqdn = "${aws_route53_record.val1-record.name}"
  port = 27017
  type = "TCP"
  failure_threshold = "3"
  request_interval = "30"
  measure_latency = 1
  cloudwatch_alarm_name = "${aws_cloudwatch_metric_alarm.val1-alarm.alarm_name}"
  cloudwatch_alarm_region = "eu-central-1"
}

I have this error when applying :

Cycle: aws_route53_health_check.val1-hc, aws_cloudwatch_metric_alarm.val1-alarm

Cycle means that each resource calls the other. When I try to remove cloudwatch_alarm_name and cloudwatch_alarm_region from the health check, a terraform error prompts that i need those two arguments (even though the doc specifies that those two are optional). How to fix that ?

Any help or suggestions are highly appreciated !

Note that you need to have your resources in US East (N. Virginia) since:

Amazon Route 53 metrics are not available if you select any other region as the current region.

Source: Monitoring Health Check Status and Getting Notifications .

I managed to make it work with eu-west-1 with this module:

variable "environment" {}
variable "domain_name" {}
variable "resource_path" {}

provider "aws" {
  alias  = "use1"
  region = "us-east-1"
}

resource "aws_route53_health_check" "health_check" {
  fqdn              = "${var.domain_name}"
  port              = 443
  type              = "HTTPS"
  resource_path     = "${var.resource_path}"
  measure_latency   = true
  request_interval  = 30
  failure_threshold = 3

  tags = {
    Name        = "${var.environment}"
    Origin      = "terraform"
    Environment = "${var.environment}"
  }
}

resource "aws_sns_topic" "topic" {
  name     = "${var.environment}-healthcheck"
  provider = "aws.use1"
}

resource "aws_cloudwatch_metric_alarm" "metric_alarm" {
  provider                  = "aws.use1"
  alarm_name                = "${var.environment}-alarm-health-check"
  comparison_operator       = "LessThanThreshold"
  evaluation_periods        = "1"
  metric_name               = "HealthCheckStatus"
  namespace                 = "AWS/Route53"
  period                    = "60"
  statistic                 = "Minimum"
  threshold                 = "1"
  insufficient_data_actions = []
  alarm_actions             = ["${aws_sns_topic.topic.arn}"]
  alarm_description         = "Send an alarm if ${var.environment} is down"

  dimensions {
    HealthCheckId = "${aws_route53_health_check.health_check.id}"
  }
}

You can't ref A from B and B from A .

Remove the reference from aws_cloudwatch_metric_alarm.val1-alarm such:

resource "aws_cloudwatch_metric_alarm" "val1-alarm" {
  alarm_name = "val-alarm"
  comparison_operator = "LessThanOrEqualToThreshold"
  evaluation_periods = "2"
  metric_name = "HealthCheckStatus"
  namespace = "AWS/Route53"
  period = "60"
  statistic = "Minimum"
  threshold = "0"
  alarm_description = "This metric monitor whether the server is down or not."
  insufficient_data_actions = []
}

resource "aws_route53_health_check" "val1-hc" {
  fqdn = "${aws_route53_record.val1-record.name}"
  port = 27017
  type = "TCP"
  failure_threshold = "3"
  request_interval = "30"
  measure_latency = 1
  cloudwatch_alarm_name = "${aws_cloudwatch_metric_alarm.val1-alarm.alarm_name}"
  cloudwatch_alarm_region = "eu-central-1"
}

See CloudWatch Alarm Example from here

On Terraform 0.9.3, I had to do the opposite and remove cloudwatch_alarm_name and cloudwatch_alarm_region from the aws_route53_health_check resource to get the alarm to connect to the health check. It felt backwards. The HealthCheckId dimension was enough to wire them together.

resource "aws_cloudwatch_metric_alarm" "val1-alarm" {
  alarm_name = "val-alarm"
  comparison_operator = "LessThanOrEqualToThreshold"
  evaluation_periods = "2"
  metric_name = "HealthCheckStatus"
  namespace = "AWS/Route53"
  period = "60"
  statistic = "Minimum"
  threshold = "0"
  dimensions {
    HealthCheckId = "${aws_route53_health_check.val1-hc.id}"
  }
  alarm_description = "This metric monitor whether the server is down or not."
  insufficient_data_actions = []
}

resource "aws_route53_health_check" "val1-hc" {
  fqdn = "${aws_route53_record.val1-record.name}"
  port = 27017
  type = "TCP"
  failure_threshold = "3"
  request_interval = "30"
  measure_latency = 1
}

命名空间 = "AWS/Route53"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM