Terraform 似乎没有接受手动更改

Terraform doesn't seem to pick up manual changes

我有一个非常令人沮丧的 Terraform 问题,我对我的 Terraform 脚本做了一些更改,但在我应用该计划时失败了。我经历了很多阴谋,可能使情况变得更糟,因为我最终手动删除了一堆 AWS 资源以试图解决这个问题。
所以现在我根本无法使用 Terraform(刷新、计划、销毁)都得到相同的错误。

情况

我有一个 Fargate 服务列表,以及一组关联 Fargate 服务不同功能的映射,例如负载均衡器的“目标组”(我在下面提供了一些代码)。问题似乎是 Terraform 没有发现这些资源已被手动删除,或者因为它们不存在而变得混乱。此时如果我 运行 一个 刷新、计划或销毁 我得到一个错误,指出一个特定的列表是空的,即使它不是(或不应该是) .
在失败的 运行 中,我在下面的列表中添加了一个新服务以及一个新的 url(见下面的代码)

Objective

然而,在这一点上,我会满足于破坏整个环境(它是我的开发环境);理想情况下,我只想让系统正常工作,这样 Terraform 就会检测到更改并正常工作。

Terraform 脚本有效

我已将我的 Terraform 脚本恢复到最后一个已知的良好版本。我有 运行 针对我们的暂存环境的好版本,它工作正常。

配置信息

MacOS Mojave 10.14.6 (18G103)

Terraform v0.12.24.

  • provider.archive v1.3.0
  • provider.aws v2.57.0
  • provider.random v2.2.1
  • provider.template v2.1.2

The Terraform state file is being stored in a S3 bucket, and terraform init --reconfigure has been called.

我做了什么

我最初遇到了类似的错误,但它在不同的位置,经过数小时的谷歌搜索和尝试(我没有写下来)我决定手动删除与有问题的代码相关的 AWS 资源( ALB、目标组、安全组)

Terraform 脚本示例

不幸的是,我不能 post 实际的脚本,因为它是私有的,但我已经 post 编辑了我认为相关的部分,但编辑了一些信息。我提到这一点的原因是,您可能看到的任何语法类型错误都是由这种修订引起的,正如我上面所说的,当我们的暂存环境中 运行 时脚本工作正常。

globalvars.tf

在根目录中。对于失败的 Terraform 运行,我在 service_names (edd = "edd") 列表中添加了一个新名称(我添加为第一个元素)。在 service_name_map_2_url 中,我添加了新条目 (edd = "edd") 作为最后一个条目。我不确定我在不同 'order' 中添加这些元素是否是问题所在,尽管它确实不应该,因为我是通过名称而不是索引

访问地图的
variable "service_names" {
  type = list(string)
  description = "This is a list/array of the images/services for the cluster"
  default = [
    "alert",
    "alert-config"
  ]
}

variable service_name_map_2_url {
  type = map(string)
  description = "This map contains the base URL used for the service"
  default = {
    alert = "alert"
    alert-config = "alert-config"
  }
}

alb.tf

modules/alb。在此模块中,我们创建一个 ALB,然后为每个服务创建一个目标组,如下所示。 globalvars.tf 中的项目被传递到此脚本中

locals {
  numberOfServices = length(var.service_names)
}

resource "aws_alb" "orchestration_alb" {
  name = "orchestration-alb"
  subnets = var.public_subnet_ids
  security_groups = [var.alb_sg_id]

  tags = {
    environment = var.environment
    group       = var.tag_group_name
    app         = var.tag_app_name
    contact     = var.tag_contact_email
  }
}

resource "aws_alb_target_group" "orchestration_tg" {
  count = local.numberOfServices
  name = "${var.service_names[count.index]}-tg"
  port = 80
  protocol = "HTTP"
  vpc_id = var.vpc_id
  target_type = "ip"
  deregistration_delay = 60
  tags = {
    environment = var.environment
    group       = var.tag_group_name
    app         = var.tag_app_name
    contact     = var.tag_contact_email
  }
  health_check {

        path = "/${var.service_name_map_2_url[var.service_names[count.index]]}/health"
        port = var.app_port
        protocol = "HTTP"
        healthy_threshold = 2
        unhealthy_threshold = 5
        interval = 30
        timeout = 5
        matcher = "200-308"
    }
}

output.tf

这是 alb.tf 的输出,输出了其他内容,但这是对这个问题重要的内容

output "target_group_arn_suffix" {
  value = aws_alb_target_group.orchestration_tg.*.arn_suffix
}

cloudwatch.tf

modules/cloudwatch。我尝试创建一个仪表板

data "template_file" "Dashboard" {
  template = file("${path.module}/dashboard.json.template")
  vars = {
  ...
   alert-tg = var.target_group_arn_suffix[0]
   alert-config-tg = var.target_group_arn_suffix[1]
   edd-cluster-name = var.ecs_cluster_name
   alb-arn-suffix = var.alb-arn-suffix
  }
}

错误

当我 运行 terraform refresh (或计划或销毁)时,我收到以下错误(我也收到与警报配置相同的错误)

Error: Invalid index

  on modules/cloudwatch/cloudwatch.tf line 146, in data "template_file" "Dashboard":
 146:     alert-tg = var.target_group_arn_suffix[0]
    |----------------
    | var.target_group_arn_suffix is empty list of string

The given key does not identify an element in this collection value.

AWS 环境

我已经手动删除了 ALBDashboard 和所有 Target Groups。我希望(这在过去有效)Terraform 会检测到这一点并适当地更新它的状态文件,这样当 运行 宁一个 计划 它会知道它必须创建 ALB 和目标组。

谢谢

Terraform 相信其状态是唯一的真实来源。在存在手动更改的情况下使用 Terraform 是可能的,但存在问题。

如果您手动删除基础架构,则需要在手动删除的资源上运行 terraform state rm [resource path]

Gruntwork has what they call The Golden Rule of Terraform:

The master branch of the live repository should be a 1:1 representation of what’s actually deployed in production.