繁体   English   中英

使用 terraform 创建 IAM 角色并将其附加到 EC2

[英]Create and attach IAM role to EC2 using terraform

我有一个 terraform 脚本来创建一个实例并为其附加一个角色。

一切都按预期创建。

我面临的问题是正在创建 IAM 角色,并且将策略附加到角色,但角色没有附加到实例 请帮忙。

我有以下 terraform 脚本:

provider "aws" {
  region = "ap-southeast-1"
}

terraform {
  backend "s3" {
    bucket = "example.com"
    key    = "terraform/aws/ec2/xxxNNN/terraform.tfstate"
    region = "ap-southeast-1"
  }
}

resource "aws_iam_policy" "xxx_nodes_role_policy" {
  name        = "xxx_nodes_role_policy"
  description = "IAM Policy for XXX nodes"
  policy      = "${file("xxx_nodes_role_policy.json")}"
}

resource "aws_iam_role" "ec2_role_for_xxx_nodes" {
  name               = "ec2_role_for_xxx_nodes"
  assume_role_policy = "${file("ec2_assumerolepolicy.json")}"
}

resource "aws_iam_role_policy_attachment" "xxx_nodes_role_policy_attachment" {
  role       = "${aws_iam_role.ec2_role_for_xxx_nodes.name}"
  policy_arn = "${aws_iam_policy.xxx_nodes_role_policy.arn}"
}

resource "aws_iam_instance_profile" "xxx_instance_profile" {
  name  = "xxx_instance_profile"
  role = "${aws_iam_role.ec2_role_for_xxx_nodes.name}"
}

variable "sgids" {
  type = list(string)
  default = [ "sg-XXX", "sg-XXX" ]
}

resource "aws_instance" "xxxNNN" {
  ami           = "ami-063e3af9d2cc7fe94"
  instance_type = "r5.large"
  iam_instance_profile = "${aws_iam_instance_profile.xxx_instance_profile.name}"

  availability_zone = "ap-southeast-1a"
  key_name = "KKK"
  vpc_security_group_ids = var.sgids
  subnet_id = "subnet-XXX"
  associate_public_ip_address = false
  user_data = "${file("set-up.sh")}"

  root_block_device {
    volume_type = "gp2"
    volume_size = "200"
    delete_on_termination = true
  }

  tags = {
    Name = "XXXXXXXXXXX/XXXNNN"
  }

  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_eip" "XXXNNN" {
  vpc = true
  instance = "${aws_instance.xxxNNN.id}"

  tags = {
    Name = "XXXNNN"
  }

  lifecycle {
    prevent_destroy = true
  }
}

xxx_nodes_role_policy.json的内容如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-southeast-1:0000:log-group:*",
                "arn:aws:logs:ap-southeast-1:0000:log-group:production:*"
            ]
        }
    ]
}

ec2_assumerolepolicy.json的内容如下:

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

一切都按预期创建。

我面临的问题是正在创建 IAM 角色并且将策略附加到角色,但角色没有附加到实例。 请帮忙。

编辑:在下面添加terraform apply output :

