首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Terraform状态-更改资源位置

Terraform状态-更改资源位置
EN

Stack Overflow用户
提问于 2021-11-01 17:24:07
回答 1查看 49关注 0票数 0

在我们的一个账户中,很久以前就创建了AWS私有子网。没有匹配的公有子网,这些私有子网中也没有资源。因此,下面的aws_subnet.private_subnets[0]aws_subnet.private_subnets[1]是空子网

代码语言:javascript
复制
aws_subnet.private_subnets[0]
aws_subnet.private_subnets[1]
aws_subnet.private_subnets[2]
aws_subnet.private_subnets[3]
aws_subnet.private_subnets[4]

子网是使用terrform创建的,如下所示:

代码语言:javascript
复制
 resource "aws_subnet" "private_subnets" {
      count      = length(split(",", var.private_subnets))
      cidr_block = element(split(",", var.private_subnets), count.index)

其中var.private_subnets是包含5个不同CIDR块的字符串。

我想要整理它,但我尝试从字符串中删除前两个CIDR块,但它仍然试图重新创建它们,因为它想要更改:

aws_subnet.private_subnets[2]aws_subnet.private_subnets[0]

aws_subnet.private_subnets[3]aws_subnet.private_subnets[1]

aws_subnet.private_subnets[4]aws_subnet.private_subnets[2]

我不希望这种情况发生,因为那样我就需要在新的子网中重新部署我们所有的EC2s。那么解决这个问题的最好方法是什么呢?是否要将它们从状态中删除,方法是:

terraform state rm aws_subnet.private_subnets[0]

然后使用以下命令更改它们:

terraform state mv 'aws_subnet.private_subnets[2]' 'aws_subnet.private_subnets[0]'

我没有太多的工作与国家和打破这可能会导致很多问题,所以我只是想确定。或者更好的方法是在AWS中手动删除它们,然后再次运行terraform?-我不确定这是否会导致与当前相同的问题

EN

回答 1

Stack Overflow用户

发布于 2021-11-03 01:10:36

如果你改变源集合的方式会影响到哪些对象属于哪些索引,那么你确实需要使用像terraform state mv这样的策略来向Terraform解释索引分配是如何改变的。

在你的例子中,看起来是这样的:

代码语言:javascript
复制
terraform state rm 'aws_subnet.private_subnets[0]'
terraform state rm 'aws_subnet.private_subnets[1]'
terraform state mv 'aws_subnet.private_subnets[2]' 'aws_subnet.private_subnets[0]'
terraform state mv 'aws_subnet.private_subnets[3]' 'aws_subnet.private_subnets[1]'
terraform state mv 'aws_subnet.private_subnets[4]' 'aws_subnet.private_subnets[2]'

这些操作的顺序很重要,因为Terraform无法跟踪同一地址上的两个不同对象,因此在将另一个实例移动到目标索引之前,我们需要始终释放目标索引。

这里的var.private_subnets似乎是一个字符串,其中包含以逗号分隔的CIDR块列表。在现代Terraform中,最好将其声明为一组字符串--这样每个CIDR块就是一个单独的元素--然后使用for_each而不是count,这样Terraform将通过CIDR块字符串本身来跟踪实例,而不是通过它们在列表中的任意位置来跟踪实例。

代码语言:javascript
复制
variable "private_subnets" {
  type = set(string)
}

resource "aws_subnet" "private_subnets" {
  for_each = var.private_subnets

  cidr_block = each.value
}

此更改还需要使用terraform state mv进行一些迁移工作,因此,既然您无论如何都要做这些工作,那么在同一时间进行此更改可能是有益的,从而避免为了达到现代习惯用法而进行两次迁移。

您的问题中没有包含CIDR地址的实际值,因此我将假定顺序地址为10.x.0.0/16,其中"x“与索引相同。在该方案下,您的迁移将看起来像这样:

代码语言:javascript
复制
terraform state rm 'aws_subnet.private_subnets[0]'
terraform state rm 'aws_subnet.private_subnets[1]'
terraform state mv 'aws_subnet.private_subnets[2]' 'aws_subnet.private_subnets["10.2.0.0/16"]'
terraform state mv 'aws_subnet.private_subnets[3]' 'aws_subnet.private_subnets["10.3.0.0/16"]'
terraform state mv 'aws_subnet.private_subnets[4]' 'aws_subnet.private_subnets["10.4.0.0/16"]'

请注意,在这种情况下,新地址的实例键是包含实际CIDR前缀的字符串,而不是列表中的整数位置。

这意味着它们不再有任何固有的顺序,Terraform将理解,如果您向集合中添加新的东西,这意味着创建一个新的子网,如果您从集合中删除一项,则意味着删除相应的子网。如果将来删除CIDR前缀,则在执行此一次性迁移后,您将不需要使用terraform state mv来修复位置,因为它们不再具有特定的位置。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69800470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档