hokanでインターン中のかわひとです。
terraformに入門して1週間経ったので、学んだことを記事にしてみました。
ちなみにQiita初記事です!
複数のEC2を一括で立ち上げてみる
for_eachを使う
provider "aws" {
region = "ap-northeast-1"
}
module "ec2" {
source = "./ec2"
arguments = {
"example1" = {
instance_type = "t2.micro"
ami = "ami-09ebacdc178ae23b7"
},
"example2" = {
instance_type = "t3.nano"
ami = "ami-0578730a012dc2185"
},
"example3" = {
instance_type = "t2.nano"
ami = "ami-0df99b3a8349462c6"
}
}
}
output "hello" {
value = module.ec2
}
variable "arguments" {
type = map(map(string))
}
resource "aws_instance" "ec2" {
for_each = var.arguments
ami = each.value.ami
instance_type = each.value.instance_type
tags = {
Name = each.key
}
}
resource "aws_eip" "eip" {
for_each = aws_instance.ec2
instance = each.value.id
}
output "ec2_ids" {
value = { for k, v in aws_instance.ec2 : k => v.id }
}
for_eachはTerraform 0.13から追加された記法です。
公式によると
The for_each meta-argument accepts a map or a set of strings
とありますから、list(map(string))
とかループしようとすると怒られます。
また作成された各EC2インスタンスをループすることもできます。
上記のコードでは、各インスタンスをループして、Elastic IP アドレスを登録しています。
各EC2インスタンスへの参照は、aws_instance.ec2[key]です。keyは上記の例でいうと、"example1"や"example2"になります。
# アウトプット
sample_output = {
"example1" = "i-060e0264a993b95d2"
"example2" = "i-025aa2d522d80c951"
"example3" = "i-0c7a2dd83f5f0499e"
}
アウトプット部分で使っているforの記法は、公式サイトを参考にしてください。
countを使う
terraformでは、count を使えば単純に数を増やせます。
resource "aws_instance" "ec2" {
ami = "ami-09ebacdc178ae23b7"
instance_type = "t2.micro"
count = 10
}
同じ性能のインスタンスが10個立ち上がります。
インスタンスによって値を変えたい場合は、count.indexを利用します。
provider "aws" {
region = "ap-northeast-1"
}
module "ec2" {
source = "./ec2"
arguments = [
{
name = "example1"
instance_type = "t2.micro"
ami = "ami-09ebacdc178ae23b7"
},
{
name = "example2"
instance_type = "t3.nano"
ami = "ami-0578730a012dc2185"
},
{
name = "example3"
instance_type = "t2.nano"
ami = "ami-0df99b3a8349462c6"
}
]
}
output "sample_output" {
value = module.ec2.ec2_id
}
variable "arguments" {
type = list(map(string))
}
resource "aws_instance" "ec2" {
count = length(var.arguments)
ami = var.arguments[count.index].ami
instance_type = var.arguments[count.index].instance_type
tags = {
Name = var.arguments[count.index].name
}
}
resource "aws_eip" "eip" {
count = length(var.arguments)
instance = aws_instance.ec2[count.index].id
}
output "ec2_id" {
value = aws_instance.ec2.*.id
# * = 1, 2, 3
}
count = length(var.arguments)
とすることで、リストの長さ分だけEC2インスタンスを作成します。またcount.index
を使うことで、リストの各要素を取り出しています。
for_eachではmapをループしましたが、countの構文ではリストをループする感じです。
またoutputの中では、*
という記号でindexを使えるっぽいです。
# アウトプット
sample_output = [
"i-0a45fc109254eb6ea",
"i-0dd457447e07d00ee",
"i-00b310944d415a592",
]
セキュリティグループのルール
ネストされたブロック内でループするには、dynamicブロックを使う必要があります。
普通にfor_eachを使おうとするとエラーがでるので注意が必要です。
variable "ingressrules" {
type = list(number)
default = [80, 443, 22, 25]
}
resource "aws_security_group" "sample" {
dynamic "ingress" {
for_each = var.ingressrules
content {
from_port = ingress.value
to_port = ingress.value
protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
とくにセキュリティグループのインバウンド/アウトバウンドルールは、単純なループになりがちなので、この記法が活躍すると思います。
for_eachの各要素にアクセスするには、each.value ではなく、ブロック名.value とする点に注意が必要です。
なお iterator を指定すると、iterator名.value とできます。
↓dynamic ブロックの使い方はこちら。