Terraform应用程序在没有更改的地方检测更改



我有一个Terraform模块,可以在同事需要时在AWS上部署实例。对于我部署的每个人:

  1. ec2实例
  2. 弹性IP
  3. 私人安全组

为了集中一切,我对模块进行了如下组织:

.
├── README.md
├── coworker1
│   ├── main.tf
│   └── variables.tf
├── keys
├── coworker2
│   ├── main.tf
│   └── variables.tf
├── templates
│   ├── cloud-init.tpl
│   ├── pubkey_rsa.pub
│   └── strat.json
├── terraform.tf
├── terraform.tfstate
└── terraform.tfstate.backup

我在根模块中使用teraform.tf文件,并使用模块块进行引用子模块。

module "corworker1" {
source = "./coworker1"
}

我从根模块运行terraform apply,并且正确创建了它的资源。然而,当我运行另一个terraform apply时,它说由于更改,它将需要重新创建实例并修改弹性ip。即使我什么都没改变。

# module.coworker1.aws_instance.ec2_instance must be replaced
-/+ resource "aws_instance" "ec2_instance" {
~ arn                                  = "arn:aws:ec2:eu-central-1:XXXXX:instance/i-0f498ac75ad66199e" -> (known after apply)
~ associate_public_ip_address          = true -> (known after apply)
~ cpu_core_count                       = 1 -> (known after apply)
~ cpu_threads_per_core                 = 1 -> (known after apply)
- disable_api_termination              = false -> null
- ebs_optimized                        = false -> null
- hibernation                          = false -> null
+ host_id                              = (known after apply)
~ id                                   = "i-0f498ac75ad66199e" -> (known after apply)
~ instance_initiated_shutdown_behavior = "stop" -> (known after apply)
~ instance_state                       = "running" -> (known after apply)
~ ipv6_address_count                   = 0 -> (known after apply)
~ ipv6_addresses                       = [] -> (known after apply)
+ key_name                             = (known after apply)
- monitoring                           = false -> null
+ outpost_arn                          = (known after apply)
+ password_data                        = (known after apply)
+ placement_group                      = (known after apply)
~ primary_network_interface_id         = "eni-06debade3df83944b" -> (known after apply)
~ private_dns                          = "ip-172-31-12-126.eu-central-1.compute.internal" -> (known after apply)
~ private_ip                           = "172.31.12.126" -> (known after apply)
~ public_dns                           = "ec2-3-67-119-191.eu-central-1.compute.amazonaws.com" -> (known after apply)
~ public_ip                            = "3.67.119.191" -> (known after apply)
~ secondary_private_ips                = [] -> (known after apply)
~ security_groups                      = [
- "ec2 coworker1.example.com",
] -> (known after apply)
~ subnet_id                            = "subnet-3e48ca72" -> (known after apply)
tags                                 = {
"HiddenName" = "coworker1"
"Name"       = "coworker1.example.com"
"Operator"   = "coworker1@example.com"
}
~ tenancy                              = "default" -> (known after apply)
# (9 unchanged attributes hidden)
~ capacity_reservation_specification {
~ capacity_reservation_preference = "open" -> (known after apply)
+ capacity_reservation_target {
+ capacity_reservation_id = (known after apply)
}
}
- credit_specification {
- cpu_credits = "standard" -> null
}
+ ebs_block_device { # forces replacement
+ delete_on_termination = true
+ device_name           = "/dev/sda1"
+ encrypted             = (known after apply)
+ iops                  = (known after apply)
+ kms_key_id            = (known after apply)
+ snapshot_id           = (known after apply)
+ throughput            = (known after apply)
+ volume_id             = (known after apply)
+ volume_size           = 200
+ volume_type           = (known after apply)
}
- ebs_block_device { # forces replacement
- delete_on_termination = true -> null
- device_name           = "/dev/sda1" -> null
- encrypted             = false -> null
- iops                  = 600 -> null
- snapshot_id           = "snap-0d8c6e92a59dec0c9" -> null
- tags                  = {} -> null
- throughput            = 0 -> null
- volume_id             = "vol-007f3d2d27b510740" -> null
- volume_size           = 200 -> null
- volume_type           = "gp2" -> null
}
~ enclave_options {
~ enabled = false -> (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               = "enabled" -> (known after apply)
~ http_put_response_hop_limit = 1 -> (known after apply)
~ http_tokens                 = "optional" -> (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 -> (known after apply)
~ device_name           = "/dev/sda1" -> (known after apply)
~ encrypted             = false -> (known after apply)
~ iops                  = 600 -> (known after apply)
+ kms_key_id            = (known after apply)
~ tags                  = {} -> (known after apply)
~ throughput            = 0 -> (known after apply)
~ volume_id             = "vol-007f3d2d27b510740" -> (known after apply)
~ volume_size           = 200 -> (known after apply)
~ volume_type           = "gp2" -> (known after apply)
}
}

这是子模块的文件main.tf

data "aws_ami" "ubuntu" {
owners = ["amazon"]
filter {
name   = "name"
values = ["Deep Learning Base AMI (Ubuntu 18.04) Version 38.0"]
}
}
resource "aws_eip" "lb" {
instance = aws_instance.ec2_instance.id
vpc      = true
}
resource "aws_security_group" "instance_private_group" {
description = "Private security group for the ${var.username}.example.com instance"
name        = "ec2 ${var.username}.example.com"
vpc_id      = data.aws_vpc.debian-ec2-env.id
ingress {
description = "description"
protocol    = "TCP"
from_port   = 22
to_port     = 22
cidr_blocks = ["XX.XX.XX.XX/32"]
}
}
data "aws_vpc" "debian-ec2-env" {
id = var.vpc_id
}
data "aws_iam_instance_profile" "instance_profile" {
name  = var.instance_profile_name
}
resource "aws_instance" "ec2_instance" {
ami                    = data.aws_ami.ubuntu.id
instance_type          = var.instance_type
vpc_security_group_ids = [aws_security_group.instance_private_group.id]
availability_zone      = var.az
iam_instance_profile   = data.aws_iam_instance_profile.instance_profile.name 
user_data              = templatefile("${path.root}/templates/cloud-init.tpl", { username = var.username, admins = var.admins })
ebs_block_device {
device_name = "/dev/sda1"
volume_size = var.storage_size
}
tags = {
Name       = "${var.username}.example.com"
HiddenName = var.username
Operator   = "${var.username}@example.com"
}
}

你认为这是什么原因造成的?

编辑1:

在调整了一些日志记录后,我试图重新运行应用程序,以减少阻止我看到重要细节的日志记录量。用户数据似乎没有更改。但我现在看到的是:

Note: Objects have changed outside of Terraform
Terraform detected the following changes made outside of Terraform since the last "terraform apply":
# module.coworker1.aws_eip.lb has been changed
~ resource "aws_eip" "lb" {
id                   = "eipalloc-52f1ee6c"
+ tags                 = {}
# (12 unchanged attributes hidden)
}
# module.coworker1.aws_instance.ec2_instance has been changed
~ resource "aws_instance" "ec2_instance" {
id                                   = "i-0f498ac75ad66199e"
~ public_dns                           = "ec2-18-197-141-73.eu-central-1.compute.amazonaws.com" -> "ec2-3-67-119-191.eu-central-1.compute.amazonaws.com"
~ public_ip                            = "18.197.141.73" -> "3.67.119.191"
tags                                 = {
"HiddenName" = "coworker1"
"Name"       = "coworker1.example.com"
"Operator"   = "coworker1@example.com"
}
# (28 unchanged attributes hidden)



# (6 unchanged blocks hidden)
}

因此,如果我正确理解,在创建Elastic IP后,公共IP会发生变化,这会导致与Terraform显示的结果不同。我应该在ec2实例上依赖Elastic IP吗?

我认为在您的示例中有两类不同的令人惊讶的行为:

  1. EC2实例的IP地址和主机名在运行后发生了更改
  2. 提供者报告说,tags从未设置变为设置为空映射,尽管未设置和空映射对该参数的意义相同

你的问题的其余部分表明你主要对其中的第一个感兴趣,所以我将在这里重点讨论这一点。

这种情况的关键在于,在创建了一个EC2实例后,将一个Elastic IP附加到该实例会导致EC2 API开始将该Elastic IP及其相关的主机名报告为public_ippublic_dns。这意味着,尽管这些值在技术上并不是"零";Terraform之外的变化";,它们在CCD_ 7的定义之外进行了更改,因为对IP地址的更改发生在EC2 API报告实例已成功创建之后。

不幸的是,这种更改public_ip的行为是在EC2实例启动后将弹性IP地址附加到EC2实例的基本行为。这是作为public_ip文档的一部分提到的,因此这里来自Terraform的消息实际上只是加强了文档中的警告。如果您实际上没有在模块中的任何其他地方使用aws_instance.ec2_instance.public_ip,那么这种值的更改是无害的,您可以将其视为Terraform只是更正其自己的IP地址记录。接受包含此消息的计划后,应将更新后的值提交给新的Terraform状态快照,并且除非您稍后分离弹性IP地址,否则不会再次报告更改。

相关内容

  • 没有找到相关文章

最新更新