infrastructure 也可以 for each 之一
课程内容与代码会放在 Github 上: https://github.com/chechiachang/terraform-30-days
赛後文章会整理放到个人的部落格上 http://chechia.net/
本章介绍 terraform 的 for_each
,以及如何运用 meta-argument 管理 resource
一般来说,每个 resource block {} 就代表一个 resource。然而在实务中,我们会有额外的需求
如果全部都写成一个一个独立的 resouce block
因此 terraform 有提供 meta-argument。使用者可以在 resource 以外的地方,使用 meta-argument 改变 terraform evaluate resource block 的行为。
几乎所有的高级程序语言都有提供 for, each, loop 等语法,来处理不断重复的逻辑。能够高频率的执行重复工作,这对软件产业的效能是至关重要的。
这也是 IaC 管理公有云时,相对於 web console 操作有决定性的优势,例如:
Terraform 在管理大量类似的云端 resource 是十分有效率的,底下为各位示范。我们可以先用自己熟悉的语言来做个想像
例如 Cloud Computing 最常用到的功能之一,使用 loop 快速 provision VM
如果是熟悉的语言,大概会是长什麽样子
# sudo code
createFirewallRule()
for i from 0 to 9 {
createPublicIP($i)
}
for j from 0 to 9 {
createVM(
name: $j
publicIP: $ip
firewallRule: $firewallRule
...
)
}
Terraform 提供两个不同用途的
范例:modules/kubernetes_cluster/node_pool.tf
# modules/kubernetes_cluster/node_pool.tf
resource "azurerm_kubernetes_cluster_node_pool" "main" {
for_each = var.node_pools
name = each.value.name
kubernetes_cluster_id = azurerm_kubernetes_cluster.main.id
vm_size = each.value.vm_size
node_count = each.value.node_count
mode = each.value.mode
priority = each.value.priority
node_labels = each.value.node_labels
node_taints = each.value.node_taints
depends_on = [
azurerm_kubernetes_cluster.main
]
}
resource.azurerm_kubernetes_cluster_node_pool.main
中使用两个 meta-arguments
depends_on
建立依赖关系,确保 node_pool
会在 azurerm_kubernetes_cluster.main
产生後才会产生for_each
可以依据 var.node_pools
,为每个 var.node_pools
的 element 产生一个 resource.azurerm_kubernetes_cluster_node_pool.main
首先先看 depends on terraform 官方文件
depends_on
explicitly 建立依赖关系,确保 node_pool
会在 azurerm_kubernetes_cluster.main
产生後才会产生depends_on
的话,plan 或 apply 仍然会成功吗?
depends_on
的话不影响顺序node_pool
的参数中, kubernetes_cluster_id = azurerm_kubernetes_cluster.main.id
就需要 cluster 的 id,而 id 是 kubernetes_cluster
的参数,产生之後才会取得,terrafrom 会自动推测(automatically infer)两者的 dependency提醒注意的地方
depends_on
meta-argument,然而官方建议使用上应该作为最後手段(last resort)depends_on
无法使用 Arbitrary expressions,意思是不能使用可变的数值,而是必须静态的值,举例
var.node_pools
内部 element 的长度,如果没有 element 就不用建立 depends_on
depends_on = [
length(var.node_pools) > 0 ? azurerm_kubernetes_cluster.main : null
]
terragrunt init
There are some problems with the configuration, described below.
The Terraform configuration must be valid before initialization so that
Terraform can determine which modules and providers need to be installed.
╷
│ Error: Invalid expression
│
│ on node_pool.tf line 16, in resource "azurerm_kubernetes_cluster_node_pool" "main":
│ 16: length(var.node_pools) > 0 ? azurerm_kubernetes_cluster.main : null
│
│ A single static variable reference is required: only attribute access and
│ indexing with constant keys. No calculations, function calls, template
│ expressions, etc are allowed here.
╵
ERRO[0003] 1 error occurred:
* exit status 1
为何无法使用,许多 meta-argument 也是必须使用静态的参数:例如 depends_on
, provider, lifecycle
使用 provider 作为范例来说明可能比较单纯
terraform 首先需要 init,明确指定使用的 provider 版本与 source,或是让 terraform 扫描并推测使用的 provider
没有 provider,便无法 plan 各个 resource,包含内部的参数 validate
读取 state 内容,plan 与 apply 都必须有静态的 provider 存在,如果 provider 使是动态产生,有时存再有时不存在便会影响上述工作
terraform 限制 provider 的使用,设定必须是静态的
但在少数的情形,可以产生 provider 後,透过操作移除已经 init 的 provider,这时远端 state 上已经存在,但本地没有 provider 可以读取与 plan,便会产生 orphan state
depends_on
概念相同,如果依赖有时为 true,有时为 false 的判断 expression,就无法建立静态的依赖性
lifecycle 可以改变 terraform plan, apply 中的行为,也需要静态的 expression 设定
上一篇DAY5: Node 的内部机制(一)主要解释了JavaScript的同步与非同步,相信看完上...
时间过得非常快,在参加 30 天不中断的 iT 邦帮忙铁人赛,在 1/3 路程的时候,就会开始有点挣...
tags: ItIron2021 Javascript 前言 今天又要继续非同步与promise的爱...
终於来到Class的章节了,Class是ES6所新增,在这之前都是使用Prototype去进行物件导...
嗨嗨~ 今天比较晚下班,还没写文章也还没写专案XD 今天先建立专案好了~ 周末再赶进度! Setup...