aws_iam_policy.xxx_nodes_role_policy: Refreshing state... [id=arn:aws:iam::XXX:policy/xxx_nodes_role_policy]
aws_iam_role.ec2_role_for_xxx_nodes: Refreshing state... [id=ec2_role_for_xxx_nodes]
data.aws_iam_policy_document.instance-assume-role-policy: Refreshing state...
aws_iam_role_policy_attachment.xxx_nodes_role_policy_attachment: Refreshing state... [id=ec2_role_for_xxx_nodes-20200717102807715700000001]
aws_iam_instance_profile.xxx_instance_profile: Refreshing state... [id=xxx_instance_profile]
aws_instance.xxxNNN: Refreshing state... [id=i-XXX]
aws_eip.XXXNNN: Refreshing state... [id=eipalloc-XXX]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_eip.XXXNNN will be created
  + resource "aws_eip" "XXXNNN" {
      + allocation_id     = (known after apply)
      + association_id    = (known after apply)
      + customer_owned_ip = (known after apply)
      + domain            = (known after apply)
      + id                = (known after apply)
      + instance          = (known after apply)
      + network_interface = (known after apply)
      + private_dns       = (known after apply)
      + private_ip        = (known after apply)
      + public_dns        = (known after apply)
      + public_ip         = (known after apply)
      + public_ipv4_pool  = (known after apply)
      + tags              = {
          + "Name" = "XXXNNN"
        }
      + vpc               = true
    }

  # aws_iam_policy.xxx_nodes_role_policy will be created
  + resource "aws_iam_policy" "xxx_nodes_role_policy" {
      + arn         = (known after apply)
      + description = "IAM Policy for XXX nodes"
      + id          = (known after apply)
      + name        = "xxx_nodes_role_policy"
      + path        = "/"
      + policy      = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = [
                          + "logs:CreateLogStream",
                          + "logs:DescribeLogGroups",
                          + "logs:DescribeLogStreams",
                          + "logs:PutLogEvents",
                        ]
                      + Effect   = "Allow"
                      + Resource = [
                          + "arn:aws:logs:ap-southeast-1:XXX:log-group:*",
                          + "arn:aws:logs:ap-southeast-1:XXX:log-group:production:*",
                        ]
                      + Sid      = "VisualEditor0"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
    }

  # aws_iam_role.ec2_role_for_xxx_nodes will be created
  + resource "aws_iam_role" "ec2_role_for_xxx_nodes" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "ec2.amazonaws.com"
                        }
                      + Sid       = ""
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + max_session_duration  = 3600
      + name                  = "ec2_role_for_xxx_nodes"
      + path                  = "/"
      + unique_id             = (known after apply)
    }

  # aws_iam_role_policy_attachment.xxx_nodes_role_policy_attachment will be created
  + resource "aws_iam_role_policy_attachment" "xxx_nodes_role_policy_attachment" {
      + id         = (known after apply)
      + policy_arn = (known after apply)
      + role       = "ec2_role_for_xxx_nodes"
    }

  # aws_instance.xxxNNN will be created
  + resource "aws_instance" "xxxNNN" {
      + ami                          = "ami-063e3af9d2cc7fe94"
      + arn                          = (known after apply)
      + associate_public_ip_address  = false
      + availability_zone            = "aws-region"
      + cpu_core_count               = (known after apply)
      + cpu_threads_per_core         = (known after apply)
      + get_password_data            = false
      + host_id                      = (known after apply)
      + iam_instance_profile         = "xxx_instance_profile"
      + id                           = (known after apply)
      + instance_state               = (known after apply)
      + instance_type                = "r5.large"
      + ipv6_address_count           = (known after apply)
      + ipv6_addresses               = (known after apply)
      + key_name                     = "key.name"
      + network_interface_id         = (known after apply)
      + outpost_arn                  = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      + primary_network_interface_id = (known after apply)
      + private_dns                  = (known after apply)
      + private_ip                   = (known after apply)
      + public_dns                   = (known after apply)
      + public_ip                    = (known after apply)
      + security_groups              = (known after apply)
      + source_dest_check            = true
      + subnet_id                    = "subnet-XXX"
      + tags                         = {
          + "Name" = "XXXNNN"
        }
      + tenancy                      = (known after apply)
      + user_data                    = "060b3d9c8929ff0f18bdd9fa151f5d982c256a78"
      + volume_tags                  = (known after apply)
      + vpc_security_group_ids       = [
          + "sg-XXX",
          + "sg-XXX",
        ]

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = true
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = 200
          + volume_type           = "gp2"
        }
    }

Plan: 5 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_iam_policy.xxx_nodes_role_policy: Creating...
aws_iam_role.ec2_role_for_xxx_nodes: Creating...
aws_instance.xxxNNN: Creating...
aws_iam_role.ec2_role_for_xxx_nodes: Creation complete after 3s [id=ec2_role_for_xxx_nodes]
aws_iam_policy.xxx_nodes_role_policy: Creation complete after 4s [id=arn:aws:iam::XXX:policy/xxx_nodes_role_policy]
aws_iam_role_policy_attachment.xxx_nodes_role_policy_attachment: Creating...
aws_iam_role_policy_attachment.xxx_nodes_role_policy_attachment: Creation complete after 2s [id=ec2_role_for_xxx_nodes-20200717110045184300000001]
aws_instance.xxxNNN: Still creating... [10s elapsed]
aws_instance.xxxNNN: Still creating... [20s elapsed]
aws_instance.xxxNNN: Creation complete after 22s [id=i-XXX]
aws_eip.XXXNNN: Creating...
aws_eip.XXXNNN: Creation complete after 3s [id=eipalloc-XXX]

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

通过与其他人的讨论,我能够自己解决这个问题。

RCA(根本原因分析)

因此,问题是第一次运行terraform apply时,创建了一个实例配置文件,但可能不是因为 IAM 权限不足,IAM 角色无法附加到 IAM 实例配置文件。 terraform apply的所有后续执行中,terraform 正在使用已经存在的实例配置文件(可能是因为我没有授予 terraform 用户销毁权限)。

我是怎么发现的

这是一件被忽视的简单事情。 如果您在问题中计算我的 terraform 脚本中的资源数量,您会看到定义的资源数量为 6,而在 output 中,terraform 总是响应:

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

这就是我认为可能永远不会删除实例配置文件的方式。

通过 AWS CLI 从 IAM 中删除实例配置文件,然后重新执行terraform apply修复了此问题。

IAM权限可以参考: https://iam.cloudonaut.io/reference/iam.html

在此 URL的页面上进行查找并搜索InstanceProfile并将所需的权限添加到您的 terraform 用户。 我把它们都加了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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