通过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

简而言之,就是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
}

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

Terraform中的for_each和count的更多相关文章

  1. 列表中的index,extend,count方法

    列表中的index,extend,count方法 #_author:Administrator#date:2019/10/24#1.index方法l=['blue','red','white','bl ...

  2. Django ORM中,如何使用Count来关联对象的子集数量

    示例models 解决方法 有时候,我们想要获取一个对象关联关系的数量,但是我们不要所有的关联对象,我们只想要符合规则的那些关联对象的数量. 示例models # models.py from dja ...

  3. mysql中MAX()函数和count()函数的技巧使用

    1.max()函数 在考虑提高数据库io的情况下,可以创建索引 ===>create index 索引名称 on 表名(列名); 2.count()函数 问题:count(*)与count(某列 ...

  4. SQL中关于不能显示count为0的行的问题

    今天在写自己一个博客项目时遇到了一个数据库问题,因为对于数据库自己所知道的还是很浅显的,对一些查询语句不怎么熟悉. 我目前有一个文章表和评论表,评论表里面有个post_id对应文章表里面的id,想查询 ...

  5. stl中的for_each() 函数的注意事项

    #include<iostream> using namespace std; #include"vector" #include"algorithm&quo ...

  6. 批量查询hive库中所有表的count

    一.准备文件 mkdir /query_hive_table_count touch query_db_name_table touch query_table_result.txt 二.编辑文件 2 ...

  7. 关于MySQL中查询结果的count和from后的条件与where后的条件对比

    啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦 ...

  8. mysql中count(),group by使用

    count()统计表中或数组中记录 count(*)返回检索行的数目,且不论其值中是否包含NULL count(column_name)返回的是对列中column_name不为NULL的行的统计 例如 ...

  9. mysql中的count(primary_key)、count(1)、count(*)的区别

    表结构如下: mysql> show create table user\G; *************************** 1. row ********************** ...

  10. 关于数据库优化1——关于count(1),count(*),和count(列名)的区别,和关于表中字段顺序的问题

    1.关于count(1),count(*),和count(列名)的区别 相信大家总是在工作中,或者是学习中对于count()的到底怎么用更快.一直有很大的疑问,有的人说count(*)更快,也有的人说 ...

随机推荐

  1. 安卓内核编译:关闭"error, forbidden warning"

    安卓内核编译:关闭error, forbidden warning 背景 最近在编译Android kernel时,遇到error, forbidden warning, 导致编译中断,大大降低了de ...

  2. 关于kubesphere集群calico网络组件报错的修复

    最近公司的项目用到了Kubesphere,于是自己先在虚拟机上测试了一番,遇到了很多的问题,现将遇到的有关calico的问题记录一下 上一篇介绍了如何离线安装kubesphere v3.0,安装之后我 ...

  3. ARM平台实现Docker容器技术

    什么是Docker? (1)Docker的架构   Docker是一个开源的应用容器引擎,让开发者可打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows机器上, ...

  4. yb课堂 开发前端项目路由 《三十五》

    Vue-Router开发前端项目路由 vue-router 是Vue.js官方的路由管理器,它和Vue.js的核心深度集成,让构建单页面应用变得易如反掌 官方文档:https://router.vue ...

  5. cf edu 133 D

    题意 思路 根据题意,最开始可以想到一个二维的dp状态 用dp[i][j]表示跳了j次刚好到i的方案数 如果是跳了j次,那么这次应该要被k+j-1整除才行 那么这样状态转移就是 dp[i][j] = ...

  6. saltStack自动化工具

    目录 SaltStack自动化工具 核心概念 1. Master 和 Minion 2. State 3. Pillar 4. Grains 5. Modules 6. Runner 7. React ...

  7. C# 算术表达式求值(后缀法),看这一篇就够了

    一.种类介绍 算术表达式有三种:前缀表达式.中缀表达式和后缀表达式.一般用的是中缀,比如1+1,前后缀就是把操作符移到前面和后面,下面简单介绍一下这三种表达式. 1.前缀表示法 前缀表示法又叫波兰表示 ...

  8. SUM-ACM——VJ天梯训练赛

    这次比赛我暴露了很多问题,一些模拟还有贪心思路错误. 补题如下: E - E 题解:一道模拟题,我的问题在于不知道怎么替换下一个,就从0开始遍历数组然后数组的值--,如果为零就continue下一个, ...

  9. 开源照片管理神器 PhotoPrism 安装和使用教程

    如今我们每个人都积累了海量的照片和视频,做自媒体的 UP 主们积累的照片和视频数量可能更多.面对这么多的照片和视频,我们该如何管理呢? 之前我一直用谷歌相册,因为它有很多优势,比如无限空间,支持智能整 ...

  10. 七天.NET 8操作SQLite入门到实战 - (3)第七天Blazor学生管理页面编写和接口对接

    前言 本章节的主要内容是完善Blazor学生管理页面的编写和接口对接. 七天.NET 8 操作 SQLite 入门到实战详细教程 第一天 SQLite 简介 第二天 在 Windows 上配置 SQL ...