Troubleshooting Terraform Dependency Cycle
So when i creating my project with my terraform modules, i have face an error when running a command terraform validate, the error shows like this:
│ Error: Cycle: module.sg_node_group.var.ingress_rules (expand), module.sg_node_group.aws_security_group.security_group, module.sg_node_group.output.security_group_id (expand), module.sg_eks.var.ingress_rules (expand), module.sg_eks.aws_security_group.security_group, module.sg_eks.output.security_group_id (expand)
When i find out, this because of terraform dependency cycle that happens when a resource reference each others, in my case is a security group.
Here is an example:
resource "aws_security_group" "a" {
# ...
ingress {
security_groups = [aws_security_group.b.id] # Depends on B
}
ingress {
self = true # Depends on A
}
}
resource "aws_security_group" "b" {
# ...
ingress {
security_groups = [aws_security_group.a.id] # Depends on A
}
}
I have security group A that needs to allow traffic from security group B, and security group B needs to allow traffic from security group A. If we define rules inline, none of them can be created first, because each one needs the ID of the other.
So to fix this error, we can create the two security groups without cross-referencing ingress rules, then create the cross security group rules separately. Including self reference, because it still can create dependency problem.
resource "aws_security_group" "a" { name = "a" }
resource "aws_security_group" "b" { name = "b" }
resource "aws_security_group_rule" "a_allow_b" {
type = "ingress"
security_group_id = aws_security_group.a.id
source_security_group_id = aws_security_group.b.id
}
resource "aws_security_group_rule" "b_allow_a" {
type = "ingress"
security_group_id = aws_security_group.b.id
source_security_group_id = aws_security_group.a.id
}
resource "aws_security_group_rule" "a_allow_a" {
type = "ingress"
security_group_id = aws_security_group.a.id
source_security_group_id = aws_security_group.a.id
}
After this terraform can decide which resource to be created first, which is security group and then attach each ingress rule afterward.
So if there is a cycle dependency or there is a loop where terraform cannot determine which resource to be created first and throw an Error: Cycle. We can extract the resource to be independent / standalone resource so terraform can decide which one to build first.