实现循环 (for)
Terraform 中本身并不支持循环的语句,但是可以通过其他形式来实现循环的效果。
每一个资源块除了他所支持的特定参数外,Terraform 也具有一种被称为 mt acmt 元参数的参数。所谓元参数就是这种参数能够引用到任意的资源块中,从而达到更改资源原有行为的目的。provisioner 就是元参数。
利用 count 元参数实现循环
默认情况下 Terraform 的资源块只允许创建一个基础设施资源对象,不过使用 count 元参数,我们可以让 terraform 一次性创建多个基础设施资源对象,对于创建服务器集群的应用场景,在count 元参数的帮助下,就方便多了。
使用 count 元参数实例
- 在模块中添加 count 参数
count 仅支持整数。count 为 2,期望 Terraform 创建两台 ec2 实例。
# 创建EC2实例
resource "aws_instance" "server" {
count = 2 // 期望创建2台ec2实例
ami = lookup(var.amis, var.region)
instance_type = var.instance_type
key_name = var.ssh_key_name
user_data = var.server_script
tags = {
Name = "${var.server_name}-${count.index}" // 引用 count.index 是实例的索引
}
}
- 引用 count.index 是实例的索引 从0开始计数。
- ${}是变量内查,会渲染成 nginx-server-1
- 在 output 中添加
使用 [*] 表示所有 instance 实例,仅想显示第一台服务器的IP,可以使用 server[0] 来表示。
join 将 IP 地址列表,拼接在一起。
output "ip" {
value = join("\n", aws_instance.server[*].public_ip) // 使用 [*] 表示所有 instance 实例
description = "aws ec2 public ip"
}
- apply
terraform apply
...
Outputs:
SS_IP = <<EOT
34.222.16.131
35.91.156.111
EOT
WEB_IP = <<EOT
34.220.166.53
54.148.9.121
EOT
- 检查
结果是符合预期的
利用 for_each 实现循环
于 count 不同的是,for_each 仅支持 map 和 set 两种类型。
Terraform 的 HCI 配置语言并没有自变量的集合表示法,所以利用 toset
函数将列表转换成集合类型。
for_each 一旦被设置就可以使用 each 变量,each 有两个对象分别是each.key
和 each.value
。在使用集合的情况下他们的结果一样,只有在使用映射时,他们的结果才会不一样。
使用 for_each 元参数实例
- 在模块中添加 for_each 参数
# 创建EC2实例
resource "aws_instance" "server" {
for_each = toset(["dev", "test"]) // 声明 for_each
ami = lookup(var.amis, var.region)
instance_type = var.instance_type
key_name = var.ssh_key_name
user_data = var.server_script
tags = {
Name = "${var.server_name}-${each.key}" // 调用 each 变量
}
}
- 在 output 中添加
output "ip" {
value = join("\n", [aws_instance.server["dev"].public_ip, aws_instance.server["test"].public_ip])
description = "aws ec2 public ip"
}
- apply
$ terraform apply
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
Outputs:
SS_IP = <<EOT
35.164.33.19
34.213.116.13
EOT
WEB_IP = <<EOT
35.87.94.147
34.221.170.139
EOT
- 检查
条件判断 (if)
在 Terraform 的 HCL 语言中通用不支持 if 判断。好在 Terraform 提供了 三目运算符,结合 count 元参数就可以实现 if 条件判断的功能了。
Terraform 的 HCL 配置语言具有以下形式的三目条件表达式。
condition ? true_val : false_val
如果条件为真,结果为真值,反之结果为假值。
当我们为不同的环境准备基础设施资源时, 每一个环境所需要的 ec2 实例数量都不一样,例如,测试环境有2台 ec2 实例,而生产环境有4台 ec2 实例,结合 terraform 的工作区,我们就可以根据相应的条件选择。
使用 count 元参数实现 if条件选择
- 在模块中添加 count 参数
count 对 terraform 的工作区名称进行判断,如果是 test 则将 2 赋值给 count。反之则赋值为 4。
# 创建EC2实例
resource "aws_instance" "server" {
count = terraform.workspace == "test" ? 2 : 4
ami = lookup(var.amis, var.region)
instance_type = var.instance_type
key_name = var.ssh_key_name
user_data = var.server_script
tags = {
Name = "${var.server_name}-${count.index}" // 调用 each 变量
}
}
- 在 output 中添加
output "ip" {
value = join("\n", aws_instance.server[*].public_ip)
description = "aws ec2 public ip"
}
- 创建 test 工作区
% terraform workspace new test
Created and switched to workspace "test"!
You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.
- apply
terraform apply
- 检查
- 切换工作区,执行 plan
% terraform workspace select default
Switched to workspace "default".
% terraform plan
...
# module.nginx-server.aws_instance.server[3] will be created
+ resource "aws_instance" "server" {
+ ami = "ami-03f65b8614a860c29"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
会计划创建4个 ec2 实例。