1. 概要
- 「Cycle」エラー(循環参照)とは
- 発生原因(リソースAがBを参照し、BがAを参照する)
- よくある発生パターン
- 解決方法(参照を外す・depends_on除去・設計の見直し)
循環参照エラーは、2つ以上のリソースが互いに依存し合ってしまったときに発生します。TerraformはDAG(有向非巡回グラフ)で依存関係を管理するため、ループする依存関係は解決できません。
2. エラーメッセージ
Error: Cycle: aws_security_group.app, aws_security_group.db
または:
Error: Cycle
aws_instance.web (destroy) -> aws_security_group.web -> aws_instance.web
3. 典型的な循環参照の例
セキュリティグループの相互参照
terraform {
required_version = ">= 1.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
variable "environment" {
description = "環境名"
type = string
default = "dev"
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "${var.environment}-main"
Environment = var.environment
ManagedBy = "terraform"
}
}
# ❌ エラー: app_sgがdb_sgを参照し、db_sgがapp_sgを参照 → 循環参照
resource "aws_security_group" "app" {
name = "${var.environment}-app-sg"
vpc_id = aws_vpc.main.id
egress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.db.id] # db_sgに依存
}
tags = {
Name = "${var.environment}-app-sg"
Environment = var.environment
ManagedBy = "terraform"
}
}
resource "aws_security_group" "db" {
name = "${var.environment}-db-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app.id] # app_sgに依存 → 循環!
}
tags = {
Name = "${var.environment}-db-sg"
Environment = var.environment
ManagedBy = "terraform"
}
}
4. 解決方法: aws_security_group_rule を分離する
# ✅ 解決: SGを空で作成し、ルールを別リソースで追加
resource "aws_security_group" "app" {
name = "${var.environment}-app-sg"
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.environment}-app-sg"
Environment = var.environment
ManagedBy = "terraform"
}
}
resource "aws_security_group" "db" {
name = "${var.environment}-db-sg"
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.environment}-db-sg"
Environment = var.environment
ManagedBy = "terraform"
}
}
# ルールを別リソースで追加(循環参照が解消される)
resource "aws_security_group_rule" "app_to_db" {
type = "egress"
from_port = 5432
to_port = 5432
protocol = "tcp"
source_security_group_id = aws_security_group.db.id
security_group_id = aws_security_group.app.id
}
resource "aws_security_group_rule" "db_from_app" {
type = "ingress"
from_port = 5432
to_port = 5432
protocol = "tcp"
source_security_group_id = aws_security_group.app.id
security_group_id = aws_security_group.db.id
}
5. depends_on による意図しない循環参照
# ❌ depends_onの設定ミスで循環参照が起きることがある
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
depends_on = [aws_instance.app] # appに依存
}
resource "aws_instance" "app" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
depends_on = [aws_instance.web] # webに依存 → 循環!
}
# ✅ 解決: 不要なdepends_onを削除する
# 実際の参照依存関係だけを使う
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
}
resource "aws_instance" "app" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
}
6. 循環参照の発見方法
# terraform graph で依存グラフを可視化
terraform graph | dot -Tpng -o graph.png
# または planでエラーを確認
terraform plan
7. 関連記事
- terraform graph の使い方 — 依存グラフの可視化
- depends_on の使い方 — 明示的依存関係の追加
- err_unintended_replace — 意図しない置換エラー — 依存関係関連の別エラー
- よくあるエラー集 — common_errors — 他のエラー一覧
- depends_on — 明示的な依存関係を宣言
- resourceブロック — 基本構文と使い方
8. まとめ
- 循環参照(Cycle)はリソースAがBを参照し、BがAを参照する状態で発生
- 最も多い例がセキュリティグループの相互参照(SGのingressとegressで互いを参照)
- 解決策はSGを空で作成し、
aws_security_group_ruleでルールを別途追加する depends_onの誤設定でも循環参照が発生するため、不要なdepends_onは削除するterraform graphで依存グラフを可視化して問題箇所を特定できる
動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/meta-arguments/depends_on