몇 번이고 잘 돌던 코드였다. Terraform으로 MySQL DB Instance를 만드는 평범한 main.tf인데, 이날은 apply를 할 때마다 같은 에러를 뱉었다.

aws_db_instance.example: Creating...
│ Error: creating RDS DB Instance (terraform-db20240505074947525100000001): InvalidVPCNetworkStateFault: The VPC vpc-05819890763cddf88 associated with the default subnet group does not exist. Please delete the default subnet group or specify another subnet group.
│       status code: 400, request id: 84afb05a-bd40-422c-9e62-958154a568c0
│
│   with aws_db_instance.example,
│   on main.tf line 25, in resource "aws_db_instance" "example":
│   25: resource "aws_db_instance" "example" {

로그에 찍힌 vpc-05819890763cddf88은 이미 존재하지 않는 VPC였다. 이 글에서는 이 참조를 떼어 내려고 해 본 일들과 결국 먹힌 방법 하나를 정리한다.

사라진 Default VPC의 흔적

짐작 가는 데가 있었다. 로그의 VPC ID는 팀원 중 한 분이 지운 기존 Default VPC로 보인다. 이날 콘솔을 보니 Default VPC가 없어서 내가 직접 새로 만들었는데, 아마 그때부터 존재하지 않는 VPC를 참조하게 된 것 같다.

VPC는 새로 생겼는데 RDS는 여전히 옛 ID를 찾는다. 처음에는 Terraform이 이 변화를 모르고 state와 꼬였다고 생각했다.

state를 전부 지워도 에러는 그대로였다

Terraform 쪽에서 지울 수 있는 건 다 지웠다.

  1. 모든 리소스 destroy

  2. state 파일 삭제

  3. .terraform 디렉터리 삭제

  4. 백엔드 상태 파일 저장소였던 S3 버킷까지 삭제

더 할 수 있는 조치가 없었는데도 apply 결과는 똑같았다. 같은 문제를 겪은 사람들의 글도 여럿 찾았지만 명쾌한 답은 없었다.

db_subnet_group_name을 명시하니 풀렸다

긴 삽질 끝에 혼자 찾은 방법은 aws_db_instance에 db_subnet_group_name을 명시적으로 넣는 것이었다. Default VPC와 그 서브넷을 data로 읽어 DB subnet group을 직접 만들고, 인스턴스가 그 그룹을 쓰게 한다.

# 지금 있는 Default VPC를 조회한다
data "aws_vpc" "default" {
  default = true
}

# 그 VPC에 속한 서브넷 목록
data "aws_subnets" "default" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.default.id]
  }
}

# RDS가 쓸 subnet group을 직접 만든다
resource "aws_db_subnet_group" "example" {
  name        = "example-subnet-group"
  subnet_ids  = data.aws_subnets.default.ids # 예제 서브넷 ID들

  tags = {
    Name = "My DB subnet group"
  }
}

resource "aws_db_instance" "example" {
  db_subnet_group_name = aws_db_subnet_group.example.name # 이 한 줄이 핵심
  identifier_prefix   = "terraform-db"
  engine              = "mysql"
  allocated_storage   = 10            # 스토리지 10 GB
  instance_class      = "db.t3.micro" # 1 CPU, 1 GB Memory
  db_name             = "example_database"
  username            = "admin"
  ...
}

범인은 state가 아니라 AWS 쪽 default subnet group이었다

당시에는 “이게 사람들이 말하는 Terraform의 미흡한 부분인가” 하고 넘어갔다. 글로 옮기며 에러 메시지를 다시 읽어 보니 답이 거기 있었다. 문제의 VPC는 “associated with the default subnet group”, 즉 RDS의 기본 DB subnet group에 묶여 있다고 적혀 있다.

db_subnet_group_name을 비워 두면 RDS는 인스턴스를 기본 DB subnet group에 만든다. 그 기본 subnet group은 Terraform이 만든 리소스가 아니라 AWS 계정 쪽에 남아 있는 리소스다. Default VPC가 지워진 뒤에도 subnet group은 옛 VPC ID를 든 채 남았고, Default VPC를 새로 만들어도 그 연결은 바뀌지 않았다. state 파일에는 애초에 이 subnet group이 없으니 state를 아무리 지워도 소용이 없었던 것이다.

에러 메시지가 제시한 해결책도 두 가지다. default subnet group을 지우거나, 다른 subnet group을 지정하거나. 나는 두 번째를 골랐다. 기본값에 기대지 않고 어떤 VPC에 DB를 둘지 코드에 적어 두는 쪽이라 다음에 같은 일이 생겨도 영향을 받지 않는다.

같은 이슈가 GitHub에도 있었다

문제를 해결하고 기록하려고 정리하다 보니 같은 증상을 다룬 이슈가 하나 더 보였다. 거기서 말하는 해결 방법도 내가 한 것과 같았다. 지금으로서는 subnet group을 명시하는 게 최선인 듯하다.