首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

Terraform中的for_each和count

编程知识
2024年08月22日 19:09

通过Terraform创建云主机时,在某些业务场景下,一个机器需要挂载多个云盘,一般云厂商都是单独创建云主机和云硬盘然后通过attachment的资源去挂载,因此我们的模板大致如下:

resource "tencentcloud_instance" "basic" {
  instance_name     = var.instance_name
  password = "xxx"
}

resource "tencentcloud_cbs_storage" "storage" {
  for_each          = var.data_disks
  storage_name      = each.key
  storage_type      = each.value.disk_type
  storage_size      = each.value.size
}

resource "tencentcloud_cbs_storage_attachment" "attachment" {
  count       = length(tencentcloud_cbs_storage.storage)
  storage_id  = element(values(tencentcloud_cbs_storage.storage)[*].id, count.index)
  instance_id = tencentcloud_instance.basic.id
}


variable "data_disks" {
  type = map(object({
    disk_type = string
    size      = number
  }))
  description = "Instance Data Disks"
  default     = {}
}

这个模板我们一直用了很久,完全满足多盘的需求,也具有一定灵活性,但是随着全方位降本的需求,在服务优化等措施下,业务方评估可以考虑减少云盘数量,因为机型的特殊性,机器也不能回收重新创建。

因为之前一直没有减盘的场景,所以一直没关注,直到最近业务方评估需要减盘,发现在减盘时盘的attachment会销毁重新创建,腾讯云这个资源的操作会伴随unmount动作,导致减盘之后盘没有被挂载上

这个现象是不在我的预期当中的,分析Terraform的日志:

  # tencentcloud_cbs_storage_attachment.attachment[0] must be replaced
-/+ resource "tencentcloud_cbs_storage_attachment" "attachment" {
      ~ id          = "disk-mcklmp5z" -> (known after apply)
      ~ storage_id  = "disk-mcklmp5z" -> "disk-rspjpenh" # forces replacement
        # (1 unchanged attribute hidden)
    }

  # tencentcloud_cbs_storage_attachment.attachment[1] must be replaced
-/+ resource "tencentcloud_cbs_storage_attachment" "attachment" {
      ~ id          = "disk-rspjpenh" -> (known after apply)
      ~ storage_id  = "disk-rspjpenh" -> "disk-k9c5lg1v" # forces replacement
        # (1 unchanged attribute hidden)
    }

  # tencentcloud_cbs_storage_attachment.attachment[2] must be replaced
-/+ resource "tencentcloud_cbs_storage_attachment" "attachment" {
      ~ id          = "disk-k9c5lg1v" -> (known after apply)
      ~ storage_id  = "disk-k9c5lg1v" -> "disk-jl5g1u7f" # forces replacement
        # (1 unchanged attribute hidden)
    }

  # tencentcloud_cbs_storage_attachment.attachment[3] must be replaced
-/+ resource "tencentcloud_cbs_storage_attachment" "attachment" {
      ~ id          = "disk-jl5g1u7f" -> (known after apply)
      ~ storage_id  = "disk-jl5g1u7f" -> "disk-mytvnnif" # forces replacement
        # (1 unchanged attribute hidden)
    }

发现attachment的索引是index,减盘的时候索引会重新计算,这就是attachment资源被销毁重建,导致云盘被卸载的原因。

原因明确了,那就好解决了,可以用for_each来解决这个问题,如下:

resource "tencentcloud_cbs_storage_attachment" "attachment" {
  for_each = toset(values(tencentcloud_cbs_storage.storage)[*].id)
  storage_id  = each.key
  instance_id = tencentcloud_instance.foo.id
}

事情往往没那么顺利:

│ Error: Invalid for_each argument
│
│   on main.tf line 61, in resource "tencentcloud_cbs_storage_attachment" "attachment":
│   61:   for_each = toset(values(tencentcloud_cbs_storage.storage)[*].id)
│     ├────────────────
│     │ tencentcloud_cbs_storage.storage is object with 6 attributes
│
│ The "for_each" value depends on resource attributes that cannot be
│ determined until apply, so Terraform cannot predict how many instances will
│ be created. To work around this, use the -target argument to first apply
│ only the resources that the for_each depends on.

好吧,在Terraform论坛发现一个issue:
https://discuss.hashicorp.com/t/the-for-each-value-depends-on-resource-attributes-that-cannot-be-determined-until-apply/25016
file

