Короткий ответ
Нужно физически перенести код ресурса в файлы нового модуля, подключить модуль в корневой конфигурации, и либо добавить в конфигурацию блок moved { from = aws_security_group.app, to = module.security.aws_security_group.app } (Terraform 1.1+, предпочтительный декларативный способ), либо выполнить эквивалентную команду terraform state mv aws_security_group.app module.security.aws_security_group.app вручную; в обоих случаях реальный ресурс в AWS не удаляется и не создаётся — меняется только адрес ресурса внутри state, после чего terraform plan должен показать No changes.
Как это работает подробнее
Terraform сопоставляет ресурсы конфигурации с объектами state по полному адресу, включающему путь модуля (module.security.aws_security_group.app отличается от aws_security_group.app); блок moved фиксирует переименование прямо в конфигурации и применяется автоматически при каждом plan/apply, что удобнее для командной работы, чем разовая ручная команда state mv, которую нужно не забыть выполнить каждому, у кого есть доступ к этому state (включая CI), прежде чем он впервые применит новую конфигурацию.
Пример кода
# root main.tf
module "security" {
source = "./modules/security"
vpc_id = aws_vpc.main.id
}
moved {
from = aws_security_group.app
to = module.security.aws_security_group.app
}
$ terraform plan
# ожидаем: Terraform will perform the following actions: (пусто/No changes)
# либо явное сообщение о применении move без destroy/create для security groupЧто использовать на практике
- Практика. после переноса обязательно нужно прогнать
terraform planи убедиться, что единственное отображаемое действие (если есть) — ожидаемое, а не неожиданный destroy/create; также стоит проверить, что вместе с самим ресурсом не потерялись связанные с ним атрибуты/зависимости (например, если на security group ссылались другие ресурсы черезaws_security_group.app.id, эти ссылки нужно обновить наmodule.security.aws_security_group.app.id), иначе план может показать изменения в зависимых ресурсах.
Подводные камни
- Ошибка. частая ошибка — перенести код ресурса в модуль, забыв добавить
moved/выполнитьstate mv, из-за чего Terraform планирует удалить старый ресурс и создать новый внутри модуля, что для security group means временное окно без нужных правил доступа; другая ошибка — выполнитьstate mvлокально у одного инженера, но не донести это изменение до CI/остальной команды до их следующегоplan, из-за чего они получают неожиданный destroy/create, потому что их state ещё не содержит нового адреса.