Terraform创建CloudWatch告警失败:实例ID类型不匹配求助
解决Terraform创建CloudWatch告警时的类型不匹配错误
我来帮你分析下这个问题:你遇到的错误核心是CloudWatch告警的InstanceId维度需要单个字符串值,但你的模块输出的是列表类型,直接赋值就会触发类型不兼容的问题。
错误信息
Error: Error running plan: 1 error(s) occurred: * aws_cloudwatch_metric_alarm.queue_1: dimensions (InstanceId): '' expected type 'string', got unconvertible type '[]interface {}'
问题原因
你的模块superb_queue_api-a的output.tf里,ec2-instance输出的是aws_instance.ec2_instances.*.id——这是列表类型(哪怕你设置no_of_inst = 1,Terraform的splat语法*.id依然会返回包含单个元素的列表)。而CloudWatch告警的InstanceId维度要求传入单个字符串格式的实例ID,直接使用列表自然会报错。
你的配置参考
主Terraform配置
module "superb_queue_api-a" { source = "../../Modules/Services" no_of_inst = 1 ami_id = "${data.aws_ami.ubuntu.id}" instance_type = "t2.micro" subnets = "${data.terraform_remote_state.state_pull.prod-pvt-sub-a}" key = "sup_queue_inst" sec-group = ["${aws_security_group.ec2_sg.id}"] tp = "${var.is_production ? true : false}" instance-name = "sup-queue-api-a" } resource "aws_cloudwatch_metric_alarm" "queue_1" { alarm_name = "sup-queue-api-a" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "1" metric_name = "CPUUtilization" namespace = "AWS/EC2" period = "120" statistic = "Average" threshold = "90" dimensions { InstanceId = "${module.superb_queue_api-a.ec2-instance}" } alarm_description = "This metric monitors ec2 cpu utilization" alarm_actions = ["${var.terraform_elb_name}"] }
模块的EC2实例配置
resource "aws_instance" "ec2_instances" { count = "${var.no_of_inst}" ami = "${var.ami_id}" instance_type = "${var.instance_type}" subnet_id = "${var.subnets}" key_name = "${var.key}" vpc_security_group_ids = ["${var.sec-group}"] disable_api_termination = "${var.tp}" root_block_device { volume_size = 100 volume_type = "gp2" } tags { Name = "${var.instance-name}" } }
模块的output.tf
output "ec2-instance" { value = "${aws_instance.ec2_instances.*.id}" } output "private_ip" { value = "${aws_instance.ec2_instances.*.private_ip}" }
解决方案
根据你的实际需求,有两种处理方式:
方式1:针对单个实例的场景(当前no_of_inst=1)
直接取列表的第一个元素,修改告警里的InstanceId赋值:
dimensions { InstanceId = "${module.superb_queue_api-a.ec2-instance[0]}" }
如果你的Terraform版本是0.12+,可以简化为更简洁的写法:
dimensions { InstanceId = module.superb_queue_api-a.ec2-instance[0] }
方式2:支持多个实例的场景(未来可能扩展no_of_inst>1)
如果以后需要创建多个EC2实例并为每个实例单独配置告警,可以用count关联实例数量,自动生成对应数量的告警:
resource "aws_cloudwatch_metric_alarm" "queue" { # 根据模块输出的实例数量创建对应数量的告警 count = length(module.superb_queue_api-a.ec2-instance) alarm_name = "sup-queue-api-${count.index}" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "1" metric_name = "CPUUtilization" namespace = "AWS/EC2" period = "120" statistic = "Average" threshold = "90" dimensions { InstanceId = module.superb_queue_api-a.ec2-instance[count.index] } alarm_description = "This metric monitors CPU utilization for EC2 instance ${module.superb_queue_api-a.ec2-instance[count.index]}" alarm_actions = [var.terraform_elb_name] }
这样不管你设置多少个实例,每个实例都会自动匹配对应的CloudWatch告警。
内容的提问来源于stack exchange,提问作者Nishant Singh
相关产品推荐
相关产品推荐