简而言之,就是foreach要求他的map key必须是已知明确的值,不能是依赖其他资源的值,所以会有如上错误。知道限制了调整下模板:

resource "tencentcloud_cbs_storage_attachment" "attachment" {
  for_each = var.data_disks
  storage_id  = tencentcloud_cbs_storage.storage[each.key].id
  instance_id = tencentcloud_instance.basic.id
}

圆满解决,新创建的实例用上新的模板,但是存量的实例无法调整还是得忍受下盘重新挂载的问题。

From:https://www.cnblogs.com/leason001/p/18374650
本文地址: http://shuzixingkong.net/article/1352
0评论
提交 加载更多评论
其他文章 逆向WeChat (五)
mmmojo,wmpfmojo。本篇逆向mojoIPC。如何从mojo core的MojoHandle找出binding层的Remote跟Receiver,并使用。包括mmmojo.dll, wmpf_host_export.dll。
逆向WeChat (五) 逆向WeChat (五) 逆向WeChat (五)
Linux基础优化与常用软件包说明
1.安装常用工具 1.1CentOS(7) 1.1.1 是否联网 ping qq.com 1.1.2 配置yum源(安装软件的软件仓库) 默认情况下yum下载软件的时候是从随机地址下载。 配置yum从国内下载(仅执行即可),修改yum配置指定统一下载地址(阿里云). 修改yum下载软件的地址,改为阿
[学习笔记]在不同项目中切换Node.js版本
@目录使用 Node Version Manager (NVM)安装 NVM使用 NVM 安装和切换 Node.js 版本为项目指定 Node.js 版本使用环境变量指定 Node.js安装多个版本的 Node.js设置环境变量验证配置使用 npm 脚本切换 在开发中,可能会遇到不同的Vue项目需要
[学习笔记]在不同项目中切换Node.js版本 [学习笔记]在不同项目中切换Node.js版本 [学习笔记]在不同项目中切换Node.js版本
设计模式之责任链模式
责任链模式是面向对象的23种设计模式中的一种,属于行为模式范围。责任链模式(Chain of Responsibility),见名知意:就是每一个处理请求的处理器组合成一个链表,链表中的每个节点(执行器)都有机会处理发送的请求。 大致的结构是这个样子: 举一个简单的例子:某公司有一名新员工要入职,则
设计模式之责任链模式 设计模式之责任链模式
为什么重写hashCode一定也要重写equals方法?
这是一个经典的问题,我们先从==开始看起 == "==" 是运算符 如果比较的对象是基本数据类型,则比较的是其存储的值是否相等; 如果比较的是引用数据类型,则比较的是所指向对象的地址值是否相等(是否是同一个对象)。 Person p1 = new Person("123
为什么重写hashCode一定也要重写equals方法?
JAVA IO流-小白版
I/O流原理 I/O 是 Input / Output 的缩写,I / O 流技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等; Java中对于数据的输入/输出操作以"流(stream)"的方式进行; Java.io 包下提供了各种"流"类和接
C# WebSocket Fleck 源码解读
最近在维护公司旧项目,偶然发现使用Fleck实现的WebSocket主动推送功能,(由于前端页面关闭时WebSocket Server中执行了多次OnClose事件回调并且打印了大量的关闭日志,),后来我特地看了源码,这里做一些分享 github: https://github.com/s
C# WebSocket Fleck 源码解读 C# WebSocket Fleck 源码解读 C# WebSocket Fleck 源码解读
WPF 模拟UWP原生窗口样式——亚克力|云母材质、自定义标题栏样式、原生DWM动画 (附我封装好的类)
先看一下最终效果,左图为使用亚克力材质并添加组合颜色的效果;右图为MicaAlt材质的效果。两者都自定义了标题栏并且最大限度地保留了DWM提供的原生窗口效果(最大化最小化、关闭出现的动画、窗口阴影、拖拽布局器等)。接下来把各部分的实现一个个拆开来讲讲。 一、使用窗口材质特效 先粗略介绍一下目前win
WPF 模拟UWP原生窗口样式——亚克力|云母材质、自定义标题栏样式、原生DWM动画 (附我封装好的类) WPF 模拟UWP原生窗口样式——亚克力|云母材质、自定义标题栏样式、原生DWM动画 (附我封装好的类) WPF 模拟UWP原生窗口样式——亚克力|云母材质、自定义标题栏样式、原生DWM动画 (附我封装好的类)