こんにちは、最近は業務でもTerraform書き書き人間になっているものです
そこで、業務中に表題の件が発生したので備忘録を兼ねてここに残しておきます
■起こったこと
・最初にTerraformでAWSのセキュリティグループ(aws_security_group_rule)を作成した
・cidr_blocks を list で受けて書いて、そこに追加で新規IPアドレスを追記した
・planを実行するとなぜか、forces replacement での反映となり、グループルールが再作成されるようになる
※必要なVPCなどはすでに作成済みです
・ルートモジュール
##Security Group Internal
module "internal_sg" {
source = "../../module/securitygroup"
general_config = var.general_config
vpc_id = module.network.vpc_id
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["10.0.0.0/16", "192.169.33.31/32", "192.168.33.32/32", "192.168.33.33/32"] ★当該箇所
sg_role = "internal"
}
→cidr_blocks に “192.168.33.33/32” を追記した
・子モジュールの変数
variable "cidr_blocks" {
type = list(string)
}
・子モジュール
##Security Group
resource "aws_security_group" "default" {
name = "${var.general_config["project"]}-${var.general_config["env"]}-${var.sg_role}-sg"
vpc_id = var.vpc_id
tags = {
Name = "${var.general_config["project"]}-${var.general_config["env"]}-${var.sg_role}-sg"
}
}
##Security Group Rule Ingress
resource "aws_security_group_rule" "ingress" {
type = "ingress"
from_port = var.from_port
to_port = var.to_port
protocol = var.protocol
cidr_blocks = var.cidr_blocks ★当該箇所
security_group_id = aws_security_group.default.id
}
##Security Group Rule Egress
resource "aws_security_group_rule" "egress" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.default.id
}
・planの実行
$ terraform plan
~省略~
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# module.internal_sg.aws_security_group_rule.ingress must be replaced
-/+ resource "aws_security_group_rule" "ingress" {
~ cidr_blocks = [ # forces replacement
# (2 unchanged elements hidden)
"192.168.33.32/32",
+ "192.168.33.33/32",
]
~ id = "sgrule-1746461875" -> (known after apply)
+ security_group_rule_id = (known after apply)
+ source_security_group_id = (known after apply)
# (6 unchanged attributes hidden)
}
Plan: 1 to add, 0 to change, 1 to destroy.
→なぜか削除と作成が実行されそう、、、、(なんでや)
■なぜ起こる??
日本語と英語を含めて色々と調査してみましたが正確な情報は分かりませんでした
ただ、同一の事象に悩んでいる方は世界中にいるようでこちらのようなissueが上がっており、既存のlistに追加した場合、terraform側でうまくいかないのかもしれないみたいです
もしこちらの事象について何かご存じでしたらご教示いただけますと幸いでございます、、、、
■改善策
1. ignore_changes を利用する
根本的な解決策にはならないですが、plan で差分を出さないようにするだけなら、一時的に cidr_blocks のみを ignore_changes に指定する方法はあります
その場合、IPの追加はAWSコンソール上から実施する必要があるので、そこは注意です(あくまでコードを合わせにいくイメージです)
##Security Group Rule Ingress
resource "aws_security_group_rule" "ingress" {
type = "ingress"
from_port = var.from_port
to_port = var.to_port
protocol = var.protocol
cidr_blocks = var.cidr_blocks
security_group_id = aws_security_group.default.id
lifecycle {
ignore_changes = [
cidr_blocks
]
}
}
2. for_each を利用する
for_each で list の中の値を一つ一つ回すようにします
##Security Group Rule Ingress
resource "aws_security_group_rule" "ingress" {
for_each = toset(var.cidr_blocks)
type = "ingress"
from_port = var.from_port
to_port = var.to_port
protocol = var.protocol
cidr_blocks = [each.key]
security_group_id = aws_security_group.default.id
}
追記後の plan 結果
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.internal_sg.aws_security_group_rule.ingress["192.168.33.33/32"] will be created
+ resource "aws_security_group_rule" "ingress" {
+ cidr_blocks = [
+ "192.168.33.33/32",
]
+ from_port = 0
+ id = (known after apply)
+ protocol = "-1"
+ security_group_id = "sg-0cf7f4a195a1299dd"
+ security_group_rule_id = (known after apply)
+ self = false
+ source_security_group_id = (known after apply)
+ to_port = 0
+ type = "ingress"
}
Plan: 1 to add, 0 to change, 0 to destroy.
→追記したIPのみが差分として出力されています!
■まとめ
いかがでしたでしょうか
正直なぜ本事象が発生したのかは分かりませんでしたが、本事象が発生することを知っていれば今後は for_each を使ってセキュリティグループを作成したほうがよさそうですね
それではまたーー