Мы сталкиваемся с проблемой зависимостей, когда используем блок данных в исходных модулях terraform. Пример: Предположим, у нас есть VPC, подсеть и Cloudwatch. Если мы вносим незначительные изменения (изменение Retention_days) в Amazon Cloudwatch приводит к воссозданию VPC и подсети. В нашем случае VPC зависит от Cloudwatch (поскольку блок cloud_watch_log_group в VPC (vpc_flow_log) требует имени CloudWatch), а подсеть зависит от VPC (из-за идентификатора vpc, используемого в подсети).
Поэтому всякий раз, когда в Cloudwatch происходят незначительные изменения, он принудительно заменяет vpc-flowlog, из-за чего vpc воссоздан, что приводит к тому, что подсеть также будет воссоздана.
Мы сталкиваемся с этой проблемой, особенно когда используем блок данных для обработки зависимости независимо от какого-либо поставщика.
Пожалуйста, дайте мне знать для получения дополнительной информации по этому вопросу.
Если мы удалим блок данных в исходных модулях, это даст ожидаемый результат. Мы также пытались обновить версии terraform и поставщика, но ничего не решило нашу проблему.
main.tf
module "cloudwatch" {
for_each = var.Amazon_CloudWatch
source = "./source_modules/cloudwatch"
cloud_watch_group_name = each.value["cloud_watch_group_name"]
retention_days = each.value["retention_days"]
}
module "vpc" {
for_each = var.AWS_VPC_Virtual_Private_Cloud
source = "./source_modules/vpc"
vpc_name = each.value["vpc_name"]
data_cloud_watch_name = each.value["data_cloud_watch_name"]
vpc_cidr = each.value["vpc_cidr"]
depends_on = [module.cloudwatch]
}
module "subnet" {
for_each = var.AWS_Subnet
source = "./source_modules/subnet"
subnet_cidr = each.value["subnet_cidr"]
subnet_name = each.value["subnet_name"]
data_vpc_name = each.value["data_vpc_name"]
depends_on=[module.vpc]
}
source_modules/vpc/main.tf
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = var.vpc_name
}
}
resource "aws_iam_role" "example" {
name = "example111"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
resource "aws_iam_role_policy" "example" {
name = "example111"
role = aws_iam_role.example.id
policy = data.aws_iam_policy_document.example.json
}
resource "aws_flow_log" "example" {
iam_role_arn = aws_iam_role.example.arn
log_destination = data.aws_cloudwatch_log_group.test_clg.arn
traffic_type = "ALL"
vpc_id = aws_vpc.main.id
}
source_modules/vpc/variables.tf
variable "data_cloud_watch_name" {
type = string
}
variable "vpc_name" {
type = string
}
variable "vpc_cidr" {
type = string
}
source_modules/vpc/data.tf
data "aws_cloudwatch_log_group" "test_clg" {
name = var.data_cloud_watch_name
}
data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["vpc-flow-logs.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
data "aws_iam_policy_document" "example" {
statement {
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
]
resources = ["*"]
}
}
source_modules/подсеть/main.tf
resource "aws_subnet" "main" {
vpc_id = data.aws_vpc.vpcid.id
cidr_block = var.subnet_cidr
tags = {
Name = var.subnet_name
}
}
source_modules/подсеть/data.tf
data "aws_vpc" "vpcid" {
tags = {
Name=var.data_vpc_name
}
}
source_modules/subnet/variables.tf
variable "subnet_cidr" {
type = string
}
variable "subnet_name" {
type = string
}
variable "data_vpc_name" {
type = string
}
source_modules/cloudwatch/main.tf
resource "aws_cloudwatch_log_group" "test" {
name = var.cloud_watch_group_name
retention_in_days = var.retention_days
}
source_modules/cloudwatch/variables.tf
variable "cloud_watch_group_name" {
type = string
}
variable "retention_days" {
type = number
}
**Terraform Plan Results**
terraform plan
module.cloudwatch["logging_01"].aws_cloudwatch_log_group.test: Refreshing state... [id=testdataissuecwg1211q]
module.vpc["vpc_01"].aws_vpc.main: Refreshing state... [id=vpc-0dba4643e6f19061a]
module.vpc["vpc_01"].aws_iam_role.example: Refreshing state... [id=stackissue1qw]
module.vpc["vpc_01"].aws_iam_role_policy.example: Refreshing state... [id=stackissue1qw:stackissue1qw]
module.vpc["vpc_01"].aws_flow_log.example: Refreshing state... [id=fl-0bf918ffe07281dd4]
module.subnet["subnet_01"].aws_subnet.main: Refreshing state... [id=subnet-0ec569f1c4cb9ef15]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
~ update in-place
-/+ destroy and then create replacement
<= read (data resources)
Terraform will perform the following actions:
# module.cloudwatch["logging_01"].aws_cloudwatch_log_group.test will be updated in-place
~ resource "aws_cloudwatch_log_group" "test" {
id = "testdataissuecwg1211q"
name = "testdataissuecwg1211q"
~ retention_in_days = 30 -> 60
tags = {}
# (4 unchanged attributes hidden)
}
# module.subnet["subnet_01"].data.aws_vpc.vpcid will be read during apply
# (depends on a resource or a module with changes pending)
<= data "aws_vpc" "vpcid" {
+ arn = (known after apply)
+ cidr_block = (known after apply)
+ cidr_block_associations = (known after apply)
+ default = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_dns_hostnames = (known after apply)
+ enable_dns_support = (known after apply)
+ enable_network_address_usage_metrics = (known after apply)
+ id = (known after apply)
+ instance_tenancy = (known after apply)
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ state = (known after apply)
+ tags = {
+ "Name" = "testvpc0111"
}
}
# module.subnet["subnet_01"].aws_subnet.main must be replaced
-/+ resource "aws_subnet" "main" {
~ arn = "arn:aws:ec2:us-east-1:************:subnet/subnet-0ec569f1c4cb9ef15" -> (known after apply)
~ availability_zone = "us-east-1c" -> (known after apply)
~ availability_zone_id = "use1-az4" -> (known after apply)
- enable_lni_at_device_index = 0 -> null
~ id = "subnet-0ec569f1c4cb9ef15" -> (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
- map_customer_owned_ip_on_launch = false -> null
~ owner_id = "************" -> (known after apply)
~ private_dns_hostname_type_on_launch = "ip-name" -> (known after apply)
tags = {
"Name" = "testdatasnet1"
}
~ vpc_id = "vpc-0dba4643e6f19061a" # forces replacement -> (known after apply) #
forces replacement
# (8 unchanged attributes hidden)
}
# module.vpc["vpc_01"].data.aws_cloudwatch_log_group.test_clg will be read during apply
# (depends on a resource or a module with changes pending)
<= data "aws_cloudwatch_log_group" "test_clg" {
+ arn = (known after apply)
+ creation_time = (known after apply)
+ id = (known after apply)
+ kms_key_id = (known after apply)
+ log_group_class = (known after apply)
+ name = "testdataissuecwg1211q"
+ retention_in_days = (known after apply)
+ tags = (known after apply)
}
# module.vpc["vpc_01"].data.aws_iam_policy_document.assume_role will be read during apply
# (depends on a resource or a module with changes pending)
<= data "aws_iam_policy_document" "assume_role" {
+ id = (known after apply)
+ json = (known after apply)
+ statement {
+ actions = [
+ "sts:AssumeRole",
]
+ effect = "Allow"
+ principals {
+ identifiers = [
+ "vpc-flow-logs.amazonaws.com",
]
+ type = "Service"
}
}
}
# module.vpc["vpc_01"].data.aws_iam_policy_document.example will be read during apply
# (depends on a resource or a module with changes pending)
<= data "aws_iam_policy_document" "example" {
+ id = (known after apply)
+ json = (known after apply)
+ statement {
+ actions = [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:DescribeLogGroups",
+ "logs:DescribeLogStreams",
+ "logs:PutLogEvents",
]
+ effect = "Allow"
+ resources = [
+ "*",
]
}
}
# module.vpc["vpc_01"].aws_flow_log.example must be replaced
-/+ resource "aws_flow_log" "example" {
~ arn = "arn:aws:ec2:us-east-1:************:vpc-flow-log/fl-0bf918ffe07281dd4" -> (known after apply)
~ id = "fl-0bf918ffe07281dd4" -> (known after apply)
~ log_destination = "arn:aws:logs:us-east-1:************:log-group:testdataissuecwg1211q" # forces replacement -> (known after apply) # forces replacement
~ log_format = "${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}" -> (known after apply)
~ log_group_name = "testdataissuecwg1211q" -> (known after apply)
- tags = {} -> null
~ tags_all = {} -> (known after apply)
# (5 unchanged attributes hidden)
}
# module.vpc["vpc_01"].aws_iam_role.example will be updated in-place
~ resource "aws_iam_role" "example" {
~ assume_role_policy = jsonencode(
{
- Statement = [
- {
- Action = "sts:AssumeRole"
- Effect = "Allow"
- Principal = {
- Service = "vpc-flow-logs.amazonaws.com"
}
},
]
- Version = "2012-10-17"
}
) -> (known after apply)
id = "stackissue1qw"
name = "stackissue1qw"
tags = {}
# (8 unchanged attributes hidden)
# (1 unchanged block hidden)
}
# module.vpc["vpc_01"].aws_iam_role_policy.example will be updated in-place
~ resource "aws_iam_role_policy" "example" {
id = "stackissue1qw:stackissue1qw"
name = "stackissue1qw"
~ policy = jsonencode(
{
- Statement = [
- {
- Action = [
- "logs:PutLogEvents",
- "logs:DescribeLogStreams",
- "logs:DescribeLogGroups",
- "logs:CreateLogStream",
- "logs:CreateLogGroup",
]
- Effect = "Allow"
- Resource = "*"
},
]
- Version = "2012-10-17"
}
) -> (known after apply)
# (1 unchanged attribute hidden)
}
Plan: 2 to add, 3 to change, 2 to destroy.
Здесь будет полезен минимальный пример.
Добавлен исходный код. Пожалуйста, дайте мне знать, если потребуется какая-либо дополнительная информация по этому поводу.
@MalathiDhandapani, не могли бы вы поделиться результатами плана, когда вы меняете параметр дней хранения?
Добавлены результаты плана. Не могли бы вы проверить и сообщить мне?
Вероятно, это из-за depend_on, вам лучше использовать ссылку на выражение, просто используйте, например, вместо данных data_vpc_name, сделайте
module.vpc.vpc_name
то же самое и с облачными часами.
из документов Hashicorp:
Вам следует использовать depend_on в крайнем случае, поскольку это может привести к Терраформируйте, чтобы создавать более консервативные планы, заменяющие ресурсы, чем необходимо. Например, Terraform может обрабатывать больше значений. как неизвестное «(известно после применения)», поскольку неизвестно, какие изменения произойдет на вышестоящем объекте. Это особенно вероятно, когда вы используйте depend_on для модулей.
Вместо depend_on мы рекомендуем использовать ссылки на выражения для подразумевайте зависимости, когда это возможно. Ссылки на выражения позволяют Terraform понять, из какой ценности исходит ссылка, и избегать планирования изменяется, если это конкретное значение не изменилось, даже если другие части вышестоящего объекта запланированы изменения.
https://developer.hashicorp.com/terraform/language/meta-arguments/dependents_on
Можете ли вы добавить код, который у вас есть, к вопросу?