无法使用 terraform 从自动缩放挂钩创建 sns

Posted

技术标签:

【中文标题】无法使用 terraform 从自动缩放挂钩创建 sns【英文标题】:Unable to create sns from an autoscaling hook with terraform 【发布时间】:2018-07-14 14:28:49 【问题描述】:

以下 terraform 脚本应为自动缩放第一组堡垒主机创建 sns 主题,并在主机启动或关闭时发送通知。

安全组:

resource "aws_security_group" "ssh_from_authorised_ips" 

          name = "ssh_from_authorised_ips"
          description = "SSH from authorised ip addresses for adminstering bastion host"
          vpc_id = "$var.vpc_id"

          ingress 
            from_port = 22
            to_port = 22
            protocol = "tcp"
            cidr_blocks = ["192.xx.xx.xx.xx/32", "62.xx.xx.xx/32"]
          

          egress 
            from_port = 0
            to_port = 0
            protocol = "tcp"
            cidr_blocks = ["0.0.0.0/0"]
          
          egress 
            from_port = 0
            to_port = 65535
            protocol = "udp"
            cidr_blocks = ["0.0.0.0/0"]
          

          tags 
            Name = "ssh_from_authorised_ips"
            "om:account_type" = "$var.tag_om_account_type"
            "om:env" = "$var.tag_om_env"
            "om:cost_center" = "network"
          
        

堡垒脚本:

data "aws_ami" "bastion_ami" 
      most_recent = true

      filter 
        name = "name"
        values = ["testami_*"]
      

      owners = ["self"]
    

resource "aws_autoscaling_group" "bastion_asg" 

  lifecycle  create_before_destroy = true 

  vpc_zone_identifier  = ["$split(",", var.public_subnets)"]

  name = "asg_$aws_launch_configuration.bastion_lc.name"
  min_size = "1"
  max_size = "1"

  default_cooldown = "180"
  health_check_grace_period = "180"
  health_check_type = "EC2"
  launch_configuration = "$aws_launch_configuration.bastion_lc.id"

  tags = [
    
      key = "Name"
      value = "bastion"
      propagate_at_launch = true
    ,
    
      key = "om:account_type"
      value = "$var.tag_om_account_type"
      propagate_at_launch = true
    
  ]


resource "aws_sns_topic" "bastion_updates" 
  name = "bastion-updates-topic"
  display_name = "Bastion_notification"


resource "aws_key_pair" "bastion_key" 
  key_name   =  "bastion_key_name"
  public_key = "$file("/home/xxxxxx/.ssh/id_rsa_bastion.pub")"


resource "aws_launch_configuration" "bastion_lc" 

  lifecycle  create_before_destroy = true 

  name_prefix = "bastion_"
  image_id = "$data.aws_ami.bastion_ami.id"
  instance_type = "$var.instance_type"
  associate_public_ip_address = true
  security_groups = ["$split(",", var.security_groups)"]

  key_name = "$aws_key_pair.bastion_key.key_name"

  root_block_device 
    volume_type = "gp2"
    volume_size = "$var.volume_size"
    delete_on_termination = true
  




resource "aws_iam_role" "bastion_notify_role" 
  name = "bastion_notify_role"

  assume_role_policy = <<EOF

  "Version": "2012-10-17",
  "Statement": [
    
      "Action": "sts:AssumeRole",
      "Principal": 
        "Service": "ec2.amazonaws.com"
      ,
      "Effect": "Allow",
      "Sid": ""
    
  ]

EOF


resource "aws_autoscaling_lifecycle_hook" "bastion_down_notify" 
 name                   = "bastion-down"
 autoscaling_group_name = "$aws_autoscaling_group.bastion_asg.name"
 default_result         = "CONTINUE"
 heartbeat_timeout      = 31
 lifecycle_transition   = "autoscaling:EC2_INSTANCE_TERMINATING"
 notification_metadata = <<EOF

 "bastion_message": "Bastion going down."

EOF
  notification_target_arn = "$aws_sns_topic.bastion_updates.arn"
  role_arn                = "$aws_iam_role.bastion_notify_role.arn"



resource "aws_autoscaling_lifecycle_hook" "bastion_up_notify" 
 name                   = "bastion-up"
 autoscaling_group_name = "$aws_autoscaling_group.bastion_asg.name"
 default_result         = "CONTINUE"
 heartbeat_timeout      = 31
 lifecycle_transition   = "autoscaling:EC2_INSTANCE_LAUNCHING"
 notification_metadata = <<EOF

 "bastion_message": "Bastion coming up."

EOF
  notification_target_arn = "$aws_sns_topic.bastion_updates.arn"
  role_arn                = "$aws_iam_role.bastion_notify_role.arn"





----------------------------------------------

我在执行 terraform apply -target=bastion_host 时收到以下错误。

module.bastion_host.aws_autoscaling_lifecycle_hook.bastion_down_notify: 1 error(s) occurred:

* aws_autoscaling_lifecycle_hook.bastion_down_notify: [DEBUG] Retrying AWS AutoScaling Lifecycle Hook: ValidationError: Unable to publish test message to notification target arn:aws:sns:eu-west-1:031768xxxx:bastion-updates-topic using IAM role arn:aws:iam::0317682xxxxx:role/bastion_notify_role. Please check your target and role configuration and try to put lifecycle hook again.
        status code: 400, request id: ad7379a6-09ca-11e8-85a3-d114xxxxxx
* module.bastion_host.aws_autoscaling_lifecycle_hook.bastion_up_notify: 1 error(s) occurred:

* aws_autoscaling_lifecycle_hook.bastion_up_notify: [DEBUG] Retrying AWS AutoScaling Lifecycle Hook: ValidationError: Unable to publish test message to notification target arn:aws:sns:eu-west-1:03176821xxxx:bastion-updates-topic using IAM role arn:aws:iam::0317682xxx:role/bastion_notify_role. Please check your target and role configuration and try to put lifecycle hook again.
        status code: 400, request id: ad7e4f1a-09ca-11e8-ac2b-2bxxxx

【问题讨论】:

【参考方案1】:

您需要一个附加到bastion_notify_role 角色的策略,允许它发布到 SNS。为此有一个 AWS 托管策略:

resource "aws_iam_role_policy_attachment" "bastion_notify_sns_access" 
  role       = "$aws_iam_role.bastion_notify_role.name"
  policy_arn = "arn:aws:iam::aws:policy/service-role/AutoScalingNotificationAccessRole"

【讨论】:

以上是关于无法使用 terraform 从自动缩放挂钩创建 sns的主要内容,如果未能解决你的问题,请参考以下文章

在 azure 中使用 terraform 为应用服务创建自动缩放规则时出错

Terraform - 不要等待自动缩放组销毁

Terraform 上的 Azure 应用服务自动缩放错误

Terraform 中的 ECS 服务如何连接到 AWS 自动缩放组

Elastic Beanstalk 自动缩放组生命周期挂钩

Terraform azurerm_application_gateway 配置容量自动缩放设置