使用 terraform 创建 IAM 角色并将其附加到 EC2
Posted
技术标签:
【中文标题】使用 terraform 创建 IAM 角色并将其附加到 EC2【英文标题】:Create and attach IAM role to EC2 using terraform 【发布时间】:2020-11-07 05:05:44 【问题描述】:我有一个 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
输出:
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.
【问题讨论】:
apply的相关输出是什么? @MattSchuchard 添加到问题本身 【参考方案1】:通过与其他人的讨论,我自己解决了这个问题。
RCA(根本原因分析)
因此,问题在于第一次运行 terraform apply
时,创建了一个实例配置文件,但可能不是因为 IAM 权限不足,IAM 角色无法附加到 IAM 实例配置文件。在terraform apply
的所有后续执行中,terraform 正在使用已经存在的实例配置文件(可能是因为我没有授予 terraform 用户销毁权限)。
我是如何发现的
这是一件被忽视的简单事情。如果您在问题中计算我的 terraform 脚本中的资源数量,您会看到定义的资源数量为 6,而在输出中,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 用户。我都添加了。
【讨论】:
@HelderSepulveda 我发布答案只是因为我自己问了这个问题,并且觉得可能会有人处于类似情况。如果版主觉得这篇文章不值得发,我会敦促他们删除这篇文章。 您的评论很清楚 6 个资源输出显示添加了 5 个...是的,您显然忽略了一个简单的事情 堆栈溢出特别是encourages answering your own question。以上是关于使用 terraform 创建 IAM 角色并将其附加到 EC2的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Terraform 创建没有代入角色策略的 AWS IAM 角色?
Terraform aws_iam_role_policy 中的 JSON 语法错误