Terraform歴
直近一年くらいAWS基盤をTerraformで構築・更改するっていう感じでした。
利用バージョンの変遷としては以下な感じ。
v0.11.3
-> v0.11.5
-> v0.11.7
まあv0.11.*
太郎なわけです。
環境も変わったことだし、いっちょv0.12.*
するか〜とv0.12.5
で書き始めたところです。
その中での備忘録です。(まだ全然途中なのでちょくちょく更新入ると思います。)
Variables
すごく見やすく && 書きやすくなりました。
反面、一部同様に書いてあげないとうまくいかないケースがありました。
以前の書き方
v0.11.7
時代の書き方
resource "aws_instance" "bastion" {
ami = "${var.ec2_ami}"
ebs_optimized = false
instance_type = "${var.ec2_type}"
monitoring = false
key_name = "${var.secret_key}"
subnet_id = "${aws_subnet.public.id}"
vpc_security_group_ids = ["${aws_security_group.bastion.id}"]
associate_public_ip_address = true
source_dest_check = true
iam_instance_profile = "${var.service_name}-bastion"
user_data = "${data.ec2_userdata.bastion.rendered}"
root_block_device {
volume_type = "gp2"
volume_size = 50
delete_on_termination = false
}
tags {
"Name" = "${var.service_name}-bastion-${var.environment}"
"Service" = "${var.service_name}"
"Env" = "${var.environment}"
}
volume_tags {
"Name" = "${var.service_name}-bastion-${var.environment}"
"Service" = "${var.service_name}"
"Env" = "${var.environment}"
}
lifecycle {
ignore_changes = [
"user_data",
"key_name",
"root_block_device.0.volume_type",
"subnet_id",
]
}
}
v0.12.5での書き方
v0.12.5
で書くと
resource "aws_instance" "bastion" {
ami = var.ec2_ami
ebs_optimized = false
instance_type = var.ec2_type
monitoring = false
key_name = var.secret_key
subnet_id = aws_subnet.public.id
vpc_security_group_ids = aws_security_group.bastion.id
associate_public_ip_address = true
source_dest_check = true
iam_instance_profile = "${var.service_name}-bastion"
user_data = data.ec2_userdata.bastion.rendered
root_block_device {
volume_type = "gp2"
volume_size = 50
delete_on_termination = false
}
tags {
"Name" = "${var.service_name}-bastion-${var.environment}"
"Service" = var.service_name
"Env" = var.environment
}
volume_tags {
"Name" = "${var.service_name}-bastion-${var.environment}"
"Service" = var.service_name
"Env" = var.environment
}
lifecycle {
ignore_changes = [
"user_data",
"key_name",
"root_block_device.0.volume_type",
"subnet_id",
]
}
}
とまあすごくスッキリしてますし、実際大量に書くときは楽です。
が、一部旧形式で書いている部分がありますね。
String
形式でもVariable単体では無い場合、やはりこういう書き方をしてあげないとplanで怒られます。
沼にハマる
個人的にはまったのはこれ。
resource "aws_subnet" "private" {
count = "${length(split(",", lookup(local.availability_zones, var.region)))}"
vpc_id = "${aws_vpc.service-vpc.id}"
cidr_block = "${cidrsubnet(aws_vpc.service-vpc.cidr_block, 4, count.index + length(split(",", lookup(local.availability_zones, var.region))) * 1)}"
availability_zone = "${element(split(",", lookup(local.availability_zones, var.region)), count.index)}"
map_public_ip_on_launch = false
depends_on = ["aws_vpc.service-vpc"]
tags = {
Name = "${var.service_name}-private-${var.environment}-${count.index}"
Env = "${var.environment}"
Service = ["${var.service_name}"]
}
}
resource "aws_db_subnet_group" "db" {
name = "${var.service_name}-${var.short_env}-db"
description = "${var.service_name} subnet group for db"
subnet_ids = ["${aws_subnet.private.*.id}"]
tags = {
Name = "${var.service_name}-${var.environment}"
Env = "${var.environment}"
Service = "${var.service_name}"
}
}
指定しているAZの数に応じてprivateサブネットを作成するようcount
を利用しているのですが、そのidを参照して作成しようとしたら怒られました
Error: Incorrect attribute value type
on rds.tf line 75, in resource "aws_db_subnet_group" "db":
75: subnet_ids = ["${aws_subnet.private.*.id}"]
Inappropriate value for attribute "subnet_ids": element 0: string required.
え、リストで指定せいゆーてたやん、、ドキュメントにも書いてあるやん。。
・subnet_ids - (Required) A list of VPC subnet IDs.
と思いつつ下記に変更したら通りました。。
resource "aws_db_subnet_group" "db" {
name = "${var.service_name}-${var.short_env}-db"
description = "${var.service_name} subnet group for db"
subnet_ids = "${aws_subnet.private.*.id}"
tags = {
Name = "${var.service_name}-${var.environment}"
Env = "${var.environment}"
Service = "${var.service_name}"
}
}
v0.11.*
にあんなに怒られたのになあ…(遠い目)と思いを馳せつつ実装を進めました。
ちなみにterraform 0.12upgrade
で実施してみたら下記のように変更されてました。
※ やる前にちゃんとGithubにあげとくなりなんなりしないと戻すの大変なので注意!!!!
resource "aws_subnet" "private" {
count = length(split(",", local.availability_zones[var.region]))
vpc_id = aws_vpc.service-vpc.id
cidr_block = cidrsubnet(aws_vpc.service-vpc.cidr_block, 4, count.index + length(split(",", local.availability_zones[var.region])) * 1,)
availability_zone = element(split(",", local.availability_zones[var.region]), count.index,)
map_public_ip_on_launch = false
depends_on = [aws_vpc.service-vpc]
tags = {
Name = "${var.service_name}-private-${var.environment}-${count.index}"
Env = var.environment
Service = var.service_name
}
}
resource "aws_db_subnet_group" "mysql-serverless" {
name = "${var.service_name}-${var.short_env}-db"
description = "${var.service_name} subnet group for db"
subnet_ids = aws_subnet.private.*.id
tags = {
Name = "${var.service_name}-${var.environment}"
Env = var.environment
Service = var.service_name
}
}
余談ですがterraform 0.12upgrade
で実施するとlength
とかcidrsubnet
みたいなところはめちゃめちゃ改行されて出力されるんでびっくりします。
Error Message
まあこればっかりは仕方ないんですが、「こんなエラー出るかもな」でplan流したら結構長めの文で怒られます。凹みます。
いや、エラーメッセージの内容がすごく細かくなっていて、指摘通りに修正してあげると割とWeb徘徊しなくても解決しちゃうことが多いです。
助かる反面、最初はビビりました…大量に出たんでそんな変わったんか!?と
自分がショボかっただけでした。
Warining Sample
初歩的な変数設定のミスなのに、こんなやりかたもあんでという母のような優しさ。
Warning: Value for undeclared variable
on sandbox.tfvars line 3:
3: service = "sandbox"
The root module does not declare a variable named "service". To use this
value, add a "variable" block to the configuration.
Using a variables file to set an undeclared variable is deprecated and will
become an error in a future release. If you wish to provide certain "global"
settings to all configurations in your organization, use TF_VAR_...
environment variables to set these instead.
Error Sample
こっちでやってみたらどうだ?という父のような頼もしさ。
Error: Missing resource instance key
on iam.tf line 18, in resource "aws_iam_role_policy_attachment" "policy-attach":
273: role = "${aws_iam_role.role.name}"
Because aws_iam_role.role has "count" set, its attributes must be
accessed on specific instances.
For example, to correlate with indices of a referring resource, use:
aws_iam_role.role[count.index]
Terraformは僕の両親です。
おまけ
新しい記法で書くとエディタがうまく反応してくれねっす。
Pycharmを使ってるんですが、バージョンが古いからかブロックの認識がうまくいかず…可読性の問題で結局元の書き方で書いて最後にぴゃぴゃっと直す的な。。
module
も使わんとなあと思いつつ、なかなか癖が抜けず。。
参考
このページだけで十分でした…神様🙏
terraform v0.12 アップデート terraform 0.12upgrade,terraform 0.12checklistサブコマンド実行結果と、ファイルの変更例